Browse Source

Scrutinizer Auto-Fixes

This commit consists of patches automatically generated for this project on https://scrutinizer-ci.com
Scrutinizer Auto-Fixer 4 years ago
parent
commit
c263c8a76c
69 changed files with 14597 additions and 14597 deletions
  1. 9 9
      htdocs/accountancy/admin/index.php
  2. 122 122
      htdocs/accountancy/customer/list.php
  3. 3 3
      htdocs/accountancy/expensereport/lines.php
  4. 3 3
      htdocs/accountancy/expensereport/list.php
  5. 66 66
      htdocs/accountancy/supplier/list.php
  6. 115 115
      htdocs/admin/bank.php
  7. 5 5
      htdocs/admin/emailcollector_card.php
  8. 364 364
      htdocs/admin/menus/edit.php
  9. 302 302
      htdocs/comm/action/class/actioncomm.class.php
  10. 487 487
      htdocs/comm/action/index.php
  11. 7 7
      htdocs/comm/propal/list.php
  12. 552 552
      htdocs/commande/class/api_orders.class.php
  13. 128 128
      htdocs/commande/class/commande.class.php
  14. 277 277
      htdocs/compta/facture/class/facture.class.php
  15. 7 7
      htdocs/contact/card.php
  16. 19 19
      htdocs/contact/list.php
  17. 14 14
      htdocs/core/class/CMailFile.class.php
  18. 264 264
      htdocs/core/class/commonobject.class.php
  19. 381 381
      htdocs/core/class/coreobject.class.php
  20. 415 415
      htdocs/core/class/extrafields.class.php
  21. 74 74
      htdocs/core/class/html.form.class.php
  22. 4 4
      htdocs/core/class/html.formmail.class.php
  23. 3 3
      htdocs/core/class/html.formticket.class.php
  24. 724 724
      htdocs/core/class/menubase.class.php
  25. 73 73
      htdocs/core/lib/accounting.lib.php
  26. 11 11
      htdocs/core/lib/company.lib.php
  27. 19 19
      htdocs/core/lib/functions.lib.php
  28. 2 2
      htdocs/core/lib/images.lib.php
  29. 48 48
      htdocs/core/lib/ticket.lib.php
  30. 6 6
      htdocs/core/menus/standard/auguria.lib.php
  31. 31 31
      htdocs/core/menus/standard/eldy.lib.php
  32. 2179 2179
      htdocs/core/modules/DolibarrModules.class.php
  33. 33 33
      htdocs/core/modules/expensereport/doc/pdf_standard.modules.php
  34. 3 3
      htdocs/core/tpl/objectline_create.tpl.php
  35. 76 76
      htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php
  36. 7 7
      htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php
  37. 5 5
      htdocs/debugbar/class/DebugBar.php
  38. 28 28
      htdocs/debugbar/class/autoloader.php
  39. 916 916
      htdocs/emailcollector/class/emailcollector.class.php
  40. 137 137
      htdocs/expedition/card.php
  41. 454 454
      htdocs/expensereport/card.php
  42. 1157 1157
      htdocs/expensereport/class/expensereport.class.php
  43. 507 507
      htdocs/fourn/class/api_supplier_invoices.class.php
  44. 667 667
      htdocs/fourn/class/fournisseur.commande.class.php
  45. 506 506
      htdocs/fourn/class/fournisseur.facture.class.php
  46. 45 45
      htdocs/fourn/commande/card.php
  47. 129 129
      htdocs/holiday/card.php
  48. 2 2
      htdocs/index.php
  49. 87 87
      htdocs/loan/class/paymentloan.class.php
  50. 123 123
      htdocs/opensurvey/card.php
  51. 612 612
      htdocs/opensurvey/class/opensurveysondage.class.php
  52. 7 7
      htdocs/product/class/product.class.php
  53. 4 4
      htdocs/product/inventory/card.php
  54. 40 40
      htdocs/product/inventory/inventory.php
  55. 4 4
      htdocs/product/list.php
  56. 1 1
      htdocs/product/stock/class/entrepot.class.php
  57. 107 107
      htdocs/product/stock/product.php
  58. 1 1
      htdocs/projet/class/project.class.php
  59. 16 16
      htdocs/recruitment/recruitmentindex.php
  60. 182 182
      htdocs/stripe/class/stripe.class.php
  61. 1881 1881
      htdocs/supplier_proposal/class/supplier_proposal.class.php
  62. 63 63
      htdocs/takepos/invoice.php
  63. 43 43
      htdocs/ticket/card.php
  64. 23 23
      htdocs/ticket/class/ticket.class.php
  65. 6 6
      htdocs/ticket/list.php
  66. 3 3
      htdocs/user/class/user.class.php
  67. 1 1
      htdocs/user/group/perms.php
  68. 1 1
      htdocs/user/perms.php
  69. 6 6
      htdocs/variants/class/ProductCombination.class.php

+ 9 - 9
htdocs/accountancy/admin/index.php

@@ -297,12 +297,12 @@ print '<tr class="oddeven">';
 print '<td>'.$langs->trans("ACCOUNTANCY_COMBO_FOR_AUX").'</td>';
 if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) {
 	print '<td class="right"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setenablesubsidiarylist&value=0">';
-    print img_picto($langs->trans("Activated"), 'switch_on');
-    print '</a></td>';
+	print img_picto($langs->trans("Activated"), 'switch_on');
+	print '</a></td>';
 } else {
 	print '<td class="right"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setenablesubsidiarylist&value=1">';
-    print img_picto($langs->trans("Disabled"), 'switch_off');
-    print '</a></td>';
+	print img_picto($langs->trans("Disabled"), 'switch_off');
+	print '</a></td>';
 }
 print '</tr>';
 
@@ -310,12 +310,12 @@ print '<tr class="oddeven">';
 print '<td>'.$langs->trans("ACCOUNTING_MANAGE_ZERO").'</td>';
 if (!empty($conf->global->ACCOUNTING_MANAGE_ZERO)) {
 	print '<td class="right"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setmanagezero&value=0">';
-    print img_picto($langs->trans("Activated"), 'switch_on');
-    print '</a></td>';
+	print img_picto($langs->trans("Activated"), 'switch_on');
+	print '</a></td>';
 } else {
 	print '<td class="right"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setmanagezero&value=1">';
-    print img_picto($langs->trans("Disabled"), 'switch_off');
-    print '</a></td>';
+	print img_picto($langs->trans("Disabled"), 'switch_off');
+	print '</a></td>';
 }
 print '</tr>';
 
@@ -387,7 +387,7 @@ foreach ($list_binding as $key)
 	} elseif ($key == 'ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER') {
 		$array=array(0=>$langs->trans("PreviousMonth"), 1=>$langs->trans("CurrentMonth"), 2=>$langs->trans("Fiscalyear"));
 		print $form->selectarray($key, $array, (isset($conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER)?$conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER:0));
-    } else {
+	} else {
 		print '<input type="text" class="maxwidth100" id="'.$key.'" name="'.$key.'" value="'.$conf->global->$key.'">';
 	}
 

+ 122 - 122
htdocs/accountancy/customer/list.php

@@ -140,48 +140,48 @@ if (empty($reshook))
 
 
 if ($massaction == 'ventil') {
-    $msg = '';
-
-    //print '<div><font color="red">' . $langs->trans("Processing") . '...</font></div>';
-    if (!empty($mesCasesCochees)) {
-        $msg = '<div>'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'</div>';
-        $msg .= '<div class="detail">';
-        $cpt = 0;
-        $ok = 0;
-        $ko = 0;
-
-        foreach ($mesCasesCochees as $maLigneCochee) {
-            $maLigneCourante = explode("_", $maLigneCochee);
-            $monId = $maLigneCourante[0];
-            $monCompte = GETPOST('codeventil'.$monId);
-
-            if ($monCompte <= 0)
-            {
-                $msg .= '<div><font color="red">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NoAccountSelected").'</font></div>';
-                $ko++;
-            } else {
-                $sql = " UPDATE ".MAIN_DB_PREFIX."facturedet";
-                $sql .= " SET fk_code_ventilation = ".$monCompte;
-                $sql .= " WHERE rowid = ".$monId;
-
-                $accountventilated = new AccountingAccount($db);
-                $accountventilated->fetch($monCompte, '');
-
-                dol_syslog("accountancy/customer/list.php sql=".$sql, LOG_DEBUG);
-                if ($db->query($sql)) {
-                    $msg .= '<div><font color="green">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("VentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'</font></div>';
-                    $ok++;
-                } else {
-                    $msg .= '<div><font color="red">'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'<br> <pre>'.$sql.'</pre></font></div>';
-                    $ko++;
-                }
-            }
-
-            $cpt++;
-        }
-        $msg .= '</div>';
-        $msg .= '<div>'.$langs->trans("EndProcessing").'</div>';
-    }
+	$msg = '';
+
+	//print '<div><font color="red">' . $langs->trans("Processing") . '...</font></div>';
+	if (!empty($mesCasesCochees)) {
+		$msg = '<div>'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'</div>';
+		$msg .= '<div class="detail">';
+		$cpt = 0;
+		$ok = 0;
+		$ko = 0;
+
+		foreach ($mesCasesCochees as $maLigneCochee) {
+			$maLigneCourante = explode("_", $maLigneCochee);
+			$monId = $maLigneCourante[0];
+			$monCompte = GETPOST('codeventil'.$monId);
+
+			if ($monCompte <= 0)
+			{
+				$msg .= '<div><font color="red">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NoAccountSelected").'</font></div>';
+				$ko++;
+			} else {
+				$sql = " UPDATE ".MAIN_DB_PREFIX."facturedet";
+				$sql .= " SET fk_code_ventilation = ".$monCompte;
+				$sql .= " WHERE rowid = ".$monId;
+
+				$accountventilated = new AccountingAccount($db);
+				$accountventilated->fetch($monCompte, '');
+
+				dol_syslog("accountancy/customer/list.php sql=".$sql, LOG_DEBUG);
+				if ($db->query($sql)) {
+					$msg .= '<div><font color="green">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("VentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'</font></div>';
+					$ok++;
+				} else {
+					$msg .= '<div><font color="red">'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'<br> <pre>'.$sql.'</pre></font></div>';
+					$ko++;
+				}
+			}
+
+			$cpt++;
+		}
+		$msg .= '</div>';
+		$msg .= '<div>'.$langs->trans("EndProcessing").'</div>';
+	}
 }
 
 
@@ -199,8 +199,8 @@ if (empty($chartaccountcode))
 {
 	print $langs->trans("ErrorChartOfAccountSystemNotSelected");
 	// End of page
-    llxFooter();
-    $db->close();
+	llxFooter();
+	$db->close();
 	exit;
 }
 
@@ -236,28 +236,28 @@ if ($search_societe) {
 	$sql .= natural_search('s.nom', $search_societe);
 }
 if ($search_lineid) {
-    $sql .= natural_search("l.rowid", $search_lineid, 1);
+	$sql .= natural_search("l.rowid", $search_lineid, 1);
 }
 if (strlen(trim($search_invoice))) {
-    $sql .= natural_search("f.ref", $search_invoice);
+	$sql .= natural_search("f.ref", $search_invoice);
 }
 if (strlen(trim($search_ref))) {
-    $sql .= natural_search("p.ref", $search_ref);
+	$sql .= natural_search("p.ref", $search_ref);
 }
 if (strlen(trim($search_label))) {
-    $sql .= natural_search("p.label", $search_label);
+	$sql .= natural_search("p.label", $search_label);
 }
 if (strlen(trim($search_desc))) {
-    $sql .= natural_search("l.description", $search_desc);
+	$sql .= natural_search("l.description", $search_desc);
 }
 if (strlen(trim($search_amount))) {
-    $sql .= natural_search("l.total_ht", $search_amount, 1);
+	$sql .= natural_search("l.total_ht", $search_amount, 1);
 }
 if (strlen(trim($search_account))) {
-    $sql .= natural_search("aa.account_number", $search_account);
+	$sql .= natural_search("aa.account_number", $search_account);
 }
 if (strlen(trim($search_vat))) {
-    $sql .= natural_search("l.tva_tx", price2num($search_vat), 1);
+	$sql .= natural_search("l.tva_tx", price2num($search_vat), 1);
 }
 $sql .= dolSqlDateFilter('f.datef', $search_day, $search_month, $search_year);
 if (strlen(trim($search_country))) {
@@ -295,13 +295,13 @@ $sql .= $db->order($sortfield, $sortorder);
 $nbtotalofrecords = '';
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
-    $result = $db->query($sql);
-    $nbtotalofrecords = $db->num_rows($result);
-    if (($page * $limit) > $nbtotalofrecords)	// if total resultset is smaller then paging size (filtering), goto and load page 0
-    {
-    	$page = 0;
-    	$offset = 0;
-    }
+	$result = $db->query($sql);
+	$nbtotalofrecords = $db->num_rows($result);
+	if (($page * $limit) > $nbtotalofrecords)	// if total resultset is smaller then paging size (filtering), goto and load page 0
+	{
+		$page = 0;
+		$offset = 0;
+	}
 }
 
 $sql .= $db->plimit($limit + 1, $offset);
@@ -336,9 +336,9 @@ if ($result) {
 	if ($search_tvaintra)	 $param .= "&search_tvaintra=".urlencode($search_tvaintra);
 
 	$arrayofmassactions = array(
-	    'ventil'=>$langs->trans("Ventilate")
-	    //'presend'=>$langs->trans("SendByMail"),
-	    //'builddoc'=>$langs->trans("PDFMerge"),
+		'ventil'=>$langs->trans("Ventilate")
+		//'presend'=>$langs->trans("SendByMail"),
+		//'builddoc'=>$langs->trans("PDFMerge"),
 	);
 	//if ($user->rights->mymodule->supprimer) $arrayofmassactions['predelete']='<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
 	//if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
@@ -376,8 +376,8 @@ if ($result) {
 	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_invoice" value="'.dol_escape_htmltag($search_invoice).'"></td>';
 	print '<td class="liste_titre center nowraponall minwidth100imp">';
    	if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) {
-        print '<input class="flat valignmiddle maxwidth25" type="text" maxlength="2" name="search_day" value="'.$search_day.'">';
-    }
+		print '<input class="flat valignmiddle maxwidth25" type="text" maxlength="2" name="search_day" value="'.$search_day.'">';
+	}
    	print '<input class="flat valignmiddle maxwidth25" type="text" maxlength="2" name="search_month" value="'.$search_month.'">';
    	$formother->select_year($search_year, 'search_year', 1, 20, 5);
 	print '</td>';
@@ -425,7 +425,7 @@ if ($result) {
 
 	$isSellerInEEC = isInEEC($mysoc);
 
-    $accountingaccount_codetotid_cache = array();
+	$accountingaccount_codetotid_cache = array();
 
 	while ($i < min($num_lines, $limit)) {
 		$objp = $db->fetch_object($result);
@@ -464,29 +464,29 @@ if ($result) {
 		$code_sell_p_notset = '';
 		$objp->aarowid_suggest = ''; // Will be set later
 
-        $isBuyerInEEC = isInEEC($objp);
+		$isBuyerInEEC = isInEEC($objp);
 
-        // Search suggested default account for product/service
-        $suggestedaccountingaccountbydefaultfor = '';
-    	if ($objp->type_l == 1) {
-    		if ($objp->country_code == $mysoc->country_code || empty($objp->country_code)) {  // If buyer in same country than seller (if not defined, we assume it is same country)
-    			$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT : '');
-    			$suggestedaccountingaccountbydefaultfor = '';
-    		} else {
-    			if ($isSellerInEEC && $isBuyerInEEC && $objp->tva_tx_line != 0) {    // European intravat sale, but with a VAT
+		// Search suggested default account for product/service
+		$suggestedaccountingaccountbydefaultfor = '';
+		if ($objp->type_l == 1) {
+			if ($objp->country_code == $mysoc->country_code || empty($objp->country_code)) {  // If buyer in same country than seller (if not defined, we assume it is same country)
+				$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT : '');
+				$suggestedaccountingaccountbydefaultfor = '';
+			} else {
+				if ($isSellerInEEC && $isBuyerInEEC && $objp->tva_tx_line != 0) {    // European intravat sale, but with a VAT
 					$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT : '');
 					$suggestedaccountingaccountbydefaultfor = 'eecwithvat';
-    			} elseif ($isSellerInEEC && $isBuyerInEEC && empty($objp->tva_intra)) {    // European intravat sale, without VAT intra community number
-    				$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT : '');
-    				$suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
+				} elseif ($isSellerInEEC && $isBuyerInEEC && empty($objp->tva_intra)) {    // European intravat sale, without VAT intra community number
+					$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT : '');
+					$suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
 				} elseif ($isSellerInEEC && $isBuyerInEEC) {    // European intravat sale
-    				$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT : '');
-    				$suggestedaccountingaccountbydefaultfor = 'eec';
-	    		} else {                                        // Foreign sale
-	    			$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT : '');
-	    			$suggestedaccountingaccountbydefaultfor = 'export';
-	    		}
-    		}
+					$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT : '');
+					$suggestedaccountingaccountbydefaultfor = 'eec';
+				} else {                                        // Foreign sale
+					$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT : '');
+					$suggestedaccountingaccountbydefaultfor = 'export';
+				}
+			}
 		} elseif ($objp->type_l == 0) {
 			if ($objp->country_code == $mysoc->country_code || empty($objp->country_code)) {  // If buyer in same country than seller (if not defined, we assume it is same country)
 				$objp->code_sell_l = (!empty($conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT : '');
@@ -512,28 +512,28 @@ if ($result) {
 		// Search suggested account for product/service (similar code exists in page index.php to make automatic binding)
 		$suggestedaccountingaccountfor = '';
 		if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) {  // If buyer in same country than seller (if not defined, we assume it is same country)
-            $objp->code_sell_p = $objp->code_sell;
-            $objp->aarowid_suggest = $objp->aarowid;
-            $suggestedaccountingaccountfor = '';
-        } else {
-        	if ($isSellerInEEC && $isBuyerInEEC && $objp->tva_tx_line != 0) {	// European intravat sale, but with VAT
+			$objp->code_sell_p = $objp->code_sell;
+			$objp->aarowid_suggest = $objp->aarowid;
+			$suggestedaccountingaccountfor = '';
+		} else {
+			if ($isSellerInEEC && $isBuyerInEEC && $objp->tva_tx_line != 0) {	// European intravat sale, but with VAT
 				$objp->code_sell_p = $objp->code_sell;
 				$objp->aarowid_suggest = $objp->aarowid;
 				$suggestedaccountingaccountfor = 'eecwithvat';
-        	} elseif ($isSellerInEEC && $isBuyerInEEC && empty($objp->tva_intra)) {	// European intravat sale, without VAT intra community number
-        		$objp->code_sell_p = $objp->code_sell;
-        		$objp->aarowid_suggest = $objp->aarowid; // There is a doubt for this case. Is it an error on vat or we just forgot to fill vat number ?
-        		$suggestedaccountingaccountfor = 'eecwithoutvatnumber';
+			} elseif ($isSellerInEEC && $isBuyerInEEC && empty($objp->tva_intra)) {	// European intravat sale, without VAT intra community number
+				$objp->code_sell_p = $objp->code_sell;
+				$objp->aarowid_suggest = $objp->aarowid; // There is a doubt for this case. Is it an error on vat or we just forgot to fill vat number ?
+				$suggestedaccountingaccountfor = 'eecwithoutvatnumber';
 			} elseif ($isSellerInEEC && $isBuyerInEEC) {          // European intravat sale
-                $objp->code_sell_p = $objp->code_sell_intra;
-                $objp->aarowid_suggest = $objp->aarowid_intra;
-                $suggestedaccountingaccountfor = 'eec';
-            } else {                                        // Foreign sale
-                $objp->code_sell_p = $objp->code_sell_export;
-                $objp->aarowid_suggest = $objp->aarowid_export;
-                $suggestedaccountingaccountfor = 'export';
-            }
-        }
+				$objp->code_sell_p = $objp->code_sell_intra;
+				$objp->aarowid_suggest = $objp->aarowid_intra;
+				$suggestedaccountingaccountfor = 'eec';
+			} else {                                        // Foreign sale
+				$objp->code_sell_p = $objp->code_sell_export;
+				$objp->aarowid_suggest = $objp->aarowid_export;
+				$suggestedaccountingaccountfor = 'export';
+			}
+		}
 
 		if (!empty($objp->code_sell_p)) {
 			// Value was defined previously
@@ -585,32 +585,32 @@ if ($result) {
 		print '<td class="tdoverflowmax100">'.$thirdpartystatic->getNomUrl(1, 'customer').'</td>';
 
 		// Country
-        print '<td>';
-        $labelcountry = ($objp->country_code && ($langs->trans("Country".$objp->country_code) != "Country".$objp->country_code)) ? $langs->trans("Country".$objp->country_code) : $objp->country_label;
-        print $labelcountry;
-        print '</td>';
+		print '<td>';
+		$labelcountry = ($objp->country_code && ($langs->trans("Country".$objp->country_code) != "Country".$objp->country_code)) ? $langs->trans("Country".$objp->country_code) : $objp->country_label;
+		print $labelcountry;
+		print '</td>';
 
 		print '<td>'.$objp->tva_intra.'</td>';
 
 		// Found accounts
 		print '<td>';
-	    $s = '<span class="small">'.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': </span>';
-	    $shelp = '';
-	    if ($suggestedaccountingaccountbydefaultfor == 'eec') $shelp .= $langs->trans("SaleEEC");
-	    elseif ($suggestedaccountingaccountbydefaultfor == 'export') $shelp .= $langs->trans("SaleExport");
-	    $s .= ($objp->code_sell_l > 0 ? length_accountg($objp->code_sell_l) : '<span style="'.$code_sell_p_notset.'">'.$langs->trans("NotDefined").'</span>');
-	    print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1);
-	    if ($objp->product_id > 0)
+		$s = '<span class="small">'.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': </span>';
+		$shelp = '';
+		if ($suggestedaccountingaccountbydefaultfor == 'eec') $shelp .= $langs->trans("SaleEEC");
+		elseif ($suggestedaccountingaccountbydefaultfor == 'export') $shelp .= $langs->trans("SaleExport");
+		$s .= ($objp->code_sell_l > 0 ? length_accountg($objp->code_sell_l) : '<span style="'.$code_sell_p_notset.'">'.$langs->trans("NotDefined").'</span>');
+		print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1);
+		if ($objp->product_id > 0)
 		{
-		    print '<br>';
-		    $s = '<span class="small">'.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': </span>';
-		    $shelp = '';
-		    if ($suggestedaccountingaccountfor == 'eec') $shelp = $langs->trans("SaleEEC");
-		    elseif ($suggestedaccountingaccountfor == 'eecwithvat') $shelp = $langs->trans("SaleEECWithVAT");
-		    elseif ($suggestedaccountingaccountfor == 'eecwithoutvatnumber') $shelp = $langs->trans("SaleEECWithoutVATNumber");
-		    elseif ($suggestedaccountingaccountfor == 'export') $shelp = $langs->trans("SaleExport");
-		    $s .= (empty($objp->code_sell_p) ? '<span style="'.$code_sell_p_notset.'">'.$langs->trans("NotDefined").'</span>' : length_accountg($objp->code_sell_p));
-		    print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1);
+			print '<br>';
+			$s = '<span class="small">'.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': </span>';
+			$shelp = '';
+			if ($suggestedaccountingaccountfor == 'eec') $shelp = $langs->trans("SaleEEC");
+			elseif ($suggestedaccountingaccountfor == 'eecwithvat') $shelp = $langs->trans("SaleEECWithVAT");
+			elseif ($suggestedaccountingaccountfor == 'eecwithoutvatnumber') $shelp = $langs->trans("SaleEECWithoutVATNumber");
+			elseif ($suggestedaccountingaccountfor == 'export') $shelp = $langs->trans("SaleExport");
+			$s .= (empty($objp->code_sell_p) ? '<span style="'.$code_sell_p_notset.'">'.$langs->trans("NotDefined").'</span>' : length_accountg($objp->code_sell_p));
+			print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1);
 		}
 		print '</td>';
 

+ 3 - 3
htdocs/accountancy/expensereport/lines.php

@@ -264,7 +264,7 @@ if ($result) {
 	print '<td class="liste_titre"><input type="text" name="search_login" class="maxwidth50" value="'.$search_login.'"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td><input type="text" class="flat maxwidth50" name="search_expensereport" value="'.dol_escape_htmltag($search_expensereport).'"></td>';
-	if (! empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
+	if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
 		print '<td class="liste_titre"></td>';
 	}
 	print '<td class="liste_titre center">';
@@ -287,7 +287,7 @@ if ($result) {
 	print_liste_field_titre("Employees", $_SERVER['PHP_SELF'], "u.login", $param, "", "", $sortfield, $sortorder);
 	print_liste_field_titre("LineId", $_SERVER["PHP_SELF"], "erd.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre("ExpenseReport", $_SERVER["PHP_SELF"], "er.ref", "", $param, '', $sortfield, $sortorder);
-	if (! empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
+	if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
 		print_liste_field_titre("DateValidation", $_SERVER["PHP_SELF"], "er.date_valid", "", $param, '', $sortfield, $sortorder, 'center ');
 	}
 	print_liste_field_titre("DateOfLine", $_SERVER["PHP_SELF"], "erd.date, erd.rowid", "", $param, '', $sortfield, $sortorder, 'center ');
@@ -341,7 +341,7 @@ if ($result) {
 		print '<td>'.$expensereportstatic->getNomUrl(1).'</td>';
 
 		// Date validation
-		if (! empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
+		if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
 			print '<td class="center">'.dol_print_date($db->jdate($objp->date_valid), 'day').'</td>';
 		}
 

+ 3 - 3
htdocs/accountancy/expensereport/list.php

@@ -303,7 +303,7 @@ if ($result) {
 	print '<td class="liste_titre"><input type="text" name="search_login" class="maxwidth50" value="'.$search_login.'"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_expensereport" value="'.dol_escape_htmltag($search_expensereport).'"></td>';
-	if (! empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
+	if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
 		print '<td class="liste_titre"></td>';
 	}
 	print '<td class="liste_titre center nowraponall minwidth100imp">';
@@ -327,7 +327,7 @@ if ($result) {
 	print_liste_field_titre("Employee", $_SERVER['PHP_SELF'], "u.login", $param, "", "", $sortfield, $sortorder);
 	print_liste_field_titre("LineId", $_SERVER["PHP_SELF"], "erd.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre("ExpenseReport", $_SERVER["PHP_SELF"], "er.ref", "", $param, '', $sortfield, $sortorder);
-	if (! empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
+	if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
 		print_liste_field_titre("DateValidation", $_SERVER["PHP_SELF"], "er.date_valid", "", $param, '', $sortfield, $sortorder, 'center ');
 	}
 	print_liste_field_titre("DateOfLine", $_SERVER["PHP_SELF"], "erd.date, erd.rowid", "", $param, '', $sortfield, $sortorder, 'center ');
@@ -381,7 +381,7 @@ if ($result) {
 		print '<td>'.$expensereport_static->getNomUrl(1).'</td>';
 
 		// Date validation
-		if (! empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
+		if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
 			print '<td class="center">'.dol_print_date($db->jdate($objp->date_valid), 'day').'</td>';
 		}
 

+ 66 - 66
htdocs/accountancy/supplier/list.php

@@ -144,48 +144,48 @@ if (empty($reshook))
 
 
 if ($massaction == 'ventil') {
-    $msg = '';
-
-    //print '<div><font color="red">' . $langs->trans("Processing") . '...</font></div>';
-    if (!empty($mesCasesCochees)) {
-        $msg = '<div>'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'</div>';
-        $msg .= '<div class="detail">';
-        $cpt = 0;
-        $ok = 0;
-        $ko = 0;
-
-        foreach ($mesCasesCochees as $maLigneCochee) {
-            $maLigneCourante = explode("_", $maLigneCochee);
-            $monId = $maLigneCourante[0];
-            $monCompte = GETPOST('codeventil'.$monId);
-
-            if ($monCompte <= 0)
-            {
-                $msg .= '<div><font color="red">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NoAccountSelected").'</font></div>';
-                $ko++;
-            } else {
-                $sql = " UPDATE ".MAIN_DB_PREFIX."facture_fourn_det";
-                $sql .= " SET fk_code_ventilation = ".$monCompte;
-                $sql .= " WHERE rowid = ".$monId;
-
-                $accountventilated = new AccountingAccount($db);
-                $accountventilated->fetch($monCompte, '');
-
-                dol_syslog('accountancy/supplier/list.php:: sql='.$sql, LOG_DEBUG);
-                if ($db->query($sql)) {
-                    $msg .= '<div><font color="green">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("VentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'</font></div>';
-                    $ok++;
-                } else {
-                    $msg .= '<div><font color="red">'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'<br/> <pre>'.$sql.'</pre></font></div>';
-                    $ko++;
-                }
-            }
-
-            $cpt++;
-        }
-        $msg .= '</div>';
-        $msg .= '<div>'.$langs->trans("EndProcessing").'</div>';
-    }
+	$msg = '';
+
+	//print '<div><font color="red">' . $langs->trans("Processing") . '...</font></div>';
+	if (!empty($mesCasesCochees)) {
+		$msg = '<div>'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'</div>';
+		$msg .= '<div class="detail">';
+		$cpt = 0;
+		$ok = 0;
+		$ko = 0;
+
+		foreach ($mesCasesCochees as $maLigneCochee) {
+			$maLigneCourante = explode("_", $maLigneCochee);
+			$monId = $maLigneCourante[0];
+			$monCompte = GETPOST('codeventil'.$monId);
+
+			if ($monCompte <= 0)
+			{
+				$msg .= '<div><font color="red">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NoAccountSelected").'</font></div>';
+				$ko++;
+			} else {
+				$sql = " UPDATE ".MAIN_DB_PREFIX."facture_fourn_det";
+				$sql .= " SET fk_code_ventilation = ".$monCompte;
+				$sql .= " WHERE rowid = ".$monId;
+
+				$accountventilated = new AccountingAccount($db);
+				$accountventilated->fetch($monCompte, '');
+
+				dol_syslog('accountancy/supplier/list.php:: sql='.$sql, LOG_DEBUG);
+				if ($db->query($sql)) {
+					$msg .= '<div><font color="green">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("VentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'</font></div>';
+					$ok++;
+				} else {
+					$msg .= '<div><font color="red">'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'<br/> <pre>'.$sql.'</pre></font></div>';
+					$ko++;
+				}
+			}
+
+			$cpt++;
+		}
+		$msg .= '</div>';
+		$msg .= '<div>'.$langs->trans("EndProcessing").'</div>';
+	}
 }
 
 
@@ -203,8 +203,8 @@ if (empty($chartaccountcode))
 {
 	print $langs->trans("ErrorChartOfAccountSystemNotSelected");
 	// End of page
-    llxFooter();
-    $db->close();
+	llxFooter();
+	$db->close();
 	exit;
 }
 
@@ -240,28 +240,28 @@ if ($search_societe) {
 	$sql .= natural_search('s.nom', $search_societe);
 }
 if ($search_lineid) {
-    $sql .= natural_search("l.rowid", $search_lineid, 1);
+	$sql .= natural_search("l.rowid", $search_lineid, 1);
 }
 if (strlen(trim($search_invoice))) {
-    $sql .= natural_search("f.ref", $search_invoice);
+	$sql .= natural_search("f.ref", $search_invoice);
 }
 if (strlen(trim($search_label))) {
 	$sql .= natural_search("f.libelle", $search_label);
 }
 if (strlen(trim($search_ref))) {
-    $sql .= natural_search("p.ref", $search_ref);
+	$sql .= natural_search("p.ref", $search_ref);
 }
 if (strlen(trim($search_desc))) {
-    $sql .= natural_search("l.description", $search_desc);
+	$sql .= natural_search("l.description", $search_desc);
 }
 if (strlen(trim($search_amount))) {
-    $sql .= natural_search("l.total_ht", $search_amount, 1);
+	$sql .= natural_search("l.total_ht", $search_amount, 1);
 }
 if (strlen(trim($search_account))) {
-    $sql .= natural_search("aa.account_number", $search_account);
+	$sql .= natural_search("aa.account_number", $search_account);
 }
 if (strlen(trim($search_vat))) {
-    $sql .= natural_search("l.tva_tx", price2num($search_vat), 1);
+	$sql .= natural_search("l.tva_tx", price2num($search_vat), 1);
 }
 $sql .= dolSqlDateFilter('f.datef', $search_day, $search_month, $search_year);
 if (strlen(trim($search_country))) {
@@ -299,13 +299,13 @@ $sql .= $db->order($sortfield, $sortorder);
 $nbtotalofrecords = '';
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
-    $result = $db->query($sql);
-    $nbtotalofrecords = $db->num_rows($result);
-    if (($page * $limit) > $nbtotalofrecords)	// if total resultset is smaller then paging size (filtering), goto and load page 0
-    {
-    	$page = 0;
-    	$offset = 0;
-    }
+	$result = $db->query($sql);
+	$nbtotalofrecords = $db->num_rows($result);
+	if (($page * $limit) > $nbtotalofrecords)	// if total resultset is smaller then paging size (filtering), goto and load page 0
+	{
+		$page = 0;
+		$offset = 0;
+	}
 }
 
 $sql .= $db->plimit($limit + 1, $offset);
@@ -337,9 +337,9 @@ if ($result) {
 	if ($search_tvaintra)	 $param .= "&search_tvaintra=".urlencode($search_tvaintra);
 
 	$arrayofmassactions = array(
-	    'ventil'=>$langs->trans("Ventilate")
-	    //'presend'=>$langs->trans("SendByMail"),
-	    //'builddoc'=>$langs->trans("PDFMerge"),
+		'ventil'=>$langs->trans("Ventilate")
+		//'presend'=>$langs->trans("SendByMail"),
+		//'builddoc'=>$langs->trans("PDFMerge"),
 	);
 	//if ($user->rights->mymodule->supprimer) $arrayofmassactions['predelete']='<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
 	//if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
@@ -572,12 +572,12 @@ if ($result) {
 		print '<td class="tdoverflowmax100">'.$thirdpartystatic->getNomUrl(1, 'supplier').'</td>';
 
 		// Country
-        print '<td>';
-        $labelcountry = ($objp->country_code && ($langs->trans("Country".$objp->country_code) != "Country".$objp->country_code)) ? $langs->trans("Country".$objp->country_code) : $objp->country_label;
-        print $labelcountry;
-        print '</td>';
+		print '<td>';
+		$labelcountry = ($objp->country_code && ($langs->trans("Country".$objp->country_code) != "Country".$objp->country_code)) ? $langs->trans("Country".$objp->country_code) : $objp->country_label;
+		print $labelcountry;
+		print '</td>';
 
-        // VAT Num
+		// VAT Num
 		print '<td>'.$objp->tva_intra.'</td>';
 
 		// Found accounts

+ 115 - 115
htdocs/admin/bank.php

@@ -51,147 +51,147 @@ $type = 'bankaccount';
 
 // Order display of bank account
 if ($action == 'setbankorder') {
-    if (dolibarr_set_const($db, "BANK_SHOW_ORDER_OPTION", GETPOST('value', 'alpha'), 'chaine', 0, '', $conf->entity) > 0)
-    {
-        header("Location: ".$_SERVER["PHP_SELF"]);
-        exit;
-    } else {
-        dol_print_error($db);
-    }
+	if (dolibarr_set_const($db, "BANK_SHOW_ORDER_OPTION", GETPOST('value', 'alpha'), 'chaine', 0, '', $conf->entity) > 0)
+	{
+		header("Location: ".$_SERVER["PHP_SELF"]);
+		exit;
+	} else {
+		dol_print_error($db);
+	}
 }
 
 // Auto report last num releve on conciliate
 if ($action == 'setreportlastnumreleve') {
-    if (dolibarr_set_const($db, "BANK_REPORT_LAST_NUM_RELEVE", 1, 'chaine', 0, '', $conf->entity) > 0)
-    {
-        header("Location: ".$_SERVER["PHP_SELF"]);
-        exit;
-    } else {
-        dol_print_error($db);
-    }
+	if (dolibarr_set_const($db, "BANK_REPORT_LAST_NUM_RELEVE", 1, 'chaine', 0, '', $conf->entity) > 0)
+	{
+		header("Location: ".$_SERVER["PHP_SELF"]);
+		exit;
+	} else {
+		dol_print_error($db);
+	}
 } elseif ($action == 'unsetreportlastnumreleve') {
-    if (dolibarr_set_const($db, "BANK_REPORT_LAST_NUM_RELEVE", 0, 'chaine', 0, '', $conf->entity) > 0)
-    {
-        header("Location: ".$_SERVER["PHP_SELF"]);
-        exit;
-    } else {
-        dol_print_error($db);
-    }
+	if (dolibarr_set_const($db, "BANK_REPORT_LAST_NUM_RELEVE", 0, 'chaine', 0, '', $conf->entity) > 0)
+	{
+		header("Location: ".$_SERVER["PHP_SELF"]);
+		exit;
+	} else {
+		dol_print_error($db);
+	}
 }
 
 // Colorize movements
 if ($action == 'setbankcolorizemovement') {
-    if (dolibarr_set_const($db, "BANK_COLORIZE_MOVEMENT", 1, 'chaine', 0, '', $conf->entity) > 0)
-    {
-        header("Location: ".$_SERVER["PHP_SELF"]);
-        exit;
-    } else {
-        dol_print_error($db);
-    }
+	if (dolibarr_set_const($db, "BANK_COLORIZE_MOVEMENT", 1, 'chaine', 0, '', $conf->entity) > 0)
+	{
+		header("Location: ".$_SERVER["PHP_SELF"]);
+		exit;
+	} else {
+		dol_print_error($db);
+	}
 } elseif ($action == 'unsetbankcolorizemovement') {
-    if (dolibarr_set_const($db, "BANK_COLORIZE_MOVEMENT", 0, 'chaine', 0, '', $conf->entity) > 0)
-    {
-        header("Location: ".$_SERVER["PHP_SELF"]);
-        exit;
-    } else {
-        dol_print_error($db);
-    }
+	if (dolibarr_set_const($db, "BANK_COLORIZE_MOVEMENT", 0, 'chaine', 0, '', $conf->entity) > 0)
+	{
+		header("Location: ".$_SERVER["PHP_SELF"]);
+		exit;
+	} else {
+		dol_print_error($db);
+	}
 }
 
 if ($actionsave)
 {
-    $db->begin();
-
-    $i = 1; $errorsaved = 0;
-    $error = 0;
-
-    // Save colors
-    while ($i <= 2)
-    {
-        $color = GETPOST('BANK_COLORIZE_MOVEMENT_COLOR'.$i, 'alpha');
-        if ($color == '-1') $color = '';
-
-        $res = dolibarr_set_const($db, 'BANK_COLORIZE_MOVEMENT_COLOR'.$i, $color, 'chaine', 0, '', $conf->entity);
-        if (!$res > 0) $error++;
-        $i++;
-    }
-
-    if (!$error)
-    {
-        $db->commit();
-        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    } else {
-        $db->rollback();
-        if (empty($errorsaved))	setEventMessages($langs->trans("Error"), null, 'errors');
-    }
+	$db->begin();
+
+	$i = 1; $errorsaved = 0;
+	$error = 0;
+
+	// Save colors
+	while ($i <= 2)
+	{
+		$color = GETPOST('BANK_COLORIZE_MOVEMENT_COLOR'.$i, 'alpha');
+		if ($color == '-1') $color = '';
+
+		$res = dolibarr_set_const($db, 'BANK_COLORIZE_MOVEMENT_COLOR'.$i, $color, 'chaine', 0, '', $conf->entity);
+		if (!$res > 0) $error++;
+		$i++;
+	}
+
+	if (!$error)
+	{
+		$db->commit();
+		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+	} else {
+		$db->rollback();
+		if (empty($errorsaved))	setEventMessages($langs->trans("Error"), null, 'errors');
+	}
 }
 
 
 if ($action == 'specimen') {
-    $modele = GETPOST('module', 'alpha');
-
-    if ($modele == 'sepamandate') {
-        $object = new CompanyBankAccount($db);
-    } else {
-        $object = new Account($db);
-    }
-    $object->initAsSpecimen();
-
-    // Search template files
-    $file = '';
-    $classname = '';
-    $filefound = 0;
-    $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
-    foreach ($dirmodels as $reldir) {
-        $file = dol_buildpath($reldir."core/modules/bank/doc/pdf_".$modele.".modules.php", 0);
-        if (file_exists($file)) {
-            $filefound = 1;
-            $classname = "pdf_".$modele;
-            break;
-        }
-    }
-
-    if ($filefound) {
-        require_once $file;
-
-        $module = new $classname($db);
-
-        if ($module->write_file($object, $langs) > 0) {
-            header("Location: ".DOL_URL_ROOT."/document.php?modulepart=bank&file=SPECIMEN.pdf");
-            return;
-        } else {
-            setEventMessages($module->error, null, 'errors');
-            dol_syslog($module->error, LOG_ERR);
-        }
-    } else {
-        setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
-        dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
-    }
+	$modele = GETPOST('module', 'alpha');
+
+	if ($modele == 'sepamandate') {
+		$object = new CompanyBankAccount($db);
+	} else {
+		$object = new Account($db);
+	}
+	$object->initAsSpecimen();
+
+	// Search template files
+	$file = '';
+	$classname = '';
+	$filefound = 0;
+	$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
+	foreach ($dirmodels as $reldir) {
+		$file = dol_buildpath($reldir."core/modules/bank/doc/pdf_".$modele.".modules.php", 0);
+		if (file_exists($file)) {
+			$filefound = 1;
+			$classname = "pdf_".$modele;
+			break;
+		}
+	}
+
+	if ($filefound) {
+		require_once $file;
+
+		$module = new $classname($db);
+
+		if ($module->write_file($object, $langs) > 0) {
+			header("Location: ".DOL_URL_ROOT."/document.php?modulepart=bank&file=SPECIMEN.pdf");
+			return;
+		} else {
+			setEventMessages($module->error, null, 'errors');
+			dol_syslog($module->error, LOG_ERR);
+		}
+	} else {
+		setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
+		dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
+	}
 }
 
 // Activate a model
 if ($action == 'set') {
-    $ret = addDocumentModel($value, $type, $label, $scandir);
+	$ret = addDocumentModel($value, $type, $label, $scandir);
 } elseif ($action == 'del') {
-    $ret = delDocumentModel($value, $type);
-    if ($ret > 0) {
-        if ($conf->global->BANKADDON_PDF == "$value")
-            dolibarr_del_const($db, 'BANKADDON_PDF', $conf->entity);
-    }
+	$ret = delDocumentModel($value, $type);
+	if ($ret > 0) {
+		if ($conf->global->BANKADDON_PDF == "$value")
+			dolibarr_del_const($db, 'BANKADDON_PDF', $conf->entity);
+	}
 }
 // Set default model
 elseif ($action == 'setdoc') {
-    if (dolibarr_set_const($db, "BANKADDON_PDF", $value, 'chaine', 0, '', $conf->entity)) {
-        // The constant that was read before the new set
-        // We therefore requires a variable to have a coherent view
-        $conf->global->BANKADDON_PDF = $value;
-    }
-
-    // On active le modele
-    $ret = delDocumentModel($value, $type);
-    if ($ret > 0) {
-        $ret = addDocumentModel($value, $type, $label, $scandir);
-    }
+	if (dolibarr_set_const($db, "BANKADDON_PDF", $value, 'chaine', 0, '', $conf->entity)) {
+		// The constant that was read before the new set
+		// We therefore requires a variable to have a coherent view
+		$conf->global->BANKADDON_PDF = $value;
+	}
+
+	// On active le modele
+	$ret = delDocumentModel($value, $type);
+	if ($ret > 0) {
+		$ret = addDocumentModel($value, $type, $label, $scandir);
+	}
 }
 
 

+ 5 - 5
htdocs/admin/emailcollector_card.php

@@ -670,12 +670,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 			// Clone
 			print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&amp;socid='.$object->socid.'&amp;action=clone&amp;object=order">'.$langs->trans("ToClone").'</a></div>';
 
-		    // Collect now
-		    if (count($object->actions) > 0) {
+			// Collect now
+			if (count($object->actions) > 0) {
 				print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=collect">'.$langs->trans("CollectNow").'</a></div>';
-		    } else {
-		    	print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NoOperations")).'">'.$langs->trans("CollectNow").'</a></div>';
-		    }
+			} else {
+				print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NoOperations")).'">'.$langs->trans("CollectNow").'</a></div>';
+			}
 
 			print '<div class="inline-block divButAction"><a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=delete">'.$langs->trans('Delete').'</a></div>';
 		}

+ 364 - 364
htdocs/admin/menus/edit.php

@@ -40,8 +40,8 @@ $dirsmartphone = array();
 $dirmenus = array_merge(array("/core/menus/"), (array) $conf->modules_parts['menus']);
 foreach ($dirmenus as $dirmenu)
 {
-    $dirstandard[] = $dirmenu.'standard';
-    $dirsmartphone[] = $dirmenu.'smartphone';
+	$dirstandard[] = $dirmenu.'standard';
+	$dirsmartphone[] = $dirmenu.'smartphone';
 }
 
 $action = GETPOST('action', 'aZ09');
@@ -66,192 +66,192 @@ if (GETPOST("menu_handler"))    $menu_handler = GETPOST("menu_handler");
 
 if ($action == 'update')
 {
-    if (!$cancel)
-    {
-        $leftmenu = ''; $mainmenu = '';
-        if (GETPOST('menuIdParent', 'alpha') && !is_numeric(GETPOST('menuIdParent', 'alpha')))
-        {
-        	$tmp = explode('&', GETPOST('menuIdParent', 'alpha'));
-            foreach ($tmp as $s)
-            {
-                if (preg_match('/fk_mainmenu=/', $s))
-                {
-                    $mainmenu = preg_replace('/fk_mainmenu=/', '', $s);
-                }
-                if (preg_match('/fk_leftmenu=/', $s))
-                {
-                    $leftmenu = preg_replace('/fk_leftmenu=/', '', $s);
-                }
-            }
-        }
-
-        $menu = new Menubase($db);
-        $result = $menu->fetch(GETPOST('menuId', 'int'));
-        if ($result > 0)
-        {
-            $menu->title = GETPOST('titre', 'alpha');
-            $menu->leftmenu = GETPOST('leftmenu', 'aZ09');
-            $menu->url = GETPOST('url', 'alpha');
-            $menu->langs = GETPOST('langs', 'alpha');
-            $menu->position = GETPOST('position', 'int');
-            $menu->enabled = GETPOST('enabled', 'alpha');
-            $menu->perms = GETPOST('perms', 'alpha');
-            $menu->target = GETPOST('target', 'alpha');
-            $menu->user = GETPOST('user', 'alpha');
-            $menu->mainmenu = GETPOST('propertymainmenu', 'alpha');
-            if (is_numeric(GETPOST('menuIdParent', 'alpha')))
-            {
-            	$menu->fk_menu = GETPOST('menuIdParent', 'alpha');
-            } else {
-    	       	if (GETPOST('type', 'alpha') == 'top') $menu->fk_menu = 0;
-    	       	else $menu->fk_menu = -1;
-            	$menu->fk_mainmenu = $mainmenu;
-            	$menu->fk_leftmenu = $leftmenu;
-            }
-
-            $result = $menu->update($user);
-            if ($result > 0)
-            {
-	            setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
-            } else {
-	            setEventMessages($menu->error, $menu->errors, 'errors');
-            }
-        } else {
-	        setEventMessages($menu->error, $menu->errors, 'errors');
-        }
-        $action = "edit";
-
-        header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
-        exit;
-    } else {
-        header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
-        exit;
-    }
+	if (!$cancel)
+	{
+		$leftmenu = ''; $mainmenu = '';
+		if (GETPOST('menuIdParent', 'alpha') && !is_numeric(GETPOST('menuIdParent', 'alpha')))
+		{
+			$tmp = explode('&', GETPOST('menuIdParent', 'alpha'));
+			foreach ($tmp as $s)
+			{
+				if (preg_match('/fk_mainmenu=/', $s))
+				{
+					$mainmenu = preg_replace('/fk_mainmenu=/', '', $s);
+				}
+				if (preg_match('/fk_leftmenu=/', $s))
+				{
+					$leftmenu = preg_replace('/fk_leftmenu=/', '', $s);
+				}
+			}
+		}
+
+		$menu = new Menubase($db);
+		$result = $menu->fetch(GETPOST('menuId', 'int'));
+		if ($result > 0)
+		{
+			$menu->title = GETPOST('titre', 'alpha');
+			$menu->leftmenu = GETPOST('leftmenu', 'aZ09');
+			$menu->url = GETPOST('url', 'alpha');
+			$menu->langs = GETPOST('langs', 'alpha');
+			$menu->position = GETPOST('position', 'int');
+			$menu->enabled = GETPOST('enabled', 'alpha');
+			$menu->perms = GETPOST('perms', 'alpha');
+			$menu->target = GETPOST('target', 'alpha');
+			$menu->user = GETPOST('user', 'alpha');
+			$menu->mainmenu = GETPOST('propertymainmenu', 'alpha');
+			if (is_numeric(GETPOST('menuIdParent', 'alpha')))
+			{
+				$menu->fk_menu = GETPOST('menuIdParent', 'alpha');
+			} else {
+			   	if (GETPOST('type', 'alpha') == 'top') $menu->fk_menu = 0;
+			   	else $menu->fk_menu = -1;
+				$menu->fk_mainmenu = $mainmenu;
+				$menu->fk_leftmenu = $leftmenu;
+			}
+
+			$result = $menu->update($user);
+			if ($result > 0)
+			{
+				setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
+			} else {
+				setEventMessages($menu->error, $menu->errors, 'errors');
+			}
+		} else {
+			setEventMessages($menu->error, $menu->errors, 'errors');
+		}
+		$action = "edit";
+
+		header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
+		exit;
+	} else {
+		header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
+		exit;
+	}
 }
 
 if ($action == 'add')
 {
-    if ($cancel)
-    {
-        header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
-        exit;
-    }
-
-    $leftmenu = ''; $mainmenu = '';
-    if (GETPOST('menuId', 'alpha', 3) && !is_numeric(GETPOST('menuId', 'alpha', 3)))
-    {
-	    $tmp = explode('&', GETPOST('menuId', 'alpha', 3));
-	    foreach ($tmp as $s)
-	    {
-	    	if (preg_match('/fk_mainmenu=/', $s))
-	    	{
+	if ($cancel)
+	{
+		header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
+		exit;
+	}
+
+	$leftmenu = ''; $mainmenu = '';
+	if (GETPOST('menuId', 'alpha', 3) && !is_numeric(GETPOST('menuId', 'alpha', 3)))
+	{
+		$tmp = explode('&', GETPOST('menuId', 'alpha', 3));
+		foreach ($tmp as $s)
+		{
+			if (preg_match('/fk_mainmenu=/', $s))
+			{
 				$mainmenu = preg_replace('/fk_mainmenu=/', '', $s);
-	    	}
-	    	if (preg_match('/fk_leftmenu=/', $s))
-	    	{
-	    		$leftmenu = preg_replace('/fk_leftmenu=/', '', $s);
-	    	}
-	    }
-    }
-
-    $langs->load("errors");
-
-    $error = 0;
-    if (!$error && !$_POST['menu_handler'])
-    {
-	    setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("MenuHandler")), null, 'errors');
-        $action = 'create';
-        $error++;
-    }
-    if (!$error && !$_POST['type'])
-    {
-	    setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
-        $action = 'create';
-        $error++;
-    }
-    if (!$error && !$_POST['url'])
-    {
-    	setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("URL")), null, 'errors');
-        $action = 'create';
-        $error++;
-    }
-    if (!$error && !$_POST['titre'])
-    {
-    	setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Title")), null, 'errors');
-        $action = 'create';
-        $error++;
-    }
-    if (!$error && $_POST['menuId'] && $_POST['type'] == 'top')
-    {
-	    setEventMessages($langs->trans("ErrorTopMenuMustHaveAParentWithId0"), null, 'errors');
-        $action = 'create';
-        $error++;
-    }
-    if (!$error && !$_POST['menuId'] && $_POST['type'] == 'left')
-    {
-	    setEventMessages($langs->trans("ErrorLeftMenuMustHaveAParentId"), null, 'errors');
-        $action = 'create';
-        $error++;
-    }
-
-    if (!$error)
-    {
-        $menu = new Menubase($db);
-        $menu->menu_handler = preg_replace('/_menu$/', '', GETPOST('menu_handler', 'aZ09'));
-        $menu->type = GETPOST('type', 'alpha');
-        $menu->title = GETPOST('titre', 'alpha');
-        $menu->url = GETPOST('url', 'alpha');
-        $menu->langs = GETPOST('langs', 'alpha');
-        $menu->position = GETPOST('position', 'int');
-        $menu->enabled = GETPOST('enabled', 'alpha');
-        $menu->perms = GETPOST('perms', 'alpha');
-        $menu->target = GETPOST('target', 'alpha');
-        $menu->user = GETPOST('user', 'alpha');
-        $menu->mainmenu = GETPOST('propertymainmenu', 'alpha');
-        if (is_numeric(GETPOST('menuId', 'alpha', 3)))
-        {
-        	$menu->fk_menu = GETPOST('menuId', 'alpha', 3);
-        } else {
-            if (GETPOST('type', 'alpha') == 'top') $menu->fk_menu = 0;
-            else $menu->fk_menu = -1;
-            $menu->fk_mainmenu = $mainmenu;
-            $menu->fk_leftmenu = $leftmenu;
-        }
-
-        $result = $menu->create($user);
-        if ($result > 0)
-        {
-            header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".GETPOST('menu_handler', 'aZ09'));
-            exit;
-        } else {
-            $action = 'create';
-	        setEventMessages($menu->error, $menu->errors, 'errors');
-        }
-    }
+			}
+			if (preg_match('/fk_leftmenu=/', $s))
+			{
+				$leftmenu = preg_replace('/fk_leftmenu=/', '', $s);
+			}
+		}
+	}
+
+	$langs->load("errors");
+
+	$error = 0;
+	if (!$error && !$_POST['menu_handler'])
+	{
+		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("MenuHandler")), null, 'errors');
+		$action = 'create';
+		$error++;
+	}
+	if (!$error && !$_POST['type'])
+	{
+		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
+		$action = 'create';
+		$error++;
+	}
+	if (!$error && !$_POST['url'])
+	{
+		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("URL")), null, 'errors');
+		$action = 'create';
+		$error++;
+	}
+	if (!$error && !$_POST['titre'])
+	{
+		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Title")), null, 'errors');
+		$action = 'create';
+		$error++;
+	}
+	if (!$error && $_POST['menuId'] && $_POST['type'] == 'top')
+	{
+		setEventMessages($langs->trans("ErrorTopMenuMustHaveAParentWithId0"), null, 'errors');
+		$action = 'create';
+		$error++;
+	}
+	if (!$error && !$_POST['menuId'] && $_POST['type'] == 'left')
+	{
+		setEventMessages($langs->trans("ErrorLeftMenuMustHaveAParentId"), null, 'errors');
+		$action = 'create';
+		$error++;
+	}
+
+	if (!$error)
+	{
+		$menu = new Menubase($db);
+		$menu->menu_handler = preg_replace('/_menu$/', '', GETPOST('menu_handler', 'aZ09'));
+		$menu->type = GETPOST('type', 'alpha');
+		$menu->title = GETPOST('titre', 'alpha');
+		$menu->url = GETPOST('url', 'alpha');
+		$menu->langs = GETPOST('langs', 'alpha');
+		$menu->position = GETPOST('position', 'int');
+		$menu->enabled = GETPOST('enabled', 'alpha');
+		$menu->perms = GETPOST('perms', 'alpha');
+		$menu->target = GETPOST('target', 'alpha');
+		$menu->user = GETPOST('user', 'alpha');
+		$menu->mainmenu = GETPOST('propertymainmenu', 'alpha');
+		if (is_numeric(GETPOST('menuId', 'alpha', 3)))
+		{
+			$menu->fk_menu = GETPOST('menuId', 'alpha', 3);
+		} else {
+			if (GETPOST('type', 'alpha') == 'top') $menu->fk_menu = 0;
+			else $menu->fk_menu = -1;
+			$menu->fk_mainmenu = $mainmenu;
+			$menu->fk_leftmenu = $leftmenu;
+		}
+
+		$result = $menu->create($user);
+		if ($result > 0)
+		{
+			header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".GETPOST('menu_handler', 'aZ09'));
+			exit;
+		} else {
+			$action = 'create';
+			setEventMessages($menu->error, $menu->errors, 'errors');
+		}
+	}
 }
 
 // delete
 if ($action == 'confirm_delete' && $_POST["confirm"] == 'yes')
 {
-    $this->db->begin();
+	$this->db->begin();
 
-    $sql = "DELETE FROM ".MAIN_DB_PREFIX."menu WHERE rowid = ".GETPOST('menuId', 'int');
-    $result = $db->query($sql);
+	$sql = "DELETE FROM ".MAIN_DB_PREFIX."menu WHERE rowid = ".GETPOST('menuId', 'int');
+	$result = $db->query($sql);
 
-    if ($result == 0)
-    {
-        $this->db->commit();
+	if ($result == 0)
+	{
+		$this->db->commit();
 
-        llxHeader();
-	    setEventMessages($langs->trans("MenuDeleted"), null, 'mesgs');
-        llxFooter();
-        exit;
-    } else {
-        $this->db->rollback();
+		llxHeader();
+		setEventMessages($langs->trans("MenuDeleted"), null, 'mesgs');
+		llxFooter();
+		exit;
+	} else {
+		$this->db->rollback();
 
-        $reload = 0;
-        $_GET["action"] = '';
-    }
+		$reload = 0;
+		$_GET["action"] = '';
+	}
 }
 
 
@@ -268,7 +268,7 @@ llxHeader('', $langs->trans("Menu"));
 
 if ($action == 'create')
 {
-    print '<script type="text/javascript" language="javascript">
+	print '<script type="text/javascript" language="javascript">
     jQuery(document).ready(function() {
     	function init_topleft()
     	{
@@ -292,231 +292,231 @@ if ($action == 'create')
     });
     </script>';
 
-    print load_fiche_titre($langs->trans("NewMenu"), '', 'title_setup');
-
-    print '<form action="./edit.php?action=add&menuId='.GETPOST('menuId', 'int').'" method="post" name="formmenucreate">';
-    print '<input type="hidden" name="token" value="'.newToken().'">';
-
-    dol_fiche_head();
-
-    print '<table class="border centpercent">';
-
-    // Id
-    $parent_rowid = GETPOST('menuId', 'int');
-    if (GETPOST('menuId', 'int'))
-    {
-        $sql = "SELECT m.rowid, m.mainmenu, m.leftmenu, m.level, m.langs FROM ".MAIN_DB_PREFIX."menu as m WHERE m.rowid = ".GETPOST('menuId', 'int');
-        $res = $db->query($sql);
-        if ($res)
-        {
-            while ($menu = $db->fetch_array($res))
-            {
-                $parent_rowid = $menu['rowid'];
-                $parent_mainmenu = $menu['mainmenu'];
-                $parent_leftmenu = $menu['leftmenu'];
-                $parent_langs = $menu['langs'];
-                $parent_level = $menu['level'];
-            }
-        }
-    }
-
-    // Handler
-    print '<tr><td class="fieldrequired">'.$langs->trans('MenuHandler').'</td>';
-    print '<td>';
-    $formadmin->select_menu_families($menu_handler.(preg_match('/_menu/', $menu_handler) ? '' : '_menu'), 'menu_handler', array_merge($dirstandard, $dirsmartphone));
-    print '</td>';
-    print '<td>'.$langs->trans('DetailMenuHandler').'</td></tr>';
-
-    // User
-    print '<tr><td class="nowrap fieldrequired">'.$langs->trans('MenuForUsers').'</td>';
-    print '<td><select class="flat" name="user">';
-    print '<option value="2" selected>'.$langs->trans("AllMenus").'</option>';
-    print '<option value="0">'.$langs->trans('Internal').'</option>';
-    print '<option value="1">'.$langs->trans('External').'</option>';
-    print '</select></td>';
-    print '<td>'.$langs->trans('DetailUser').'</td></tr>';
-
-    // Type
-    print '<tr><td class="fieldrequired">'.$langs->trans('Type').'</td><td>';
-    if ($parent_rowid)
-    {
-        print $langs->trans('Left');
-        print '<input type="hidden" name="type" value="left">';
-    } else {
-        print '<select name="type" class="flat" id="topleft">';
-        print '<option value="">&nbsp;</option>';
-        print '<option value="top"'.($_POST["type"] && $_POST["type"] == 'top' ? ' selected' : '').'>'.$langs->trans('Top').'</option>';
-        print '<option value="left"'.($_POST["type"] && $_POST["type"] == 'left' ? ' selected' : '').'>'.$langs->trans('Left').'</option>';
-        print '</select>';
-    }
-    print '</td><td>'.$langs->trans('DetailType').'</td></tr>';
-
-    // Mainmenu code
-    print '<tr><td class="fieldrequired">'.$langs->trans('MainMenuCode').'</td>';
+	print load_fiche_titre($langs->trans("NewMenu"), '', 'title_setup');
+
+	print '<form action="./edit.php?action=add&menuId='.GETPOST('menuId', 'int').'" method="post" name="formmenucreate">';
+	print '<input type="hidden" name="token" value="'.newToken().'">';
+
+	dol_fiche_head();
+
+	print '<table class="border centpercent">';
+
+	// Id
+	$parent_rowid = GETPOST('menuId', 'int');
+	if (GETPOST('menuId', 'int'))
+	{
+		$sql = "SELECT m.rowid, m.mainmenu, m.leftmenu, m.level, m.langs FROM ".MAIN_DB_PREFIX."menu as m WHERE m.rowid = ".GETPOST('menuId', 'int');
+		$res = $db->query($sql);
+		if ($res)
+		{
+			while ($menu = $db->fetch_array($res))
+			{
+				$parent_rowid = $menu['rowid'];
+				$parent_mainmenu = $menu['mainmenu'];
+				$parent_leftmenu = $menu['leftmenu'];
+				$parent_langs = $menu['langs'];
+				$parent_level = $menu['level'];
+			}
+		}
+	}
+
+	// Handler
+	print '<tr><td class="fieldrequired">'.$langs->trans('MenuHandler').'</td>';
+	print '<td>';
+	$formadmin->select_menu_families($menu_handler.(preg_match('/_menu/', $menu_handler) ? '' : '_menu'), 'menu_handler', array_merge($dirstandard, $dirsmartphone));
+	print '</td>';
+	print '<td>'.$langs->trans('DetailMenuHandler').'</td></tr>';
+
+	// User
+	print '<tr><td class="nowrap fieldrequired">'.$langs->trans('MenuForUsers').'</td>';
+	print '<td><select class="flat" name="user">';
+	print '<option value="2" selected>'.$langs->trans("AllMenus").'</option>';
+	print '<option value="0">'.$langs->trans('Internal').'</option>';
+	print '<option value="1">'.$langs->trans('External').'</option>';
+	print '</select></td>';
+	print '<td>'.$langs->trans('DetailUser').'</td></tr>';
+
+	// Type
+	print '<tr><td class="fieldrequired">'.$langs->trans('Type').'</td><td>';
+	if ($parent_rowid)
+	{
+		print $langs->trans('Left');
+		print '<input type="hidden" name="type" value="left">';
+	} else {
+		print '<select name="type" class="flat" id="topleft">';
+		print '<option value="">&nbsp;</option>';
+		print '<option value="top"'.($_POST["type"] && $_POST["type"] == 'top' ? ' selected' : '').'>'.$langs->trans('Top').'</option>';
+		print '<option value="left"'.($_POST["type"] && $_POST["type"] == 'left' ? ' selected' : '').'>'.$langs->trans('Left').'</option>';
+		print '</select>';
+	}
+	print '</td><td>'.$langs->trans('DetailType').'</td></tr>';
+
+	// Mainmenu code
+	print '<tr><td class="fieldrequired">'.$langs->trans('MainMenuCode').'</td>';
    	print '<td><input type="text" class="minwidth300" id="propertymainmenu" name="propertymainmenu" value="'.(GETPOST("propertymainmenu", 'alpha') ?GETPOST("propertymainmenu", 'alpha') : '').'"></td>';
-    print '<td>';
-    print $langs->trans("Example").': mytopmenukey';
-    print '</td></tr>';
+	print '<td>';
+	print $langs->trans("Example").': mytopmenukey';
+	print '</td></tr>';
 
-    // MenuId Parent
-    print '<tr><td class="fieldrequired">'.$langs->trans('MenuIdParent').'</td>';
-    if ($parent_rowid)
-    {
-        print '<td>'.$parent_rowid.'<input type="hidden" name="menuId" value="'.$parent_rowid.'"></td>';
-    } else {
-        print '<td><input type="text" class="minwidth300" id="menuId" name="menuId" value="'.(GETPOST("menuId", 'int') ?GETPOST("menuId", 'int') : '').'"></td>';
-    }
-    print '<td>'.$langs->trans('DetailMenuIdParent');
-    print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def';
-    print '</td></tr>';
+	// MenuId Parent
+	print '<tr><td class="fieldrequired">'.$langs->trans('MenuIdParent').'</td>';
+	if ($parent_rowid)
+	{
+		print '<td>'.$parent_rowid.'<input type="hidden" name="menuId" value="'.$parent_rowid.'"></td>';
+	} else {
+		print '<td><input type="text" class="minwidth300" id="menuId" name="menuId" value="'.(GETPOST("menuId", 'int') ?GETPOST("menuId", 'int') : '').'"></td>';
+	}
+	print '<td>'.$langs->trans('DetailMenuIdParent');
+	print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def';
+	print '</td></tr>';
 
-    // Title
-    print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag(GETPOST("titre", 'alpha')).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
+	// Title
+	print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag(GETPOST("titre", 'alpha')).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
 
-    // URL
-    print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td><td><input type="text" class="minwidth500" name="url" value="'.GETPOST("url", 'alpha').'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
+	// URL
+	print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td><td><input type="text" class="minwidth500" name="url" value="'.GETPOST("url", 'alpha').'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
 
-    // Langs
-    print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" class="minwidth300" name="langs" value="'.$parent_langs.'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
+	// Langs
+	print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" class="minwidth300" name="langs" value="'.$parent_langs.'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
 
-    // Position
-    print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" class="width100" name="position" value="'.dol_escape_htmltag(isset($_POST["position"]) ? $_POST["position"] : 100).'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
+	// Position
+	print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" class="width100" name="position" value="'.dol_escape_htmltag(isset($_POST["position"]) ? $_POST["position"] : 100).'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
 
-    // Target
-    print '<tr><td>'.$langs->trans('Target').'</td><td><select class="flat" name="target">';
-    print '<option value=""'.($menu->target == "" ? ' selected' : '').'>&nbsp;</option>';
-    print '<option value="_blank"'.($menu->target == "_blank" ? ' selected' : '').'>'.$langs->trans('_blank').'</option>';
-    print '</select></td></td><td>'.$langs->trans('DetailTarget').'</td></tr>';
+	// Target
+	print '<tr><td>'.$langs->trans('Target').'</td><td><select class="flat" name="target">';
+	print '<option value=""'.($menu->target == "" ? ' selected' : '').'>&nbsp;</option>';
+	print '<option value="_blank"'.($menu->target == "_blank" ? ' selected' : '').'>'.$langs->trans('_blank').'</option>';
+	print '</select></td></td><td>'.$langs->trans('DetailTarget').'</td></tr>';
 
-    // Enabled
-    print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" class="minwidth500" name="enabled" value="'.(GETPOSTISSET('enabled') ?GETPOST("enabled", 'alpha') : '1').'"></td><td>'.$langs->trans('DetailEnabled').'</td></tr>';
+	// Enabled
+	print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" class="minwidth500" name="enabled" value="'.(GETPOSTISSET('enabled') ?GETPOST("enabled", 'alpha') : '1').'"></td><td>'.$langs->trans('DetailEnabled').'</td></tr>';
 
-    // Perms
-    print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" class="minwidth500" name="perms" value="'.(GETPOSTISSET('perms') ?GETPOST('perms', 'alpha') : '1').'"></td><td>'.$langs->trans('DetailRight').'</td></tr>';
+	// Perms
+	print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" class="minwidth500" name="perms" value="'.(GETPOSTISSET('perms') ?GETPOST('perms', 'alpha') : '1').'"></td><td>'.$langs->trans('DetailRight').'</td></tr>';
 
-    print '</table>';
+	print '</table>';
 
-    dol_fiche_end();
+	dol_fiche_end();
 
-    print '<div class="center">';
+	print '<div class="center">';
 	print '<input type="submit" class="button" name="save" value="'.$langs->trans("Save").'">';
-    print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
-    print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
+	print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+	print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
 	print '</div>';
 
-    print '</form>';
+	print '</form>';
 } elseif ($action == 'edit')
 {
-    print load_fiche_titre($langs->trans("ModifMenu"), '', 'title_setup');
-    print '<br>';
+	print load_fiche_titre($langs->trans("ModifMenu"), '', 'title_setup');
+	print '<br>';
 
-    print '<form action="./edit.php?action=update" method="POST" name="formmenuedit">';
-    print '<input type="hidden" name="token" value="'.newToken().'">';
-    print '<input type="hidden" name="handler_origine" value="'.$menu_handler.'">';
-    print '<input type="hidden" name="menuId" value="'.GETPOST('menuId', 'int').'">';
+	print '<form action="./edit.php?action=update" method="POST" name="formmenuedit">';
+	print '<input type="hidden" name="token" value="'.newToken().'">';
+	print '<input type="hidden" name="handler_origine" value="'.$menu_handler.'">';
+	print '<input type="hidden" name="menuId" value="'.GETPOST('menuId', 'int').'">';
 
-    dol_fiche_head();
+	dol_fiche_head();
 
-    print '<table class="border centpercent">';
+	print '<table class="border centpercent">';
 
-    $menu = new Menubase($db);
-    $result = $menu->fetch(GETPOST('menuId', 'int'));
-    //var_dump($menu);
+	$menu = new Menubase($db);
+	$result = $menu->fetch(GETPOST('menuId', 'int'));
+	//var_dump($menu);
 
-    // Id
-    print '<tr><td>'.$langs->trans('Id').'</td><td>'.$menu->id.'</td><td>'.$langs->trans('DetailId').'</td></tr>';
+	// Id
+	print '<tr><td>'.$langs->trans('Id').'</td><td>'.$menu->id.'</td><td>'.$langs->trans('DetailId').'</td></tr>';
 
-    // Module
-    print '<tr><td>'.$langs->trans('MenuModule').'</td><td>'.$menu->module.'</td><td>'.$langs->trans('DetailMenuModule').'</td></tr>';
+	// Module
+	print '<tr><td>'.$langs->trans('MenuModule').'</td><td>'.$menu->module.'</td><td>'.$langs->trans('DetailMenuModule').'</td></tr>';
 
-    // Handler
-    if ($menu->menu_handler == 'all') $handler = $langs->trans('AllMenus');
-    else $handler = $menu->menu_handler;
-    print '<tr><td class="fieldrequired">'.$langs->trans('MenuHandler').'</td><td>'.$handler.'</td><td>'.$langs->trans('DetailMenuHandler').'</td></tr>';
+	// Handler
+	if ($menu->menu_handler == 'all') $handler = $langs->trans('AllMenus');
+	else $handler = $menu->menu_handler;
+	print '<tr><td class="fieldrequired">'.$langs->trans('MenuHandler').'</td><td>'.$handler.'</td><td>'.$langs->trans('DetailMenuHandler').'</td></tr>';
 
-    // User
-    print '<tr><td class="nowrap fieldrequired">'.$langs->trans('MenuForUsers').'</td><td><select class="flat" name="user">';
-    print '<option value="2"'.($menu->user == 2 ? ' selected' : '').'>'.$langs->trans("AllMenus").'</option>';
-    print '<option value="0"'.($menu->user == 0 ? ' selected' : '').'>'.$langs->trans('Internal').'</option>';
-    print '<option value="1"'.($menu->user == 1 ? ' selected' : '').'>'.$langs->trans('External').'</option>';
-    print '</select></td><td>'.$langs->trans('DetailUser').'</td></tr>';
+	// User
+	print '<tr><td class="nowrap fieldrequired">'.$langs->trans('MenuForUsers').'</td><td><select class="flat" name="user">';
+	print '<option value="2"'.($menu->user == 2 ? ' selected' : '').'>'.$langs->trans("AllMenus").'</option>';
+	print '<option value="0"'.($menu->user == 0 ? ' selected' : '').'>'.$langs->trans('Internal').'</option>';
+	print '<option value="1"'.($menu->user == 1 ? ' selected' : '').'>'.$langs->trans('External').'</option>';
+	print '</select></td><td>'.$langs->trans('DetailUser').'</td></tr>';
 
-    // Type
-    print '<tr><td class="fieldrequired">'.$langs->trans('Type').'</td><td>'.$langs->trans(ucfirst($menu->type)).'</td><td>'.$langs->trans('DetailType').'</td></tr>';
+	// Type
+	print '<tr><td class="fieldrequired">'.$langs->trans('Type').'</td><td>'.$langs->trans(ucfirst($menu->type)).'</td><td>'.$langs->trans('DetailType').'</td></tr>';
 
-    // Mainmenu code
-    if ($menu->type == 'top')
-    {
-	    print '<tr><td class="fieldrequired">'.$langs->trans('MainMenuCode').'</td>';
-	    /*if ($parent_rowid)
+	// Mainmenu code
+	if ($menu->type == 'top')
+	{
+		print '<tr><td class="fieldrequired">'.$langs->trans('MainMenuCode').'</td>';
+		/*if ($parent_rowid)
 	     {
 	     print '<td>'.$parent_rowid.'<input type="hidden" name="propertyleftmenu" value="'.$parent_rowid.'"></td>';
 	     }
 	     else
 	     {*/
-	    print '<td><input type="text" class="minwidth300" id="propertymainmenu" name="propertymainmenu" value="'.(GETPOST("propertymainmenu", 'alpha') ?GETPOST("propertymainmenu", 'alpha') : $menu->mainmenu).'"></td>';
-	    //}
-	    print '<td>';
-	    print $langs->trans("Example").': mytopmenukey';
-	    print '</td></tr>';
-    }
-
-    // MenuId Parent
-    print '<tr><td class="fieldrequired">'.$langs->trans('MenuIdParent');
-    print '</td>';
-    $valtouse = $menu->fk_menu;
-    if ($menu->fk_mainmenu) $valtouse = 'fk_mainmenu='.$menu->fk_mainmenu;
-    if ($menu->fk_leftmenu) $valtouse .= '&fk_leftmenu='.$menu->fk_leftmenu;
-    print '<td><input type="text" name="menuIdParent" value="'.$valtouse.'" class="minwidth300"></td>';
-    print '<td>'.$langs->trans('DetailMenuIdParent');
-    print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def';
-    print '</td></tr>';
-
-    // Niveau
-    //print '<tr><td>'.$langs->trans('Level').'</td><td>'.$menu->level.'</td><td>'.$langs->trans('DetailLevel').'</td></tr>';
-
-    // Title
-    print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag($menu->title).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
-
-    // Url
-    print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td><td><input type="text" class="quatrevingtpercent" name="url" value="'.$menu->url.'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
-
-    // Langs
-    print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" class="minwidth300" name="langs" value="'.dol_escape_htmltag($menu->langs).'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
-
-    // Position
-    print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" class="minwidth100" name="position" value="'.$menu->position.'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
-
-    // Target
-    print '<tr><td>'.$langs->trans('Target').'</td><td><select class="flat" name="target">';
-    print '<option value=""'.($menu->target == "" ? ' selected' : '').'>&nbsp;</option>';
-    print '<option value="_blank"'.($menu->target == "_blank" ? ' selected' : '').'>'.$langs->trans('_blank').'</option>';
-    print '</select></td><td>'.$langs->trans('DetailTarget').'</td></tr>';
-
-    // Enabled
-    print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" class="minwidth500" name="enabled" value="'.dol_escape_htmltag($menu->enabled).'"></td><td>'.$langs->trans('DetailEnabled');
-    if (!empty($menu->enabled)) print ' ('.$langs->trans("ConditionIsCurrently").': '.yn(dol_eval($menu->enabled, 1)).')';
-    print '</td></tr>';
-
-    // Perms
-    print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" class="minwidth500" name="perms" value="'.dol_escape_htmltag($menu->perms).'"></td><td>'.$langs->trans('DetailRight');
-    if (!empty($menu->perms)) print ' ('.$langs->trans("ConditionIsCurrently").': '.yn(dol_eval($menu->perms, 1)).')';
-    print '</td></tr>';
-
-    print '</table>';
-
-    dol_fiche_end();
-
-    // Bouton
-    print '<div class="center">';
+		print '<td><input type="text" class="minwidth300" id="propertymainmenu" name="propertymainmenu" value="'.(GETPOST("propertymainmenu", 'alpha') ?GETPOST("propertymainmenu", 'alpha') : $menu->mainmenu).'"></td>';
+		//}
+		print '<td>';
+		print $langs->trans("Example").': mytopmenukey';
+		print '</td></tr>';
+	}
+
+	// MenuId Parent
+	print '<tr><td class="fieldrequired">'.$langs->trans('MenuIdParent');
+	print '</td>';
+	$valtouse = $menu->fk_menu;
+	if ($menu->fk_mainmenu) $valtouse = 'fk_mainmenu='.$menu->fk_mainmenu;
+	if ($menu->fk_leftmenu) $valtouse .= '&fk_leftmenu='.$menu->fk_leftmenu;
+	print '<td><input type="text" name="menuIdParent" value="'.$valtouse.'" class="minwidth300"></td>';
+	print '<td>'.$langs->trans('DetailMenuIdParent');
+	print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def';
+	print '</td></tr>';
+
+	// Niveau
+	//print '<tr><td>'.$langs->trans('Level').'</td><td>'.$menu->level.'</td><td>'.$langs->trans('DetailLevel').'</td></tr>';
+
+	// Title
+	print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag($menu->title).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
+
+	// Url
+	print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td><td><input type="text" class="quatrevingtpercent" name="url" value="'.$menu->url.'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
+
+	// Langs
+	print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" class="minwidth300" name="langs" value="'.dol_escape_htmltag($menu->langs).'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
+
+	// Position
+	print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" class="minwidth100" name="position" value="'.$menu->position.'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
+
+	// Target
+	print '<tr><td>'.$langs->trans('Target').'</td><td><select class="flat" name="target">';
+	print '<option value=""'.($menu->target == "" ? ' selected' : '').'>&nbsp;</option>';
+	print '<option value="_blank"'.($menu->target == "_blank" ? ' selected' : '').'>'.$langs->trans('_blank').'</option>';
+	print '</select></td><td>'.$langs->trans('DetailTarget').'</td></tr>';
+
+	// Enabled
+	print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" class="minwidth500" name="enabled" value="'.dol_escape_htmltag($menu->enabled).'"></td><td>'.$langs->trans('DetailEnabled');
+	if (!empty($menu->enabled)) print ' ('.$langs->trans("ConditionIsCurrently").': '.yn(dol_eval($menu->enabled, 1)).')';
+	print '</td></tr>';
+
+	// Perms
+	print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" class="minwidth500" name="perms" value="'.dol_escape_htmltag($menu->perms).'"></td><td>'.$langs->trans('DetailRight');
+	if (!empty($menu->perms)) print ' ('.$langs->trans("ConditionIsCurrently").': '.yn(dol_eval($menu->perms, 1)).')';
+	print '</td></tr>';
+
+	print '</table>';
+
+	dol_fiche_end();
+
+	// Bouton
+	print '<div class="center">';
 	print '<input type="submit" class="button" name="save" value="'.$langs->trans("Save").'">';
-    print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
-    print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
+	print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+	print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
 	print '</div>';
 
-    print '</form>';
+	print '</form>';
 
-    print '<br>';
+	print '<br>';
 }
 
 // End of page

+ 302 - 302
htdocs/comm/action/class/actioncomm.class.php

@@ -498,7 +498,7 @@ class ActionComm extends CommonObject
 		$sql .= ((isset($this->socid) && $this->socid > 0) ? $this->socid : "null").", ";
 		$sql .= ((isset($this->fk_project) && $this->fk_project > 0) ? $this->fk_project : "null").", ";
 		$sql .= " '".$this->db->escape($this->note_private)."', ";
-		$sql .= ((isset($this->contact_id) && $this->contact_id > 0) ? $this->contact_id : "null").", ";	// deprecated, use ->socpeopleassigned
+		$sql .= ((isset($this->contact_id) && $this->contact_id > 0) ? $this->contact_id : "null").", "; // deprecated, use ->socpeopleassigned
 		$sql .= (isset($user->id) && $user->id > 0 ? $user->id : "null").", ";
 		$sql .= ($userownerid > 0 ? $userownerid : "null").", ";
 		$sql .= ($userdoneid > 0 ? $userdoneid : "null").", ";
@@ -632,173 +632,173 @@ class ActionComm extends CommonObject
 		//$this->fetch_userassigned();
 		$this->fetchResources();
 
-        $this->id = 0;
+		$this->id = 0;
 
-        // Create clone
+		// Create clone
 		$this->context['createfromclone'] = 'createfromclone';
 		$result = $this->create($fuser);
-        if ($result < 0) $error++;
-
-        if (!$error)
-        {
-            // Hook of thirdparty module
-            if (is_object($hookmanager))
-            {
-                $parameters = array('objFrom'=>$objFrom);
-                $action = '';
-                $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
-                if ($reshook < 0) $error++;
-            }
-
-            // Call trigger
-            $result = $this->call_trigger('ACTION_CLONE', $fuser);
-            if ($result < 0) { $error++; }
-            // End call triggers
-        }
-
-        unset($this->context['createfromclone']);
-
-        // End
-        if (!$error)
-        {
-            $this->db->commit();
-            return $this->id;
-        } else {
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-    /**
-     *  Load object from database
-     *
-     *  @param  int		$id     		Id of action to get
-     *  @param  string	$ref    		Ref of action to get
-     *  @param  string	$ref_ext		Ref ext to get
+		if ($result < 0) $error++;
+
+		if (!$error)
+		{
+			// Hook of thirdparty module
+			if (is_object($hookmanager))
+			{
+				$parameters = array('objFrom'=>$objFrom);
+				$action = '';
+				$reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+				if ($reshook < 0) $error++;
+			}
+
+			// Call trigger
+			$result = $this->call_trigger('ACTION_CLONE', $fuser);
+			if ($result < 0) { $error++; }
+			// End call triggers
+		}
+
+		unset($this->context['createfromclone']);
+
+		// End
+		if (!$error)
+		{
+			$this->db->commit();
+			return $this->id;
+		} else {
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	/**
+	 *  Load object from database
+	 *
+	 *  @param  int		$id     		Id of action to get
+	 *  @param  string	$ref    		Ref of action to get
+	 *  @param  string	$ref_ext		Ref ext to get
 	 *  @param	string	$email_msgid	Email msgid
-     *  @return	int						<0 if KO, >0 if OK
-     */
-    public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '')
-    {
-        global $langs;
-
-        $sql = "SELECT a.id,";
-        $sql .= " a.id as ref,";
-        $sql .= " a.entity,";
-        $sql .= " a.ref_ext,";
-        $sql .= " a.datep,";
-        $sql .= " a.datep2,";
-        $sql .= " a.durationp,"; // deprecated
-        $sql .= " a.datec,";
-        $sql .= " a.tms as datem,";
-        $sql .= " a.code, a.label, a.note,";
-        $sql .= " a.fk_soc,";
-        $sql .= " a.fk_project,";
-        $sql .= " a.fk_user_author, a.fk_user_mod,";
-        $sql .= " a.fk_user_action, a.fk_user_done,";
-        $sql .= " a.fk_contact, a.percent as percentage,";
-        $sql .= " a.fk_element as elementid, a.elementtype,";
-        $sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
-        $sql .= " a.email_msgid, a.email_subject, a.email_from, a.email_to, a.email_tocc, a.email_tobcc, a.errors_to,";
-        $sql .= " c.id as type_id, c.code as type_code, c.libelle as type_label, c.color as type_color, c.picto as type_picto,";
-        $sql .= " s.nom as socname,";
-        $sql .= " u.firstname, u.lastname as lastname";
-        $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a ";
-        $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action=c.id ";
-        $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author";
-        $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
-        $sql .= " WHERE ";
-        if ($ref) $sql .= " a.id = ".((int) $ref); // No field ref, we use id
-        elseif ($ref_ext) $sql .= " a.ref_ext = '".$this->db->escape($ref_ext)."'";
-        elseif ($email_msgid) $sql .= " a.email_msgid = '".$this->db->escape($email_msgid)."'";
-        else $sql .= " a.id = ".((int) $id);
-
-        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-        	$num = $this->db->num_rows($resql);
-            if ($num)
-            {
-                $obj = $this->db->fetch_object($resql);
-
-                $this->id         = $obj->id;
+	 *  @return	int						<0 if KO, >0 if OK
+	 */
+	public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '')
+	{
+		global $langs;
+
+		$sql = "SELECT a.id,";
+		$sql .= " a.id as ref,";
+		$sql .= " a.entity,";
+		$sql .= " a.ref_ext,";
+		$sql .= " a.datep,";
+		$sql .= " a.datep2,";
+		$sql .= " a.durationp,"; // deprecated
+		$sql .= " a.datec,";
+		$sql .= " a.tms as datem,";
+		$sql .= " a.code, a.label, a.note,";
+		$sql .= " a.fk_soc,";
+		$sql .= " a.fk_project,";
+		$sql .= " a.fk_user_author, a.fk_user_mod,";
+		$sql .= " a.fk_user_action, a.fk_user_done,";
+		$sql .= " a.fk_contact, a.percent as percentage,";
+		$sql .= " a.fk_element as elementid, a.elementtype,";
+		$sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
+		$sql .= " a.email_msgid, a.email_subject, a.email_from, a.email_to, a.email_tocc, a.email_tobcc, a.errors_to,";
+		$sql .= " c.id as type_id, c.code as type_code, c.libelle as type_label, c.color as type_color, c.picto as type_picto,";
+		$sql .= " s.nom as socname,";
+		$sql .= " u.firstname, u.lastname as lastname";
+		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a ";
+		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action=c.id ";
+		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author";
+		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
+		$sql .= " WHERE ";
+		if ($ref) $sql .= " a.id = ".((int) $ref); // No field ref, we use id
+		elseif ($ref_ext) $sql .= " a.ref_ext = '".$this->db->escape($ref_ext)."'";
+		elseif ($email_msgid) $sql .= " a.email_msgid = '".$this->db->escape($email_msgid)."'";
+		else $sql .= " a.id = ".((int) $id);
+
+		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			$num = $this->db->num_rows($resql);
+			if ($num)
+			{
+				$obj = $this->db->fetch_object($resql);
+
+				$this->id         = $obj->id;
 				$this->entity = $obj->entity;
-                $this->ref        = $obj->ref;
-                $this->ref_ext    = $obj->ref_ext;
-
-                // Properties of parent table llx_c_actioncomm
-                $this->type_id    = $obj->type_id;
-                $this->type_code  = $obj->type_code;
-                $this->type_color = $obj->type_color;
-                $this->type_picto = $obj->type_picto;
-                $transcode = $langs->trans("Action".$obj->type_code);
-                $this->type       = (($transcode != "Action".$obj->type_code) ? $transcode : $obj->type_label);
-                $transcode = $langs->trans("Action".$obj->type_code.'Short');
-                $this->type_short = (($transcode != "Action".$obj->type_code.'Short') ? $transcode : '');
+				$this->ref        = $obj->ref;
+				$this->ref_ext    = $obj->ref_ext;
+
+				// Properties of parent table llx_c_actioncomm
+				$this->type_id    = $obj->type_id;
+				$this->type_code  = $obj->type_code;
+				$this->type_color = $obj->type_color;
+				$this->type_picto = $obj->type_picto;
+				$transcode = $langs->trans("Action".$obj->type_code);
+				$this->type       = (($transcode != "Action".$obj->type_code) ? $transcode : $obj->type_label);
+				$transcode = $langs->trans("Action".$obj->type_code.'Short');
+				$this->type_short = (($transcode != "Action".$obj->type_code.'Short') ? $transcode : '');
 
 				$this->code = $obj->code;
-                $this->label = $obj->label;
-                $this->datep = $this->db->jdate($obj->datep);
-                $this->datef = $this->db->jdate($obj->datep2);
-
-                $this->datec = $this->db->jdate($obj->datec);
-                $this->datem = $this->db->jdate($obj->datem);
-
-                $this->note = $obj->note; // deprecated
-                $this->note_private = $obj->note;
-                $this->percentage = $obj->percentage;
-
-                $this->authorid = $obj->fk_user_author;
-                $this->usermodid = $obj->fk_user_mod;
-
-                if (!is_object($this->author)) $this->author = new stdClass(); // To avoid warning
-                $this->author->id = $obj->fk_user_author; // deprecated
-                $this->author->firstname = $obj->firstname; // deprecated
-                $this->author->lastname = $obj->lastname; // deprecated
-                if (!is_object($this->usermod)) $this->usermod = new stdClass(); // To avoid warning
-                $this->usermod->id = $obj->fk_user_mod; // deprecated
-
-                $this->userownerid = $obj->fk_user_action;
-                $this->userdoneid = $obj->fk_user_done;
-                $this->priority				= $obj->priority;
-                $this->fulldayevent			= $obj->fulldayevent;
-                $this->location				= $obj->location;
-                $this->transparency			= $obj->transparency;
-
-                $this->socid = $obj->fk_soc; // To have fetch_thirdparty method working
-                $this->contact_id = $obj->fk_contact; // To have fetch_contact method working
-                $this->fk_project = $obj->fk_project; // To have fetch_projet method working
-
-                //$this->societe->id			= $obj->fk_soc;			// deprecated
-                //$this->contact->id			= $obj->fk_contact;		// deprecated
-
-                $this->fk_element = $obj->elementid;
-                $this->elementid = $obj->elementid;
-                $this->elementtype = $obj->elementtype;
-
-                $this->fetchResources();
-            }
-            $this->db->free($resql);
-        } else {
-            $this->error = $this->db->lasterror();
-            return -1;
-        }
-
-        return $num;
-    }
-
-    /**
-     *    Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact assigned to event
-     *
-     *    @return   int				<0 if KO, >0 if OK
-     */
-    public function fetchResources()
-    {
-    	$this->userassigned = array();
-    	$this->socpeopleassigned = array();
-
-    	$sql = 'SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency';
+				$this->label = $obj->label;
+				$this->datep = $this->db->jdate($obj->datep);
+				$this->datef = $this->db->jdate($obj->datep2);
+
+				$this->datec = $this->db->jdate($obj->datec);
+				$this->datem = $this->db->jdate($obj->datem);
+
+				$this->note = $obj->note; // deprecated
+				$this->note_private = $obj->note;
+				$this->percentage = $obj->percentage;
+
+				$this->authorid = $obj->fk_user_author;
+				$this->usermodid = $obj->fk_user_mod;
+
+				if (!is_object($this->author)) $this->author = new stdClass(); // To avoid warning
+				$this->author->id = $obj->fk_user_author; // deprecated
+				$this->author->firstname = $obj->firstname; // deprecated
+				$this->author->lastname = $obj->lastname; // deprecated
+				if (!is_object($this->usermod)) $this->usermod = new stdClass(); // To avoid warning
+				$this->usermod->id = $obj->fk_user_mod; // deprecated
+
+				$this->userownerid = $obj->fk_user_action;
+				$this->userdoneid = $obj->fk_user_done;
+				$this->priority				= $obj->priority;
+				$this->fulldayevent			= $obj->fulldayevent;
+				$this->location				= $obj->location;
+				$this->transparency			= $obj->transparency;
+
+				$this->socid = $obj->fk_soc; // To have fetch_thirdparty method working
+				$this->contact_id = $obj->fk_contact; // To have fetch_contact method working
+				$this->fk_project = $obj->fk_project; // To have fetch_projet method working
+
+				//$this->societe->id			= $obj->fk_soc;			// deprecated
+				//$this->contact->id			= $obj->fk_contact;		// deprecated
+
+				$this->fk_element = $obj->elementid;
+				$this->elementid = $obj->elementid;
+				$this->elementtype = $obj->elementtype;
+
+				$this->fetchResources();
+			}
+			$this->db->free($resql);
+		} else {
+			$this->error = $this->db->lasterror();
+			return -1;
+		}
+
+		return $num;
+	}
+
+	/**
+	 *    Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact assigned to event
+	 *
+	 *    @return   int				<0 if KO, >0 if OK
+	 */
+	public function fetchResources()
+	{
+		$this->userassigned = array();
+		$this->socpeopleassigned = array();
+
+		$sql = 'SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency';
 		$sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm_resources';
 		$sql .= ' WHERE fk_actioncomm = '.$this->id;
 		$sql .= " AND element_type IN ('user', 'socpeople')";
@@ -1937,168 +1937,168 @@ class ActionComm extends CommonObject
 		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
 	}
 
-    /**
-     *  Is the action delayed?
-     *
-     *  @return bool
-     */
-    public function hasDelay()
-    {
-        global $conf;
-
-        $now = dol_now();
-
-        return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
-    }
-
-
-    /**
-     *  Send reminders by emails
-     *  CAN BE A CRON TASK
-     *
-     *  @return int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
-     */
-    public function sendEmailsReminder()
-    {
-    	global $conf, $langs, $user;
-
-    	$error = 0;
-    	$this->output = '';
+	/**
+	 *  Is the action delayed?
+	 *
+	 *  @return bool
+	 */
+	public function hasDelay()
+	{
+		global $conf;
+
+		$now = dol_now();
+
+		return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
+	}
+
+
+	/**
+	 *  Send reminders by emails
+	 *  CAN BE A CRON TASK
+	 *
+	 *  @return int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
+	 */
+	public function sendEmailsReminder()
+	{
+		global $conf, $langs, $user;
+
+		$error = 0;
+		$this->output = '';
 		$this->error = '';
 		$nbMailSend = 0;
 		$errorsMsg = array();
 
-    	if (empty($conf->agenda->enabled))	// Should not happen. If module disabled, cron job should not be visible.
+		if (empty($conf->agenda->enabled))	// Should not happen. If module disabled, cron job should not be visible.
 		{
 			$langs->load("agenda");
 			$this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
 			return 0;
 		}
 		if (empty($conf->global->AGENDA_REMINDER_EMAIL))
-    	{
-    		$langs->load("agenda");
-    		$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
-    		return 0;
-    	}
+		{
+			$langs->load("agenda");
+			$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
+			return 0;
+		}
 
-    	$now = dol_now();
+		$now = dol_now();
 
-    	dol_syslog(__METHOD__, LOG_DEBUG);
+		dol_syslog(__METHOD__, LOG_DEBUG);
 
-        $this->db->begin();
+		$this->db->begin();
 
-        //Select all action comm reminder
-    	$sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
+		//Select all action comm reminder
+		$sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
 		$sql .= " WHERE typeremind = 'email' AND status = 0";
 		$sql .= " AND dateremind <= '".$this->db->idate(dol_now())."'";
 		$sql .= $this->db->order("dateremind", "ASC");
-        $resql = $this->db->query($sql);
+		$resql = $this->db->query($sql);
 
-        if ($resql) {
-            $formmail = new FormMail($this->db);
-            $actionCommReminder = new ActionCommReminder($this->db);
+		if ($resql) {
+			$formmail = new FormMail($this->db);
+			$actionCommReminder = new ActionCommReminder($this->db);
 
 			while ($obj = $this->db->fetch_object($resql)){
-                $res = $actionCommReminder->fetch($obj->id);
-                if ($res < 0) {
-                    $error++;
-                    $errorsMsg[] = "Failed to load invoice ActionComm Reminder";
-                }
-
-                if (!$error)
-                {
-                	//Select email template
-                	$arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
-
-                	// Load event
-                	$res = $this->fetch($actionCommReminder->fk_actioncomm);
-                	if ($res > 0)
-                	{
-                		// PREPARE EMAIL
-
-                		// Make substitution in email content
-                		$substitutionarray = getCommonSubstitutionArray($langs, 0, '', $this);
-
-                		complete_substitutions_array($substitutionarray, $langs, $this);
-
-                		// Content
-                		$sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
-
-                		//Topic
-                		$sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->trans('EventReminder'));
-
-                		// Recipient
-                		$recipient = new User($this->db);
-                		$res = $recipient->fetch($actionCommReminder->fk_user);
-                		if ($res > 0 && !empty($recipient->email)) $to = $recipient->email;
-                		else {
-                			$errorsMsg[] = "Failed to load recipient";
-                			$error++;
-                		}
-
-                		// Sender
-                		$from = $conf->global->MAIN_MAIL_EMAIL_FROM;
-                		if (empty($from)) {
-                			$errorsMsg[] = "Failed to load recipient";
-                			$error++;
-                		}
-
-                		// Errors Recipient
-                		$errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
-
-                		// Mail Creation
-                		$cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
-
-                		// Sending Mail
-                		if ($cMailFile->sendfile())
-                		{
-                			$actionCommReminder->status = $actionCommReminder::STATUS_DONE;
-                			$res = $actionCommReminder->update($user);
-                			if ($res < 0)
-                			{
-                				$errorsMsg[] = "Failed to update status of ActionComm Reminder";
-                				$error++;
-                				break;	// This is to avoid to have this error on all the selected email. If we fails here for one record, it may fails for others. We must solve first.
-                			} else {
-                				$nbMailSend++;
-                			}
-                		} else {
-                			$errorsMsg[] = $cMailFile->error.' : '.$to;
-                			$error++;
-                		}
-                	} else {
-                		$error++;
-                	}
-                }
-            }
-        } else {
-            $error++;
-        }
-
-        if (!$error)
-        {
-            // Delete also very old past events (we do not keep more than 1 month record in past)
-            $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
+				$res = $actionCommReminder->fetch($obj->id);
+				if ($res < 0) {
+					$error++;
+					$errorsMsg[] = "Failed to load invoice ActionComm Reminder";
+				}
+
+				if (!$error)
+				{
+					//Select email template
+					$arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
+
+					// Load event
+					$res = $this->fetch($actionCommReminder->fk_actioncomm);
+					if ($res > 0)
+					{
+						// PREPARE EMAIL
+
+						// Make substitution in email content
+						$substitutionarray = getCommonSubstitutionArray($langs, 0, '', $this);
+
+						complete_substitutions_array($substitutionarray, $langs, $this);
+
+						// Content
+						$sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
+
+						//Topic
+						$sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->trans('EventReminder'));
+
+						// Recipient
+						$recipient = new User($this->db);
+						$res = $recipient->fetch($actionCommReminder->fk_user);
+						if ($res > 0 && !empty($recipient->email)) $to = $recipient->email;
+						else {
+							$errorsMsg[] = "Failed to load recipient";
+							$error++;
+						}
+
+						// Sender
+						$from = $conf->global->MAIN_MAIL_EMAIL_FROM;
+						if (empty($from)) {
+							$errorsMsg[] = "Failed to load recipient";
+							$error++;
+						}
+
+						// Errors Recipient
+						$errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
+
+						// Mail Creation
+						$cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
+
+						// Sending Mail
+						if ($cMailFile->sendfile())
+						{
+							$actionCommReminder->status = $actionCommReminder::STATUS_DONE;
+							$res = $actionCommReminder->update($user);
+							if ($res < 0)
+							{
+								$errorsMsg[] = "Failed to update status of ActionComm Reminder";
+								$error++;
+								break;	// This is to avoid to have this error on all the selected email. If we fails here for one record, it may fails for others. We must solve first.
+							} else {
+								$nbMailSend++;
+							}
+						} else {
+							$errorsMsg[] = $cMailFile->error.' : '.$to;
+							$error++;
+						}
+					} else {
+						$error++;
+					}
+				}
+			}
+		} else {
+			$error++;
+		}
+
+		if (!$error)
+		{
+			// Delete also very old past events (we do not keep more than 1 month record in past)
+			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
 			$sql .= " WHERE dateremind < '".$this->db->idate($now - (3600 * 24 * 32))."'";
-            $resql = $this->db->query($sql);
-
-            if (!$resql) {
-                $errorsMsg[] = 'Failed to delete old reminders';
-                //$error++;		// If this fails, we must not rollback other SQL requests already done. Never mind.
-            }
-        }
-
-        if (!$error) {
-        	$this->output = 'Nb of emails sent : '.$nbMailSend;
-        	$this->db->commit();
-            return 0;
-        }
-        else {
-            $this->db->rollback();
-            $this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg)) ? join(', ', $errorsMsg) : $error;
-            return $error;
-        }
-    }
+			$resql = $this->db->query($sql);
+
+			if (!$resql) {
+				$errorsMsg[] = 'Failed to delete old reminders';
+				//$error++;		// If this fails, we must not rollback other SQL requests already done. Never mind.
+			}
+		}
+
+		if (!$error) {
+			$this->output = 'Nb of emails sent : '.$nbMailSend;
+			$this->db->commit();
+			return 0;
+		}
+		else {
+			$this->db->rollback();
+			$this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg)) ? join(', ', $errorsMsg) : $error;
+			return $error;
+		}
+	}
 
 	/**
 	 * Udpate the percent value of a event with the given id

File diff suppressed because it is too large
+ 487 - 487
htdocs/comm/action/index.php


+ 7 - 7
htdocs/comm/propal/list.php

@@ -1291,21 +1291,21 @@ if ($resql)
 			foreach ($toselect as $checked) {
 				if ($tmpproposal->fetch($checked)) {
 					if ($tmpproposal->statut == 0) {
-						if ($tmpproposal->valid($user)){
-							setEventMessage($tmpproposal->ref . " " . $langs->trans('PassedInOpenStatus'), 'mesgs');
+						if ($tmpproposal->valid($user)) {
+							setEventMessage($tmpproposal->ref." ".$langs->trans('PassedInOpenStatus'), 'mesgs');
 						} else {
 							setEventMessage($langs->trans('CantBeValidated'), 'errors');
 							$error++;
 						}
 					} else {
-						setEventMessage($tmpproposal->ref . " " . $langs->trans('IsNotADraft'), 'errors');
+						setEventMessage($tmpproposal->ref." ".$langs->trans('IsNotADraft'), 'errors');
 						$error++;
 					}
 				}
 				dol_print_error($db);
 				$error++;
 			}
-			if ($error){
+			if ($error) {
 				$db->rollback();
 			} else {
 				$db->commit();
@@ -1323,13 +1323,13 @@ if ($resql)
 					if ($tmpproposal->statut == 1) {
 						$tmpproposal->statut = 2;
 						if ($tmpproposal->update($user)) {
-							setEventMessage($tmpproposal->ref . " " . $langs->trans('Signed'), 'mesgs');
+							setEventMessage($tmpproposal->ref." ".$langs->trans('Signed'), 'mesgs');
 						} else {
 							dol_print_error($db);
 							$error++;
 						}
 					} else {
-						setEventMessage($tmpproposal->ref . " " . $langs->trans('CantBeSign'), 'errors');
+						setEventMessage($tmpproposal->ref." ".$langs->trans('CantBeSign'), 'errors');
 						$error++;
 					}
 				} else {
@@ -1337,7 +1337,7 @@ if ($resql)
 					$error++;
 				}
 			}
-			if ($error){
+			if ($error) {
 				$db->rollback();
 			} else {
 				$db->commit();

File diff suppressed because it is too large
+ 552 - 552
htdocs/commande/class/api_orders.class.php


+ 128 - 128
htdocs/commande/class/commande.class.php

@@ -99,13 +99,13 @@ class Commande extends CommonOrder
 	 */
 	public $ref_client;
 
-    /**
+	/**
 	 * @var string Internal ref for order
 	 * @deprecated
 	 */
 	public $ref_int;
 
-    /**
+	/**
 	 * @var int Contact ID
 	 */
 	public $contactid;
@@ -121,15 +121,15 @@ class Commande extends CommonOrder
 	 */
 	public $billed;
 
-    /**
-     * @var int Draft Status of the order
-     */
-    public $brouillon;
-    public $cond_reglement_code;
+	/**
+	 * @var int Draft Status of the order
+	 */
+	public $brouillon;
+	public $cond_reglement_code;
 
 	/**
-     * @var int bank account ID
-     */
+	 * @var int bank account ID
+	 */
 	public $fk_account;
 
 	/**
@@ -168,12 +168,12 @@ class Commande extends CommonOrder
 	public $demand_reason_id; // Source reason. Why we receive order (after a phone campaign, ...)
 	public $demand_reason_code;
 	/**
-     * @var int Date of order
+	 * @var int Date of order
 	 */
 	public $date;
 
 	/**
-     * @var int Date of order
+	 * @var int Date of order
 	 * @deprecated
 	 * @see $date
 	 */
@@ -182,8 +182,8 @@ class Commande extends CommonOrder
 	public $date_livraison; // Date expected of shipment (date starting shipment, not the reception that occurs some days after)
 
 	/**
-     * @var int ID
-     */
+	 * @var int ID
+	 */
 	public $fk_remise_except;
 
 	public $remise_percent;
@@ -197,13 +197,13 @@ class Commande extends CommonOrder
 	public $linked_objects = array();
 
 	/**
-     * @var int User author ID
-     */
+	 * @var int User author ID
+	 */
 	public $user_author_id;
 
-    /**
-     * @var int User validator ID
-     */
+	/**
+	 * @var int User validator ID
+	 */
 	public $user_valid;
 
 	/**
@@ -213,8 +213,8 @@ class Commande extends CommonOrder
 
 	// Multicurrency
 	/**
-     * @var int Currency ID
-     */
+	 * @var int Currency ID
+	 */
 	public $fk_multicurrency;
 
 	public $multicurrency_code;
@@ -223,9 +223,9 @@ class Commande extends CommonOrder
 	public $multicurrency_total_tva;
 	public $multicurrency_total_ttc;
 
-    /**
-     * @var Commande clone of order object
-     */
+	/**
+	 * @var Commande clone of order object
+	 */
 	public $oldcopy;
 
 	//! key of module source when order generated from a dedicated module ('cashdesk', 'takepos', ...)
@@ -394,11 +394,11 @@ class Commande extends CommonOrder
 				$mybool |= @include_once $dir.$file;
 			}
 
-            if ($mybool === false)
-            {
-                dol_print_error('', "Failed to include file ".$file);
-                return '';
-            }
+			if ($mybool === false)
+			{
+				dol_print_error('', "Failed to include file ".$file);
+				return '';
+			}
 
 			$obj = new $classname();
 			$numref = $obj->getNextValue($soc, $this);
@@ -568,7 +568,7 @@ class Commande extends CommonOrder
 		{
 			$this->ref = $num;
 			$this->statut = self::STATUS_VALIDATED;
-            $this->brouillon = 0;
+			$this->brouillon = 0;
 		}
 
 		if (!$error)
@@ -589,9 +589,9 @@ class Commande extends CommonOrder
 	 *	@param	int		$idwarehouse	Warehouse ID to use for stock change (Used only if option STOCK_CALCULATE_ON_VALIDATE_ORDER is on)
 	 *	@return	int						<0 if KO, >0 if OK
 	 */
-    public function setDraft($user, $idwarehouse = -1)
-    {
-        //phpcs:enable
+	public function setDraft($user, $idwarehouse = -1)
+	{
+		//phpcs:enable
 		global $conf, $langs;
 
 		$error = 0;
@@ -619,12 +619,12 @@ class Commande extends CommonOrder
 
 		if ($this->db->query($sql))
 		{
-		    if (!$error)
-		    {
-		        $this->oldcopy = clone $this;
-		    }
+			if (!$error)
+			{
+				$this->oldcopy = clone $this;
+			}
 
-		    // If stock is decremented on validate order, we must reincrement it
+			// If stock is decremented on validate order, we must reincrement it
 			if (!empty($conf->stock->enabled) && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1)
 			{
 				$result = 0;
@@ -665,7 +665,7 @@ class Commande extends CommonOrder
 			$this->db->rollback();
 			return -1;
 		}
-    }
+	}
 
 
 	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
@@ -678,7 +678,7 @@ class Commande extends CommonOrder
 	 */
 	public function set_reopen($user)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		$error = 0;
 
 		if ($this->statut != self::STATUS_CANCELED && $this->statut != self::STATUS_CLOSED)
@@ -958,7 +958,7 @@ class Commande extends CommonOrder
 		$sql .= ", ".(int) $this->fk_incoterms;
 		$sql .= ", '".$this->db->escape($this->location_incoterms)."'";
 		$sql .= ", ".setEntity($this);
-        $sql .= ", ".($this->module_source ? "'".$this->db->escape($this->module_source)."'" : "null");
+		$sql .= ", ".($this->module_source ? "'".$this->db->escape($this->module_source)."'" : "null");
 		$sql .= ", ".($this->pos_source != '' ? "'".$this->db->escape($this->pos_source)."'" : "null");
 		$sql .= ", ".(int) $this->fk_multicurrency;
 		$sql .= ", '".$this->db->escape($this->multicurrency_code)."'";
@@ -1009,7 +1009,7 @@ class Commande extends CommonOrder
 						$line->ref_ext = '';
 					}
 
-                    $result = $this->addline(
+					$result = $this->addline(
 						$line->desc,
 						$line->subprice,
 						$line->qty,
@@ -1033,10 +1033,10 @@ class Commande extends CommonOrder
 						$line->label,
 						$line->array_options,
 						$line->fk_unit,
-	                    $origintype,
-	                    $originid,
+						$origintype,
+						$originid,
 						0,
-	                    $line->ref_ext
+						$line->ref_ext
 					);
 					if ($result < 0)
 					{
@@ -1357,8 +1357,8 @@ class Commande extends CommonOrder
 
 		if (empty($conf->global->MAIN_DISABLE_PROPAGATE_NOTES_FROM_ORIGIN))
 		{
-            $this->note_private         = $object->note_private;
-            $this->note_public          = $object->note_public;
+			$this->note_private         = $object->note_private;
+			$this->note_public          = $object->note_public;
 		}
 
 		$this->origin = $object->element;
@@ -1502,7 +1502,7 @@ class Commande extends CommonOrder
 				return -1;
 			}
 
-            $this->db->begin();
+			$this->db->begin();
 
 			$product_type = $type;
 			if (!empty($fk_product))
@@ -1681,7 +1681,7 @@ class Commande extends CommonOrder
 	 */
 	public function add_product($idproduct, $qty, $remise_percent = 0.0, $date_start = '', $date_end = '')
 	{
-        // phpcs:enable
+		// phpcs:enable
 		global $conf, $mysoc;
 
 		if (!$qty) $qty = 1;
@@ -1780,7 +1780,7 @@ class Commande extends CommonOrder
 		$sql .= ', c.fk_incoterms, c.location_incoterms';
 		$sql .= ", c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva, c.multicurrency_total_ttc";
 		$sql .= ", c.module_source, c.pos_source";
-        $sql .= ", i.libelle as label_incoterms";
+		$sql .= ", i.libelle as label_incoterms";
 		$sql .= ', p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
 		$sql .= ', cr.code as cond_reglement_code, cr.libelle as cond_reglement_libelle, cr.libelle_facture as cond_reglement_libelle_doc';
 		$sql .= ', ca.code as availability_code, ca.label as availability_label';
@@ -1917,7 +1917,7 @@ class Commande extends CommonOrder
 	 */
 	public function insert_discount($idremise)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		global $langs;
 
 		include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
@@ -1992,7 +1992,7 @@ class Commande extends CommonOrder
 	public function fetch_lines($only_product = 0, $loadalsotranslation = 0)
 	{
 		global $langs, $conf;
-        // phpcs:enable
+		// phpcs:enable
 		$this->lines = array();
 
 		$sql = 'SELECT l.rowid, l.fk_product, l.fk_parent_line, l.product_type, l.fk_commande, l.label as custom_label, l.description, l.price, l.qty, l.vat_src_code, l.tva_tx, l.ref_ext,';
@@ -2086,13 +2086,13 @@ class Commande extends CommonOrder
 				$line->fetch_optionals();
 
 				// multilangs
-        		if (!empty($conf->global->MAIN_MULTILANGS) && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
-            		$line = new Product($this->db);
-            		$line->fetch($objp->fk_product);
-            		$line->getMultiLangs();
-        		}
+				if (!empty($conf->global->MAIN_MULTILANGS) && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
+					$line = new Product($this->db);
+					$line->fetch($objp->fk_product);
+					$line->getMultiLangs();
+				}
 
-                $this->lines[$i] = $line;
+				$this->lines[$i] = $line;
 
 				$i++;
 			}
@@ -2224,7 +2224,7 @@ class Commande extends CommonOrder
 	 */
 	public function nb_expedition()
 	{
-        // phpcs:enable
+		// phpcs:enable
 		$sql = 'SELECT count(*)';
 		$sql .= ' FROM '.MAIN_DB_PREFIX.'expedition as e';
 		$sql .= ', '.MAIN_DB_PREFIX.'element_element as el';
@@ -2251,7 +2251,7 @@ class Commande extends CommonOrder
 	 */
 	public function stock_array($filtre_statut = self::STATUS_CANCELED)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		$this->stocks = array();
 
 		// Tableau des id de produit de la commande
@@ -2359,7 +2359,7 @@ class Commande extends CommonOrder
 	 */
 	public function set_remise($user, $remise, $notrigger = 0)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		$remise = trim($remise) ?trim($remise) : 0;
 
 		if ($user->rights->commande->creer)
@@ -2425,7 +2425,7 @@ class Commande extends CommonOrder
 	 */
 	public function set_remise_absolue($user, $remise, $notrigger = 0)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		$remise = trim($remise) ?trim($remise) : 0;
 
 		if ($user->rights->commande->creer)
@@ -2491,7 +2491,7 @@ class Commande extends CommonOrder
 	 */
 	public function set_date($user, $date, $notrigger = 0)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		if ($user->rights->commande->creer)
 		{
 			$error = 0;
@@ -2553,7 +2553,7 @@ class Commande extends CommonOrder
 	 */
 	public function set_date_livraison($user, $date_livraison, $notrigger = 0)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		if ($user->rights->commande->creer)
 		{
 			$error = 0;
@@ -2620,7 +2620,7 @@ class Commande extends CommonOrder
 	 */
 	public function liste_array($shortlist = 0, $draft = 0, $excluser = '', $socid = 0, $limit = 0, $offset = 0, $sortfield = 'c.date_commande', $sortorder = 'DESC')
 	{
-        // phpcs:enable
+		// phpcs:enable
 		global $user;
 
 		$ga = array();
@@ -2750,7 +2750,7 @@ class Commande extends CommonOrder
 	 */
 	public function demand_reason($demand_reason_id, $notrigger = 0)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		global $user;
 
 		dol_syslog('Commande::demand_reason('.$demand_reason_id.')');
@@ -2819,7 +2819,7 @@ class Commande extends CommonOrder
 	 */
 	public function set_ref_client($user, $ref_client, $notrigger = 0)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		if ($user->rights->commande->creer)
 		{
 			$error = 0;
@@ -3321,9 +3321,9 @@ class Commande extends CommonOrder
 		if (!$error)
 		{
 			// Delete extrafields of order details
-                        $main = MAIN_DB_PREFIX.'commandedet';
-                        $ef = $main."_extrafields";
-                        $sql = "DELETE FROM $ef WHERE fk_object IN (SELECT rowid FROM $main WHERE fk_commande = ".$this->id.")";
+						$main = MAIN_DB_PREFIX.'commandedet';
+						$ef = $main."_extrafields";
+						$sql = "DELETE FROM $ef WHERE fk_object IN (SELECT rowid FROM $main WHERE fk_commande = ".$this->id.")";
 			if (!$this->db->query($sql))
 			{
 				$error++;
@@ -3432,7 +3432,7 @@ class Commande extends CommonOrder
 	 */
 	public function load_board($user)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		global $conf, $langs;
 
 		$clause = " WHERE";
@@ -3521,45 +3521,45 @@ class Commande extends CommonOrder
 	 */
 	public function LibStatut($status, $billed, $mode, $donotshowbilled = 0)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		global $langs, $conf;
 
 		$billedtext = '';
 		if (empty($donotshowbilled)) $billedtext .= ($billed ? ' - '.$langs->trans("Billed") : '');
 
 		if ($status == self::STATUS_CANCELED) {
-		    $labelStatus = $langs->trans('StatusOrderCanceled');
-		    $labelStatusShort = $langs->trans('StatusOrderCanceledShort');
-		    $statusType = 'status9';
+			$labelStatus = $langs->trans('StatusOrderCanceled');
+			$labelStatusShort = $langs->trans('StatusOrderCanceledShort');
+			$statusType = 'status9';
 		} elseif ($status == self::STATUS_DRAFT) {
-		    $labelStatus = $langs->trans('StatusOrderDraft');
-		    $labelStatusShort = $langs->trans('StatusOrderDraftShort');
-		    $statusType = 'status0';
+			$labelStatus = $langs->trans('StatusOrderDraft');
+			$labelStatusShort = $langs->trans('StatusOrderDraftShort');
+			$statusType = 'status0';
 		} elseif ($status == self::STATUS_VALIDATED) {
-		    $labelStatus = $langs->trans('StatusOrderValidated').$billedtext;
-		    $labelStatusShort = $langs->trans('StatusOrderValidatedShort').$billedtext;
-		    $statusType = 'status1';
+			$labelStatus = $langs->trans('StatusOrderValidated').$billedtext;
+			$labelStatusShort = $langs->trans('StatusOrderValidatedShort').$billedtext;
+			$statusType = 'status1';
 		} elseif ($status == self::STATUS_SHIPMENTONPROCESS) {
-		    $labelStatus = $langs->trans('StatusOrderSentShort').$billedtext;
-		    $labelStatusShort = $langs->trans('StatusOrderSentShort').$billedtext;
-		    $statusType = 'status4';
+			$labelStatus = $langs->trans('StatusOrderSentShort').$billedtext;
+			$labelStatusShort = $langs->trans('StatusOrderSentShort').$billedtext;
+			$statusType = 'status4';
 		} elseif ($status == self::STATUS_CLOSED && (!$billed && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) {
-		    $labelStatus = $langs->trans('StatusOrderToBill');
-		    $labelStatusShort = $langs->trans('StatusOrderToBillShort');
-		    $statusType = 'status4';
+			$labelStatus = $langs->trans('StatusOrderToBill');
+			$labelStatusShort = $langs->trans('StatusOrderToBillShort');
+			$statusType = 'status4';
 		} elseif ($status == self::STATUS_CLOSED && ($billed && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) {
-		    $labelStatus = $langs->trans('StatusOrderProcessed').$billedtext;
-		    $labelStatusShort = $langs->trans('StatusOrderProcessed').$billedtext;
-		    $statusType = 'status6';
+			$labelStatus = $langs->trans('StatusOrderProcessed').$billedtext;
+			$labelStatusShort = $langs->trans('StatusOrderProcessed').$billedtext;
+			$statusType = 'status6';
 		} elseif ($status == self::STATUS_CLOSED && (!empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) {
-		    $labelStatus = $langs->trans('StatusOrderDelivered');
-		    $labelStatusShort = $langs->trans('StatusOrderDelivered');
-		    $statusType = 'status6';
+			$labelStatus = $langs->trans('StatusOrderDelivered');
+			$labelStatusShort = $langs->trans('StatusOrderDelivered');
+			$statusType = 'status6';
 		} else {
-		    $labelStatus = $langs->trans('Unknown');
-		    $labelStatusShort = '';
-		    $statusType = '';
-		    $mode = 0;
+			$labelStatus = $langs->trans('Unknown');
+			$labelStatusShort = '';
+			$statusType = '';
+			$mode = 0;
 		}
 
 		return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
@@ -3825,7 +3825,7 @@ class Commande extends CommonOrder
 	 */
 	public function load_state_board()
 	{
-        // phpcs:enable
+		// phpcs:enable
 		global $user;
 
 		$this->nb = array();
@@ -4024,10 +4024,10 @@ class OrderLine extends CommonOrderLine
 	 *
 	 *      @param     DoliDB	$db      handler d'acces base de donnee
 	 */
-    public function __construct($db)
-    {
-        $this->db = $db;
-    }
+	public function __construct($db)
+	{
+		$this->db = $db;
+	}
 
 	/**
 	 *  Load line order
@@ -4125,32 +4125,32 @@ class OrderLine extends CommonOrderLine
 
 		$error = 0;
 
-        // check if order line is not in a shipment line before deleting
-        $sqlCheckShipmentLine  = "SELECT";
-        $sqlCheckShipmentLine .= " ed.rowid";
-        $sqlCheckShipmentLine .= " FROM ".MAIN_DB_PREFIX."expeditiondet ed";
-        $sqlCheckShipmentLine .= " WHERE ed.fk_origin_line = ".$this->rowid;
-
-        $resqlCheckShipmentLine = $this->db->query($sqlCheckShipmentLine);
-        if (!$resqlCheckShipmentLine) {
-            $error++;
-            $this->error    = $this->db->lasterror();
-            $this->errors[] = $this->error;
-        } else {
-            $langs->load('errors');
-            $num = $this->db->num_rows($resqlCheckShipmentLine);
-            if ($num > 0) {
-                $error++;
-                $objCheckShipmentLine = $this->db->fetch_object($resqlCheckShipmentLine);
-                $this->error = $langs->trans('ErrorRecordAlreadyExists').' : '.$langs->trans('ShipmentLine').' '.$objCheckShipmentLine->rowid;
-                $this->errors[] = $this->error;
-            }
-            $this->db->free($resqlCheckShipmentLine);
-        }
-        if ($error) {
-            dol_syslog(__METHOD__.'Error ; '.$this->error, LOG_ERR);
-            return -1;
-        }
+		// check if order line is not in a shipment line before deleting
+		$sqlCheckShipmentLine  = "SELECT";
+		$sqlCheckShipmentLine .= " ed.rowid";
+		$sqlCheckShipmentLine .= " FROM ".MAIN_DB_PREFIX."expeditiondet ed";
+		$sqlCheckShipmentLine .= " WHERE ed.fk_origin_line = ".$this->rowid;
+
+		$resqlCheckShipmentLine = $this->db->query($sqlCheckShipmentLine);
+		if (!$resqlCheckShipmentLine) {
+			$error++;
+			$this->error    = $this->db->lasterror();
+			$this->errors[] = $this->error;
+		} else {
+			$langs->load('errors');
+			$num = $this->db->num_rows($resqlCheckShipmentLine);
+			if ($num > 0) {
+				$error++;
+				$objCheckShipmentLine = $this->db->fetch_object($resqlCheckShipmentLine);
+				$this->error = $langs->trans('ErrorRecordAlreadyExists').' : '.$langs->trans('ShipmentLine').' '.$objCheckShipmentLine->rowid;
+				$this->errors[] = $this->error;
+			}
+			$this->db->free($resqlCheckShipmentLine);
+		}
+		if ($error) {
+			dol_syslog(__METHOD__.'Error ; '.$this->error, LOG_ERR);
+			return -1;
+		}
 
 		$this->db->begin();
 
@@ -4482,7 +4482,7 @@ class OrderLine extends CommonOrderLine
 	 */
 	public function update_total()
 	{
-        // phpcs:enable
+		// phpcs:enable
 		$this->db->begin();
 
 		// Clean parameters

File diff suppressed because it is too large
+ 277 - 277
htdocs/compta/facture/class/facture.class.php


+ 7 - 7
htdocs/contact/card.php

@@ -177,10 +177,10 @@ if (empty($reshook))
 		if ($canvas) $object->canvas = $canvas;
 
 		$object->entity = (GETPOSTISSET('entity') ?GETPOST('entity', 'int') : $conf->entity);
-		$object->socid			= GETPOST("socid", 'int');
+		$object->socid = GETPOST("socid", 'int');
 		$object->lastname = GETPOST("lastname", 'alpha');
 		$object->firstname = GETPOST("firstname", 'alpha');
-		$object->civility_code	= GETPOST("civility_code", 'alpha');
+		$object->civility_code = GETPOST("civility_code", 'alpha');
 		$object->poste			= GETPOST("poste", 'alpha');
 		$object->address = GETPOST("address", 'alpha');
 		$object->zip = GETPOST("zipcode", 'alpha');
@@ -1355,7 +1355,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action))
 
 		$object->fetch_thirdparty();
 
-		if (! empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) {
+		if (!empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) {
 			if ($object->thirdparty->client == 2 || $object->thirdparty->client == 3)
 			{
 				print '<br>';
@@ -1368,11 +1368,11 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action))
 				print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
 				print $langs->trans('ProspectLevel');
 				print '<td>';
-				if ($action != 'editlevel' && $user->rights->societe->contact->creer) print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editlevel&amp;id=' . $object->id . '">' . img_edit($langs->trans('Modify'), 1) . '</a></td>';
+				if ($action != 'editlevel' && $user->rights->societe->contact->creer) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editlevel&amp;id='.$object->id.'">'.img_edit($langs->trans('Modify'), 1).'</a></td>';
 				print '</tr></table>';
 				print '</td><td>';
 				if ($action == 'editlevel') {
-					$formcompany->formProspectContactLevel($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_prospectlevel, 'prospect_contact_level_id', 1);
+					$formcompany->formProspectContactLevel($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_prospectlevel, 'prospect_contact_level_id', 1);
 				} else {
 					print $object->getLibProspLevel();
 				}
@@ -1381,13 +1381,13 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action))
 
 				// Status of prospection
 				$object->loadCacheOfProspStatus();
-				print '<tr><td>' . $langs->trans("StatusProsp") . '</td><td>' . $object->getLibProspCommStatut(4, $object->cacheprospectstatus[$object->stcomm_id]['label']);
+				print '<tr><td>'.$langs->trans("StatusProsp").'</td><td>'.$object->getLibProspCommStatut(4, $object->cacheprospectstatus[$object->stcomm_id]['label']);
 				print ' &nbsp; &nbsp; ';
 				print '<div class="floatright">';
 				foreach ($object->cacheprospectstatus as $key => $val) {
 					$titlealt = 'default';
 					if (!empty($val['code']) && !in_array($val['code'], array('ST_NO', 'ST_NEVER', 'ST_TODO', 'ST_PEND', 'ST_DONE'))) $titlealt = $val['label'];
-					if ($object->stcomm_id != $val['id']) print '<a class="pictosubstatus" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&stcomm=' . $val['code'] . '&action=setstcomm">' . img_action($titlealt, $val['code'], $val['picto']) . '</a>';
+					if ($object->stcomm_id != $val['id']) print '<a class="pictosubstatus" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&stcomm='.$val['code'].'&action=setstcomm">'.img_action($titlealt, $val['code'], $val['picto']).'</a>';
 				}
 				print '</div></td></tr>';
 

+ 19 - 19
htdocs/contact/list.php

@@ -158,8 +158,8 @@ $fieldstosearchall = array(
 	'p.phone_perso'=>"PhonePerso",
 	'p.phone_mobile'=>"PhoneMobile",
 	'p.fax'=>"Fax",
-    'p.note_public'=>"NotePublic",
-    'p.note_private'=>"NotePrivate",
+	'p.note_public'=>"NotePublic",
+	'p.note_private'=>"NotePrivate",
 );
 
 // Definition of fields for list
@@ -541,7 +541,7 @@ $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
 $newcardbutton = '';
 if ($user->rights->societe->contact->creer)
 {
-    $newcardbutton .= dolGetButtonTitle($langs->trans('NewContactAddress'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/contact/card.php?action=create');
+	$newcardbutton .= dolGetButtonTitle($langs->trans('NewContactAddress'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/contact/card.php?action=create');
 }
 
 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'" name="formfilter">';
@@ -734,9 +734,9 @@ if (!empty($arrayfields['p.thirdparty']['checked']))
 if (!empty($arrayfields['p.priv']['checked']))
 {
 	print '<td class="liste_titre center">';
-    $selectarray = array('0'=>$langs->trans("ContactPublic"), '1'=>$langs->trans("ContactPrivate"));
-    print $form->selectarray('search_priv', $selectarray, $search_priv, 1);
-    print '</td>';
+	$selectarray = array('0'=>$langs->trans("ContactPublic"), '1'=>$langs->trans("ContactPrivate"));
+	print $form->selectarray('search_priv', $selectarray, $search_priv, 1);
+	print '</td>';
 }
 // Prospect level
 if (!empty($arrayfields['p.fk_prospectcontactlevel']['checked']))
@@ -808,7 +808,7 @@ if (!empty($arrayfields['p.town']['checked']))                print_liste_field_
 //if (! empty($arrayfields['state.nom']['checked']))           print_liste_field_titre($arrayfields['state.nom']['label'],$_SERVER["PHP_SELF"],"state.nom","",$param,'',$sortfield,$sortorder);
 //if (! empty($arrayfields['region.nom']['checked']))          print_liste_field_titre($arrayfields['region.nom']['label'],$_SERVER["PHP_SELF"],"region.nom","",$param,'',$sortfield,$sortorder);
 if (!empty($arrayfields['country.code_iso']['checked'])) {
-    print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "co.code_iso", "", $param, '', $sortfield, $sortorder, 'center ');
+	print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "co.code_iso", "", $param, '', $sortfield, $sortorder, 'center ');
 }
 if (!empty($arrayfields['p.phone']['checked']))               print_liste_field_titre($arrayfields['p.phone']['label'], $_SERVER["PHP_SELF"], "p.phone", $begin, $param, '', $sortfield, $sortorder);
 if (!empty($arrayfields['p.phone_perso']['checked']))         print_liste_field_titre($arrayfields['p.phone_perso']['label'], $_SERVER["PHP_SELF"], "p.phone_perso", $begin, $param, '', $sortfield, $sortorder);
@@ -831,24 +831,24 @@ if (!empty($arrayfields['p.fk_stcommcontact']['checked'])) 			print_liste_field_
 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
 // Hook fields
 $parameters = array(
-    'arrayfields'=>$arrayfields,
-    'param'=>$param,
-    'sortfield'=>$sortfield,
-    'sortorder'=>$sortorder,
+	'arrayfields'=>$arrayfields,
+	'param'=>$param,
+	'sortfield'=>$sortfield,
+	'sortorder'=>$sortorder,
 );
 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
 print $hookmanager->resPrint;
 if (!empty($arrayfields['p.datec']['checked'])) {
-    print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
+	print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
 }
 if (!empty($arrayfields['p.tms']['checked'])) {
-    print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
+	print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
 }
 if (!empty($arrayfields['p.statut']['checked'])) {
-    print_liste_field_titre($arrayfields['p.statut']['label'], $_SERVER["PHP_SELF"], "p.statut", "", $param, '', $sortfield, $sortorder, 'center ');
+	print_liste_field_titre($arrayfields['p.statut']['label'], $_SERVER["PHP_SELF"], "p.statut", "", $param, '', $sortfield, $sortorder, 'center ');
 }
 if (!empty($arrayfields['p.import_key']['checked'])) {
-    print_liste_field_titre($arrayfields['p.import_key']['label'], $_SERVER["PHP_SELF"], "p.import_key", "", $param, '', $sortfield, $sortorder, 'center ');
+	print_liste_field_titre($arrayfields['p.import_key']['label'], $_SERVER["PHP_SELF"], "p.import_key", "", $param, '', $sortfield, $sortorder, 'center ');
 }
 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
 print "</tr>\n";
@@ -986,15 +986,15 @@ while ($i < min($num, $limit))
 			}
 		}
 	}
-    // Company
+	// Company
 	if (!empty($arrayfields['p.thirdparty']['checked']))
 	{
 		print '<td>';
 		if ($obj->socid)
 		{
-		    $objsoc = new Societe($db);
-		    $objsoc->fetch($obj->socid);
-		    print $objsoc->getNomUrl(1);
+			$objsoc = new Societe($db);
+			$objsoc->fetch($obj->socid);
+			print $objsoc->getNomUrl(1);
 		} else print '&nbsp;';
 		print '</td>';
 		if (!$i) $totalarray['nbfield']++;

+ 14 - 14
htdocs/core/class/CMailFile.class.php

@@ -170,7 +170,7 @@ class CMailFile
 		$this->sendmode = '';
 		if (!empty($this->sendcontext)) {
 			$smtpContextKey = strtoupper($this->sendcontext);
-			$keyForSMTPSendMode = 'MAIN_MAIL_SENDMODE_' . $smtpContextKey;
+			$keyForSMTPSendMode = 'MAIN_MAIL_SENDMODE_'.$smtpContextKey;
 			$smtpContextSendMode = $conf->global->{$keyForSMTPSendMode};
 			if (!empty($smtpContextSendMode) && $smtpContextSendMode != 'default') {
 				$this->sendmode = $smtpContextSendMode;
@@ -443,9 +443,9 @@ class CMailFile
 
 			// Set the From address with an associative array
 			//$this->message->setFrom(array('john@doe.com' => 'John Doe'));
-			if (! empty($this->addr_from)) {
+			if (!empty($this->addr_from)) {
 				try {
-					if (! empty($conf->global->MAIN_FORCE_DISABLE_MAIL_SPOOFING)) {
+					if (!empty($conf->global->MAIN_FORCE_DISABLE_MAIL_SPOOFING)) {
 						// Prevent email spoofing for smtp server with a strict configuration
 						$regexp = '/([a-z0-9_\.\-\+])+\@(([a-z0-9\-])+\.)+([a-z0-9]{2,4})+/i'; // This regular expression extracts all emails from a string
 						$emailMatchs = preg_match_all($regexp, $from, $adressEmailFrom);
@@ -465,7 +465,7 @@ class CMailFile
 			}
 
 			// Set the To addresses with an associative array
-			if (! empty($this->addr_to)) {
+			if (!empty($this->addr_to)) {
 				try {
 					$result = $this->message->setTo($this->getArrayAddress($this->addr_to));
 				} catch (Exception $e) {
@@ -473,7 +473,7 @@ class CMailFile
 				}
 			}
 
-			if (! empty($this->reply_to)) {
+			if (!empty($this->reply_to)) {
 				try {
 					$result = $this->message->SetReplyTo($this->getArrayAddress($this->reply_to));
 				} catch (Exception $e) {
@@ -529,8 +529,8 @@ class CMailFile
 				}
 			}
 
-			if (! empty($this->addr_cc)) $this->message->setCc($this->getArrayAddress($this->addr_cc));
-			if (! empty($this->addr_bcc)) $this->message->setBcc($this->getArrayAddress($this->addr_bcc));
+			if (!empty($this->addr_cc)) $this->message->setCc($this->getArrayAddress($this->addr_cc));
+			if (!empty($this->addr_bcc)) $this->message->setBcc($this->getArrayAddress($this->addr_bcc));
 			//if (! empty($this->errors_to)) $this->message->setErrorsTo($this->getArrayAddress($this->errors_to));
 			if (isset($this->deliveryreceipt) && $this->deliveryreceipt == 1) $this->message->setReadReceiptTo($this->getArrayAddress($this->addr_from));
 		} else {
@@ -641,15 +641,15 @@ class CMailFile
 			$keyforstarttls  = 'MAIN_MAIL_EMAIL_STARTTLS';
 			if (!empty($this->sendcontext)) {
 				$smtpContextKey = strtoupper($this->sendcontext);
-				$keyForSMTPSendMode = 'MAIN_MAIL_SENDMODE_' . $smtpContextKey;
+				$keyForSMTPSendMode = 'MAIN_MAIL_SENDMODE_'.$smtpContextKey;
 				$smtpContextSendMode = $conf->global->{$keyForSMTPSendMode};
 				if (!empty($smtpContextSendMode) && $smtpContextSendMode != 'default') {
-					$keyforsmtpserver = 'MAIN_MAIL_SMTP_SERVER_' . $smtpContextKey;
-					$keyforsmtpport   = 'MAIN_MAIL_SMTP_PORT_' . $smtpContextKey;
-					$keyforsmtpid     = 'MAIN_MAIL_SMTPS_ID_' . $smtpContextKey;
-					$keyforsmtppw     = 'MAIN_MAIL_SMTPS_PW_' . $smtpContextKey;
-					$keyfortls        = 'MAIN_MAIL_EMAIL_TLS_' . $smtpContextKey;
-					$keyforstarttls   = 'MAIN_MAIL_EMAIL_STARTTLS_' . $smtpContextKey;
+					$keyforsmtpserver = 'MAIN_MAIL_SMTP_SERVER_'.$smtpContextKey;
+					$keyforsmtpport   = 'MAIN_MAIL_SMTP_PORT_'.$smtpContextKey;
+					$keyforsmtpid     = 'MAIN_MAIL_SMTPS_ID_'.$smtpContextKey;
+					$keyforsmtppw     = 'MAIN_MAIL_SMTPS_PW_'.$smtpContextKey;
+					$keyfortls        = 'MAIN_MAIL_EMAIL_TLS_'.$smtpContextKey;
+					$keyforstarttls   = 'MAIN_MAIL_EMAIL_STARTTLS_'.$smtpContextKey;
 				}
 			}
 

+ 264 - 264
htdocs/core/class/commonobject.class.php

@@ -4567,245 +4567,245 @@ abstract class CommonObject
 
 		if (empty($reshook))
 		{
-		    dol_syslog("commonGenerateDocument modele=".$modele." outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null'));
-
-		    // Increase limit for PDF build
-		    $err = error_reporting();
-		    error_reporting(0);
-		    @set_time_limit(120);
-		    error_reporting($err);
-
-		    // If selected model is a filename template (then $modele="modelname" or "modelname:filename")
-		    $tmp = explode(':', $modele, 2);
-		    if (!empty($tmp[1]))
-		    {
-			    $modele = $tmp[0];
-			    $srctemplatepath = $tmp[1];
-		    }
-
-		    // Search template files
+			dol_syslog("commonGenerateDocument modele=".$modele." outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null'));
+
+			// Increase limit for PDF build
+			$err = error_reporting();
+			error_reporting(0);
+			@set_time_limit(120);
+			error_reporting($err);
+
+			// If selected model is a filename template (then $modele="modelname" or "modelname:filename")
+			$tmp = explode(':', $modele, 2);
+			if (!empty($tmp[1]))
+			{
+				$modele = $tmp[0];
+				$srctemplatepath = $tmp[1];
+			}
+
+			// Search template files
 			$file = '';
 			$classname = '';
 			$filefound = '';
-		    $dirmodels = array('/');
-		    if (is_array($conf->modules_parts['models'])) $dirmodels = array_merge($dirmodels, $conf->modules_parts['models']);
-		    foreach ($dirmodels as $reldir)
-		    {
-			    foreach (array('doc', 'pdf') as $prefix)
-			    {
-				    if (in_array(get_class($this), array('Adherent'))) $file = $prefix."_".$modele.".class.php"; // Member module use prefix_module.class.php
-				    else $file = $prefix."_".$modele.".modules.php";
-
-				    // On verifie l'emplacement du modele
-				    $file = dol_buildpath($reldir.$modelspath.$file, 0);
-				    if (file_exists($file))
-				    {
-					    $filefound = $file;
-					    $classname = $prefix.'_'.$modele;
-					    break;
-				    }
-			    }
-			    if ($filefound) break;
-		    }
-
-		    // If generator was found
-		    if ($filefound)
-		    {
-			    global $db; // Required to solve a conception default making an include of code using $db instead of $this->db just after.
-
-			    require_once $file;
-
-			    $obj = new $classname($this->db);
-
-			    // If generator is ODT, we must have srctemplatepath defined, if not we set it.
-			    if ($obj->type == 'odt' && empty($srctemplatepath))
-			    {
-				    $varfortemplatedir = $obj->scandir;
-				    if ($varfortemplatedir && !empty($conf->global->$varfortemplatedir))
-				    {
-					    $dirtoscan = $conf->global->$varfortemplatedir;
-
-					    $listoffiles = array();
-
-					    // Now we add first model found in directories scanned
-					    $listofdir = explode(',', $dirtoscan);
-					    foreach ($listofdir as $key => $tmpdir)
-					    {
-						    $tmpdir = trim($tmpdir);
-						    $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
-						    if (!$tmpdir) { unset($listofdir[$key]); continue; }
-						    if (is_dir($tmpdir))
-						    {
-							    $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.od(s|t)$', '', 'name', SORT_ASC, 0);
-							    if (count($tmpfiles)) $listoffiles = array_merge($listoffiles, $tmpfiles);
-						    }
-					    }
-
-					    if (count($listoffiles))
-					    {
-						    foreach ($listoffiles as $record)
-						    {
-							    $srctemplatepath = $record['fullname'];
-							    break;
-						    }
-					    }
-				    }
-
-				    if (empty($srctemplatepath))
-				    {
-					    $this->error = 'ErrorGenerationAskedForOdtTemplateWithSrcFileNotDefined';
-					    return -1;
-				    }
-			    }
-
-			    if ($obj->type == 'odt' && !empty($srctemplatepath))
-			    {
-				    if (!dol_is_file($srctemplatepath))
-				    {
-				    	dol_syslog("Failed to locate template file ".$srctemplatepath, LOG_WARNING);
-					    $this->error = 'ErrorGenerationAskedForOdtTemplateWithSrcFileNotFound';
-					    return -1;
-				    }
-			    }
-
-			    // We save charset_output to restore it because write_file can change it if needed for
-			    // output format that does not support UTF8.
-			    $sav_charset_output = $outputlangs->charset_output;
-
-			    if (in_array(get_class($this), array('Adherent')))
-			    {
-				    $arrayofrecords = array(); // The write_file of templates of adherent class need this var
-				    $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, 'member', 1, $moreparams);
-			    } else {
-				     $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, $hidedetails, $hidedesc, $hideref, $moreparams);
-			    }
-			    // After call of write_file $obj->result['fullpath'] is set with generated file. It will be used to update the ECM database index.
-
-			    if ($resultwritefile > 0)
-			    {
-				    $outputlangs->charset_output = $sav_charset_output;
-
-				    // We delete old preview
-				    require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
-				    dol_delete_preview($this);
-
-				    // Index file in database
-				    if (!empty($obj->result['fullpath']))
-				    {
-					    $destfull = $obj->result['fullpath'];
-					    $upload_dir = dirname($destfull);
-					    $destfile = basename($destfull);
-					    $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $upload_dir);
-
-					    if (!preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir))     // If not a tmp dir
-					    {
-						    $filename = basename($destfile);
-						    $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
-						    $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
-
-						    include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
-						    $ecmfile = new EcmFiles($this->db);
-						    $result = $ecmfile->fetch(0, '', ($rel_dir ? $rel_dir.'/' : '').$filename);
-
-						     // Set the public "share" key
-						    $setsharekey = false;
-						    if ($this->element == 'propal')
-						    {
-							    $useonlinesignature = $conf->global->MAIN_FEATURES_LEVEL; // Replace this with 1 when feature to make online signature is ok
-							    if ($useonlinesignature) $setsharekey = true;
-							    if (!empty($conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD)) $setsharekey = true;
-						    }
-						    if ($this->element == 'commande' && !empty($conf->global->ORDER_ALLOW_EXTERNAL_DOWNLOAD)) {
-							    $setsharekey = true;
-						    }
-						    if ($this->element == 'facture' && !empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD)) {
-							    $setsharekey = true;
-						    }
-						    if ($this->element == 'bank_account' && !empty($conf->global->BANK_ACCOUNT_ALLOW_EXTERNAL_DOWNLOAD)) {
-							    $setsharekey = true;
-						    }
-
-						    if ($setsharekey) {
-							    if (empty($ecmfile->share))	// Because object not found or share not set yet
-							    {
-								    require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
-								    $ecmfile->share = getRandomPassword(true);
-							    }
-						    }
-
-						    if ($result > 0)
-						     {
-							    $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
-							    $ecmfile->fullpath_orig = '';
-							    $ecmfile->gen_or_uploaded = 'generated';
-							    $ecmfile->description = ''; // indexed content
-							    $ecmfile->keyword = ''; // keyword content
-							    $result = $ecmfile->update($user);
-							    if ($result < 0) {
-								    setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
-							    }
-						    } else {
-							    $ecmfile->entity = $conf->entity;
-							    $ecmfile->filepath = $rel_dir;
-							    $ecmfile->filename = $filename;
-							    $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
-							    $ecmfile->fullpath_orig = '';
-							    $ecmfile->gen_or_uploaded = 'generated';
-							    $ecmfile->description = ''; // indexed content
-							    $ecmfile->keyword = ''; // keyword content
-							    $ecmfile->src_object_type = $this->table_element;
-							    $ecmfile->src_object_id   = $this->id;
-
-							    $result = $ecmfile->create($user);
-							    if ($result < 0) {
-								    setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
-							    }
-						    }
-
-						    /*$this->result['fullname']=$destfull;
+			$dirmodels = array('/');
+			if (is_array($conf->modules_parts['models'])) $dirmodels = array_merge($dirmodels, $conf->modules_parts['models']);
+			foreach ($dirmodels as $reldir)
+			{
+				foreach (array('doc', 'pdf') as $prefix)
+				{
+					if (in_array(get_class($this), array('Adherent'))) $file = $prefix."_".$modele.".class.php"; // Member module use prefix_module.class.php
+					else $file = $prefix."_".$modele.".modules.php";
+
+					// On verifie l'emplacement du modele
+					$file = dol_buildpath($reldir.$modelspath.$file, 0);
+					if (file_exists($file))
+					{
+						$filefound = $file;
+						$classname = $prefix.'_'.$modele;
+						break;
+					}
+				}
+				if ($filefound) break;
+			}
+
+			// If generator was found
+			if ($filefound)
+			{
+				global $db; // Required to solve a conception default making an include of code using $db instead of $this->db just after.
+
+				require_once $file;
+
+				$obj = new $classname($this->db);
+
+				// If generator is ODT, we must have srctemplatepath defined, if not we set it.
+				if ($obj->type == 'odt' && empty($srctemplatepath))
+				{
+					$varfortemplatedir = $obj->scandir;
+					if ($varfortemplatedir && !empty($conf->global->$varfortemplatedir))
+					{
+						$dirtoscan = $conf->global->$varfortemplatedir;
+
+						$listoffiles = array();
+
+						// Now we add first model found in directories scanned
+						$listofdir = explode(',', $dirtoscan);
+						foreach ($listofdir as $key => $tmpdir)
+						{
+							$tmpdir = trim($tmpdir);
+							$tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
+							if (!$tmpdir) { unset($listofdir[$key]); continue; }
+							if (is_dir($tmpdir))
+							{
+								$tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.od(s|t)$', '', 'name', SORT_ASC, 0);
+								if (count($tmpfiles)) $listoffiles = array_merge($listoffiles, $tmpfiles);
+							}
+						}
+
+						if (count($listoffiles))
+						{
+							foreach ($listoffiles as $record)
+							{
+								$srctemplatepath = $record['fullname'];
+								break;
+							}
+						}
+					}
+
+					if (empty($srctemplatepath))
+					{
+						$this->error = 'ErrorGenerationAskedForOdtTemplateWithSrcFileNotDefined';
+						return -1;
+					}
+				}
+
+				if ($obj->type == 'odt' && !empty($srctemplatepath))
+				{
+					if (!dol_is_file($srctemplatepath))
+					{
+						dol_syslog("Failed to locate template file ".$srctemplatepath, LOG_WARNING);
+						$this->error = 'ErrorGenerationAskedForOdtTemplateWithSrcFileNotFound';
+						return -1;
+					}
+				}
+
+				// We save charset_output to restore it because write_file can change it if needed for
+				// output format that does not support UTF8.
+				$sav_charset_output = $outputlangs->charset_output;
+
+				if (in_array(get_class($this), array('Adherent')))
+				{
+					$arrayofrecords = array(); // The write_file of templates of adherent class need this var
+					$resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, 'member', 1, $moreparams);
+				} else {
+					 $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, $hidedetails, $hidedesc, $hideref, $moreparams);
+				}
+				// After call of write_file $obj->result['fullpath'] is set with generated file. It will be used to update the ECM database index.
+
+				if ($resultwritefile > 0)
+				{
+					$outputlangs->charset_output = $sav_charset_output;
+
+					// We delete old preview
+					require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+					dol_delete_preview($this);
+
+					// Index file in database
+					if (!empty($obj->result['fullpath']))
+					{
+						$destfull = $obj->result['fullpath'];
+						$upload_dir = dirname($destfull);
+						$destfile = basename($destfull);
+						$rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $upload_dir);
+
+						if (!preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir))     // If not a tmp dir
+						{
+							$filename = basename($destfile);
+							$rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
+							$rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
+
+							include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
+							$ecmfile = new EcmFiles($this->db);
+							$result = $ecmfile->fetch(0, '', ($rel_dir ? $rel_dir.'/' : '').$filename);
+
+							 // Set the public "share" key
+							$setsharekey = false;
+							if ($this->element == 'propal')
+							{
+								$useonlinesignature = $conf->global->MAIN_FEATURES_LEVEL; // Replace this with 1 when feature to make online signature is ok
+								if ($useonlinesignature) $setsharekey = true;
+								if (!empty($conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD)) $setsharekey = true;
+							}
+							if ($this->element == 'commande' && !empty($conf->global->ORDER_ALLOW_EXTERNAL_DOWNLOAD)) {
+								$setsharekey = true;
+							}
+							if ($this->element == 'facture' && !empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD)) {
+								$setsharekey = true;
+							}
+							if ($this->element == 'bank_account' && !empty($conf->global->BANK_ACCOUNT_ALLOW_EXTERNAL_DOWNLOAD)) {
+								$setsharekey = true;
+							}
+
+							if ($setsharekey) {
+								if (empty($ecmfile->share))	// Because object not found or share not set yet
+								{
+									require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
+									$ecmfile->share = getRandomPassword(true);
+								}
+							}
+
+							if ($result > 0)
+							 {
+								$ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
+								$ecmfile->fullpath_orig = '';
+								$ecmfile->gen_or_uploaded = 'generated';
+								$ecmfile->description = ''; // indexed content
+								$ecmfile->keyword = ''; // keyword content
+								$result = $ecmfile->update($user);
+								if ($result < 0) {
+									setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
+								}
+							} else {
+								$ecmfile->entity = $conf->entity;
+								$ecmfile->filepath = $rel_dir;
+								$ecmfile->filename = $filename;
+								$ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content
+								$ecmfile->fullpath_orig = '';
+								$ecmfile->gen_or_uploaded = 'generated';
+								$ecmfile->description = ''; // indexed content
+								$ecmfile->keyword = ''; // keyword content
+								$ecmfile->src_object_type = $this->table_element;
+								$ecmfile->src_object_id   = $this->id;
+
+								$result = $ecmfile->create($user);
+								if ($result < 0) {
+									setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
+								}
+							}
+
+							/*$this->result['fullname']=$destfull;
 						    $this->result['filepath']=$ecmfile->filepath;
 						    $this->result['filename']=$ecmfile->filename;*/
-						    //var_dump($obj->update_main_doc_field);exit;
-
-						    // Update the last_main_doc field into main object (if documenent generator has property ->update_main_doc_field set)
-						    $update_main_doc_field = 0;
-						    if (!empty($obj->update_main_doc_field)) $update_main_doc_field = 1;
-						    if ($update_main_doc_field && !empty($this->table_element))
-						    {
-							    $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element." SET last_main_doc = '".$this->db->escape($ecmfile->filepath.'/'.$ecmfile->filename)."'";
-							    $sql .= ' WHERE rowid = '.$this->id;
-
-							    $resql = $this->db->query($sql);
-							    if (!$resql) {
+							//var_dump($obj->update_main_doc_field);exit;
+
+							// Update the last_main_doc field into main object (if documenent generator has property ->update_main_doc_field set)
+							$update_main_doc_field = 0;
+							if (!empty($obj->update_main_doc_field)) $update_main_doc_field = 1;
+							if ($update_main_doc_field && !empty($this->table_element))
+							{
+								$sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element." SET last_main_doc = '".$this->db->escape($ecmfile->filepath.'/'.$ecmfile->filename)."'";
+								$sql .= ' WHERE rowid = '.$this->id;
+
+								$resql = $this->db->query($sql);
+								if (!$resql) {
 									dol_print_error($this->db);
 								} else {
-							        $this->last_main_doc = $ecmfile->filepath.'/'.$ecmfile->filename;
-							    }
-						    }
-					    }
-				    } else {
-					    dol_syslog('Method ->write_file was called on object '.get_class($obj).' and return a success but the return array ->result["fullpath"] was not set.', LOG_WARNING);
-				    }
-
-				    // Success in building document. We build meta file.
-				    dol_meta_create($this);
-
-				    return 1;
-			    } else {
-				    $outputlangs->charset_output = $sav_charset_output;
-				    dol_print_error($this->db, "Error generating document for ".__CLASS__.". Error: ".$obj->error, $obj->errors);
-				    return -1;
-			    }
-		    } else {
-		    	if (!$filefound) {
-			    	$this->error = $langs->trans("Error").' Failed to load doc generator with modelpaths='.$modelspath.' - modele='.$modele;
-			    	dol_print_error('', $this->error);
-		    	} else {
-		    		$this->error = $langs->trans("Error")." ".$langs->trans("ErrorFileDoesNotExists", $filefound);
-		    		dol_print_error('', $this->error);
-		    	}
-			    return -1;
-		    }
+									$this->last_main_doc = $ecmfile->filepath.'/'.$ecmfile->filename;
+								}
+							}
+						}
+					} else {
+						dol_syslog('Method ->write_file was called on object '.get_class($obj).' and return a success but the return array ->result["fullpath"] was not set.', LOG_WARNING);
+					}
+
+					// Success in building document. We build meta file.
+					dol_meta_create($this);
+
+					return 1;
+				} else {
+					$outputlangs->charset_output = $sav_charset_output;
+					dol_print_error($this->db, "Error generating document for ".__CLASS__.". Error: ".$obj->error, $obj->errors);
+					return -1;
+				}
+			} else {
+				if (!$filefound) {
+					$this->error = $langs->trans("Error").' Failed to load doc generator with modelpaths='.$modelspath.' - modele='.$modele;
+					dol_print_error('', $this->error);
+				} else {
+					$this->error = $langs->trans("Error")." ".$langs->trans("ErrorFileDoesNotExists", $filefound);
+					dol_print_error('', $this->error);
+				}
+				return -1;
+			}
 		} else return $reshook;
 	}
 
@@ -7987,46 +7987,46 @@ abstract class CommonObject
 
 		// Delete cascade first
 		if (is_array($this->childtablesoncascade) && !empty($this->childtablesoncascade)) {
-            foreach ($this->childtablesoncascade as $table)
-            {
-	            $deleteFromObject = explode(':', $table);
-	            if (count($deleteFromObject) >= 2) {
-		            $className = str_replace('@', '', $deleteFromObject[0]);
-		            $filePath = $deleteFromObject[1];
-		            $columnName = $deleteFromObject[2];
-		            if (dol_include_once($filePath)) {
-			            $childObject = new $className($this->db);
-			            if (method_exists($childObject, 'deleteByParentField')) {
-				            $result = $childObject->deleteByParentField($this->id, $columnName);
-				            if ($result < 0) {
+			foreach ($this->childtablesoncascade as $table)
+			{
+				$deleteFromObject = explode(':', $table);
+				if (count($deleteFromObject) >= 2) {
+					$className = str_replace('@', '', $deleteFromObject[0]);
+					$filePath = $deleteFromObject[1];
+					$columnName = $deleteFromObject[2];
+					if (dol_include_once($filePath)) {
+						$childObject = new $className($this->db);
+						if (method_exists($childObject, 'deleteByParentField')) {
+							$result = $childObject->deleteByParentField($this->id, $columnName);
+							if ($result < 0) {
 								$error++;
-					            $this->errors[] = $childObject->error;
-					            break;
-				            }
-			            } else {
+								$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++;
+					} else {
+						$error++;
 						$this->errors[] = 'Cannot include child class file '.$filePath;
-			            break;
-		            }
-	            } else {
-	            	// Delete record in child table
-	            	$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$table.' WHERE '.$this->fk_element.' = '.$this->id;
-
-		            $resql = $this->db->query($sql);
-		            if (!$resql) {
+						break;
+					}
+				} else {
+					// Delete record in child table
+					$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->error = $this->db->lasterror();
+						$this->errors[] = $this->error;
 						break;
-		            }
-	            }
-            }
-        }
+					}
+				}
+			}
+		}
 
 		if (!$error) {
 			if (!$notrigger) {

+ 381 - 381
htdocs/core/class/coreobject.class.php

@@ -31,385 +31,385 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  */
 class CoreObject extends CommonObject
 {
-    public $withChild = true;
-
-    /**
-     *  @var Array $_fields Fields to synchronize with Database
-     */
-    protected $fields = array();
-
-    /**
-     *  Constructor
-     *
-     *  @param      DoliDB		$db      Database handler
-     */
-    public function __construct(DoliDB &$db)
-    {
-        $this->db = $db;
-    }
-
-    /**
-     * Function to init fields
-     *
-     * @return bool
-     */
-    protected function init()
-    {
-        $this->id = 0;
-        $this->datec = 0;
-        $this->tms = 0;
-
-        if (!empty($this->fields))
-        {
-            foreach ($this->fields as $field=>$info)
-            {
-                if ($this->isDate($info)) $this->{$field} = time();
-                elseif ($this->isArray($info)) $this->{$field} = array();
-                elseif ($this->isInt($info)) $this->{$field} = (int) 0;
-                elseif ($this->isFloat($info)) $this->{$field} = (double) 0;
-                else $this->{$field} = '';
-            }
-
-            $this->to_delete = false;
-            $this->is_clone = false;
-
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Test type of field
-     *
-     * @param   string  $field  name of field
-     * @param   string  $type   type of field to test
-     * @return  boolean         value of field or false
-     */
-    private function checkFieldType($field, $type)
-    {
-        if (isset($this->fields[$field]) && method_exists($this, 'is_'.$type))
-        {
-            return $this->{'is_'.$type}($this->fields[$field]);
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     *	Get object and children from database
-     *
-     *	@param      int			$id       		Id of object to load
-     * 	@param		bool		$loadChild		used to load children from database
-     *	@return     int         				>0 if OK, <0 if KO, 0 if not found
-     */
-    public function fetch($id, $loadChild = true)
-    {
-        $res = $this->fetchCommon($id);
-        if ($res > 0) {
-            if ($loadChild) $this->fetchChild();
-        }
-
-        return $res;
-    }
-
-
-    /**
-     * Function to instantiate a new child
-     *
-     * @param   string  $tabName        Table name of child
-     * @param   int     $id             If id is given, we try to return his key if exist or load if we try_to_load
-     * @param   string  $key            Attribute name of the object id
-     * @param   bool    $try_to_load    Force the fetch if an id is given
-     * @return                          int
-     */
-    public function addChild($tabName, $id = 0, $key = 'id', $try_to_load = false)
-    {
-        if (!empty($id))
-        {
-            foreach ($this->{$tabName} as $k=>&$object)
-            {
-                if ($object->{$key} === $id) return $k;
-            }
-        }
-
-        $k = count($this->{$tabName});
-
-        $className = ucfirst($tabName);
-        $this->{$tabName}[$k] = new $className($this->db);
-        if ($id > 0 && $key === 'id' && $try_to_load)
-        {
-            $this->{$tabName}[$k]->fetch($id);
-        }
-
-        return $k;
-    }
-
-
-    /**
-     * Function to set a child as to delete
-     *
-     * @param   string  $tabName        Table name of child
-     * @param   int     $id             Id of child to set as to delete
-     * @param   string  $key            Attribute name of the object id
-     * @return                          bool
-     */
-    public function removeChild($tabName, $id, $key = 'id')
-    {
-        foreach ($this->{$tabName} as &$object)
-        {
-            if ($object->{$key} == $id)
-            {
-                $object->to_delete = true;
-                return true;
-            }
-        }
-        return false;
-    }
-
-
-    /**
-     * Function to fetch children objects
-     *
-     * @return void
-     */
-    public function fetchChild()
-    {
-        if ($this->withChild && !empty($this->childtables) && !empty($this->fk_element))
-        {
-            foreach ($this->childtables as &$childTable)
-            {
-                $className = ucfirst($childTable);
-
-                $this->{$className} = array();
-
-                $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.$childTable.' WHERE '.$this->fk_element.' = '.$this->id;
-                $res = $this->db->query($sql);
-
-                if ($res)
-                {
-                    while ($obj = $this->db->fetch_object($res))
-                    {
-                        $o = new $className($this->db);
-                        $o->fetch($obj->rowid);
-
-                        $this->{$className}[] = $o;
-                    }
-                } else {
-                    $this->errors[] = $this->db->lasterror();
-                }
-            }
-        }
-    }
-
-    /**
-     * Function to update children data
-     *
-     * @param   User    $user   user object
-     * @return void
-     */
-    public function saveChild(User &$user)
-    {
-        if ($this->withChild && !empty($this->childtables) && !empty($this->fk_element))
-        {
-            foreach ($this->childtables as &$childTable)
-            {
-                $className = ucfirst($childTable);
-                if (!empty($this->{$className}))
-                {
-                    foreach ($this->{$className} as $i => &$object)
-                    {
-                        $object->{$this->fk_element} = $this->id;
-
-                        $object->update($user);
-                        if ($this->unsetChildDeleted && isset($object->to_delete) && $object->to_delete == true) unset($this->{$className}[$i]);
-                    }
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Function to update object or create or delete if needed
-     *
-     * @param   User    $user   User object
-     * @return  int             < 0 if KO, > 0 if OK
-     */
-    public function update(User &$user)
-    {
-        if (empty($this->id)) return $this->create($user); // To test, with that, no need to test on high level object, the core decide it, update just needed
-        elseif (isset($this->to_delete) && $this->to_delete == true) return $this->delete($user);
-
-        $error = 0;
-        $this->db->begin();
-
-        $res = $this->updateCommon($user);
-        if ($res)
-        {
-            $result = $this->call_trigger(strtoupper($this->element).'_UPDATE', $user);
-            if ($result < 0) $error++;
-            else $this->saveChild($user);
-        } else {
-            $error++;
-            $this->error = $this->db->lasterror();
-            $this->errors[] = $this->error;
-        }
-
-        if (empty($error))
-        {
-            $this->db->commit();
-            return $this->id;
-        } else {
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-    /**
-     * Function to create object in database
-     *
-     * @param   User    $user   User object
-     * @return  int             < 0 if KO, > 0 if OK
-     */
-    public function create(User $user)
-    {
-        if ($this->id > 0) return $this->update($user);
-
-        $error = 0;
-        $this->db->begin();
-
-        $res = $this->createCommon($user);
-        if ($res)
-        {
-            $this->id = $this->db->last_insert_id($this->table_element);
-
-            $result = $this->call_trigger(strtoupper($this->element).'_CREATE', $user);
-            if ($result < 0) $error++;
-            else $this->saveChild($user);
-        } else {
-            $error++;
-            $this->error = $this->db->lasterror();
-            $this->errors[] = $this->error;
-        }
-
-        if (empty($error))
-        {
-            $this->db->commit();
-            return $this->id;
-        } else {
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-    /**
-     * Function to delete object in database
-     *
-     * @param   User    $user   user object
-     * @return  int             < 0 if KO, > 0 if OK
-     */
-    public function delete(User &$user)
-    {
-        if ($this->id <= 0) return 0;
-
-        $error = 0;
-        $this->db->begin();
-
-        $result = $this->call_trigger(strtoupper($this->element).'_DELETE', $user);
-        if ($result < 0) $error++;
-
-        if (!$error)
-        {
-            $this->deleteCommon($user);
-            if ($this->withChild && !empty($this->childtables))
-            {
-                foreach ($this->childtables as &$childTable)
-                {
-                    $className = ucfirst($childTable);
-                    if (!empty($this->{$className}))
-                    {
-                        foreach ($this->{$className} as &$object)
-                        {
-                            $object->delete($user);
-                        }
-                    }
-                }
-            }
-        }
-
-        if (empty($error))
-        {
-            $this->db->commit();
-            return 1;
-        } else {
-            $this->error = $this->db->lasterror();
-            $this->errors[] = $this->error;
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-
-    /**
-     * Function to get a formatted date
-     *
-     * @param   string  $field  Attribute to return
-     * @param   string  $format Output date format
-     * @return          string
-     */
-    public function getDate($field, $format = '')
-    {
-        if (empty($this->{$field})) return '';
-        else {
-            return dol_print_date($this->{$field}, $format);
-        }
-    }
-
-    /**
-     * Function to set date in field
-     *
-     * @param   string  $field  field to set
-     * @param   string  $date   formatted date to convert
-     * @return                  mixed
-     */
-    public function setDate($field, $date)
-    {
-        if (empty($date))
-        {
-            $this->{$field} = 0;
-        } else {
-            require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
-            $this->{$field} = dol_stringtotime($date);
-        }
-
-        return $this->{$field};
-    }
-
-
-    /**
-     * Function to update current object
-     *
-     * @param   array   $Tab    Array of values
-     * @return                  int
-     */
-    public function setValues(&$Tab)
-    {
-        foreach ($Tab as $key => $value)
-        {
-            if ($this->checkFieldType($key, 'date'))
-            {
-                $this->setDate($key, $value);
-            } elseif ($this->checkFieldType($key, 'float'))
-            {
-                $this->{$key} = (double) price2num($value);
-            } elseif ($this->checkFieldType($key, 'int')) {
-                $this->{$key} = (int) price2num($value);
-            } else {
-            	$this->{$key} = dol_string_nohtmltag($value);
-            }
-        }
-
-        return 1;
-    }
+	public $withChild = true;
+
+	/**
+	 *  @var Array $_fields Fields to synchronize with Database
+	 */
+	protected $fields = array();
+
+	/**
+	 *  Constructor
+	 *
+	 *  @param      DoliDB		$db      Database handler
+	 */
+	public function __construct(DoliDB &$db)
+	{
+		$this->db = $db;
+	}
+
+	/**
+	 * Function to init fields
+	 *
+	 * @return bool
+	 */
+	protected function init()
+	{
+		$this->id = 0;
+		$this->datec = 0;
+		$this->tms = 0;
+
+		if (!empty($this->fields))
+		{
+			foreach ($this->fields as $field=>$info)
+			{
+				if ($this->isDate($info)) $this->{$field} = time();
+				elseif ($this->isArray($info)) $this->{$field} = array();
+				elseif ($this->isInt($info)) $this->{$field} = (int) 0;
+				elseif ($this->isFloat($info)) $this->{$field} = (double) 0;
+				else $this->{$field} = '';
+			}
+
+			$this->to_delete = false;
+			$this->is_clone = false;
+
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Test type of field
+	 *
+	 * @param   string  $field  name of field
+	 * @param   string  $type   type of field to test
+	 * @return  boolean         value of field or false
+	 */
+	private function checkFieldType($field, $type)
+	{
+		if (isset($this->fields[$field]) && method_exists($this, 'is_'.$type))
+		{
+			return $this->{'is_'.$type}($this->fields[$field]);
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 *	Get object and children from database
+	 *
+	 *	@param      int			$id       		Id of object to load
+	 * 	@param		bool		$loadChild		used to load children from database
+	 *	@return     int         				>0 if OK, <0 if KO, 0 if not found
+	 */
+	public function fetch($id, $loadChild = true)
+	{
+		$res = $this->fetchCommon($id);
+		if ($res > 0) {
+			if ($loadChild) $this->fetchChild();
+		}
+
+		return $res;
+	}
+
+
+	/**
+	 * Function to instantiate a new child
+	 *
+	 * @param   string  $tabName        Table name of child
+	 * @param   int     $id             If id is given, we try to return his key if exist or load if we try_to_load
+	 * @param   string  $key            Attribute name of the object id
+	 * @param   bool    $try_to_load    Force the fetch if an id is given
+	 * @return                          int
+	 */
+	public function addChild($tabName, $id = 0, $key = 'id', $try_to_load = false)
+	{
+		if (!empty($id))
+		{
+			foreach ($this->{$tabName} as $k=>&$object)
+			{
+				if ($object->{$key} === $id) return $k;
+			}
+		}
+
+		$k = count($this->{$tabName});
+
+		$className = ucfirst($tabName);
+		$this->{$tabName}[$k] = new $className($this->db);
+		if ($id > 0 && $key === 'id' && $try_to_load)
+		{
+			$this->{$tabName}[$k]->fetch($id);
+		}
+
+		return $k;
+	}
+
+
+	/**
+	 * Function to set a child as to delete
+	 *
+	 * @param   string  $tabName        Table name of child
+	 * @param   int     $id             Id of child to set as to delete
+	 * @param   string  $key            Attribute name of the object id
+	 * @return                          bool
+	 */
+	public function removeChild($tabName, $id, $key = 'id')
+	{
+		foreach ($this->{$tabName} as &$object)
+		{
+			if ($object->{$key} == $id)
+			{
+				$object->to_delete = true;
+				return true;
+			}
+		}
+		return false;
+	}
+
+
+	/**
+	 * Function to fetch children objects
+	 *
+	 * @return void
+	 */
+	public function fetchChild()
+	{
+		if ($this->withChild && !empty($this->childtables) && !empty($this->fk_element))
+		{
+			foreach ($this->childtables as &$childTable)
+			{
+				$className = ucfirst($childTable);
+
+				$this->{$className} = array();
+
+				$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.$childTable.' WHERE '.$this->fk_element.' = '.$this->id;
+				$res = $this->db->query($sql);
+
+				if ($res)
+				{
+					while ($obj = $this->db->fetch_object($res))
+					{
+						$o = new $className($this->db);
+						$o->fetch($obj->rowid);
+
+						$this->{$className}[] = $o;
+					}
+				} else {
+					$this->errors[] = $this->db->lasterror();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Function to update children data
+	 *
+	 * @param   User    $user   user object
+	 * @return void
+	 */
+	public function saveChild(User &$user)
+	{
+		if ($this->withChild && !empty($this->childtables) && !empty($this->fk_element))
+		{
+			foreach ($this->childtables as &$childTable)
+			{
+				$className = ucfirst($childTable);
+				if (!empty($this->{$className}))
+				{
+					foreach ($this->{$className} as $i => &$object)
+					{
+						$object->{$this->fk_element} = $this->id;
+
+						$object->update($user);
+						if ($this->unsetChildDeleted && isset($object->to_delete) && $object->to_delete == true) unset($this->{$className}[$i]);
+					}
+				}
+			}
+		}
+	}
+
+
+	/**
+	 * Function to update object or create or delete if needed
+	 *
+	 * @param   User    $user   User object
+	 * @return  int             < 0 if KO, > 0 if OK
+	 */
+	public function update(User &$user)
+	{
+		if (empty($this->id)) return $this->create($user); // To test, with that, no need to test on high level object, the core decide it, update just needed
+		elseif (isset($this->to_delete) && $this->to_delete == true) return $this->delete($user);
+
+		$error = 0;
+		$this->db->begin();
+
+		$res = $this->updateCommon($user);
+		if ($res)
+		{
+			$result = $this->call_trigger(strtoupper($this->element).'_UPDATE', $user);
+			if ($result < 0) $error++;
+			else $this->saveChild($user);
+		} else {
+			$error++;
+			$this->error = $this->db->lasterror();
+			$this->errors[] = $this->error;
+		}
+
+		if (empty($error))
+		{
+			$this->db->commit();
+			return $this->id;
+		} else {
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	/**
+	 * Function to create object in database
+	 *
+	 * @param   User    $user   User object
+	 * @return  int             < 0 if KO, > 0 if OK
+	 */
+	public function create(User $user)
+	{
+		if ($this->id > 0) return $this->update($user);
+
+		$error = 0;
+		$this->db->begin();
+
+		$res = $this->createCommon($user);
+		if ($res)
+		{
+			$this->id = $this->db->last_insert_id($this->table_element);
+
+			$result = $this->call_trigger(strtoupper($this->element).'_CREATE', $user);
+			if ($result < 0) $error++;
+			else $this->saveChild($user);
+		} else {
+			$error++;
+			$this->error = $this->db->lasterror();
+			$this->errors[] = $this->error;
+		}
+
+		if (empty($error))
+		{
+			$this->db->commit();
+			return $this->id;
+		} else {
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	/**
+	 * Function to delete object in database
+	 *
+	 * @param   User    $user   user object
+	 * @return  int             < 0 if KO, > 0 if OK
+	 */
+	public function delete(User &$user)
+	{
+		if ($this->id <= 0) return 0;
+
+		$error = 0;
+		$this->db->begin();
+
+		$result = $this->call_trigger(strtoupper($this->element).'_DELETE', $user);
+		if ($result < 0) $error++;
+
+		if (!$error)
+		{
+			$this->deleteCommon($user);
+			if ($this->withChild && !empty($this->childtables))
+			{
+				foreach ($this->childtables as &$childTable)
+				{
+					$className = ucfirst($childTable);
+					if (!empty($this->{$className}))
+					{
+						foreach ($this->{$className} as &$object)
+						{
+							$object->delete($user);
+						}
+					}
+				}
+			}
+		}
+
+		if (empty($error))
+		{
+			$this->db->commit();
+			return 1;
+		} else {
+			$this->error = $this->db->lasterror();
+			$this->errors[] = $this->error;
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+
+	/**
+	 * Function to get a formatted date
+	 *
+	 * @param   string  $field  Attribute to return
+	 * @param   string  $format Output date format
+	 * @return          string
+	 */
+	public function getDate($field, $format = '')
+	{
+		if (empty($this->{$field})) return '';
+		else {
+			return dol_print_date($this->{$field}, $format);
+		}
+	}
+
+	/**
+	 * Function to set date in field
+	 *
+	 * @param   string  $field  field to set
+	 * @param   string  $date   formatted date to convert
+	 * @return                  mixed
+	 */
+	public function setDate($field, $date)
+	{
+		if (empty($date))
+		{
+			$this->{$field} = 0;
+		} else {
+			require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+			$this->{$field} = dol_stringtotime($date);
+		}
+
+		return $this->{$field};
+	}
+
+
+	/**
+	 * Function to update current object
+	 *
+	 * @param   array   $Tab    Array of values
+	 * @return                  int
+	 */
+	public function setValues(&$Tab)
+	{
+		foreach ($Tab as $key => $value)
+		{
+			if ($this->checkFieldType($key, 'date'))
+			{
+				$this->setDate($key, $value);
+			} elseif ($this->checkFieldType($key, 'float'))
+			{
+				$this->{$key} = (double) price2num($value);
+			} elseif ($this->checkFieldType($key, 'int')) {
+				$this->{$key} = (int) price2num($value);
+			} else {
+				$this->{$key} = dol_string_nohtmltag($value);
+			}
+		}
+
+		return 1;
+	}
 }

File diff suppressed because it is too large
+ 415 - 415
htdocs/core/class/extrafields.class.php


+ 74 - 74
htdocs/core/class/html.form.class.php

@@ -647,7 +647,7 @@ class Form
 
 		$disabled = 0;
 		$ret = '<div class="centpercent center">';
-                $ret .= '<select class="flat'.(empty($conf->use_javascript_ajax) ? '' : ' hideobject').' '.$name.' '.$name.'select valignmiddle alignstart" name="'.$name.'"'.($disabled ? ' disabled="disabled"' : '').'>';
+				$ret .= '<select class="flat'.(empty($conf->use_javascript_ajax) ? '' : ' hideobject').' '.$name.' '.$name.'select valignmiddle alignstart" name="'.$name.'"'.($disabled ? ' disabled="disabled"' : '').'>';
 
 		// Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['currentcontext'] completed by executeHooks.
 		$parameters = array();
@@ -666,11 +666,11 @@ class Form
 
 		$ret .= '</select>';
 
-                if (empty($conf->dol_optimize_smallscreen)) $ret .= ajax_combobox('.'.$name.'select');
+				if (empty($conf->dol_optimize_smallscreen)) $ret .= ajax_combobox('.'.$name.'select');
 
 		// Warning: if you set submit button to disabled, post using 'Enter' will no more work if there is no another input submit. So we add a hidden button
 		$ret .= '<input type="submit" name="confirmmassactioninvisible" style="display: none" tabindex="-1">'; // Hidden button BEFORE so it is the one used when we submit with ENTER.
-                $ret .= '<input type="submit" disabled name="confirmmassaction" class="button'.(empty($conf->use_javascript_ajax) ? '' : ' hideobject').' '.$name.' '.$name.'confirmed" value="'.dol_escape_htmltag($langs->trans("Confirm")).'">';
+				$ret .= '<input type="submit" disabled name="confirmmassaction" class="button'.(empty($conf->use_javascript_ajax) ? '' : ' hideobject').' '.$name.' '.$name.'confirmed" value="'.dol_escape_htmltag($langs->trans("Confirm")).'">';
 		$ret .= '</div>';
 
 		if (!empty($conf->use_javascript_ajax))
@@ -5591,15 +5591,15 @@ class Form
 			{
 				if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
 				//$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
-                if ($addnowlink == 1)
-                {
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H', 'tzuser').'\');';
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').change();';
-                } elseif ($addnowlink == 2)
-                {
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(d.getHours().pad());';
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').change();';
-                }
+				if ($addnowlink == 1)
+				{
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H', 'tzuser').'\');';
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').change();';
+				} elseif ($addnowlink == 2)
+				{
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(d.getHours().pad());';
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').change();';
+				}
 
 				if ($fullday) $reset_scripts .= ' } ';
 			}
@@ -5608,15 +5608,15 @@ class Form
 			{
 				if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
 				//$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
-                if ($addnowlink == 1)
-                {
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M', 'tzuser').'\');';
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').change();';
-                } elseif ($addnowlink == 2)
-                {
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(d.getMinutes().pad());';
-                    $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').change();';
-                }
+				if ($addnowlink == 1)
+				{
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M', 'tzuser').'\');';
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'min\').change();';
+				} elseif ($addnowlink == 2)
+				{
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(d.getMinutes().pad());';
+					$reset_scripts .= 'jQuery(\'#'.$prefix.'min\').change();';
+				}
 				if ($fullday) $reset_scripts .= ' } ';
 			}
 			// If reset_scripts is not empty, print the link with the reset_scripts in the onClick
@@ -5684,20 +5684,20 @@ class Form
 	{
 		global $langs;
 
-        $TDurationTypes = array('y'=>$langs->trans('Years'), 'm'=>$langs->trans('Month'), 'w'=>$langs->trans('Weeks'), 'd'=>$langs->trans('Days'), 'h'=>$langs->trans('Hours'), 'i'=>$langs->trans('Minutes'));
+		$TDurationTypes = array('y'=>$langs->trans('Years'), 'm'=>$langs->trans('Month'), 'w'=>$langs->trans('Weeks'), 'd'=>$langs->trans('Days'), 'h'=>$langs->trans('Hours'), 'i'=>$langs->trans('Minutes'));
 
-        $retstring = '<select class="flat" id="select_'.$prefix.'type_duration" name="'.$prefix.'type_duration">';
-        foreach ($TDurationTypes as $key=>$typeduration) {
-            $retstring .= '<option value="'.$key.'"';
-            if ($key == $selected) {
-                $retstring .= " selected";
-            }
-            $retstring .= ">".$typeduration."</option>";
-        }
-        $retstring .= "</select>";
+		$retstring = '<select class="flat" id="select_'.$prefix.'type_duration" name="'.$prefix.'type_duration">';
+		foreach ($TDurationTypes as $key=>$typeduration) {
+			$retstring .= '<option value="'.$key.'"';
+			if ($key == $selected) {
+				$retstring .= " selected";
+			}
+			$retstring .= ">".$typeduration."</option>";
+		}
+		$retstring .= "</select>";
 
-        return $retstring;
-    }
+		return $retstring;
+	}
 
 	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
 	/**
@@ -6545,23 +6545,23 @@ class Form
 
 		foreach ($array as $key => $val)
 		{
-		    /* var_dump($val);
+			/* var_dump($val);
             var_dump(array_key_exists('enabled', $val));
             var_dump(!$val['enabled']);*/
-		    if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled'])
-		    {
-			    unset($array[$key]); // We don't want this field
-			    continue;
-		    }
-		    if ($val['label'])
-		    {
-		    	if (!empty($val['langfile']) && is_object($langs)) {
-		    		$langs->load($val['langfile']);
-		    	}
-
-		        $lis .= '<li><input type="checkbox" id="checkbox'.$key.'" value="'.$key.'"'.(empty($val['checked']) ? '' : ' checked="checked"').'/><label for="checkbox'.$key.'">'.dol_escape_htmltag($langs->trans($val['label'])).'</label></li>';
-			    $listcheckedstring .= (empty($val['checked']) ? '' : $key.',');
-		    }
+			if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled'])
+			{
+				unset($array[$key]); // We don't want this field
+				continue;
+			}
+			if ($val['label'])
+			{
+				if (!empty($val['langfile']) && is_object($langs)) {
+					$langs->load($val['langfile']);
+				}
+
+				$lis .= '<li><input type="checkbox" id="checkbox'.$key.'" value="'.$key.'"'.(empty($val['checked']) ? '' : ' checked="checked"').'/><label for="checkbox'.$key.'">'.dol_escape_htmltag($langs->trans($val['label'])).'</label></li>';
+				$listcheckedstring .= (empty($val['checked']) ? '' : $key.',');
+			}
 		}
 
 		$out = '<!-- Component multiSelectArrayWithCheckbox '.$htmlname.' -->
@@ -7542,16 +7542,16 @@ class Form
 	 *
 	 *  @param  string  $cssclass                  CSS class
 	 *  @param  int     $calljsfunction            0=default. 1=call function initCheckForSelect() after changing status of checkboxes
-         *  @param  string  $massactionname            Mass action button name that will launch an action on the selected items
+	 *  @param  string  $massactionname            Mass action button name that will launch an action on the selected items
 	 *  @return	string
 	 */
-    public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
+	public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
 	{
 		global $conf, $langs;
 
 		$out = '';
 		$id = uniqid();
-                if (!empty($conf->use_javascript_ajax)) $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="'.$cssclass.'s" name="'.$cssclass.'s" class="checkallactions"></div>';
+				if (!empty($conf->use_javascript_ajax)) $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="'.$cssclass.'s" name="'.$cssclass.'s" class="checkallactions"></div>';
 		$out .= '<script>
             $(document).ready(function() {
                 $("#' . $cssclass.'s").click(function() {
@@ -7564,7 +7564,7 @@ class Form
                         console.log("We uncheck all");
                 		$(".'.$cssclass.'").prop(\'checked\', false).trigger(\'change\');
                     }'."\n";
-                if ($calljsfunction) $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "'.$massactionname.'", "'.$cssclass.'"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
+				if ($calljsfunction) $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "'.$massactionname.'", "'.$cssclass.'"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
 		$out .= '         });
 
                 $(".' . $cssclass.'").change(function() {
@@ -7983,34 +7983,34 @@ class Form
 	 * @param	int		 $default	 1=Show also Default mail template
 	 * @return  string               HTML select string
 	 */
-    public function selectModelMail($prefix, $modelType = '', $default = 0)
-    {
-        global $langs, $db, $user;
+	public function selectModelMail($prefix, $modelType = '', $default = 0)
+	{
+		global $langs, $db, $user;
 
-        $retstring = '';
+		$retstring = '';
 
-        $TModels = array();
+		$TModels = array();
 
-        include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
-        $formmail = new FormMail($db);
-        $result =  $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
+		include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
+		$formmail = new FormMail($db);
+		$result =  $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
 
-        if ($default) $TModels[0] = $langs->trans('DefaultMailModel');
-        if ($result > 0) {
-            foreach ($formmail->lines_model as $model){
-                $TModels[$model->id] = $model->label;
-            }
-        }
+		if ($default) $TModels[0] = $langs->trans('DefaultMailModel');
+		if ($result > 0) {
+			foreach ($formmail->lines_model as $model){
+				$TModels[$model->id] = $model->label;
+			}
+		}
 
-        $retstring .= '<select class="flat" id="select_'.$prefix.'model_mail" name="'.$prefix.'model_mail">';
+		$retstring .= '<select class="flat" id="select_'.$prefix.'model_mail" name="'.$prefix.'model_mail">';
 
-        foreach ($TModels as $id_model=>$label_model){
-            $retstring .= '<option value="'.$id_model.'"';
-            $retstring .= ">".$label_model."</option>";
-        }
+		foreach ($TModels as $id_model=>$label_model){
+			$retstring .= '<option value="'.$id_model.'"';
+			$retstring .= ">".$label_model."</option>";
+		}
 
-        $retstring .= "</select>";
+		$retstring .= "</select>";
 
-        return $retstring;
-    }
+		return $retstring;
+	}
 }

+ 4 - 4
htdocs/core/class/html.formmail.class.php

@@ -855,7 +855,7 @@ class FormMail extends Form
 						{
 							$out .= '<div id="attachfile_'.$key.'">';
 							// Preview of attachment
-							preg_match('#^(/)(\w+)(/)(.+)$#', substr($val, (strlen(DOL_DATA_ROOT)-strlen($val))), $formfile_params);
+							preg_match('#^(/)(\w+)(/)(.+)$#', substr($val, (strlen(DOL_DATA_ROOT) - strlen($val))), $formfile_params);
 							$out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
 							$out .= $formfile->showPreview(array(), $formfile_params[2], $formfile_params[4]);
 							if (!$this->withfilereadonly)
@@ -956,13 +956,13 @@ class FormMail extends Form
 					$atleastonecomponentishtml++;
 				}
 				if ($atleastonecomponentishtml) {
-					if (! dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
+					if (!dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
 						$this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
 					}
-					if (! dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
+					if (!dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
 						$this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = dol_nl2br($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__']);
 					}
-					if (! dol_textishtml($defaultmessage)) {
+					if (!dol_textishtml($defaultmessage)) {
 						$defaultmessage = dol_nl2br($defaultmessage);
 					}
 				}

+ 3 - 3
htdocs/core/class/html.formticket.class.php

@@ -986,12 +986,12 @@ class FormTicket
 			print '</td></tr>';
 		}
 
-        // MESSAGE
-        $defaultmessage="";
+		// MESSAGE
+		$defaultmessage="";
 		if (is_object($arraydefaultmessage) && $arraydefaultmessage->content) {
 			$defaultmessage = $arraydefaultmessage->content;
 		}
-        $defaultmessage = str_replace('\n', "\n", $defaultmessage);
+		$defaultmessage = str_replace('\n', "\n", $defaultmessage);
 
 		// Deal with format differences between message and signature (text / HTML)
 		if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__USER_SIGNATURE__'])) {

+ 724 - 724
htdocs/core/class/menubase.class.php

@@ -29,731 +29,731 @@
  */
 class Menubase
 {
-    /**
-     * @var DoliDB Database handler.
-     */
-    public $db;
-
-    /**
-     * @var string Error code (or message)
-     */
-    public $error;
-
-    /**
-     * @var string[] Error codes (or messages)
-     */
-    public $errors = array();
-
-    /**
-     * @var int ID
-     */
-    public $id;
-
-    /**
-     * @var string Menu handler
-     */
-    public $menu_handler;
-
-    /**
-     * @var string Module name if record is added by a module
-     */
-    public $module;
-
-    /**
-     * @var string Menu top or left
-     */
-    public $type;
-
-    /**
-     * @var string Name family/module for top menu (home, companies, ...)
-     */
-    public $mainmenu;
-
-    /**
-     * @var int 0 or Id of mother menu line, or -1 if we use fk_mainmenu and fk_leftmenu
-     */
-    public $fk_menu;
-
-    /**
-     * @var string fk_mainmenu
-     */
-    public $fk_mainmenu;
-
-    /**
-     * @var string fk_leftmenu
-     */
-    public $fk_leftmenu;
-
-    /**
-     * @var int Sort order of entry
-     */
-    public $position;
-
-    /**
-     * @var string Relative (or absolute) url to go
-     */
-    public $url;
-
-    /**
-     * @var string Target of Url link
-     */
-    public $target;
-
-    /**
-     * @var string Key for menu translation
-     * @deprecated
-     * @see $title
-     */
-    public $titre;
-
-    /**
-     * @var string Key for menu translation
-     */
-    public $title;
-
-    /**
-     * @var string Lang file to load for translation
-     */
-    public $langs;
-
-    /**
-     * @var string Not used
-     * @deprecated
-     */
-    public $level;
-
-    /**
-     * @var string Name family/module for left menu (setup, info, ...)
-     */
-    public $leftmenu;
-
-    /**
-     * @var string Condition to show enabled or disabled
-     */
-    public $perms;
-
-    /**
-     * @var string Condition to show or hide
-     */
-    public $enabled;
-
-    /**
-     * @var int 0 if menu for all users, 1 for external only, 2 for internal only
-     */
-    public $user;
-
-    /**
-     * @var int timestamp
-     */
-    public $tms;
-
-
-    /**
+	/**
+	 * @var DoliDB Database handler.
+	 */
+	public $db;
+
+	/**
+	 * @var string Error code (or message)
+	 */
+	public $error;
+
+	/**
+	 * @var string[] Error codes (or messages)
+	 */
+	public $errors = array();
+
+	/**
+	 * @var int ID
+	 */
+	public $id;
+
+	/**
+	 * @var string Menu handler
+	 */
+	public $menu_handler;
+
+	/**
+	 * @var string Module name if record is added by a module
+	 */
+	public $module;
+
+	/**
+	 * @var string Menu top or left
+	 */
+	public $type;
+
+	/**
+	 * @var string Name family/module for top menu (home, companies, ...)
+	 */
+	public $mainmenu;
+
+	/**
+	 * @var int 0 or Id of mother menu line, or -1 if we use fk_mainmenu and fk_leftmenu
+	 */
+	public $fk_menu;
+
+	/**
+	 * @var string fk_mainmenu
+	 */
+	public $fk_mainmenu;
+
+	/**
+	 * @var string fk_leftmenu
+	 */
+	public $fk_leftmenu;
+
+	/**
+	 * @var int Sort order of entry
+	 */
+	public $position;
+
+	/**
+	 * @var string Relative (or absolute) url to go
+	 */
+	public $url;
+
+	/**
+	 * @var string Target of Url link
+	 */
+	public $target;
+
+	/**
+	 * @var string Key for menu translation
+	 * @deprecated
+	 * @see $title
+	 */
+	public $titre;
+
+	/**
+	 * @var string Key for menu translation
+	 */
+	public $title;
+
+	/**
+	 * @var string Lang file to load for translation
+	 */
+	public $langs;
+
+	/**
+	 * @var string Not used
+	 * @deprecated
+	 */
+	public $level;
+
+	/**
+	 * @var string Name family/module for left menu (setup, info, ...)
+	 */
+	public $leftmenu;
+
+	/**
+	 * @var string Condition to show enabled or disabled
+	 */
+	public $perms;
+
+	/**
+	 * @var string Condition to show or hide
+	 */
+	public $enabled;
+
+	/**
+	 * @var int 0 if menu for all users, 1 for external only, 2 for internal only
+	 */
+	public $user;
+
+	/**
+	 * @var int timestamp
+	 */
+	public $tms;
+
+
+	/**
 	 *  Constructor
 	 *
 	 *  @param		DoliDB		$db 		    Database handler
-     *  @param     	string		$menu_handler	Menu handler
-     */
-    public function __construct($db, $menu_handler = '')
-    {
-        $this->db = $db;
-        $this->menu_handler = $menu_handler;
-        return 1;
-    }
-
-
-    /**
-     *  Create menu entry into database
-     *
-     *  @param      User	$user       User that create
-     *  @return     int      			<0 if KO, Id of record if OK
-     */
-    public function create($user = null)
-    {
-        global $conf, $langs;
-
-        // Clean parameters
-        $this->menu_handler = trim($this->menu_handler);
-        $this->module = trim($this->module);
-        $this->type = trim($this->type);
-        $this->mainmenu = trim($this->mainmenu);
-        $this->leftmenu = trim($this->leftmenu);
-        $this->fk_menu = (int) $this->fk_menu; // If -1, fk_mainmenu and fk_leftmenu must be defined
-        $this->fk_mainmenu = trim($this->fk_mainmenu);
-        $this->fk_leftmenu = trim($this->fk_leftmenu);
-        $this->position = (int) $this->position;
-        $this->url = trim($this->url);
-        $this->target = trim($this->target);
-        $this->title = trim($this->title);
-        $this->langs = trim($this->langs);
-        $this->perms = trim($this->perms);
-        $this->enabled = trim($this->enabled);
-        $this->user = (int) $this->user;
-        if (empty($this->position)) $this->position = 0;
-        if (!$this->level) $this->level = 0;
-
-        // Check parameters
-        if (empty($this->menu_handler)) return -1;
-
-        // For PGSQL, we must first found the max rowid and use it as rowid in insert because postgresql
-        // may use an already used value because its internal cursor does not increase when we do
-        // an insert with a forced id.
-        if (in_array($this->db->type, array('pgsql')))
-        {
-            $sql = "SELECT MAX(rowid) as maxrowid FROM ".MAIN_DB_PREFIX."menu";
-            $resqlrowid = $this->db->query($sql);
-            if ($resqlrowid) {
-                $obj = $this->db->fetch_object($resqlrowid);
-                $maxrowid = $obj->maxrowid;
-
-                // Max rowid can be empty if there is no record yet
-                if (empty($maxrowid)) $maxrowid = 1;
-
-                $sql = "SELECT setval('".MAIN_DB_PREFIX."menu_rowid_seq', ".($maxrowid).")";
-                //print $sql; exit;
-                $resqlrowidset = $this->db->query($sql);
-                if (!$resqlrowidset) dol_print_error($this->db);
-            } else dol_print_error($this->db);
-        }
-
-        // Check that entry does not exists yet on key menu_handler-fk_menu-position-url-entity, to avoid errors with postgresql
-        $sql = "SELECT count(*)";
-        $sql .= " FROM ".MAIN_DB_PREFIX."menu";
-        $sql .= " WHERE menu_handler = '".$this->db->escape($this->menu_handler)."'";
-        $sql .= " AND fk_menu = ".((int) $this->fk_menu);
-        $sql .= " AND position = ".((int) $this->position);
-        $sql .= " AND url = '".$this->db->escape($this->url)."'";
-        $sql .= " AND entity = ".$conf->entity;
-
-        $result = $this->db->query($sql);
-        if ($result)
-        {
-        	$row = $this->db->fetch_row($result);
-
-        	if ($row[0] == 0)   // If not found
-        	{
-		        // Insert request
-		        $sql = "INSERT INTO ".MAIN_DB_PREFIX."menu(";
-		        $sql .= "menu_handler,";
-		        $sql .= "entity,";
-		        $sql .= "module,";
-		        $sql .= "type,";
-		        $sql .= "mainmenu,";
-		        $sql .= "leftmenu,";
-		        $sql .= "fk_menu,";
-		        $sql .= "fk_mainmenu,";
-		        $sql .= "fk_leftmenu,";
-		        $sql .= "position,";
-		        $sql .= "url,";
-		        $sql .= "target,";
-		        $sql .= "titre,";
-		        $sql .= "langs,";
-		        $sql .= "perms,";
-		        $sql .= "enabled,";
-		        $sql .= "usertype";
-		        $sql .= ") VALUES (";
-		        $sql .= " '".$this->db->escape($this->menu_handler)."',";
-		        $sql .= " '".$this->db->escape($conf->entity)."',";
-		        $sql .= " '".$this->db->escape($this->module)."',";
-		        $sql .= " '".$this->db->escape($this->type)."',";
-		        $sql .= " ".($this->mainmenu ? "'".$this->db->escape($this->mainmenu)."'" : "''").","; // Can't be null
-		        $sql .= " ".($this->leftmenu ? "'".$this->db->escape($this->leftmenu)."'" : "null").",";
-		        $sql .= " ".((int) $this->fk_menu).",";
-		        $sql .= " ".($this->fk_mainmenu ? "'".$this->db->escape($this->fk_mainmenu)."'" : "null").",";
-		        $sql .= " ".($this->fk_leftmenu ? "'".$this->db->escape($this->fk_leftmenu)."'" : "null").",";
-		        $sql .= " ".((int) $this->position).",";
-		        $sql .= " '".$this->db->escape($this->url)."',";
-		        $sql .= " '".$this->db->escape($this->target)."',";
-		        $sql .= " '".$this->db->escape($this->title)."',";
-		        $sql .= " '".$this->db->escape($this->langs)."',";
-		        $sql .= " '".$this->db->escape($this->perms)."',";
-		        $sql .= " '".$this->db->escape($this->enabled)."',";
-		        $sql .= " '".$this->db->escape($this->user)."'";
-		        $sql .= ")";
-
-		        dol_syslog(get_class($this)."::create", LOG_DEBUG);
-		        $resql = $this->db->query($sql);
-		        if ($resql)
-		        {
-		            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."menu");
-		            dol_syslog(get_class($this)."::create record added has rowid=".$this->id, LOG_DEBUG);
-
-		            return $this->id;
-		        } else {
-		            $this->error = "Error ".$this->db->lasterror();
-		            return -1;
-		        }
-        	} else {
-        		dol_syslog(get_class($this)."::create menu entry already exists", LOG_WARNING);
-        		$this->error = 'Error Menu entry already exists';
-        		return 0;
-        	}
-        } else {
-        	return -1;
-        }
-    }
-
-    /**
-     *  Update menu entry into database.
-     *
-     *  @param	User	$user        	User that modify
-     *  @param  int		$notrigger	    0=no, 1=yes (no update trigger)
-     *  @return int 		        	<0 if KO, >0 if OK
-     */
-    public function update($user = null, $notrigger = 0)
-    {
-        //global $conf, $langs;
-
-        // Clean parameters
-        $this->rowid = trim($this->rowid);
-        $this->menu_handler = trim($this->menu_handler);
-        $this->module = trim($this->module);
-        $this->type = trim($this->type);
-        $this->mainmenu = trim($this->mainmenu);
-        $this->leftmenu = trim($this->leftmenu);
-        $this->fk_menu = (int) $this->fk_menu;
-        $this->fk_mainmenu = trim($this->fk_mainmenu);
-        $this->fk_leftmenu = trim($this->fk_leftmenu);
-        $this->position = (int) $this->position;
-        $this->url = trim($this->url);
-        $this->target = trim($this->target);
-        $this->title = trim($this->title);
-        $this->langs = trim($this->langs);
-        $this->perms = trim($this->perms);
-        $this->enabled = trim($this->enabled);
-        $this->user = (int) $this->user;
-
-        // Check parameters
-        // Put here code to add control on parameters values
-
-        // Update request
-        $sql = "UPDATE ".MAIN_DB_PREFIX."menu SET";
-        $sql .= " menu_handler='".$this->db->escape($this->menu_handler)."',";
-        $sql .= " module='".$this->db->escape($this->module)."',";
-        $sql .= " type='".$this->db->escape($this->type)."',";
-        $sql .= " mainmenu='".$this->db->escape($this->mainmenu)."',";
-        $sql .= " leftmenu='".$this->db->escape($this->leftmenu)."',";
-        $sql .= " fk_menu=".$this->fk_menu.",";
-        $sql .= " fk_mainmenu=".($this->fk_mainmenu ? "'".$this->db->escape($this->fk_mainmenu)."'" : "null").",";
-        $sql .= " fk_leftmenu=".($this->fk_leftmenu ? "'".$this->db->escape($this->fk_leftmenu)."'" : "null").",";
-        $sql .= " position=".($this->position > 0 ? $this->position : 0).",";
-        $sql .= " url='".$this->db->escape($this->url)."',";
-        $sql .= " target='".$this->db->escape($this->target)."',";
-        $sql .= " titre='".$this->db->escape($this->title)."',";
-        $sql .= " langs='".$this->db->escape($this->langs)."',";
-        $sql .= " perms='".$this->db->escape($this->perms)."',";
-        $sql .= " enabled='".$this->db->escape($this->enabled)."',";
-        $sql .= " usertype='".$this->db->escape($this->user)."'";
-        $sql .= " WHERE rowid=".$this->id;
-
-        dol_syslog(get_class($this)."::update", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if (!$resql)
-        {
-            $this->error = "Error ".$this->db->lasterror();
-            return -1;
-        }
-
-        return 1;
-    }
-
-
-    /**
-     *   Load object in memory from database
-     *
-     *   @param		int		$id         Id object
-     *   @param		User    $user       User that load
-     *   @return	int         		<0 if KO, >0 if OK
-     */
-    public function fetch($id, $user = null)
-    {
-        //global $langs;
-
-        $sql = "SELECT";
-        $sql .= " t.rowid,";
-        $sql .= " t.menu_handler,";
-        $sql .= " t.entity,";
-        $sql .= " t.module,";
-        $sql .= " t.type,";
-        $sql .= " t.mainmenu,";
-        $sql .= " t.leftmenu,";
-        $sql .= " t.fk_menu,";
-        $sql .= " t.fk_mainmenu,";
-        $sql .= " t.fk_leftmenu,";
-        $sql .= " t.position,";
-        $sql .= " t.url,";
-        $sql .= " t.target,";
-        $sql .= " t.titre as title,";
-        $sql .= " t.langs,";
-        $sql .= " t.perms,";
-        $sql .= " t.enabled,";
-        $sql .= " t.usertype as user,";
-        $sql .= " t.tms";
-        $sql .= " FROM ".MAIN_DB_PREFIX."menu as t";
-        $sql .= " WHERE t.rowid = ".$id;
-
-        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            if ($this->db->num_rows($resql))
-            {
-                $obj = $this->db->fetch_object($resql);
-
-                $this->id = $obj->rowid;
-
-                $this->menu_handler = $obj->menu_handler;
-                $this->entity = $obj->entity;
-                $this->module = $obj->module;
-                $this->type = $obj->type;
-                $this->mainmenu = $obj->mainmenu;
-                $this->leftmenu = $obj->leftmenu;
-                $this->fk_menu = $obj->fk_menu;
-                $this->fk_mainmenu = $obj->fk_mainmenu;
-                $this->fk_leftmenu = $obj->fk_leftmenu;
-                $this->position = $obj->position;
-                $this->url = $obj->url;
-                $this->target = $obj->target;
-                $this->title = $obj->title;
-                $this->langs = $obj->langs;
-                $this->perms = $obj->perms;
-                $this->enabled = str_replace("\"", "'", $obj->enabled);
-                $this->user = $obj->user;
-                $this->tms = $this->db->jdate($obj->tms);
-            }
-            $this->db->free($resql);
-
-            return 1;
-        } else {
-            $this->error = "Error ".$this->db->lasterror();
-            return -1;
-        }
-    }
-
-
-    /**
-     *  Delete object in database
-     *
-     *	@param	User	$user       User that delete
-     *	@return	int					<0 if KO, >0 if OK
-     */
-    public function delete($user)
-    {
-        //global $conf, $langs;
-
-        $sql = "DELETE FROM ".MAIN_DB_PREFIX."menu";
-        $sql .= " WHERE rowid=".$this->id;
-
-        dol_syslog(get_class($this)."::delete", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if (!$resql)
-        {
-            $this->error = "Error ".$this->db->lasterror();
-            return -1;
-        }
-
-        return 1;
-    }
-
-
-    /**
-     *  Initialise an instance with random values.
-     *  Used to build previews or test instances.
-     *	id must be 0 if object instance is a specimen.
-     *
-     *  @return	void
-     */
-    public function initAsSpecimen()
-    {
-        $this->id = 0;
-
-        $this->menu_handler = 'all';
-        $this->module = 'specimen';
-        $this->type = 'top';
-        $this->mainmenu = '';
-        $this->fk_menu = '0';
-        $this->position = '';
-        $this->url = 'http://dummy';
-        $this->target = '';
-        $this->title = 'Specimen menu';
-        $this->langs = '';
-        $this->leftmenu = '';
-        $this->perms = '';
-        $this->enabled = '';
-        $this->user = '';
-        $this->tms = '';
-    }
-
-
-    /**
-     *	Load tabMenu array with top menu entries found into database.
-     *
-     * 	@param	string	$mymainmenu		Value for mainmenu to filter menu to load (always '')
-     * 	@param	string	$myleftmenu		Value for leftmenu to filter menu to load (always '')
-     * 	@param	int		$type_user		0=Menu for backoffice, 1=Menu for front office
-     * 	@param	string	$menu_handler	Filter on name of menu_handler used (auguria, eldy...)
-     * 	@param  array	$tabMenu       If array with menu entries already loaded, we put this array here (in most cases, it's empty)
-     * 	@return	array					Return array with menu entries for top menu
-     */
-    public function menuTopCharger($mymainmenu, $myleftmenu, $type_user, $menu_handler, &$tabMenu)
-    {
-        global $langs, $user, $conf; // To export to dol_eval function
-        global $mainmenu, $leftmenu; // To export to dol_eval function
-
-        $mainmenu = $mymainmenu; // To export to dol_eval function
-        $leftmenu = $myleftmenu; // To export to dol_eval function
-
-        $newTabMenu = array();
-        foreach ($tabMenu as $val)
-        {
-            if ($val['type'] == 'top') $newTabMenu[] = $val;
-        }
-
-        return $newTabMenu;
-    }
-
-    /**
-     * 	Load entries found from database (and stored into $tabMenu) in $this->newmenu array.
-     *  Warning: Entries in $tabMenu must have child after parent
-     *
-     * 	@param	Menu	$newmenu        Menu array to complete (in most cases, it's empty, may be already initialized with some menu manager like eldy)
-     * 	@param	string	$mymainmenu		Value for mainmenu to filter menu to load (often $_SESSION["mainmenu"])
-     * 	@param	string	$myleftmenu		Value for leftmenu to filter menu to load (always '')
-     * 	@param	int		$type_user		0=Menu for backoffice, 1=Menu for front office
-     * 	@param	string	$menu_handler	Filter on name of menu_handler used (auguria, eldy...)
-     * 	@param  array	$tabMenu       Array with menu entries already loaded
-     * 	@return Menu    		       	Menu array for particular mainmenu value or full tabArray
-     */
-    public function menuLeftCharger($newmenu, $mymainmenu, $myleftmenu, $type_user, $menu_handler, &$tabMenu)
-    {
-        global $langs, $user, $conf; // To export to dol_eval function
-        global $mainmenu, $leftmenu; // To export to dol_eval function
-
-        $mainmenu = $mymainmenu; // To export to dol_eval function
-        $leftmenu = $myleftmenu; // To export to dol_eval function
-
-        // Detect what is top mainmenu id
-        $menutopid = '';
-        foreach ($tabMenu as $key => $val)
-        {
-            // Define menutopid of mainmenu
-            if (empty($menutopid) && $val['type'] == 'top' && $val['mainmenu'] == $mainmenu)
-            {
-                $menutopid = $val['rowid'];
-                break;
-            }
-        }
-
-        // We initialize newmenu with first already found menu entries
-        $this->newmenu = $newmenu;
-
-        // Now complete $this->newmenu->list to add entries found into $tabMenu that are childs of mainmenu=$menutopid, using the fk_menu link that is int (old method)
-        $this->recur($tabMenu, $menutopid, 1);
-
-        // Now complete $this->newmenu->list when fk_menu value is -1 (left menu added by modules with no top menu)
-        foreach ($tabMenu as $key => $val)
-        {
-        	//var_dump($tabMenu);
-        	if ($val['fk_menu'] == -1 && $val['fk_mainmenu'] == $mainmenu)    // We found a menu entry not linked to parent with good mainmenu
-        	{
-        		//print 'Try to add menu (current is mainmenu='.$mainmenu.' leftmenu='.$leftmenu.') for '.join(',',$val).' fk_mainmenu='.$val['fk_mainmenu'].' fk_leftmenu='.$val['fk_leftmenu'].'<br>';
-        		//var_dump($this->newmenu->liste);exit;
-
-        		if (empty($val['fk_leftmenu']))
-        		{
-        			$this->newmenu->add($val['url'], $val['titre'], 0, $val['perms'], $val['target'], $val['mainmenu'], $val['leftmenu'], $val['position']);
-        			//var_dump($this->newmenu->liste);
-        		} else {
-        			// Search first menu with this couple (mainmenu,leftmenu)=(fk_mainmenu,fk_leftmenu)
-        			$searchlastsub = 0; $lastid = 0; $nextid = 0; $found = 0;
-        			foreach ($this->newmenu->liste as $keyparent => $valparent)
-        			{
-        				//var_dump($valparent);
-        				if ($searchlastsub)    // If we started to search for last submenu
-        				{
-        					if ($valparent['level'] >= $searchlastsub) $lastid = $keyparent;
-        					if ($valparent['level'] < $searchlastsub)
-        					{
-        						$nextid = $keyparent;
-        						break;
-        					}
-        				}
-        				if ($valparent['mainmenu'] == $val['fk_mainmenu'] && $valparent['leftmenu'] == $val['fk_leftmenu'])
-        				{
-        					//print "We found parent: keyparent='.$keyparent.' - level=".$valparent['level'].' - '.join(',',$valparent).'<br>';
-        					// Now we look to find last subelement of this parent (we add at end)
-        					$searchlastsub = ($valparent['level'] + 1);
-        					$lastid = $keyparent;
-        					$found = 1;
-        				}
-        			}
-        			//print 'We must insert menu entry between entry '.$lastid.' and '.$nextid.'<br>';
-        			if ($found) $this->newmenu->insert($lastid, $val['url'], $val['titre'], $searchlastsub, $val['perms'], $val['target'], $val['mainmenu'], $val['leftmenu'], $val['position']);
-        			else {
-        			    dol_syslog("Error. Modules ".$val['module']." has defined a menu entry with a parent='fk_mainmenu=".$val['fk_leftmenu'].",fk_leftmenu=".$val['fk_leftmenu']."' and position=".$val['position'].'. The parent was not found. May be you forget it into your definition of menu, or may be the parent has a "position" that is after the child (fix field "position" of parent or child in this case).', LOG_WARNING);
-        			    //print "Parent menu not found !!<br>";
-        			}
-        		}
-        	}
-        }
-
-        return $this->newmenu;
-    }
-
-
-    /**
-     *  Load entries found in database into variable $tabMenu. Note that only "database menu entries" are loaded here, hardcoded will not be present into output.
-     *
-     *  @param	string	$mymainmenu     Value for mainmenu that defined mainmenu
-     *  @param	string	$myleftmenu     Value for left that defined leftmenu
-     *  @param  int		$type_user      Looks for menu entry for 0=Internal users, 1=External users
-     *  @param  string	$menu_handler   Name of menu_handler used ('auguria', 'eldy'...)
-     *  @param  array	$tabMenu        Array to store new entries found (in most cases, it's empty, but may be alreay filled)
-     *  @return int     		        >0 if OK, <0 if KO
-     */
-    public function menuLoad($mymainmenu, $myleftmenu, $type_user, $menu_handler, &$tabMenu)
-    {
-        global $langs, $user, $conf; // To export to dol_eval function
-        global $mainmenu, $leftmenu; // To export to dol_eval function
-
-        $mainmenu = $mymainmenu; // To export to dol_eval function
-        $leftmenu = $myleftmenu; // To export to dol_eval function
-
-        $sql = "SELECT m.rowid, m.type, m.module, m.fk_menu, m.fk_mainmenu, m.fk_leftmenu, m.url, m.titre, m.langs, m.perms, m.enabled, m.target, m.mainmenu, m.leftmenu, m.position";
-        $sql .= " FROM ".MAIN_DB_PREFIX."menu as m";
-        $sql .= " WHERE m.entity IN (0,".$conf->entity.")";
-        $sql .= " AND m.menu_handler IN ('".$menu_handler."','all')";
-        if ($type_user == 0) $sql .= " AND m.usertype IN (0,2)";
-        if ($type_user == 1) $sql .= " AND m.usertype IN (1,2)";
-        $sql .= " ORDER BY m.position, m.rowid";
-        //print $sql;
-
-        //dol_syslog(get_class($this)."::menuLoad mymainmenu=".$mymainmenu." myleftmenu=".$myleftmenu." type_user=".$type_user." menu_handler=".$menu_handler." tabMenu size=".count($tabMenu)."", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            $numa = $this->db->num_rows($resql);
-
-            $a = 0;
-            $b = 0;
-            while ($a < $numa)
-            {
-                //$objm = $this->db->fetch_object($resql);
-                $menu = $this->db->fetch_array($resql);
-
-                // Define $right
-                $perms = true;
-                if (isset($menu['perms']))
-                {
-                	$tmpcond = $menu['perms'];
-                	if ($leftmenu == 'all') $tmpcond = preg_replace('/\$leftmenu\s*==\s*["\'a-zA-Z_]+/', '1==1', $tmpcond); // Force part of condition to true
-                	$perms = verifCond($tmpcond);
-                    //print "verifCond rowid=".$menu['rowid']." ".$tmpcond.":".$perms."<br>\n";
-                }
-
-                // Define $enabled
-                $enabled = true;
-                if (isset($menu['enabled']))
-                {
-                	$tmpcond = $menu['enabled'];
-                	if ($leftmenu == 'all') $tmpcond = preg_replace('/\$leftmenu\s*==\s*["\'a-zA-Z_]+/', '1==1', $tmpcond); // Force part of condition to true
-                    $enabled = verifCond($tmpcond);
-                }
-
-                // Define $title
-                if ($enabled)
-                {
-                	$title = $langs->trans($menu['titre']); // If $menu['titre'] start with $, a dol_eval is done.
-                	//var_dump($title.'-'.$menu['titre']);
-                    if ($title == $menu['titre'])   // Translation not found
-                    {
-                        if (!empty($menu['langs']))    // If there is a dedicated translation file
-                        {
-                        	//print 'Load file '.$menu['langs'].'<br>';
-                            $langs->load($menu['langs']);
-                        }
-
-                        $substitarray = array('__LOGIN__' => $user->login, '__USER_ID__' => $user->id, '__USER_SUPERVISOR_ID__' => $user->fk_user);
-                        $menu['titre'] = make_substitutions($menu['titre'], $substitarray);
-
-                        if (preg_match("/\//", $menu['titre'])) // To manage translation when title is string1/string2
-                        {
-                            $tab_titre = explode("/", $menu['titre']);
-                            $title = $langs->trans($tab_titre[0])."/".$langs->trans($tab_titre[1]);
-                        } elseif (preg_match('/\|\|/', $menu['titre']))
-                        {
-                            // To manage different translation (Title||AltTitle@ConditionForAltTitle)
-                        	$tab_title = explode("||", $menu['titre']);
-                        	$alt_title = explode("@", $tab_title[1]);
-                        	$title_enabled = verifCond($alt_title[1]);
-                        	$title = ($title_enabled ? $langs->trans($alt_title[0]) : $langs->trans($tab_title[0]));
-                        } else {
-                            $title = $langs->trans($menu['titre']);
-                        }
-                    }
-                    //$tmp4=microtime(true);
-                    //print '>>> 3 '.($tmp4 - $tmp3).'<br>';
-
-                    // We complete tabMenu
-                    $tabMenu[$b]['rowid']       = $menu['rowid'];
-                    $tabMenu[$b]['module']      = $menu['module'];
-                    $tabMenu[$b]['fk_menu']     = $menu['fk_menu'];
-                    $tabMenu[$b]['url']         = $menu['url'];
-                    if (!preg_match("/^(http:\/\/|https:\/\/)/i", $tabMenu[$b]['url']))
-                    {
-                        if (preg_match('/\?/', $tabMenu[$b]['url'])) $tabMenu[$b]['url'] .= '&amp;idmenu='.$menu['rowid'];
-                        else $tabMenu[$b]['url'] .= '?idmenu='.$menu['rowid'];
-                    }
-                    $tabMenu[$b]['titre']       = $title;
-                    $tabMenu[$b]['target']      = $menu['target'];
-                    $tabMenu[$b]['mainmenu']    = $menu['mainmenu'];
-                    $tabMenu[$b]['leftmenu']    = $menu['leftmenu'];
-                    $tabMenu[$b]['perms']       = $perms;
-                    $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]['fk_mainmenu'] = $menu['fk_mainmenu'];
-                    $tabMenu[$b]['fk_leftmenu'] = $menu['fk_leftmenu'];
-                    $tabMenu[$b]['position']    = (int) $menu['position'];
-
-                    $b++;
-                }
-
-                $a++;
-            }
-            $this->db->free($resql);
-
-            // Currently $tabMenu is sorted on position.
-            // If a child have a position lower that its parent, we can make a loop to fix this here, but we prefer to show a warning
-            // into the leftMenuCharger later to avoid useless operations.
-
-            return 1;
-        } else {
-            dol_print_error($this->db);
-            return -1;
-        }
-    }
-
-    /**
-     *  Complete this->newmenu with menu entry found in $tab
-     *
-     *  @param  array	$tab			Tab array with all menu entries
-     *  @param  int		$pere			Id of parent
-     *  @param  int		$level			Level
-     *  @return	void
-     */
-    private function recur($tab, $pere, $level)
-    {
-        // Loop on tab array
-        $num = count($tab);
-        for ($x = 0; $x < $num; $x++)
-        {
-            //si un element a pour pere : $pere
-            if ((($tab[$x]['fk_menu'] >= 0 && $tab[$x]['fk_menu'] == $pere)) && $tab[$x]['enabled'])
-            {
-                $this->newmenu->add($tab[$x]['url'], $tab[$x]['titre'], ($level - 1), $tab[$x]['perms'], $tab[$x]['target'], $tab[$x]['mainmenu'], $tab[$x]['leftmenu']);
-                $this->recur($tab, $tab[$x]['rowid'], ($level + 1));
-            }
-        }
-    }
+	 *  @param     	string		$menu_handler	Menu handler
+	 */
+	public function __construct($db, $menu_handler = '')
+	{
+		$this->db = $db;
+		$this->menu_handler = $menu_handler;
+		return 1;
+	}
+
+
+	/**
+	 *  Create menu entry into database
+	 *
+	 *  @param      User	$user       User that create
+	 *  @return     int      			<0 if KO, Id of record if OK
+	 */
+	public function create($user = null)
+	{
+		global $conf, $langs;
+
+		// Clean parameters
+		$this->menu_handler = trim($this->menu_handler);
+		$this->module = trim($this->module);
+		$this->type = trim($this->type);
+		$this->mainmenu = trim($this->mainmenu);
+		$this->leftmenu = trim($this->leftmenu);
+		$this->fk_menu = (int) $this->fk_menu; // If -1, fk_mainmenu and fk_leftmenu must be defined
+		$this->fk_mainmenu = trim($this->fk_mainmenu);
+		$this->fk_leftmenu = trim($this->fk_leftmenu);
+		$this->position = (int) $this->position;
+		$this->url = trim($this->url);
+		$this->target = trim($this->target);
+		$this->title = trim($this->title);
+		$this->langs = trim($this->langs);
+		$this->perms = trim($this->perms);
+		$this->enabled = trim($this->enabled);
+		$this->user = (int) $this->user;
+		if (empty($this->position)) $this->position = 0;
+		if (!$this->level) $this->level = 0;
+
+		// Check parameters
+		if (empty($this->menu_handler)) return -1;
+
+		// For PGSQL, we must first found the max rowid and use it as rowid in insert because postgresql
+		// may use an already used value because its internal cursor does not increase when we do
+		// an insert with a forced id.
+		if (in_array($this->db->type, array('pgsql')))
+		{
+			$sql = "SELECT MAX(rowid) as maxrowid FROM ".MAIN_DB_PREFIX."menu";
+			$resqlrowid = $this->db->query($sql);
+			if ($resqlrowid) {
+				$obj = $this->db->fetch_object($resqlrowid);
+				$maxrowid = $obj->maxrowid;
+
+				// Max rowid can be empty if there is no record yet
+				if (empty($maxrowid)) $maxrowid = 1;
+
+				$sql = "SELECT setval('".MAIN_DB_PREFIX."menu_rowid_seq', ".($maxrowid).")";
+				//print $sql; exit;
+				$resqlrowidset = $this->db->query($sql);
+				if (!$resqlrowidset) dol_print_error($this->db);
+			} else dol_print_error($this->db);
+		}
+
+		// Check that entry does not exists yet on key menu_handler-fk_menu-position-url-entity, to avoid errors with postgresql
+		$sql = "SELECT count(*)";
+		$sql .= " FROM ".MAIN_DB_PREFIX."menu";
+		$sql .= " WHERE menu_handler = '".$this->db->escape($this->menu_handler)."'";
+		$sql .= " AND fk_menu = ".((int) $this->fk_menu);
+		$sql .= " AND position = ".((int) $this->position);
+		$sql .= " AND url = '".$this->db->escape($this->url)."'";
+		$sql .= " AND entity = ".$conf->entity;
+
+		$result = $this->db->query($sql);
+		if ($result)
+		{
+			$row = $this->db->fetch_row($result);
+
+			if ($row[0] == 0)   // If not found
+			{
+				// Insert request
+				$sql = "INSERT INTO ".MAIN_DB_PREFIX."menu(";
+				$sql .= "menu_handler,";
+				$sql .= "entity,";
+				$sql .= "module,";
+				$sql .= "type,";
+				$sql .= "mainmenu,";
+				$sql .= "leftmenu,";
+				$sql .= "fk_menu,";
+				$sql .= "fk_mainmenu,";
+				$sql .= "fk_leftmenu,";
+				$sql .= "position,";
+				$sql .= "url,";
+				$sql .= "target,";
+				$sql .= "titre,";
+				$sql .= "langs,";
+				$sql .= "perms,";
+				$sql .= "enabled,";
+				$sql .= "usertype";
+				$sql .= ") VALUES (";
+				$sql .= " '".$this->db->escape($this->menu_handler)."',";
+				$sql .= " '".$this->db->escape($conf->entity)."',";
+				$sql .= " '".$this->db->escape($this->module)."',";
+				$sql .= " '".$this->db->escape($this->type)."',";
+				$sql .= " ".($this->mainmenu ? "'".$this->db->escape($this->mainmenu)."'" : "''").","; // Can't be null
+				$sql .= " ".($this->leftmenu ? "'".$this->db->escape($this->leftmenu)."'" : "null").",";
+				$sql .= " ".((int) $this->fk_menu).",";
+				$sql .= " ".($this->fk_mainmenu ? "'".$this->db->escape($this->fk_mainmenu)."'" : "null").",";
+				$sql .= " ".($this->fk_leftmenu ? "'".$this->db->escape($this->fk_leftmenu)."'" : "null").",";
+				$sql .= " ".((int) $this->position).",";
+				$sql .= " '".$this->db->escape($this->url)."',";
+				$sql .= " '".$this->db->escape($this->target)."',";
+				$sql .= " '".$this->db->escape($this->title)."',";
+				$sql .= " '".$this->db->escape($this->langs)."',";
+				$sql .= " '".$this->db->escape($this->perms)."',";
+				$sql .= " '".$this->db->escape($this->enabled)."',";
+				$sql .= " '".$this->db->escape($this->user)."'";
+				$sql .= ")";
+
+				dol_syslog(get_class($this)."::create", LOG_DEBUG);
+				$resql = $this->db->query($sql);
+				if ($resql)
+				{
+					$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."menu");
+					dol_syslog(get_class($this)."::create record added has rowid=".$this->id, LOG_DEBUG);
+
+					return $this->id;
+				} else {
+					$this->error = "Error ".$this->db->lasterror();
+					return -1;
+				}
+			} else {
+				dol_syslog(get_class($this)."::create menu entry already exists", LOG_WARNING);
+				$this->error = 'Error Menu entry already exists';
+				return 0;
+			}
+		} else {
+			return -1;
+		}
+	}
+
+	/**
+	 *  Update menu entry into database.
+	 *
+	 *  @param	User	$user        	User that modify
+	 *  @param  int		$notrigger	    0=no, 1=yes (no update trigger)
+	 *  @return int 		        	<0 if KO, >0 if OK
+	 */
+	public function update($user = null, $notrigger = 0)
+	{
+		//global $conf, $langs;
+
+		// Clean parameters
+		$this->rowid = trim($this->rowid);
+		$this->menu_handler = trim($this->menu_handler);
+		$this->module = trim($this->module);
+		$this->type = trim($this->type);
+		$this->mainmenu = trim($this->mainmenu);
+		$this->leftmenu = trim($this->leftmenu);
+		$this->fk_menu = (int) $this->fk_menu;
+		$this->fk_mainmenu = trim($this->fk_mainmenu);
+		$this->fk_leftmenu = trim($this->fk_leftmenu);
+		$this->position = (int) $this->position;
+		$this->url = trim($this->url);
+		$this->target = trim($this->target);
+		$this->title = trim($this->title);
+		$this->langs = trim($this->langs);
+		$this->perms = trim($this->perms);
+		$this->enabled = trim($this->enabled);
+		$this->user = (int) $this->user;
+
+		// Check parameters
+		// Put here code to add control on parameters values
+
+		// Update request
+		$sql = "UPDATE ".MAIN_DB_PREFIX."menu SET";
+		$sql .= " menu_handler='".$this->db->escape($this->menu_handler)."',";
+		$sql .= " module='".$this->db->escape($this->module)."',";
+		$sql .= " type='".$this->db->escape($this->type)."',";
+		$sql .= " mainmenu='".$this->db->escape($this->mainmenu)."',";
+		$sql .= " leftmenu='".$this->db->escape($this->leftmenu)."',";
+		$sql .= " fk_menu=".$this->fk_menu.",";
+		$sql .= " fk_mainmenu=".($this->fk_mainmenu ? "'".$this->db->escape($this->fk_mainmenu)."'" : "null").",";
+		$sql .= " fk_leftmenu=".($this->fk_leftmenu ? "'".$this->db->escape($this->fk_leftmenu)."'" : "null").",";
+		$sql .= " position=".($this->position > 0 ? $this->position : 0).",";
+		$sql .= " url='".$this->db->escape($this->url)."',";
+		$sql .= " target='".$this->db->escape($this->target)."',";
+		$sql .= " titre='".$this->db->escape($this->title)."',";
+		$sql .= " langs='".$this->db->escape($this->langs)."',";
+		$sql .= " perms='".$this->db->escape($this->perms)."',";
+		$sql .= " enabled='".$this->db->escape($this->enabled)."',";
+		$sql .= " usertype='".$this->db->escape($this->user)."'";
+		$sql .= " WHERE rowid=".$this->id;
+
+		dol_syslog(get_class($this)."::update", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if (!$resql)
+		{
+			$this->error = "Error ".$this->db->lasterror();
+			return -1;
+		}
+
+		return 1;
+	}
+
+
+	/**
+	 *   Load object in memory from database
+	 *
+	 *   @param		int		$id         Id object
+	 *   @param		User    $user       User that load
+	 *   @return	int         		<0 if KO, >0 if OK
+	 */
+	public function fetch($id, $user = null)
+	{
+		//global $langs;
+
+		$sql = "SELECT";
+		$sql .= " t.rowid,";
+		$sql .= " t.menu_handler,";
+		$sql .= " t.entity,";
+		$sql .= " t.module,";
+		$sql .= " t.type,";
+		$sql .= " t.mainmenu,";
+		$sql .= " t.leftmenu,";
+		$sql .= " t.fk_menu,";
+		$sql .= " t.fk_mainmenu,";
+		$sql .= " t.fk_leftmenu,";
+		$sql .= " t.position,";
+		$sql .= " t.url,";
+		$sql .= " t.target,";
+		$sql .= " t.titre as title,";
+		$sql .= " t.langs,";
+		$sql .= " t.perms,";
+		$sql .= " t.enabled,";
+		$sql .= " t.usertype as user,";
+		$sql .= " t.tms";
+		$sql .= " FROM ".MAIN_DB_PREFIX."menu as t";
+		$sql .= " WHERE t.rowid = ".$id;
+
+		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			if ($this->db->num_rows($resql))
+			{
+				$obj = $this->db->fetch_object($resql);
+
+				$this->id = $obj->rowid;
+
+				$this->menu_handler = $obj->menu_handler;
+				$this->entity = $obj->entity;
+				$this->module = $obj->module;
+				$this->type = $obj->type;
+				$this->mainmenu = $obj->mainmenu;
+				$this->leftmenu = $obj->leftmenu;
+				$this->fk_menu = $obj->fk_menu;
+				$this->fk_mainmenu = $obj->fk_mainmenu;
+				$this->fk_leftmenu = $obj->fk_leftmenu;
+				$this->position = $obj->position;
+				$this->url = $obj->url;
+				$this->target = $obj->target;
+				$this->title = $obj->title;
+				$this->langs = $obj->langs;
+				$this->perms = $obj->perms;
+				$this->enabled = str_replace("\"", "'", $obj->enabled);
+				$this->user = $obj->user;
+				$this->tms = $this->db->jdate($obj->tms);
+			}
+			$this->db->free($resql);
+
+			return 1;
+		} else {
+			$this->error = "Error ".$this->db->lasterror();
+			return -1;
+		}
+	}
+
+
+	/**
+	 *  Delete object in database
+	 *
+	 *	@param	User	$user       User that delete
+	 *	@return	int					<0 if KO, >0 if OK
+	 */
+	public function delete($user)
+	{
+		//global $conf, $langs;
+
+		$sql = "DELETE FROM ".MAIN_DB_PREFIX."menu";
+		$sql .= " WHERE rowid=".$this->id;
+
+		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if (!$resql)
+		{
+			$this->error = "Error ".$this->db->lasterror();
+			return -1;
+		}
+
+		return 1;
+	}
+
+
+	/**
+	 *  Initialise an instance with random values.
+	 *  Used to build previews or test instances.
+	 *	id must be 0 if object instance is a specimen.
+	 *
+	 *  @return	void
+	 */
+	public function initAsSpecimen()
+	{
+		$this->id = 0;
+
+		$this->menu_handler = 'all';
+		$this->module = 'specimen';
+		$this->type = 'top';
+		$this->mainmenu = '';
+		$this->fk_menu = '0';
+		$this->position = '';
+		$this->url = 'http://dummy';
+		$this->target = '';
+		$this->title = 'Specimen menu';
+		$this->langs = '';
+		$this->leftmenu = '';
+		$this->perms = '';
+		$this->enabled = '';
+		$this->user = '';
+		$this->tms = '';
+	}
+
+
+	/**
+	 *	Load tabMenu array with top menu entries found into database.
+	 *
+	 * 	@param	string	$mymainmenu		Value for mainmenu to filter menu to load (always '')
+	 * 	@param	string	$myleftmenu		Value for leftmenu to filter menu to load (always '')
+	 * 	@param	int		$type_user		0=Menu for backoffice, 1=Menu for front office
+	 * 	@param	string	$menu_handler	Filter on name of menu_handler used (auguria, eldy...)
+	 * 	@param  array	$tabMenu       If array with menu entries already loaded, we put this array here (in most cases, it's empty)
+	 * 	@return	array					Return array with menu entries for top menu
+	 */
+	public function menuTopCharger($mymainmenu, $myleftmenu, $type_user, $menu_handler, &$tabMenu)
+	{
+		global $langs, $user, $conf; // To export to dol_eval function
+		global $mainmenu, $leftmenu; // To export to dol_eval function
+
+		$mainmenu = $mymainmenu; // To export to dol_eval function
+		$leftmenu = $myleftmenu; // To export to dol_eval function
+
+		$newTabMenu = array();
+		foreach ($tabMenu as $val)
+		{
+			if ($val['type'] == 'top') $newTabMenu[] = $val;
+		}
+
+		return $newTabMenu;
+	}
+
+	/**
+	 * 	Load entries found from database (and stored into $tabMenu) in $this->newmenu array.
+	 *  Warning: Entries in $tabMenu must have child after parent
+	 *
+	 * 	@param	Menu	$newmenu        Menu array to complete (in most cases, it's empty, may be already initialized with some menu manager like eldy)
+	 * 	@param	string	$mymainmenu		Value for mainmenu to filter menu to load (often $_SESSION["mainmenu"])
+	 * 	@param	string	$myleftmenu		Value for leftmenu to filter menu to load (always '')
+	 * 	@param	int		$type_user		0=Menu for backoffice, 1=Menu for front office
+	 * 	@param	string	$menu_handler	Filter on name of menu_handler used (auguria, eldy...)
+	 * 	@param  array	$tabMenu       Array with menu entries already loaded
+	 * 	@return Menu    		       	Menu array for particular mainmenu value or full tabArray
+	 */
+	public function menuLeftCharger($newmenu, $mymainmenu, $myleftmenu, $type_user, $menu_handler, &$tabMenu)
+	{
+		global $langs, $user, $conf; // To export to dol_eval function
+		global $mainmenu, $leftmenu; // To export to dol_eval function
+
+		$mainmenu = $mymainmenu; // To export to dol_eval function
+		$leftmenu = $myleftmenu; // To export to dol_eval function
+
+		// Detect what is top mainmenu id
+		$menutopid = '';
+		foreach ($tabMenu as $key => $val)
+		{
+			// Define menutopid of mainmenu
+			if (empty($menutopid) && $val['type'] == 'top' && $val['mainmenu'] == $mainmenu)
+			{
+				$menutopid = $val['rowid'];
+				break;
+			}
+		}
+
+		// We initialize newmenu with first already found menu entries
+		$this->newmenu = $newmenu;
+
+		// Now complete $this->newmenu->list to add entries found into $tabMenu that are childs of mainmenu=$menutopid, using the fk_menu link that is int (old method)
+		$this->recur($tabMenu, $menutopid, 1);
+
+		// Now complete $this->newmenu->list when fk_menu value is -1 (left menu added by modules with no top menu)
+		foreach ($tabMenu as $key => $val)
+		{
+			//var_dump($tabMenu);
+			if ($val['fk_menu'] == -1 && $val['fk_mainmenu'] == $mainmenu)    // We found a menu entry not linked to parent with good mainmenu
+			{
+				//print 'Try to add menu (current is mainmenu='.$mainmenu.' leftmenu='.$leftmenu.') for '.join(',',$val).' fk_mainmenu='.$val['fk_mainmenu'].' fk_leftmenu='.$val['fk_leftmenu'].'<br>';
+				//var_dump($this->newmenu->liste);exit;
+
+				if (empty($val['fk_leftmenu']))
+				{
+					$this->newmenu->add($val['url'], $val['titre'], 0, $val['perms'], $val['target'], $val['mainmenu'], $val['leftmenu'], $val['position']);
+					//var_dump($this->newmenu->liste);
+				} else {
+					// Search first menu with this couple (mainmenu,leftmenu)=(fk_mainmenu,fk_leftmenu)
+					$searchlastsub = 0; $lastid = 0; $nextid = 0; $found = 0;
+					foreach ($this->newmenu->liste as $keyparent => $valparent)
+					{
+						//var_dump($valparent);
+						if ($searchlastsub)    // If we started to search for last submenu
+						{
+							if ($valparent['level'] >= $searchlastsub) $lastid = $keyparent;
+							if ($valparent['level'] < $searchlastsub)
+							{
+								$nextid = $keyparent;
+								break;
+							}
+						}
+						if ($valparent['mainmenu'] == $val['fk_mainmenu'] && $valparent['leftmenu'] == $val['fk_leftmenu'])
+						{
+							//print "We found parent: keyparent='.$keyparent.' - level=".$valparent['level'].' - '.join(',',$valparent).'<br>';
+							// Now we look to find last subelement of this parent (we add at end)
+							$searchlastsub = ($valparent['level'] + 1);
+							$lastid = $keyparent;
+							$found = 1;
+						}
+					}
+					//print 'We must insert menu entry between entry '.$lastid.' and '.$nextid.'<br>';
+					if ($found) $this->newmenu->insert($lastid, $val['url'], $val['titre'], $searchlastsub, $val['perms'], $val['target'], $val['mainmenu'], $val['leftmenu'], $val['position']);
+					else {
+						dol_syslog("Error. Modules ".$val['module']." has defined a menu entry with a parent='fk_mainmenu=".$val['fk_leftmenu'].",fk_leftmenu=".$val['fk_leftmenu']."' and position=".$val['position'].'. The parent was not found. May be you forget it into your definition of menu, or may be the parent has a "position" that is after the child (fix field "position" of parent or child in this case).', LOG_WARNING);
+						//print "Parent menu not found !!<br>";
+					}
+				}
+			}
+		}
+
+		return $this->newmenu;
+	}
+
+
+	/**
+	 *  Load entries found in database into variable $tabMenu. Note that only "database menu entries" are loaded here, hardcoded will not be present into output.
+	 *
+	 *  @param	string	$mymainmenu     Value for mainmenu that defined mainmenu
+	 *  @param	string	$myleftmenu     Value for left that defined leftmenu
+	 *  @param  int		$type_user      Looks for menu entry for 0=Internal users, 1=External users
+	 *  @param  string	$menu_handler   Name of menu_handler used ('auguria', 'eldy'...)
+	 *  @param  array	$tabMenu        Array to store new entries found (in most cases, it's empty, but may be alreay filled)
+	 *  @return int     		        >0 if OK, <0 if KO
+	 */
+	public function menuLoad($mymainmenu, $myleftmenu, $type_user, $menu_handler, &$tabMenu)
+	{
+		global $langs, $user, $conf; // To export to dol_eval function
+		global $mainmenu, $leftmenu; // To export to dol_eval function
+
+		$mainmenu = $mymainmenu; // To export to dol_eval function
+		$leftmenu = $myleftmenu; // To export to dol_eval function
+
+		$sql = "SELECT m.rowid, m.type, m.module, m.fk_menu, m.fk_mainmenu, m.fk_leftmenu, m.url, m.titre, m.langs, m.perms, m.enabled, m.target, m.mainmenu, m.leftmenu, m.position";
+		$sql .= " FROM ".MAIN_DB_PREFIX."menu as m";
+		$sql .= " WHERE m.entity IN (0,".$conf->entity.")";
+		$sql .= " AND m.menu_handler IN ('".$menu_handler."','all')";
+		if ($type_user == 0) $sql .= " AND m.usertype IN (0,2)";
+		if ($type_user == 1) $sql .= " AND m.usertype IN (1,2)";
+		$sql .= " ORDER BY m.position, m.rowid";
+		//print $sql;
+
+		//dol_syslog(get_class($this)."::menuLoad mymainmenu=".$mymainmenu." myleftmenu=".$myleftmenu." type_user=".$type_user." menu_handler=".$menu_handler." tabMenu size=".count($tabMenu)."", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			$numa = $this->db->num_rows($resql);
+
+			$a = 0;
+			$b = 0;
+			while ($a < $numa)
+			{
+				//$objm = $this->db->fetch_object($resql);
+				$menu = $this->db->fetch_array($resql);
+
+				// Define $right
+				$perms = true;
+				if (isset($menu['perms']))
+				{
+					$tmpcond = $menu['perms'];
+					if ($leftmenu == 'all') $tmpcond = preg_replace('/\$leftmenu\s*==\s*["\'a-zA-Z_]+/', '1==1', $tmpcond); // Force part of condition to true
+					$perms = verifCond($tmpcond);
+					//print "verifCond rowid=".$menu['rowid']." ".$tmpcond.":".$perms."<br>\n";
+				}
+
+				// Define $enabled
+				$enabled = true;
+				if (isset($menu['enabled']))
+				{
+					$tmpcond = $menu['enabled'];
+					if ($leftmenu == 'all') $tmpcond = preg_replace('/\$leftmenu\s*==\s*["\'a-zA-Z_]+/', '1==1', $tmpcond); // Force part of condition to true
+					$enabled = verifCond($tmpcond);
+				}
+
+				// Define $title
+				if ($enabled)
+				{
+					$title = $langs->trans($menu['titre']); // If $menu['titre'] start with $, a dol_eval is done.
+					//var_dump($title.'-'.$menu['titre']);
+					if ($title == $menu['titre'])   // Translation not found
+					{
+						if (!empty($menu['langs']))    // If there is a dedicated translation file
+						{
+							//print 'Load file '.$menu['langs'].'<br>';
+							$langs->load($menu['langs']);
+						}
+
+						$substitarray = array('__LOGIN__' => $user->login, '__USER_ID__' => $user->id, '__USER_SUPERVISOR_ID__' => $user->fk_user);
+						$menu['titre'] = make_substitutions($menu['titre'], $substitarray);
+
+						if (preg_match("/\//", $menu['titre'])) // To manage translation when title is string1/string2
+						{
+							$tab_titre = explode("/", $menu['titre']);
+							$title = $langs->trans($tab_titre[0])."/".$langs->trans($tab_titre[1]);
+						} elseif (preg_match('/\|\|/', $menu['titre']))
+						{
+							// To manage different translation (Title||AltTitle@ConditionForAltTitle)
+							$tab_title = explode("||", $menu['titre']);
+							$alt_title = explode("@", $tab_title[1]);
+							$title_enabled = verifCond($alt_title[1]);
+							$title = ($title_enabled ? $langs->trans($alt_title[0]) : $langs->trans($tab_title[0]));
+						} else {
+							$title = $langs->trans($menu['titre']);
+						}
+					}
+					//$tmp4=microtime(true);
+					//print '>>> 3 '.($tmp4 - $tmp3).'<br>';
+
+					// We complete tabMenu
+					$tabMenu[$b]['rowid']       = $menu['rowid'];
+					$tabMenu[$b]['module']      = $menu['module'];
+					$tabMenu[$b]['fk_menu']     = $menu['fk_menu'];
+					$tabMenu[$b]['url']         = $menu['url'];
+					if (!preg_match("/^(http:\/\/|https:\/\/)/i", $tabMenu[$b]['url']))
+					{
+						if (preg_match('/\?/', $tabMenu[$b]['url'])) $tabMenu[$b]['url'] .= '&amp;idmenu='.$menu['rowid'];
+						else $tabMenu[$b]['url'] .= '?idmenu='.$menu['rowid'];
+					}
+					$tabMenu[$b]['titre']       = $title;
+					$tabMenu[$b]['target']      = $menu['target'];
+					$tabMenu[$b]['mainmenu']    = $menu['mainmenu'];
+					$tabMenu[$b]['leftmenu']    = $menu['leftmenu'];
+					$tabMenu[$b]['perms']       = $perms;
+					$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]['fk_mainmenu'] = $menu['fk_mainmenu'];
+					$tabMenu[$b]['fk_leftmenu'] = $menu['fk_leftmenu'];
+					$tabMenu[$b]['position']    = (int) $menu['position'];
+
+					$b++;
+				}
+
+				$a++;
+			}
+			$this->db->free($resql);
+
+			// Currently $tabMenu is sorted on position.
+			// If a child have a position lower that its parent, we can make a loop to fix this here, but we prefer to show a warning
+			// into the leftMenuCharger later to avoid useless operations.
+
+			return 1;
+		} else {
+			dol_print_error($this->db);
+			return -1;
+		}
+	}
+
+	/**
+	 *  Complete this->newmenu with menu entry found in $tab
+	 *
+	 *  @param  array	$tab			Tab array with all menu entries
+	 *  @param  int		$pere			Id of parent
+	 *  @param  int		$level			Level
+	 *  @return	void
+	 */
+	private function recur($tab, $pere, $level)
+	{
+		// Loop on tab array
+		$num = count($tab);
+		for ($x = 0; $x < $num; $x++)
+		{
+			//si un element a pour pere : $pere
+			if ((($tab[$x]['fk_menu'] >= 0 && $tab[$x]['fk_menu'] == $pere)) && $tab[$x]['enabled'])
+			{
+				$this->newmenu->add($tab[$x]['url'], $tab[$x]['titre'], ($level - 1), $tab[$x]['perms'], $tab[$x]['target'], $tab[$x]['mainmenu'], $tab[$x]['leftmenu']);
+				$this->recur($tab, $tab[$x]['rowid'], ($level + 1));
+			}
+		}
+	}
 }

+ 73 - 73
htdocs/core/lib/accounting.lib.php

@@ -173,75 +173,75 @@ function length_accounta($accounta)
  */
 function journalHead($nom, $variante, $period, $periodlink, $description, $builddate, $exportlink = '', $moreparam = array(), $calcmode = '', $varlink = '')
 {
-    global $langs;
-
-    print "\n\n<!-- start banner journal -->\n";
-
-    if (!is_empty($varlink)) $varlink = '?'.$varlink;
-
-    $head = array();
-    $h = 0;
-    $head[$h][0] = $_SERVER["PHP_SELF"].$varlink;
-    $head[$h][1] = $langs->trans("Journalization");
-    $head[$h][2] = 'journal';
-
-    print '<form method="POST" action="'.$_SERVER["PHP_SELF"].$varlink.'">';
-    print '<input type="hidden" name="token" value="'.newToken().'">';
-
-    dol_fiche_head($head, 'journal');
-
-    foreach ($moreparam as $key => $value)
-    {
-        print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
-    }
-    print '<table width="100%" class="border">';
-
-    // Ligne de titre
-    print '<tr>';
-    print '<td width="110">'.$langs->trans("Name").'</td>';
-    print '<td colspan="3">';
-    print $nom;
-    print '</td>';
-    print '</tr>';
-
-    // Calculation mode
-    if ($calcmode)
-    {
-        print '<tr>';
-        print '<td width="110">'.$langs->trans("CalculationMode").'</td>';
-        if (!$variante) print '<td colspan="3">';
-        else print '<td>';
-        print $calcmode;
-        if ($variante) print '</td><td colspan="2">'.$variante;
-        print '</td>';
-        print '</tr>';
-    }
-
-    // Ligne de la periode d'analyse du rapport
-    print '<tr>';
-    print '<td>'.$langs->trans("ReportPeriod").'</td>';
-    if (!$periodlink) print '<td colspan="3">';
-    else print '<td>';
-    if ($period) print $period;
-    if ($periodlink) print '</td><td colspan="2">'.$periodlink;
-    print '</td>';
-    print '</tr>';
-
-    // Ligne de description
-    print '<tr>';
-    print '<td>'.$langs->trans("ReportDescription").'</td>';
-    print '<td colspan="3">'.$description.'</td>';
-    print '</tr>';
-
-    print '</table>';
-
-    dol_fiche_end();
-
-    print '<div class="center"><input type="submit" class="button" name="submit" value="'.$langs->trans("Refresh").'"></div>';
-
-    print '</form>';
-
-    print "\n<!-- end banner journal -->\n\n";
+	global $langs;
+
+	print "\n\n<!-- start banner journal -->\n";
+
+	if (!is_empty($varlink)) $varlink = '?'.$varlink;
+
+	$head = array();
+	$h = 0;
+	$head[$h][0] = $_SERVER["PHP_SELF"].$varlink;
+	$head[$h][1] = $langs->trans("Journalization");
+	$head[$h][2] = 'journal';
+
+	print '<form method="POST" action="'.$_SERVER["PHP_SELF"].$varlink.'">';
+	print '<input type="hidden" name="token" value="'.newToken().'">';
+
+	dol_fiche_head($head, 'journal');
+
+	foreach ($moreparam as $key => $value)
+	{
+		print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
+	}
+	print '<table width="100%" class="border">';
+
+	// Ligne de titre
+	print '<tr>';
+	print '<td width="110">'.$langs->trans("Name").'</td>';
+	print '<td colspan="3">';
+	print $nom;
+	print '</td>';
+	print '</tr>';
+
+	// Calculation mode
+	if ($calcmode)
+	{
+		print '<tr>';
+		print '<td width="110">'.$langs->trans("CalculationMode").'</td>';
+		if (!$variante) print '<td colspan="3">';
+		else print '<td>';
+		print $calcmode;
+		if ($variante) print '</td><td colspan="2">'.$variante;
+		print '</td>';
+		print '</tr>';
+	}
+
+	// Ligne de la periode d'analyse du rapport
+	print '<tr>';
+	print '<td>'.$langs->trans("ReportPeriod").'</td>';
+	if (!$periodlink) print '<td colspan="3">';
+	else print '<td>';
+	if ($period) print $period;
+	if ($periodlink) print '</td><td colspan="2">'.$periodlink;
+	print '</td>';
+	print '</tr>';
+
+	// Ligne de description
+	print '<tr>';
+	print '<td>'.$langs->trans("ReportDescription").'</td>';
+	print '<td colspan="3">'.$description.'</td>';
+	print '</tr>';
+
+	print '</table>';
+
+	dol_fiche_end();
+
+	print '<div class="center"><input type="submit" class="button" name="submit" value="'.$langs->trans("Refresh").'"></div>';
+
+	print '</form>';
+
+	print "\n<!-- end banner journal -->\n\n";
 }
 
 /**
@@ -255,7 +255,7 @@ function getDefaultDatesForTransfer()
 
 	// Period by default on transfer (0: previous month | 1: current month | 2: fiscal year)
 	$periodbydefaultontransfer = $conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER;
-	isset($periodbydefaultontransfer)?$periodbydefaultontransfer:0;
+	isset($periodbydefaultontransfer) ? $periodbydefaultontransfer : 0;
 	if ($periodbydefaultontransfer == 2) {
 		$sql = "SELECT date_start, date_end from ".MAIN_DB_PREFIX."accounting_fiscalyear ";
 		$sql .= " where date_start < '".$db->idate(dol_now())."' and date_end > '".$db->idate(dol_now())."'";
@@ -284,15 +284,15 @@ function getDefaultDatesForTransfer()
 		$pastmonthyear = $year_current;
 		if ($pastmonth == 0) {
 			$pastmonth = 12;
-			$pastmonthyear --;
+			$pastmonthyear--;
 		}
 	} else {
 		$year_current = strftime("%Y", dol_now());
-		$pastmonth = strftime("%m", dol_now())-1;
+		$pastmonth = strftime("%m", dol_now()) - 1;
 		$pastmonthyear = $year_current;
 		if ($pastmonth == 0) {
 			$pastmonth = 12;
-			$pastmonthyear --;
+			$pastmonthyear--;
 		}
 	}
 

+ 11 - 11
htdocs/core/lib/company.lib.php

@@ -1402,32 +1402,32 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin
 			}
 		}
 
-		if (! empty($search_start) && ! empty($search_end)) {
+		if (!empty($search_start) && !empty($search_end)) {
 			$sql .= " AND ((a.datep BETWEEN '$search_start' AND '$search_end') OR (a.datep2 BETWEEN '$search_start' AND '$search_end'))";
 		}
-		elseif (empty($search_start) && ! empty($search_end)) {
+		elseif (empty($search_start) && !empty($search_end)) {
 			$sql .= " AND ((a.datep <= '$search_end') OR (a.datep2 <= '$search_end'))";
 		}
-		elseif (! empty($search_start) && empty($search_end)) {
+		elseif (!empty($search_start) && empty($search_end)) {
 			$sql .= " AND ((a.datep >= '$search_start') OR (a.datep2 >= '$search_start'))";
 		}
 
-		if (is_array($actioncode) && ! empty($actioncode)) {
+		if (is_array($actioncode) && !empty($actioncode)) {
 			$sql .= ' AND (';
 			foreach ($actioncode as $key => $code) {
 				if ($key != 0) $sql .= "OR (";
-				if (! empty($code)) addEventTypeSQL($sql, $code, $donetodo, $now, $filters, "");
+				if (!empty($code)) addEventTypeSQL($sql, $code, $donetodo, $now, $filters, "");
 				if ($key != 0) $sql .= ")";
 			}
 			$sql .= ')';
 		}
-		elseif (! empty($actioncode)) addEventTypeSQL($sql, $actioncode, $donetodo, $now, $filters);
+		elseif (!empty($actioncode)) addEventTypeSQL($sql, $actioncode, $donetodo, $now, $filters);
 
 		if (is_array($actioncode)) {
 			foreach ($actioncode as $code) {
 				$sql2 = addMailingEventTypeSQL($code, $objcon, $filterobj);
-				if (! empty($sql2)) {
-					if (! empty($sql)) $sql = $sql." UNION ".$sql2;
+				if (!empty($sql2)) {
+					if (!empty($sql)) $sql = $sql." UNION ".$sql2;
 					elseif (empty($sql)) $sql = $sql2;
 					break;
 				}
@@ -1435,10 +1435,10 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin
 		}
 		else {
 			$sql2 = addMailingEventTypeSQL($actioncode, $objcon, $filterobj);
-			if (! empty($sql) && ! empty($sql2)) {
+			if (!empty($sql) && !empty($sql2)) {
 				$sql = $sql." UNION ".$sql2;
 			}
-			elseif (empty($sql) && ! empty($sql2)) {
+			elseif (empty($sql) && !empty($sql2)) {
 				$sql = $sql2;
 			}
 		}
@@ -1671,7 +1671,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin
 				$labeltype = $langs->trans("Message");
 			} else {
 				if (!empty($arraylist[$labeltype])) $labeltype = $arraylist[$labeltype];
-				if ($actionstatic->type_code == 'AC_OTH_AUTO' && ($actionstatic->type_code != $actionstatic->code) && $labeltype && !empty($arraylist[$actionstatic->code])) $labeltype .= ' - '.$arraylist[$actionstatic->code];		// Use code in priority on type_code
+				if ($actionstatic->type_code == 'AC_OTH_AUTO' && ($actionstatic->type_code != $actionstatic->code) && $labeltype && !empty($arraylist[$actionstatic->code])) $labeltype .= ' - '.$arraylist[$actionstatic->code]; // Use code in priority on type_code
 			}
 			$out .= dol_trunc($labeltype, 28);
 			$out .= '</td>';

+ 19 - 19
htdocs/core/lib/functions.lib.php

@@ -1063,10 +1063,10 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename =
 	if (empty($conf->syslog->enabled)) return;
 
 	// Check if we are into execution of code of a website
-	if (defined('USEEXTERNALSERVER') && ! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) {
+	if (defined('USEEXTERNALSERVER') && !defined('USEDOLIBARRSERVER') && !defined('USEDOLIBARREDITOR')) {
 		global $website, $websitekey;
-		if (is_object($website) && ! empty($website->ref)) $suffixinfilename.='_website_'.$website->ref;
-		elseif (! empty($websitekey)) $suffixinfilename.='_website_'.$websitekey;
+		if (is_object($website) && !empty($website->ref)) $suffixinfilename .= '_website_'.$website->ref;
+		elseif (!empty($websitekey)) $suffixinfilename .= '_website_'.$websitekey;
 	}
 
 	if ($ident < 0)
@@ -5912,7 +5912,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
 		// Add SIGNATURE into substitutionarray first, so, when we will make the substitution,
 		// this will include signature content first and then replace var found into content of signature
 		$signature = $user->signature;
-        $substitutionarray = array_merge($substitutionarray, array(
+		$substitutionarray = array_merge($substitutionarray, array(
 			'__USER_SIGNATURE__' => (string) (($signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : '')
 		)
 			);
@@ -6184,16 +6184,16 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
 						foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $label) {
 							$substitutionarray['__EXTRAFIELD_'.strtoupper($key).'__'] = $object->array_options['options_'.$key];
 							if ($extrafields->attributes[$object->table_element]['type'][$key] == 'date') {
-                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '__'] = dol_print_date($object->array_options['options_' . $key], 'day');
-                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_LOCALE__'] = dol_print_date($object->array_options['options_' . $key], 'day', 'tzserver', $outputlangs);
-                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_RFC__'] = dol_print_date($object->array_options['options_' . $key], 'dayrfc');
+								$substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '__'] = dol_print_date($object->array_options['options_' . $key], 'day');
+								$substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_LOCALE__'] = dol_print_date($object->array_options['options_' . $key], 'day', 'tzserver', $outputlangs);
+								$substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_RFC__'] = dol_print_date($object->array_options['options_' . $key], 'dayrfc');
 							} elseif ($extrafields->attributes[$object->table_element]['type'][$key] == 'datetime') {
-                                $datetime = $object->array_options['options_'.$key];
-                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhour') : '');
-                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhour', 'tzserver', $outputlangs) : '');
-                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_DAY_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'day', 'tzserver', $outputlangs) : '');
-                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_RFC__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhourrfc') : '');
-                            }
+								$datetime = $object->array_options['options_'.$key];
+								$substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhour') : '');
+								$substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhour', 'tzserver', $outputlangs) : '');
+								$substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_DAY_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'day', 'tzserver', $outputlangs) : '');
+								$substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '_RFC__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhourrfc') : '');
+							}
 						}
 					}
 				}
@@ -6239,12 +6239,12 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
 				if (is_object($object) && $object->element == 'facture') $substitutionarray['__URL_INVOICE__'] = DOL_MAIN_URL_ROOT."/compta/facture/card.php?id=".$object->id;
 			}
 
-            if (is_object($object) && $object->element == 'action')
-            {
-                $substitutionarray['__EVENT_LABEL__'] = $object->label;
-                $substitutionarray['__EVENT_DATE__'] = dol_print_date($object->datep, '%A %d %b %Y');
-                $substitutionarray['__EVENT_TIME__'] = dol_print_date($object->datep, '%H:%M:%S');
-            }
+			if (is_object($object) && $object->element == 'action')
+			{
+				$substitutionarray['__EVENT_LABEL__'] = $object->label;
+				$substitutionarray['__EVENT_DATE__'] = dol_print_date($object->datep, '%A %d %b %Y');
+				$substitutionarray['__EVENT_TIME__'] = dol_print_date($object->datep, '%H:%M:%S');
+			}
 		}
 	}
 	if (empty($exclude) || !in_array('objectamount', $exclude))

+ 2 - 2
htdocs/core/lib/images.lib.php

@@ -41,8 +41,8 @@ function image_format_supported($file, $acceptsvg = 0)
 	global $conf;
 
 	$regeximgext = '\.gif|\.jpg|\.jpeg|\.png|\.bmp|\.webp|\.xpm|\.xbm'; // See also into product.class.php
-	if ($acceptsvg || ! empty($conf->global->MAIN_ALLOW_SVG_FILES_AS_IMAGES)) {
-		$regeximgext .= '|\.svg';		// Not allowed by default. SVG can contains javascript
+	if ($acceptsvg || !empty($conf->global->MAIN_ALLOW_SVG_FILES_AS_IMAGES)) {
+		$regeximgext .= '|\.svg'; // Not allowed by default. SVG can contains javascript
 	}
 
 	// Case filename is not a format image

+ 48 - 48
htdocs/core/lib/ticket.lib.php

@@ -206,54 +206,54 @@ function generate_random_id($car = 16)
  */
 function llxHeaderTicket($title, $head = "", $disablejs = 0, $disablehead = 0, $arrayofjs = '', $arrayofcss = '')
 {
-    global $user, $conf, $langs, $mysoc;
-
-    top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); // Show html headers
-
-    print '<body id="mainbody" class="publicnewticketform">';
-    print '<div class="center">';
-
-    // Define urllogo
-    if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO) || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) {
-        // Print logo
-        if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO))
-        {
-        	$urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png';
-
-        	if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) {
-        		$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_small);
-        	} elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) {
-        		$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/'.$mysoc->logo);
-        	} elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) {
-        		$urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg';
-        	}
-        }
-    }
-
-    // Output html code for logo
-    if ($urllogo || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC))
-    {
-    	print '<div class="backgreypublicpayment">';
-    	print '<div class="logopublicpayment">';
-    	if ($urllogo) {
-	    	print '<a href="'.($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE : dol_buildpath('/public/ticket/index.php', 1)).'">';
-	    	print '<img id="dolpaymentlogo" src="'.$urllogo.'"';
-	    	print '>';
-	    	print '</a>';
-    	}
-    	if (!empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) {
-    		print '<div class="clearboth"></div><strong>'.($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC ? $conf->global->TICKET_PUBLIC_INTERFACE_TOPIC : $langs->trans("TicketSystem")).'</strong>';
-    	}
-    	print '</div>';
-    	if (empty($conf->global->MAIN_HIDE_POWERED_BY)) {
-    		print '<div class="poweredbypublicpayment opacitymedium right"><a href="https://www.dolibarr.org" target="dolibarr">'.$langs->trans("PoweredBy").'<br><img src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg" width="80px"></a></div>';
-    	}
-    	print '</div>';
-    }
-
-    print '</div>';
-
-    print '<div class="ticketlargemargin">';
+	global $user, $conf, $langs, $mysoc;
+
+	top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); // Show html headers
+
+	print '<body id="mainbody" class="publicnewticketform">';
+	print '<div class="center">';
+
+	// Define urllogo
+	if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO) || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) {
+		// Print logo
+		if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO))
+		{
+			$urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png';
+
+			if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) {
+				$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_small);
+			} elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) {
+				$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/'.$mysoc->logo);
+			} elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) {
+				$urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg';
+			}
+		}
+	}
+
+	// Output html code for logo
+	if ($urllogo || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC))
+	{
+		print '<div class="backgreypublicpayment">';
+		print '<div class="logopublicpayment">';
+		if ($urllogo) {
+			print '<a href="'.($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE : dol_buildpath('/public/ticket/index.php', 1)).'">';
+			print '<img id="dolpaymentlogo" src="'.$urllogo.'"';
+			print '>';
+			print '</a>';
+		}
+		if (!empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) {
+			print '<div class="clearboth"></div><strong>'.($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC ? $conf->global->TICKET_PUBLIC_INTERFACE_TOPIC : $langs->trans("TicketSystem")).'</strong>';
+		}
+		print '</div>';
+		if (empty($conf->global->MAIN_HIDE_POWERED_BY)) {
+			print '<div class="poweredbypublicpayment opacitymedium right"><a href="https://www.dolibarr.org" target="dolibarr">'.$langs->trans("PoweredBy").'<br><img src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg" width="80px"></a></div>';
+		}
+		print '</div>';
+	}
+
+	print '</div>';
+
+	print '<div class="ticketlargemargin">';
 }
 
 

+ 6 - 6
htdocs/core/menus/standard/auguria.lib.php

@@ -385,16 +385,16 @@ function print_left_auguria_menu($db, $menu_array_before, $menu_array_after, &$t
 					$nature = '';
 
 					// Must match array $sourceList defined into journals_list.php
-					if ($objp->nature == 2 && ! empty($conf->facture->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_SALES)) $nature="sells";
+					if ($objp->nature == 2 && !empty($conf->facture->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_SALES)) $nature = "sells";
 					if ($objp->nature == 3
 						&& (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_invoice->enabled))
 						&& empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES))
 						$nature = "purchases";
-					if ($objp->nature == 4 && ! empty($conf->banque->enabled)) $nature="bank";
-					if ($objp->nature == 5 && ! empty($conf->expensereport->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS)) $nature="expensereports";
-					if ($objp->nature == 1) $nature="various";
-					if ($objp->nature == 8) $nature="inventory";
-					if ($objp->nature == 9) $nature="hasnew";
+					if ($objp->nature == 4 && !empty($conf->banque->enabled)) $nature = "bank";
+					if ($objp->nature == 5 && !empty($conf->expensereport->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS)) $nature = "expensereports";
+					if ($objp->nature == 1) $nature = "various";
+					if ($objp->nature == 8) $nature = "inventory";
+					if ($objp->nature == 9) $nature = "hasnew";
 
 					// To enable when page exists
 					if (empty($conf->global->ACCOUNTANCY_SHOW_DEVELOP_JOURNAL))

+ 31 - 31
htdocs/core/menus/standard/eldy.lib.php

@@ -1226,35 +1226,35 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM
 					$newmenu->add("/accountancy/admin/export.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("ExportOptions"), 1, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_export', 130);
 				}
 
-                // Transfer in accounting
-                $newmenu->add("/accountancy/index.php?leftmenu=accountancy_transfer", $langs->trans("TransferInAccounting"), 0, $user->rights->accounting->bind->write, '', $mainmenu, 'transfer', 1);
-
-                // Binding
-                // $newmenu->add("", $langs->trans("Binding"), 0, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch');
-                if (!empty($conf->facture->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_SALES))
-                {
-                	$newmenu->add("/accountancy/customer/index.php?leftmenu=accountancy_dispatch_customer&amp;mainmenu=accountancy", $langs->trans("CustomersVentilation"), 1, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch_customer');
-                	if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_dispatch_customer/', $leftmenu)) {
-                		$newmenu->add("/accountancy/customer/list.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_customer", $langs->trans("ToBind"), 2, $user->rights->accounting->bind->write);
-                		$newmenu->add("/accountancy/customer/lines.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_customer", $langs->trans("Binded"), 2, $user->rights->accounting->bind->write);
-                	}
-                }
-                if (!empty($conf->supplier_invoice->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES))
-                {
-                	$newmenu->add("/accountancy/supplier/index.php?leftmenu=accountancy_dispatch_supplier&amp;mainmenu=accountancy", $langs->trans("SuppliersVentilation"), 1, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch_supplier');
-                	if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_dispatch_supplier/', $leftmenu)) {
-                		$newmenu->add("/accountancy/supplier/list.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_supplier", $langs->trans("ToBind"), 2, $user->rights->accounting->bind->write);
-                		$newmenu->add("/accountancy/supplier/lines.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_supplier", $langs->trans("Binded"), 2, $user->rights->accounting->bind->write);
-                	}
-                }
-                if (!empty($conf->expensereport->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS))
-                {
-                	$newmenu->add("/accountancy/expensereport/index.php?leftmenu=accountancy_dispatch_expensereport&amp;mainmenu=accountancy", $langs->trans("ExpenseReportsVentilation"), 1, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch_expensereport');
-                	if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_dispatch_expensereport/', $leftmenu)) {
-                		$newmenu->add("/accountancy/expensereport/list.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_expensereport", $langs->trans("ToBind"), 2, $user->rights->accounting->bind->write);
-                		$newmenu->add("/accountancy/expensereport/lines.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_expensereport", $langs->trans("Binded"), 2, $user->rights->accounting->bind->write);
-                	}
-                }
+				// Transfer in accounting
+				$newmenu->add("/accountancy/index.php?leftmenu=accountancy_transfer", $langs->trans("TransferInAccounting"), 0, $user->rights->accounting->bind->write, '', $mainmenu, 'transfer', 1);
+
+				// Binding
+				// $newmenu->add("", $langs->trans("Binding"), 0, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch');
+				if (!empty($conf->facture->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_SALES))
+				{
+					$newmenu->add("/accountancy/customer/index.php?leftmenu=accountancy_dispatch_customer&amp;mainmenu=accountancy", $langs->trans("CustomersVentilation"), 1, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch_customer');
+					if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_dispatch_customer/', $leftmenu)) {
+						$newmenu->add("/accountancy/customer/list.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_customer", $langs->trans("ToBind"), 2, $user->rights->accounting->bind->write);
+						$newmenu->add("/accountancy/customer/lines.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_customer", $langs->trans("Binded"), 2, $user->rights->accounting->bind->write);
+					}
+				}
+				if (!empty($conf->supplier_invoice->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES))
+				{
+					$newmenu->add("/accountancy/supplier/index.php?leftmenu=accountancy_dispatch_supplier&amp;mainmenu=accountancy", $langs->trans("SuppliersVentilation"), 1, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch_supplier');
+					if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_dispatch_supplier/', $leftmenu)) {
+						$newmenu->add("/accountancy/supplier/list.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_supplier", $langs->trans("ToBind"), 2, $user->rights->accounting->bind->write);
+						$newmenu->add("/accountancy/supplier/lines.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_supplier", $langs->trans("Binded"), 2, $user->rights->accounting->bind->write);
+					}
+				}
+				if (!empty($conf->expensereport->enabled) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS))
+				{
+					$newmenu->add("/accountancy/expensereport/index.php?leftmenu=accountancy_dispatch_expensereport&amp;mainmenu=accountancy", $langs->trans("ExpenseReportsVentilation"), 1, $user->rights->accounting->bind->write, '', $mainmenu, 'dispatch_expensereport');
+					if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_dispatch_expensereport/', $leftmenu)) {
+						$newmenu->add("/accountancy/expensereport/list.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_expensereport", $langs->trans("ToBind"), 2, $user->rights->accounting->bind->write);
+						$newmenu->add("/accountancy/expensereport/lines.php?mainmenu=accountancy&amp;leftmenu=accountancy_dispatch_expensereport", $langs->trans("Binded"), 2, $user->rights->accounting->bind->write);
+					}
+				}
 
 				// Journals
 				if (!empty($conf->accounting->enabled) && !empty($user->rights->accounting->comptarapport->lire) && $mainmenu == 'accountancy')
@@ -1450,8 +1450,8 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM
 				$newmenu->add("/asset/type.php?leftmenu=asset_type", $langs->trans("MenuTypeAssets"), 1, $user->rights->asset->read, '', $mainmenu, 'asset_type');
 				if ($usemenuhider || empty($leftmenu) || preg_match('/asset_type/', $leftmenu)) {
 					$newmenu->add("/asset/type.php?leftmenu=asset_type&amp;action=create", $langs->trans("MenuNewTypeAssets"), 2, (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->setup_advance));
-                    $newmenu->add("/asset/type.php?leftmenu=asset_type", $langs->trans("MenuListTypeAssets"), 2, $user->rights->asset->read);
-                }
+					$newmenu->add("/asset/type.php?leftmenu=asset_type", $langs->trans("MenuListTypeAssets"), 2, $user->rights->asset->read);
+				}
 			}
 		}
 

File diff suppressed because it is too large
+ 2179 - 2179
htdocs/core/modules/DolibarrModules.class.php


+ 33 - 33
htdocs/core/modules/expensereport/doc/pdf_standard.modules.php

@@ -349,57 +349,57 @@ class pdf_standard extends ModeleExpenseReport
 				$pdf->setTopMargin($tab_top_newpage);
 				// Loop on each lines
 				$i = 0;
-                while ($i < $nblines) {
+				while ($i < $nblines) {
 					$pdf->SetFont('', '', $default_font_size - 2); // Into loop to work with multipage
 					$pdf->SetTextColor(0, 0, 0);
 
 					$pdf->setTopMargin($tab_top_newpage);
-                    if (empty($showpricebeforepagebreak) && ($i !== ($nblines - 1))) {
-                        $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
-                    } else {
-                        $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
-                    }
+					if (empty($showpricebeforepagebreak) && ($i !== ($nblines - 1))) {
+						$pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
+					} else {
+						$pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
+					}
 
 					$pageposbefore = $pdf->getPage();
-                    $curY = $nexY;
-                    $pdf->startTransaction();
-                    $this->printLine($pdf, $object, $i, $curY, $default_font_size, $outputlangs, $hidedetails);
-                    $pageposafter = $pdf->getPage();
+					$curY = $nexY;
+					$pdf->startTransaction();
+					$this->printLine($pdf, $object, $i, $curY, $default_font_size, $outputlangs, $hidedetails);
+					$pageposafter = $pdf->getPage();
 					if ($pageposafter > $pageposbefore) {
-                        // There is a pagebreak
+						// There is a pagebreak
 						$pdf->rollbackTransaction(true);
 						$pageposafter = $pageposbefore;
 						//print $pageposafter.'-'.$pageposbefore;exit;
 						if (empty($showpricebeforepagebreak)) {
-                            $pdf->AddPage('', '', true);
-                            if (!empty($tplidx)) {
-                                $pdf->useTemplate($tplidx);
-                            }
-                            if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
-                                 $this->_pagehead($pdf, $object, 0, $outputlangs);
-                            }
-                            $pdf->setPage($pageposafter + 1);
-                            $showpricebeforepagebreak = 1;
-                            $nexY = $tab_top_newpage;
-                            $nexY += ($pdf->getFontSize() * 1.3); // Add space between lines
-                            $pdf->SetFont('', '', $default_font_size - 2); // Into loop to work with multipage
-                            $pdf->SetTextColor(0, 0, 0);
-
-                            $pdf->setTopMargin($tab_top_newpage);
-                            continue;
-                        } else {
-                            $pdf->setPageOrientation('', 1, $heightforfooter);
-                            $showpricebeforepagebreak = 0;
-                        }
+							$pdf->AddPage('', '', true);
+							if (!empty($tplidx)) {
+								$pdf->useTemplate($tplidx);
+							}
+							if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
+								 $this->_pagehead($pdf, $object, 0, $outputlangs);
+							}
+							$pdf->setPage($pageposafter + 1);
+							$showpricebeforepagebreak = 1;
+							$nexY = $tab_top_newpage;
+							$nexY += ($pdf->getFontSize() * 1.3); // Add space between lines
+							$pdf->SetFont('', '', $default_font_size - 2); // Into loop to work with multipage
+							$pdf->SetTextColor(0, 0, 0);
+
+							$pdf->setTopMargin($tab_top_newpage);
+							continue;
+						} else {
+							$pdf->setPageOrientation('', 1, $heightforfooter);
+							$showpricebeforepagebreak = 0;
+						}
 
 						$this->printLine($pdf, $object, $i, $curY, $default_font_size, $outputlangs, $hidedetails);
 						$pageposafter = $pdf->getPage();
 						$posyafter = $pdf->GetY();
 						//var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
 						if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) {
-                            // There is no space left for total+free text
+							// There is no space left for total+free text
 							if ($i == ($nblines - 1)) {
-                                // No more lines, and no space left to show total, so we create a new page
+								// No more lines, and no space left to show total, so we create a new page
 								$pdf->AddPage('', '', true);
 								if (!empty($tplidx)) $pdf->useTemplate($tplidx);
 								if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);

+ 3 - 3
htdocs/core/tpl/objectline_create.tpl.php

@@ -426,13 +426,13 @@ if ((!empty($conf->service->enabled) || ($object->element == 'contrat')) && $dat
 
 	$prefillDates = false;
 
-	if (!empty($conf->global->MAIN_FILL_SERVICE_DATES_FROM_LAST_SERVICE_LINE) && ! empty($object->lines))
+	if (!empty($conf->global->MAIN_FILL_SERVICE_DATES_FROM_LAST_SERVICE_LINE) && !empty($object->lines))
 	{
 		for ($i = count($object->lines) - 1; $i >= 0; $i--)
 		{
 			$lastline = $object->lines[$i];
 
-			if ($lastline->product_type == Product::TYPE_SERVICE && (! empty($lastline->date_start) || ! empty($lastline->date_end)))
+			if ($lastline->product_type == Product::TYPE_SERVICE && (!empty($lastline->date_start) || !empty($lastline->date_end)))
 			{
 				$date_start_prefill = $lastline->date_start;
 				$date_end_prefill = $lastline->date_end;
@@ -459,7 +459,7 @@ if ((!empty($conf->service->enabled) || ($object->element == 'contrat')) && $dat
 
 	if ($prefillDates)
 	{
-		echo ' <span class="small"><a href="#" id="prefill_service_dates">' . $langs->trans('FillWithLastServiceDates') .  '</a></span>';
+		echo ' <span class="small"><a href="#" id="prefill_service_dates">'.$langs->trans('FillWithLastServiceDates').'</a></span>';
 	}
 
 	print '<script>';

+ 76 - 76
htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php

@@ -756,64 +756,64 @@ class InterfaceActionsAuto extends DolibarrTriggers
 			$object->sendtoid = 0;
 		} elseif ($action == 'TICKET_ASSIGNED')
 		{
-		    // Load translation files required by the page
-		    $langs->loadLangs(array("agenda", "other", "projects"));
-
-		    if (empty($object->actionmsg2)) $object->actionmsg2 = $langs->transnoentities("TICKET_ASSIGNEDInDolibarr", $object->ref);
-		    $object->actionmsg = $langs->transnoentities("TICKET_ASSIGNEDInDolibarr", $object->ref);
-		    if ($object->oldcopy->fk_user_assign > 0)
-		    {
-		        $tmpuser = new User($this->db);
-		        $tmpuser->fetch($object->oldcopy->fk_user_assign);
-		        $object->actionmsg .= "\n".$langs->transnoentities("OldUser").': '.$tmpuser->getFullName($langs);
-		    } else {
-		        $object->actionmsg .= "\n".$langs->transnoentities("OldUser").': '.$langs->trans("None");
-		    }
-		    if ($object->fk_user_assign > 0)
-		    {
-		        $tmpuser = new User($this->db);
-		        $tmpuser->fetch($object->fk_user_assign);
-		        $object->actionmsg .= "\n".$langs->transnoentities("NewUser").': '.$tmpuser->getFullName($langs);
-		    } else {
-		        $object->actionmsg .= "\n".$langs->transnoentities("NewUser").': '.$langs->trans("None");
-		    }
-		    $object->sendtoid = 0;
+			// Load translation files required by the page
+			$langs->loadLangs(array("agenda", "other", "projects"));
+
+			if (empty($object->actionmsg2)) $object->actionmsg2 = $langs->transnoentities("TICKET_ASSIGNEDInDolibarr", $object->ref);
+			$object->actionmsg = $langs->transnoentities("TICKET_ASSIGNEDInDolibarr", $object->ref);
+			if ($object->oldcopy->fk_user_assign > 0)
+			{
+				$tmpuser = new User($this->db);
+				$tmpuser->fetch($object->oldcopy->fk_user_assign);
+				$object->actionmsg .= "\n".$langs->transnoentities("OldUser").': '.$tmpuser->getFullName($langs);
+			} else {
+				$object->actionmsg .= "\n".$langs->transnoentities("OldUser").': '.$langs->trans("None");
+			}
+			if ($object->fk_user_assign > 0)
+			{
+				$tmpuser = new User($this->db);
+				$tmpuser->fetch($object->fk_user_assign);
+				$object->actionmsg .= "\n".$langs->transnoentities("NewUser").': '.$tmpuser->getFullName($langs);
+			} else {
+				$object->actionmsg .= "\n".$langs->transnoentities("NewUser").': '.$langs->trans("None");
+			}
+			$object->sendtoid = 0;
 		}
 		// TODO Merge all previous cases into this generic one
 		else // $action = BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ...
 		{
-		    // Note: We are here only if $conf->global->MAIN_AGENDA_ACTIONAUTO_action is on (tested at begining of this function).
-		    // Note that these key can be set in agenda setup, only if defined into c_action_trigger
-		    // Load translation files required by the page
-            if (empty($object->actionmsg2)) {
-            	$langs->loadLangs(array("agenda", "other"));
-            	if ($langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref)) != $action."InDolibarr") {	// specific translation key
-            		$object->actionmsg2 = $langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref));
-            	} else {	// generic translation key
-            		$tmp = explode('_', $action);
-            		$object->actionmsg2 = $langs->transnoentities($tmp[count($tmp)-1]."InDolibarr", ($object->newref ? $object->newref : $object->ref));
-            	}
-            }
-            if (empty($object->actionmsg))  {
-            	$langs->loadLangs(array("agenda", "other"));
-            	if ($langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref)) != $action."InDolibarr") {	// specific translation key
-            		$object->actionmsg = $langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref));
-            	} else {	// generic translation key
-            		$tmp = explode('_', $action);
-            		$object->actionmsg = $langs->transnoentities($tmp[count($tmp)-1]."InDolibarr", ($object->newref ? $object->newref : $object->ref));
-            	}
-            }
-
-		    if (!isset($object->sendtoid) || !is_array($object->sendtoid)) {
-		    	$object->sendtoid = 0;
-		    }
+			// Note: We are here only if $conf->global->MAIN_AGENDA_ACTIONAUTO_action is on (tested at begining of this function).
+			// Note that these key can be set in agenda setup, only if defined into c_action_trigger
+			// Load translation files required by the page
+			if (empty($object->actionmsg2)) {
+				$langs->loadLangs(array("agenda", "other"));
+				if ($langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref)) != $action."InDolibarr") {	// specific translation key
+					$object->actionmsg2 = $langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref));
+				} else {	// generic translation key
+					$tmp = explode('_', $action);
+					$object->actionmsg2 = $langs->transnoentities($tmp[count($tmp)-1]."InDolibarr", ($object->newref ? $object->newref : $object->ref));
+				}
+			}
+			if (empty($object->actionmsg))  {
+				$langs->loadLangs(array("agenda", "other"));
+				if ($langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref)) != $action."InDolibarr") {	// specific translation key
+					$object->actionmsg = $langs->transnoentities($action."InDolibarr", ($object->newref ? $object->newref : $object->ref));
+				} else {	// generic translation key
+					$tmp = explode('_', $action);
+					$object->actionmsg = $langs->transnoentities($tmp[count($tmp)-1]."InDolibarr", ($object->newref ? $object->newref : $object->ref));
+				}
+			}
+
+			if (!isset($object->sendtoid) || !is_array($object->sendtoid)) {
+				$object->sendtoid = 0;
+			}
 		}
 
 		$object->actionmsg = $langs->transnoentities("Author").': '.$user->login."\n".$object->actionmsg;
 
 		dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
 
-        // Add entry in event table
+		// Add entry in event table
 		$now = dol_now();
 
 		if (isset($_SESSION['listofnames-'.$object->trackid]))
@@ -821,37 +821,37 @@ class InterfaceActionsAuto extends DolibarrTriggers
 			$attachs = $_SESSION['listofnames-'.$object->trackid];
 			if ($attachs && strpos($action, 'SENTBYMAIL'))
 			{
-                $object->actionmsg = dol_concatdesc($object->actionmsg, "\n".$langs->transnoentities("AttachedFiles").': '.$attachs);
+				$object->actionmsg = dol_concatdesc($object->actionmsg, "\n".$langs->transnoentities("AttachedFiles").': '.$attachs);
 			}
 		}
-        require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
-        require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
+		require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
+		require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
 		$contactforaction = new Contact($this->db);
-        $societeforaction = new Societe($this->db);
-        // Set contactforaction if there is only 1 contact.
-
-        if (is_array($object->sendtoid))
-        {
-            if (count($object->sendtoid) == 1) $contactforaction->fetch(reset($object->sendtoid));
-        } else {
-            if ($object->sendtoid > 0) $contactforaction->fetch($object->sendtoid);
-        }
-        // Set societeforaction.
-        if ($object->socid > 0)			$societeforaction->fetch($object->socid);
-        elseif ($object->fk_soc > 0)	$societeforaction->fetch($object->fk_soc);
-
-        $projectid = isset($object->fk_project) ? $object->fk_project : 0;
-        if ($object->element == 'project') $projectid = $object->id;
-
-        $elementid = $object->id;			// id of object
-        $elementtype = $object->element;
-        $elementmodule = $object->module;
-        if ($object->element == 'subscription')
-        {
-        	$elementid = $object->fk_adherent;
-        	$elementtype = 'member';
-        }
-        //var_dump($societeforaction);var_dump($contactforaction);var_dump($elementid);var_dump($elementtype);exit;
+		$societeforaction = new Societe($this->db);
+		// Set contactforaction if there is only 1 contact.
+
+		if (is_array($object->sendtoid))
+		{
+			if (count($object->sendtoid) == 1) $contactforaction->fetch(reset($object->sendtoid));
+		} else {
+			if ($object->sendtoid > 0) $contactforaction->fetch($object->sendtoid);
+		}
+		// Set societeforaction.
+		if ($object->socid > 0)			$societeforaction->fetch($object->socid);
+		elseif ($object->fk_soc > 0)	$societeforaction->fetch($object->fk_soc);
+
+		$projectid = isset($object->fk_project) ? $object->fk_project : 0;
+		if ($object->element == 'project') $projectid = $object->id;
+
+		$elementid = $object->id;			// id of object
+		$elementtype = $object->element;
+		$elementmodule = $object->module;
+		if ($object->element == 'subscription')
+		{
+			$elementid = $object->fk_adherent;
+			$elementtype = 'member';
+		}
+		//var_dump($societeforaction);var_dump($contactforaction);var_dump($elementid);var_dump($elementtype);exit;
 
 		// Insertion action
 		require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';

+ 7 - 7
htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php

@@ -197,9 +197,9 @@ class InterfaceTicketEmail extends DolibarrTriggers
 						$subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketNewEmailSubjectAdmin');
 						$message_admin = $langs->transnoentities('TicketNewEmailBodyAdmin', $object->track_id).'<br><br>';
 						$message_admin .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
-						$message_admin .= '<li>' . $langs->trans('Type') . ' : ' . $langs->getLabelFromKey($this->db, 'TicketTypeShort' . $object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code) . '</li>';
-						$message_admin .= '<li>' . $langs->trans('Category') . ' : ' . $langs->getLabelFromKey($this->db, 'TicketCategoryShort' . $object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code) . '</li>';
-						$message_admin .= '<li>' . $langs->trans('Severity') . ' : ' . $langs->getLabelFromKey($this->db, 'TicketSeverityShort' . $object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code) . '</li>';
+						$message_admin .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
+						$message_admin .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
+						$message_admin .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
 						$message_admin .= '<li>'.$langs->trans('From').' : '.($object->email_from ? $object->email_from : ($object->fk_user_create > 0 ? $langs->trans('Internal') : '')).'</li>';
 						// Extrafields
 						$extraFields = new ExtraFields($this->db);
@@ -207,7 +207,7 @@ class InterfaceTicketEmail extends DolibarrTriggers
 						if (is_array($object->array_options) && count($object->array_options) > 0) {
 							foreach ($object->array_options as $key => $value) {
 								$key = substr($key, 8); // remove "options_"
-								$message_admin .= '<li>' . $langs->trans($extraFields->attributes[$object->element]['label'][$key]) . ' : ' . $extraFields->showOutputField($key, $value) . '</li>';
+								$message_admin .= '<li>'.$langs->trans($extraFields->attributes[$object->element]['label'][$key]).' : '.$extraFields->showOutputField($key, $value).'</li>';
 							}
 						}
 						$message_admin .= '</ul>';
@@ -267,9 +267,9 @@ class InterfaceTicketEmail extends DolibarrTriggers
 						$subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketNewEmailSubjectCustomer');
 						$message_customer = $langs->transnoentities('TicketNewEmailBodyCustomer', $object->track_id).'<br><br>';
 						$message_customer .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
-						$message_customer .= '<li>' . $langs->trans('Type') . ' : ' . $langs->getLabelFromKey($this->db, 'TicketTypeShort' . $object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code) . '</li>';
-						$message_customer .= '<li>' . $langs->trans('Category') . ' : ' . $langs->getLabelFromKey($this->db, 'TicketCategoryShort' . $object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code) . '</li>';
-						$message_customer .= '<li>' . $langs->trans('Severity') . ' : ' . $langs->getLabelFromKey($this->db, 'TicketSeverityShort' . $object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code) . '</li>';
+						$message_customer .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
+						$message_customer .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
+						$message_customer .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
 
 						// Extrafields
 						foreach ($this->attributes[$object->table_element]['label'] as $key => $value)

+ 5 - 5
htdocs/debugbar/class/DebugBar.php

@@ -51,10 +51,10 @@ class DolibarrDebugBar extends DebugBar
 	 */
 	public function getRenderer()
 	{
-	    $renderer = parent::getJavascriptRenderer(DOL_URL_ROOT.'/includes/maximebf/debugbar/src/DebugBar/Resources');
-	    //$renderer->disableVendor('jquery');
-	    $renderer->disableVendor('fontawesome');
-	    $renderer->disableVendor('highlightjs');
-	    return $renderer;
+		$renderer = parent::getJavascriptRenderer(DOL_URL_ROOT.'/includes/maximebf/debugbar/src/DebugBar/Resources');
+		//$renderer->disableVendor('jquery');
+		$renderer->disableVendor('fontawesome');
+		$renderer->disableVendor('highlightjs');
+		return $renderer;
 	}
 }

+ 28 - 28
htdocs/debugbar/class/autoloader.php

@@ -4,33 +4,33 @@
  * Simple autoloader, so we don't need Composer just for this.
  */
 
-spl_autoload_register(function ($class) {
+spl_autoload_register(function($class) {
 	if (preg_match('/^DebugBar/', $class)) {
-        $file = DOL_DOCUMENT_ROOT.'/includes/maximebf/debugbar/src/'.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
-        //var_dump($class.' - '.file_exists($file).' - '.$file);
-        if (file_exists($file)) {
-    		require_once $file;
-    		return true;
-    	}
-    	return false;
-    }
-    if (preg_match('/^'.preg_quote('Psr\Log', '/').'/', $class)) {
-    	$file = DOL_DOCUMENT_ROOT.'/includes/'.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
-    	//var_dump($class.' - '.file_exists($file).' - '.$file);
-    	if (file_exists($file)) {
-    		require_once $file;
-    		return true;
-    	}
-    	return false;
-    }
-    if (preg_match('/^'.preg_quote('Symfony\Component\VarDumper', '/').'/', $class)) {
-    	$class = preg_replace('/'.preg_quote('Symfony\Component\VarDumper', '/').'/', '', $class);
-    	$file = DOL_DOCUMENT_ROOT.'/includes/symfony/var-dumper/'.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
-    	if (file_exists($file)) {
-    		require_once $file;
-    		return true;
-    	}
-    	return false;
-    }
-    return true;
+		$file = DOL_DOCUMENT_ROOT.'/includes/maximebf/debugbar/src/'.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
+		//var_dump($class.' - '.file_exists($file).' - '.$file);
+		if (file_exists($file)) {
+			require_once $file;
+			return true;
+		}
+		return false;
+	}
+	if (preg_match('/^'.preg_quote('Psr\Log', '/').'/', $class)) {
+		$file = DOL_DOCUMENT_ROOT.'/includes/'.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
+		//var_dump($class.' - '.file_exists($file).' - '.$file);
+		if (file_exists($file)) {
+			require_once $file;
+			return true;
+		}
+		return false;
+	}
+	if (preg_match('/^'.preg_quote('Symfony\Component\VarDumper', '/').'/', $class)) {
+		$class = preg_replace('/'.preg_quote('Symfony\Component\VarDumper', '/').'/', '', $class);
+		$file = DOL_DOCUMENT_ROOT.'/includes/symfony/var-dumper/'.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
+		if (file_exists($file)) {
+			require_once $file;
+			return true;
+		}
+		return false;
+	}
+	return true;
 });

File diff suppressed because it is too large
+ 916 - 916
htdocs/emailcollector/class/emailcollector.class.php


+ 137 - 137
htdocs/expedition/card.php

@@ -1005,191 +1005,191 @@ if ($action == 'create')
 			}
 
 
-            // Incoterms
+			// Incoterms
 			if (!empty($conf->incoterm->enabled))
 			{
 				print '<tr>';
 				print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->label_incoterms, 1).'</label></td>';
-		        print '<td colspan="3" class="maxwidthonsmartphone">';
-		        print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''));
+				print '<td colspan="3" class="maxwidthonsmartphone">';
+				print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''));
 				print '</td></tr>';
 			}
 
-            // Document model
+			// Document model
 			include_once DOL_DOCUMENT_ROOT.'/core/modules/expedition/modules_expedition.php';
 			$liste = ModelePdfExpedition::liste_modeles($db);
 			if (count($liste) > 1)
 			{
-    			print "<tr><td>".$langs->trans("DefaultModel")."</td>";
-                print '<td colspan="3">';
-    			print $form->selectarray('model', $liste, $conf->global->EXPEDITION_ADDON_PDF);
-                print "</td></tr>\n";
+				print "<tr><td>".$langs->trans("DefaultModel")."</td>";
+				print '<td colspan="3">';
+				print $form->selectarray('model', $liste, $conf->global->EXPEDITION_ADDON_PDF);
+				print "</td></tr>\n";
 			}
 
-            print "</table>";
+			print "</table>";
 
-            dol_fiche_end();
+			dol_fiche_end();
 
 
-            // Shipment lines
+			// Shipment lines
 
-            $numAsked = count($object->lines);
+			$numAsked = count($object->lines);
 
-            print '<script type="text/javascript" language="javascript">
+			print '<script type="text/javascript" language="javascript">
             jQuery(document).ready(function() {
 	            jQuery("#autofill").click(function() {';
-    	    $i = 0;
-    	    while ($i < $numAsked)
-    	    {
-    	    	print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
-                if (!empty($conf->productbatch->enabled)) print 'jQuery("#qtyl'.$i.'_'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
-    	    	$i++;
-    	    }
-        	print '});
+			$i = 0;
+			while ($i < $numAsked)
+			{
+				print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
+				if (!empty($conf->productbatch->enabled)) print 'jQuery("#qtyl'.$i.'_'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
+				$i++;
+			}
+			print '});
 	            jQuery("#autoreset").click(function() {';
-    	    $i = 0;
-    	    while ($i < $numAsked)
-    	    {
-    	    	print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
-                if (!empty($conf->productbatch->enabled)) print 'jQuery("#qtyl'.$i.'_'.$i.'").val(0);'."\n";
-    	    	$i++;
-    	    }
-        	print '});
+			$i = 0;
+			while ($i < $numAsked)
+			{
+				print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
+				if (!empty($conf->productbatch->enabled)) print 'jQuery("#qtyl'.$i.'_'.$i.'").val(0);'."\n";
+				$i++;
+			}
+			print '});
         	});
             </script>';
 
-            print '<br>';
+			print '<br>';
 
-            print '<table class="noborder centpercent">';
+			print '<table class="noborder centpercent">';
 
-            // Load shipments already done for same order
-            $object->loadExpeditions();
+			// Load shipments already done for same order
+			$object->loadExpeditions();
 
-            if ($numAsked)
-            {
-                print '<tr class="liste_titre">';
-                print '<td>'.$langs->trans("Description").'</td>';
-                print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
-                print '<td class="center">'.$langs->trans("QtyShipped").'</td>';
-                print '<td class="center">'.$langs->trans("QtyToShip");
+			if ($numAsked)
+			{
+				print '<tr class="liste_titre">';
+				print '<td>'.$langs->trans("Description").'</td>';
+				print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
+				print '<td class="center">'.$langs->trans("QtyShipped").'</td>';
+				print '<td class="center">'.$langs->trans("QtyToShip");
 				if (empty($conf->productbatch->enabled))
 				{
-	                print '<br><a href="#" id="autofill">'.$langs->trans("Fill").'</a>';
-	                print ' / ';
+					print '<br><a href="#" id="autofill">'.$langs->trans("Fill").'</a>';
+					print ' / ';
 				} else {
 					print '<br>';
 				}
 				print '<a href="#" id="autoreset">'.$langs->trans("Reset").'</a>';
-                print '</td>';
-                if (!empty($conf->stock->enabled))
-                {
+				print '</td>';
+				if (!empty($conf->stock->enabled))
+				{
 					if (empty($conf->productbatch->enabled))
 					{
-                    	print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
+						print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
 					} else {
 						print '<td class="left">'.$langs->trans("Warehouse").' / '.$langs->trans("Batch").' ('.$langs->trans("Stock").')</td>';
 					}
-                }
-                print "</tr>\n";
-            }
-
-            $indiceAsked = 0;
-            while ($indiceAsked < $numAsked)
-            {
-                $product = new Product($db);
-
-                $line = $object->lines[$indiceAsked];
-
-                $parameters = array('i' => $indiceAsked, 'line' => $line, 'num' => $numAsked);
-                $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action);
-                if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
-
-                if (empty($reshook))
-                {
-	                // Show product and description
-	                $type = $line->product_type ? $line->product_type : $line->fk_product_type;
-	                // Try to enhance type detection using date_start and date_end for free lines where type
-	                // was not saved.
-	                if (!empty($line->date_start)) $type = 1;
-	                if (!empty($line->date_end)) $type = 1;
-
-	                print '<!-- line '.$line->rowid.' for product -->'."\n";
-	                print '<tr class="oddeven">'."\n";
-
-	                // Product label
-	                if ($line->fk_product > 0)  // If predefined product
-	                {
-	                    $product->fetch($line->fk_product);
-	                    $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
-	                    //var_dump($product->stock_warehouse[1]);
-
-	                    print '<td>';
-	                    print '<a name="'.$line->rowid.'"></a>'; // ancre pour retourner sur la ligne
-
-	                    // Show product and description
-	                    $product_static->type = $line->fk_product_type;
-	                    $product_static->id = $line->fk_product;
-	                    $product_static->ref = $line->ref;
-	                    $product_static->status_batch = $line->product_tobatch;
-	                    $text = $product_static->getNomUrl(1);
-	                    $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
-	                    $description = ($conf->global->PRODUIT_DESC_IN_FORM ? '' : dol_htmlentitiesbr($line->desc));
-	                    print $form->textwithtooltip($text, $description, 3, '', '', $i);
-
-	                    // Show range
-	                    print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
-
-	                    // Add description in form
-	                    if (!empty($conf->global->PRODUIT_DESC_IN_FORM))
-	                    {
-	                        print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
-	                    }
-
-	                    print '</td>';
-	                } else {
-					    print "<td>";
-	                    if ($type == 1) $text = img_object($langs->trans('Service'), 'service');
-	                    else $text = img_object($langs->trans('Product'), 'product');
-
-	                    if (!empty($line->label)) {
-	                    	$text .= ' <strong>'.$line->label.'</strong>';
-	                    	print $form->textwithtooltip($text, $line->desc, 3, '', '', $i);
-	                    } else {
-	                    	print $text.' '.nl2br($line->desc);
-	                    }
-
-	                    // Show range
-	                    print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
-	                    print "</td>\n";
-	                }
-
-	                // Qty
-	                print '<td class="center">'.$line->qty;
-	                print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
-	                print '</td>';
-	                $qtyProdCom = $line->qty;
-
-	                // Qty already shipped
-	                print '<td class="center">';
-	                $quantityDelivered = $object->expeditions[$line->id];
-	                print $quantityDelivered;
-	                print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
-	                print '</td>';
-
-	                // Qty to ship
-	                $quantityAsked = $line->qty;
+				}
+				print "</tr>\n";
+			}
+
+			$indiceAsked = 0;
+			while ($indiceAsked < $numAsked)
+			{
+				$product = new Product($db);
+
+				$line = $object->lines[$indiceAsked];
+
+				$parameters = array('i' => $indiceAsked, 'line' => $line, 'num' => $numAsked);
+				$reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action);
+				if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+
+				if (empty($reshook))
+				{
+					// Show product and description
+					$type = $line->product_type ? $line->product_type : $line->fk_product_type;
+					// Try to enhance type detection using date_start and date_end for free lines where type
+					// was not saved.
+					if (!empty($line->date_start)) $type = 1;
+					if (!empty($line->date_end)) $type = 1;
+
+					print '<!-- line '.$line->rowid.' for product -->'."\n";
+					print '<tr class="oddeven">'."\n";
+
+					// Product label
+					if ($line->fk_product > 0)  // If predefined product
+					{
+						$product->fetch($line->fk_product);
+						$product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
+						//var_dump($product->stock_warehouse[1]);
+
+						print '<td>';
+						print '<a name="'.$line->rowid.'"></a>'; // ancre pour retourner sur la ligne
+
+						// Show product and description
+						$product_static->type = $line->fk_product_type;
+						$product_static->id = $line->fk_product;
+						$product_static->ref = $line->ref;
+						$product_static->status_batch = $line->product_tobatch;
+						$text = $product_static->getNomUrl(1);
+						$text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
+						$description = ($conf->global->PRODUIT_DESC_IN_FORM ? '' : dol_htmlentitiesbr($line->desc));
+						print $form->textwithtooltip($text, $description, 3, '', '', $i);
+
+						// Show range
+						print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
+
+						// Add description in form
+						if (!empty($conf->global->PRODUIT_DESC_IN_FORM))
+						{
+							print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
+						}
+
+						print '</td>';
+					} else {
+						print "<td>";
+						if ($type == 1) $text = img_object($langs->trans('Service'), 'service');
+						else $text = img_object($langs->trans('Product'), 'product');
+
+						if (!empty($line->label)) {
+							$text .= ' <strong>'.$line->label.'</strong>';
+							print $form->textwithtooltip($text, $line->desc, 3, '', '', $i);
+						} else {
+							print $text.' '.nl2br($line->desc);
+						}
+
+						// Show range
+						print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
+						print "</td>\n";
+					}
+
+					// Qty
+					print '<td class="center">'.$line->qty;
+					print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
+					print '</td>';
+					$qtyProdCom = $line->qty;
+
+					// Qty already shipped
+					print '<td class="center">';
+					$quantityDelivered = $object->expeditions[$line->id];
+					print $quantityDelivered;
+					print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
+					print '</td>';
+
+					// Qty to ship
+					$quantityAsked = $line->qty;
 					if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES))
 					{
 						$quantityToBeDelivered = 0;
 					} else {
 						$quantityToBeDelivered = $quantityAsked - $quantityDelivered;
 					}
-	                $warehouse_id = GETPOST('entrepot_id', 'int');
+					$warehouse_id = GETPOST('entrepot_id', 'int');
 
 					$warehouseObject = null;
 					if ($warehouse_id > 0 || !($line->fk_product > 0) || empty($conf->stock->enabled))     // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
 					{
-					    print '<!-- Case warehouse already known or product not a predefined product -->';
+						print '<!-- Case warehouse already known or product not a predefined product -->';
 						//ship from preselected location
 						$stock = + $product->stock_warehouse[$warehouse_id]->real; // Convert to number
 						$deliverableQty = min($quantityToBeDelivered, $stock);

File diff suppressed because it is too large
+ 454 - 454
htdocs/expensereport/card.php


File diff suppressed because it is too large
+ 1157 - 1157
htdocs/expensereport/class/expensereport.class.php


+ 507 - 507
htdocs/fourn/class/api_supplier_invoices.class.php

@@ -30,519 +30,519 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
  */
 class SupplierInvoices extends DolibarrApi
 {
-    /**
-     *
-     * @var array   $FIELDS     Mandatory fields, checked when create and update object
-     */
-    static $FIELDS = array(
-        'socid',
-    );
-
-    /**
-     * @var FactureFournisseur $invoice {@type FactureFournisseur}
-     */
-    public $invoice;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        global $db;
-        $this->db = $db;
-        $this->invoice = new FactureFournisseur($this->db);
-    }
-
-    /**
-     * Get properties of a supplier invoice object
-     *
-     * Return an array with supplier invoice information
-     *
-     * @param 	int 	$id ID of supplier invoice
-     * @return 	array|mixed data without useless information
-     *
-     * @throws 	RestException
-     */
-    public function get($id)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
-            throw new RestException(401);
-        }
-
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Supplier invoice not found');
-        }
-
-        if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
-            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
-        }
-
-        $this->invoice->fetchObjectLinked();
-        return $this->_cleanObjectDatas($this->invoice);
-    }
-
-    /**
-     * List invoices
-     *
-     * Get a list of supplier invoices
-     *
-     * @param string	$sortfield	      Sort field
-     * @param string	$sortorder	      Sort order
-     * @param int		$limit		      Limit for list
-     * @param int		$page		      Page number
-     * @param string   	$thirdparty_ids	  Thirdparty ids to filter invoices of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i}
-     * @param string	$status		      Filter by invoice status : draft | unpaid | paid | cancelled
-     * @param string    $sqlfilters       Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.datec:<:'20160101')"
-     * @return array                      Array of invoice objects
-     *
-     * @throws RestException
-     */
-    public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $status = '', $sqlfilters = '')
-    {
-        global $db;
-
-        $obj_ret = array();
-
-        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
-        $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
-
-        // If the internal user must only see his customers, force searching by him
-        $search_sale = 0;
-        if (!DolibarrApiAccess::$user->rights->societe->client->voir) $search_sale = DolibarrApiAccess::$user->id;
-
-        $sql = "SELECT t.rowid";
-        // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
-        if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user";
-        $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as t";
-
-        // We need this table joined to the select in order to filter by sale
-        if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
-
-        $sql .= ' WHERE t.entity IN ('.getEntity('supplier_invoice').')';
-        if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= " AND t.fk_soc = sc.fk_soc";
-        if ($socids) $sql .= " AND t.fk_soc IN (".$socids.")";
-        if ($search_sale > 0) $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
-
-        // Filter by status
-        if ($status == 'draft') {
-            $sql .= " AND t.fk_statut IN (0)";
-        }
-        if ($status == 'unpaid') {
-            $sql .= " AND t.fk_statut IN (1)";
-        }
-        if ($status == 'paid') {
-            $sql .= " AND t.fk_statut IN (2)";
-        }
-        if ($status == 'cancelled') {
-            $sql .= " AND t.fk_statut IN (3)";
-        }
-        // Insert sale filter
-        if ($search_sale > 0) {
-            $sql .= " AND sc.fk_user = ".$search_sale;
-        }
-        // Add sql filters
-        if ($sqlfilters)
-        {
-            if (!DolibarrApi::_checkFilters($sqlfilters))
-            {
-                throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
-            }
-            $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
-            $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
-        }
-
-        $sql .= $db->order($sortfield, $sortorder);
-        if ($limit) {
-            if ($page < 0)
-            {
-                $page = 0;
-            }
-            $offset = $limit * $page;
-
-            $sql .= $db->plimit($limit + 1, $offset);
-        }
-
-        $result = $db->query($sql);
-        if ($result) {
-            $i = 0;
-            $num = $db->num_rows($result);
-            $min = min($num, ($limit <= 0 ? $num : $limit));
-            while ($i < $min)
-            {
-                $obj = $db->fetch_object($result);
-                $invoice_static = new FactureFournisseur($db);
-                if ($invoice_static->fetch($obj->rowid)) {
-                    $obj_ret[] = $this->_cleanObjectDatas($invoice_static);
-                }
-                $i++;
-            }
-        } else {
-            throw new RestException(503, 'Error when retrieve supplier invoice list : '.$db->lasterror());
-        }
-        if (!count($obj_ret)) {
-            throw new RestException(404, 'No supplier invoice found');
-        }
-        return $obj_ret;
-    }
-
-    /**
-     * Create supplier invoice object
-     *
-     * @param array $request_data Request datas
-     *
-     * @return int  ID of supplier invoice
-     *
-     * @throws RestException 401
-     * @throws RestException 500
-     */
-    public function post($request_data = null)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
-            throw new RestException(401, "Insuffisant rights");
-        }
-        // Check mandatory fields
-        $result = $this->_validate($request_data);
-
-        foreach ($request_data as $field => $value) {
-            $this->invoice->$field = $value;
-        }
-        if (!array_key_exists('date', $request_data)) {
-            $this->invoice->date = dol_now();
-        }
-
-        if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
-            throw new RestException(500, "Error creating order", array_merge(array($this->invoice->error), $this->invoice->errors));
-        }
-        return $this->invoice->id;
-    }
-
-    /**
-     * Update supplier invoice
-     *
-     * @param int   $id             Id of supplier invoice to update
-     * @param array $request_data   Datas
-     *
-     * @return int
-     *
-     * @throws RestException 401
-     * @throws RestException 404
-     */
-    public function put($id, $request_data = null)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
-            throw new RestException(401);
-        }
-
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Supplier invoice not found');
-        }
-
-        if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
-            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
-        }
-
-        foreach ($request_data as $field => $value) {
-            if ($field == 'id') continue;
-            $this->invoice->$field = $value;
-        }
-
-        if ($this->invoice->update($id, DolibarrApiAccess::$user))
-            return $this->get($id);
-
-        return false;
-    }
-
-    /**
-     * Delete supplier invoice
-     *
-     * @param int   $id Supplier invoice ID
-     *
-     * @return array
-     *
-     * @throws RestException 401
-     * @throws RestException 404
-     * @throws RestException 500
-     */
-    public function delete($id)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->supprimer) {
-            throw new RestException(401);
-        }
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Supplier invoice not found');
-        }
-
-        if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
-            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
-        }
-
-        if ($this->invoice->delete(DolibarrApiAccess::$user) < 0)
-        {
-            throw new RestException(500);
-        }
-
-        return array(
-            'success' => array(
-                'code' => 200,
-                'message' => 'Supplier invoice deleted'
-            )
-        );
-    }
-
-    /**
-     * Validate an invoice
-     *
-     * @param   int $id             Invoice ID
-     * @param   int $idwarehouse    Warehouse ID
-     * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
-     *
-     * @url POST    {id}/validate
-     *
-     * @return  array
-     *
-     * @throws RestException 304
-     * @throws RestException 401
-     * @throws RestException 404
-     * @throws RestException 405
-     * @throws RestException 500
-     */
-    public function validate($id, $idwarehouse = 0, $notrigger = 0)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
-            throw new RestException(401);
-        }
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Invoice not found');
-        }
-
-        if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
-            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
-        }
-
-        $result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
-        if ($result == 0) {
-            throw new RestException(304, 'Error nothing done. The invoice is already validated');
-        }
-        if ($result < 0) {
-            throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
-        }
-
-        return array(
-            'success' => array(
-                'code' => 200,
-                'message' => 'Invoice validated (Ref='.$this->invoice->ref.')'
-            )
-        );
-    }
-
-    /**
-     * Get list of payments of a given supplier invoice
-     *
-     * @param int   $id             Id of SupplierInvoice
-     *
-     * @url     GET {id}/payments
-     *
-     * @return array
-     * @throws RestException 400
-     * @throws RestException 401
-     * @throws RestException 404
-     * @throws RestException 405
-     */
-    public function getPayments($id)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
-            throw new RestException(401);
-        }
-        if (empty($id)) {
-            throw new RestException(400, 'Invoice ID is mandatory');
-        }
+	/**
+	 *
+	 * @var array   $FIELDS     Mandatory fields, checked when create and update object
+	 */
+	static $FIELDS = array(
+		'socid',
+	);
+
+	/**
+	 * @var FactureFournisseur $invoice {@type FactureFournisseur}
+	 */
+	public $invoice;
+
+	/**
+	 * Constructor
+	 */
+	public function __construct()
+	{
+		global $db;
+		$this->db = $db;
+		$this->invoice = new FactureFournisseur($this->db);
+	}
+
+	/**
+	 * Get properties of a supplier invoice object
+	 *
+	 * Return an array with supplier invoice information
+	 *
+	 * @param 	int 	$id ID of supplier invoice
+	 * @return 	array|mixed data without useless information
+	 *
+	 * @throws 	RestException
+	 */
+	public function get($id)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
+			throw new RestException(401);
+		}
+
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Supplier invoice not found');
+		}
 
 		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
 
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Invoice not found');
-        }
-
-        $result = $this->invoice->getListOfPayments();
-        if ($result < 0) {
-            throw new RestException(405, $this->invoice->error);
-        }
-
-        return $result;
-    }
-
-
-    /**
-     * Add payment line to a specific supplier invoice with the remain to pay as amount.
-     *
-     * @param int     $id                               Id of invoice
-     * @param string  $datepaye           {@from body}  Payment date        {@type timestamp}
-     * @param int     $payment_mode_id    {@from body}  Payment mode ID (look it up via REST GET to /setup/dictionary/payment_types) {@min 1}
-     * @param string  $closepaidinvoices  {@from body}  Close paid invoices {@choice yes,no}
-     * @param int     $accountid          {@from body}  Bank account ID (look it up via REST GET to /bankaccounts) {@min 1}
-     * @param string  $num_payment        {@from body}  Payment number (optional)
-     * @param string  $comment            {@from body}  Note (optional)
-     * @param string  $chqemetteur        {@from body}  Payment issuer (mandatory if payment_mode_id corresponds to 'CHQ'-payment type)
-     * @param string  $chqbank            {@from body}  Issuer bank name (optional)
-     *
-     * @url     POST {id}/payments
-     *
-     * @return int  Payment ID
-     * @throws RestException 400
-     * @throws RestException 401
-     * @throws RestException 404
-     */
-    public function addPayment($id, $datepaye, $payment_mode_id, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '')
-    {
-        global $conf;
-
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
-            throw new RestException(403);
-        }
-        if (empty($id)) {
-            throw new RestException(400, 'Invoice ID is mandatory');
-        }
-
-        if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
-            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
-        }
-
-        if (!empty($conf->banque->enabled)) {
-            if (empty($accountid)) {
-                throw new RestException(400, 'Bank account ID is mandatory');
-            }
-        }
-
-        if (empty($payment_mode_id)) {
-            throw new RestException(400, 'Payment mode ID is mandatory');
-        }
-
-
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Invoice not found');
-        }
-
-        // Calculate amount to pay
-        $totalpaye = $this->invoice->getSommePaiement();
-        $totaldeposits = $this->invoice->getSumDepositsUsed();
-        $resteapayer = price2num($this->invoice->total_ttc - $totalpaye - $totaldeposits, 'MT');
-
-        $this->db->begin();
-
-        $amounts = array();
-        $multicurrency_amounts = array();
-
-        $resteapayer = price2num($resteapayer, 'MT');
-        $amounts[$id] = $resteapayer;
-
-        // Multicurrency
-        $newvalue = price2num($this->invoice->multicurrency_total_ttc, 'MT');
-        $multicurrency_amounts[$id] = $newvalue;
-
-        // Creation of payment line
-        $paiement = new PaiementFourn($this->db);
-        $paiement->datepaye     = $datepaye;
-        $paiement->amounts      = $amounts; // Array with all payments dispatching with invoice id
-        $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
-        $paiement->paiementid = $payment_mode_id;
-        $paiement->paiementcode = dol_getIdFromCode($this->db, $payment_mode_id, 'c_paiement', 'id', 'code', 1);
-        $paiement->oper = $paiement->paiementcode;	// For backward compatibility
-        $paiement->num_payment = $num_payment;
-        $paiement->note_public = $comment;
-
-        $paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
-        if ($paiement_id < 0)
-        {
-            $this->db->rollback();
-            throw new RestException(400, 'Payment error : '.$paiement->error);
-        }
-
-        if (!empty($conf->banque->enabled)) {
-            $result = $paiement->addPaymentToBank(DolibarrApiAccess::$user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, $chqemetteur, $chqbank);
-            if ($result < 0)
-            {
-                $this->db->rollback();
-                throw new RestException(400, 'Add payment to bank error : '.$paiement->error);
-            }
-        }
-
-        $this->db->commit();
-
-        return $paiement_id;
-    }
-
-    /**
-     * Get lines of a supplier invoice
-     *
-     * @param int   $id             Id of supplier invoice
-     *
-     * @url	GET {id}/lines
-     *
-     * @return array
-     */
-    public function getLines($id)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
-            throw new RestException(401);
-        }
-
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Supplier invoice not found');
-        }
-
-        if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
-            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
-        }
-        $this->invoice->fetch_lines();
-        $result = array();
-        foreach ($this->invoice->lines as $line) {
-            array_push($result, $this->_cleanObjectDatas($line));
-        }
-        return $result;
-    }
-
-    /**
-     * Add a line to given supplier invoice
-     *
-     * @param int   $id             Id of supplier invoice to update
-     * @param array $request_data   supplier invoice line data
-     *
-     * @url	POST {id}/lines
-     *
-     * @return int|bool
-     */
-    public function postLine($id, $request_data = null)
-    {
-        if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
-            throw new RestException(401);
-        }
-
-        $result = $this->invoice->fetch($id);
-        if (!$result) {
-            throw new RestException(404, 'Supplier invoice not found');
-        }
-
-        if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
-            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
-        }
-        $request_data = (object) $request_data;
-
-        $updateRes = $this->invoice->addline(
-            $request_data->description,
-    		$request_data->pu_ht,
+		$this->invoice->fetchObjectLinked();
+		return $this->_cleanObjectDatas($this->invoice);
+	}
+
+	/**
+	 * List invoices
+	 *
+	 * Get a list of supplier invoices
+	 *
+	 * @param string	$sortfield	      Sort field
+	 * @param string	$sortorder	      Sort order
+	 * @param int		$limit		      Limit for list
+	 * @param int		$page		      Page number
+	 * @param string   	$thirdparty_ids	  Thirdparty ids to filter invoices of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i}
+	 * @param string	$status		      Filter by invoice status : draft | unpaid | paid | cancelled
+	 * @param string    $sqlfilters       Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.datec:<:'20160101')"
+	 * @return array                      Array of invoice objects
+	 *
+	 * @throws RestException
+	 */
+	public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $status = '', $sqlfilters = '')
+	{
+		global $db;
+
+		$obj_ret = array();
+
+		// case of external user, $thirdparty_ids param is ignored and replaced by user's socid
+		$socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
+
+		// If the internal user must only see his customers, force searching by him
+		$search_sale = 0;
+		if (!DolibarrApiAccess::$user->rights->societe->client->voir) $search_sale = DolibarrApiAccess::$user->id;
+
+		$sql = "SELECT t.rowid";
+		// We need these fields in order to filter by sale (including the case where the user can only see his prospects)
+		if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user";
+		$sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as t";
+
+		// We need this table joined to the select in order to filter by sale
+		if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
+
+		$sql .= ' WHERE t.entity IN ('.getEntity('supplier_invoice').')';
+		if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) $sql .= " AND t.fk_soc = sc.fk_soc";
+		if ($socids) $sql .= " AND t.fk_soc IN (".$socids.")";
+		if ($search_sale > 0) $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
+
+		// Filter by status
+		if ($status == 'draft') {
+			$sql .= " AND t.fk_statut IN (0)";
+		}
+		if ($status == 'unpaid') {
+			$sql .= " AND t.fk_statut IN (1)";
+		}
+		if ($status == 'paid') {
+			$sql .= " AND t.fk_statut IN (2)";
+		}
+		if ($status == 'cancelled') {
+			$sql .= " AND t.fk_statut IN (3)";
+		}
+		// Insert sale filter
+		if ($search_sale > 0) {
+			$sql .= " AND sc.fk_user = ".$search_sale;
+		}
+		// Add sql filters
+		if ($sqlfilters)
+		{
+			if (!DolibarrApi::_checkFilters($sqlfilters))
+			{
+				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
+			}
+			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
+			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
+		}
+
+		$sql .= $db->order($sortfield, $sortorder);
+		if ($limit) {
+			if ($page < 0)
+			{
+				$page = 0;
+			}
+			$offset = $limit * $page;
+
+			$sql .= $db->plimit($limit + 1, $offset);
+		}
+
+		$result = $db->query($sql);
+		if ($result) {
+			$i = 0;
+			$num = $db->num_rows($result);
+			$min = min($num, ($limit <= 0 ? $num : $limit));
+			while ($i < $min)
+			{
+				$obj = $db->fetch_object($result);
+				$invoice_static = new FactureFournisseur($db);
+				if ($invoice_static->fetch($obj->rowid)) {
+					$obj_ret[] = $this->_cleanObjectDatas($invoice_static);
+				}
+				$i++;
+			}
+		} else {
+			throw new RestException(503, 'Error when retrieve supplier invoice list : '.$db->lasterror());
+		}
+		if (!count($obj_ret)) {
+			throw new RestException(404, 'No supplier invoice found');
+		}
+		return $obj_ret;
+	}
+
+	/**
+	 * Create supplier invoice object
+	 *
+	 * @param array $request_data Request datas
+	 *
+	 * @return int  ID of supplier invoice
+	 *
+	 * @throws RestException 401
+	 * @throws RestException 500
+	 */
+	public function post($request_data = null)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
+			throw new RestException(401, "Insuffisant rights");
+		}
+		// Check mandatory fields
+		$result = $this->_validate($request_data);
+
+		foreach ($request_data as $field => $value) {
+			$this->invoice->$field = $value;
+		}
+		if (!array_key_exists('date', $request_data)) {
+			$this->invoice->date = dol_now();
+		}
+
+		if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
+			throw new RestException(500, "Error creating order", array_merge(array($this->invoice->error), $this->invoice->errors));
+		}
+		return $this->invoice->id;
+	}
+
+	/**
+	 * Update supplier invoice
+	 *
+	 * @param int   $id             Id of supplier invoice to update
+	 * @param array $request_data   Datas
+	 *
+	 * @return int
+	 *
+	 * @throws RestException 401
+	 * @throws RestException 404
+	 */
+	public function put($id, $request_data = null)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
+			throw new RestException(401);
+		}
+
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Supplier invoice not found');
+		}
+
+		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+		foreach ($request_data as $field => $value) {
+			if ($field == 'id') continue;
+			$this->invoice->$field = $value;
+		}
+
+		if ($this->invoice->update($id, DolibarrApiAccess::$user))
+			return $this->get($id);
+
+		return false;
+	}
+
+	/**
+	 * Delete supplier invoice
+	 *
+	 * @param int   $id Supplier invoice ID
+	 *
+	 * @return array
+	 *
+	 * @throws RestException 401
+	 * @throws RestException 404
+	 * @throws RestException 500
+	 */
+	public function delete($id)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->supprimer) {
+			throw new RestException(401);
+		}
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Supplier invoice not found');
+		}
+
+		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+		if ($this->invoice->delete(DolibarrApiAccess::$user) < 0)
+		{
+			throw new RestException(500);
+		}
+
+		return array(
+			'success' => array(
+				'code' => 200,
+				'message' => 'Supplier invoice deleted'
+			)
+		);
+	}
+
+	/**
+	 * Validate an invoice
+	 *
+	 * @param   int $id             Invoice ID
+	 * @param   int $idwarehouse    Warehouse ID
+	 * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
+	 *
+	 * @url POST    {id}/validate
+	 *
+	 * @return  array
+	 *
+	 * @throws RestException 304
+	 * @throws RestException 401
+	 * @throws RestException 404
+	 * @throws RestException 405
+	 * @throws RestException 500
+	 */
+	public function validate($id, $idwarehouse = 0, $notrigger = 0)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
+			throw new RestException(401);
+		}
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Invoice not found');
+		}
+
+		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+		$result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
+		if ($result == 0) {
+			throw new RestException(304, 'Error nothing done. The invoice is already validated');
+		}
+		if ($result < 0) {
+			throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
+		}
+
+		return array(
+			'success' => array(
+				'code' => 200,
+				'message' => 'Invoice validated (Ref='.$this->invoice->ref.')'
+			)
+		);
+	}
+
+	/**
+	 * Get list of payments of a given supplier invoice
+	 *
+	 * @param int   $id             Id of SupplierInvoice
+	 *
+	 * @url     GET {id}/payments
+	 *
+	 * @return array
+	 * @throws RestException 400
+	 * @throws RestException 401
+	 * @throws RestException 404
+	 * @throws RestException 405
+	 */
+	public function getPayments($id)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
+			throw new RestException(401);
+		}
+		if (empty($id)) {
+			throw new RestException(400, 'Invoice ID is mandatory');
+		}
+
+		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Invoice not found');
+		}
+
+		$result = $this->invoice->getListOfPayments();
+		if ($result < 0) {
+			throw new RestException(405, $this->invoice->error);
+		}
+
+		return $result;
+	}
+
+
+	/**
+	 * Add payment line to a specific supplier invoice with the remain to pay as amount.
+	 *
+	 * @param int     $id                               Id of invoice
+	 * @param string  $datepaye           {@from body}  Payment date        {@type timestamp}
+	 * @param int     $payment_mode_id    {@from body}  Payment mode ID (look it up via REST GET to /setup/dictionary/payment_types) {@min 1}
+	 * @param string  $closepaidinvoices  {@from body}  Close paid invoices {@choice yes,no}
+	 * @param int     $accountid          {@from body}  Bank account ID (look it up via REST GET to /bankaccounts) {@min 1}
+	 * @param string  $num_payment        {@from body}  Payment number (optional)
+	 * @param string  $comment            {@from body}  Note (optional)
+	 * @param string  $chqemetteur        {@from body}  Payment issuer (mandatory if payment_mode_id corresponds to 'CHQ'-payment type)
+	 * @param string  $chqbank            {@from body}  Issuer bank name (optional)
+	 *
+	 * @url     POST {id}/payments
+	 *
+	 * @return int  Payment ID
+	 * @throws RestException 400
+	 * @throws RestException 401
+	 * @throws RestException 404
+	 */
+	public function addPayment($id, $datepaye, $payment_mode_id, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '')
+	{
+		global $conf;
+
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
+			throw new RestException(403);
+		}
+		if (empty($id)) {
+			throw new RestException(400, 'Invoice ID is mandatory');
+		}
+
+		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+		if (!empty($conf->banque->enabled)) {
+			if (empty($accountid)) {
+				throw new RestException(400, 'Bank account ID is mandatory');
+			}
+		}
+
+		if (empty($payment_mode_id)) {
+			throw new RestException(400, 'Payment mode ID is mandatory');
+		}
+
+
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Invoice not found');
+		}
+
+		// Calculate amount to pay
+		$totalpaye = $this->invoice->getSommePaiement();
+		$totaldeposits = $this->invoice->getSumDepositsUsed();
+		$resteapayer = price2num($this->invoice->total_ttc - $totalpaye - $totaldeposits, 'MT');
+
+		$this->db->begin();
+
+		$amounts = array();
+		$multicurrency_amounts = array();
+
+		$resteapayer = price2num($resteapayer, 'MT');
+		$amounts[$id] = $resteapayer;
+
+		// Multicurrency
+		$newvalue = price2num($this->invoice->multicurrency_total_ttc, 'MT');
+		$multicurrency_amounts[$id] = $newvalue;
+
+		// Creation of payment line
+		$paiement = new PaiementFourn($this->db);
+		$paiement->datepaye     = $datepaye;
+		$paiement->amounts      = $amounts; // Array with all payments dispatching with invoice id
+		$paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
+		$paiement->paiementid = $payment_mode_id;
+		$paiement->paiementcode = dol_getIdFromCode($this->db, $payment_mode_id, 'c_paiement', 'id', 'code', 1);
+		$paiement->oper = $paiement->paiementcode;	// For backward compatibility
+		$paiement->num_payment = $num_payment;
+		$paiement->note_public = $comment;
+
+		$paiement_id = $paiement->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
+		if ($paiement_id < 0)
+		{
+			$this->db->rollback();
+			throw new RestException(400, 'Payment error : '.$paiement->error);
+		}
+
+		if (!empty($conf->banque->enabled)) {
+			$result = $paiement->addPaymentToBank(DolibarrApiAccess::$user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, $chqemetteur, $chqbank);
+			if ($result < 0)
+			{
+				$this->db->rollback();
+				throw new RestException(400, 'Add payment to bank error : '.$paiement->error);
+			}
+		}
+
+		$this->db->commit();
+
+		return $paiement_id;
+	}
+
+	/**
+	 * Get lines of a supplier invoice
+	 *
+	 * @param int   $id             Id of supplier invoice
+	 *
+	 * @url	GET {id}/lines
+	 *
+	 * @return array
+	 */
+	public function getLines($id)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
+			throw new RestException(401);
+		}
+
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Supplier invoice not found');
+		}
+
+		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+		$this->invoice->fetch_lines();
+		$result = array();
+		foreach ($this->invoice->lines as $line) {
+			array_push($result, $this->_cleanObjectDatas($line));
+		}
+		return $result;
+	}
+
+	/**
+	 * Add a line to given supplier invoice
+	 *
+	 * @param int   $id             Id of supplier invoice to update
+	 * @param array $request_data   supplier invoice line data
+	 *
+	 * @url	POST {id}/lines
+	 *
+	 * @return int|bool
+	 */
+	public function postLine($id, $request_data = null)
+	{
+		if (!DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
+			throw new RestException(401);
+		}
+
+		$result = $this->invoice->fetch($id);
+		if (!$result) {
+			throw new RestException(404, 'Supplier invoice not found');
+		}
+
+		if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->invoice->id, 'facture_fourn', 'facture')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+		$request_data = (object) $request_data;
+
+		$updateRes = $this->invoice->addline(
+			$request_data->description,
+			$request_data->pu_ht,
 			$request_data->tva_tx,
-    		$request_data->localtax1_tx,
-    		$request_data->localtax2_tx,
-    		$request_data->qty,
+			$request_data->localtax1_tx,
+			$request_data->localtax2_tx,
+			$request_data->qty,
 			$request_data->fk_product,
 			$request_data->remise_percent,
 			$request_data->date_start,

File diff suppressed because it is too large
+ 667 - 667
htdocs/fourn/class/fournisseur.commande.class.php


File diff suppressed because it is too large
+ 506 - 506
htdocs/fourn/class/fournisseur.facture.class.php


+ 45 - 45
htdocs/fourn/commande/card.php

@@ -1936,53 +1936,53 @@ if ($action == 'create')
 	$morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $usercancreate, 'string', '', null, null, '', 1);
 	// Thirdparty
 	$morehtmlref .= '<br>'.$langs->trans('ThirdParty');
-    if (!empty($conf->global->MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER) && !empty($usercancreate) && $action == 'edit_thirdparty') {
-        $morehtmlref .= ' : ';
-        $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
-        $morehtmlref .= '<input type="hidden" name="action" value="set_thirdparty">';
-        $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
-        $morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', 's.fournisseur=1', '', 0, 0, array(), 0, 'minwidth300');
-        $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
-        $morehtmlref .= '</form>';
-    }
-    if (empty($conf->global->MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER) || $action != 'edit_thirdparty') {
-        if (!empty($conf->global->MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER) && $object->statut == CommandeFournisseur::STATUS_DRAFT) {
-            $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=edit_thirdparty&amp;id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetThirdParty')).'</a>';
-        }
-        $morehtmlref .= ' : '.$object->thirdparty->getNomUrl(1);
-        if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php?socid='.$object->thirdparty->id.'&search_company='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherOrders").'</a>)';
-    }
+	if (!empty($conf->global->MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER) && !empty($usercancreate) && $action == 'edit_thirdparty') {
+		$morehtmlref .= ' : ';
+		$morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
+		$morehtmlref .= '<input type="hidden" name="action" value="set_thirdparty">';
+		$morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
+		$morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', 's.fournisseur=1', '', 0, 0, array(), 0, 'minwidth300');
+		$morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
+		$morehtmlref .= '</form>';
+	}
+	if (empty($conf->global->MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER) || $action != 'edit_thirdparty') {
+		if (!empty($conf->global->MAIN_CAN_EDIT_SUPPLIER_ON_SUPPLIER_ORDER) && $object->statut == CommandeFournisseur::STATUS_DRAFT) {
+			$morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=edit_thirdparty&amp;id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetThirdParty')).'</a>';
+		}
+		$morehtmlref .= ' : '.$object->thirdparty->getNomUrl(1);
+		if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php?socid='.$object->thirdparty->id.'&search_company='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherOrders").'</a>)';
+	}
 
 	// Project
-    if (!empty($conf->projet->enabled)) {
-        $langs->load("projects");
-        $morehtmlref .= '<br>'.$langs->trans('Project').' ';
-        if ($usercancreate) {
-            if ($action != 'classify')
-                $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&amp;id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> : ';
-            if ($action == 'classify') {
-                //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
-                $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
-                $morehtmlref .= '<input type="hidden" name="action" value="classin">';
-                $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
-                $morehtmlref .= $formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $object->socid : -1), $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500');
-                $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
-                $morehtmlref .= '</form>';
-            } else {
-                $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
-            }
-        } else {
-            if (!empty($object->fk_project)) {
-                $proj = new Project($db);
-                $proj->fetch($object->fk_project);
-                $morehtmlref .= '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$object->fk_project.'" title="'.$langs->trans('ShowProject').'">';
-                $morehtmlref .= $proj->ref;
-                $morehtmlref .= '</a>';
-            } else {
-                $morehtmlref .= '';
-            }
-        }
-    }
+	if (!empty($conf->projet->enabled)) {
+		$langs->load("projects");
+		$morehtmlref .= '<br>'.$langs->trans('Project').' ';
+		if ($usercancreate) {
+			if ($action != 'classify')
+				$morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&amp;id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> : ';
+			if ($action == 'classify') {
+				//$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
+				$morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
+				$morehtmlref .= '<input type="hidden" name="action" value="classin">';
+				$morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
+				$morehtmlref .= $formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $object->socid : -1), $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500');
+				$morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
+				$morehtmlref .= '</form>';
+			} else {
+				$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
+			}
+		} else {
+			if (!empty($object->fk_project)) {
+				$proj = new Project($db);
+				$proj->fetch($object->fk_project);
+				$morehtmlref .= '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$object->fk_project.'" title="'.$langs->trans('ShowProject').'">';
+				$morehtmlref .= $proj->ref;
+				$morehtmlref .= '</a>';
+			} else {
+				$morehtmlref .= '';
+			}
+		}
+	}
 	$morehtmlref .= '</div>';
 
 

+ 129 - 129
htdocs/holiday/card.php

@@ -111,152 +111,152 @@ if (empty($reshook))
 			header("Location: ".$backtopage);
 			exit;
 		}
-	    $action = '';
+		$action = '';
 	}
 
 	// If create a request
 	if ($action == 'create')
 	{
-	    // If no right to create a request
-	    if (!$cancreate)
-	    {
-	    	$error++;
-	    	setEventMessages($langs->trans('CantCreateCP'), null, 'errors');
-	    	$action = 'request';
-	    }
+		// If no right to create a request
+		if (!$cancreate)
+		{
+			$error++;
+			setEventMessages($langs->trans('CantCreateCP'), null, 'errors');
+			$action = 'request';
+		}
 
-	    if (!$error)
-	    {
-	        $object = new Holiday($db);
-
-	    	$db->begin();
-
-		    $date_debut = dol_mktime(0, 0, 0, GETPOST('date_debut_month'), GETPOST('date_debut_day'), GETPOST('date_debut_year'));
-		    $date_fin = dol_mktime(0, 0, 0, GETPOST('date_fin_month'), GETPOST('date_fin_day'), GETPOST('date_fin_year'));
-		    $date_debut_gmt = dol_mktime(0, 0, 0, GETPOST('date_debut_month'), GETPOST('date_debut_day'), GETPOST('date_debut_year'), 1);
-		    $date_fin_gmt = dol_mktime(0, 0, 0, GETPOST('date_fin_month'), GETPOST('date_fin_day'), GETPOST('date_fin_year'), 1);
-		    $starthalfday = GETPOST('starthalfday');
-		    $endhalfday = GETPOST('endhalfday');
-		    $type = GETPOST('type');
-		    $halfday = 0;
-		    if ($starthalfday == 'afternoon' && $endhalfday == 'morning') $halfday = 2;
-		    elseif ($starthalfday == 'afternoon') $halfday = -1;
-		    elseif ($endhalfday == 'morning') $halfday = 1;
-
-		    $valideur = GETPOST('valideur', 'int');
-		    $description = trim(GETPOST('description', 'none'));
-
-	    	// If no type
-		    if ($type <= 0)
-		    {
-		        setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
-		        $error++;
-		        $action = 'create';
-		    }
-
-		    // If no start date
-		    if (empty($date_debut))
-		    {
-		        setEventMessages($langs->trans("NoDateDebut"), null, 'errors');
-		        $error++;
-		        $action = 'create';
-		    }
-		    // If no end date
-		    if (empty($date_fin))
-		    {
-		        setEventMessages($langs->trans("NoDateFin"), null, 'errors');
-		        $error++;
-		        $action = 'create';
-		    }
-		    // If start date after end date
-		    if ($date_debut > $date_fin)
-		    {
-		        setEventMessages($langs->trans("ErrorEndDateCP"), null, 'errors');
-		        $error++;
-		        $action = 'create';
-		    }
-
-		    // Check if there is already holiday for this period
-		    $verifCP = $object->verifDateHolidayCP($fuserid, $date_debut, $date_fin, $halfday);
-		    if (!$verifCP)
-		    {
-		        setEventMessages($langs->trans("alreadyCPexist"), null, 'errors');
-		        $error++;
-		        $action = 'create';
-		    }
-
-		    // If there is no Business Days within request
-		    $nbopenedday = num_open_day($date_debut_gmt, $date_fin_gmt, 0, 1, $halfday);
-		    if ($nbopenedday < 0.5)
-		    {
-		        setEventMessages($langs->trans("ErrorDureeCP"), null, 'errors');
-		        $error++;
-		        $action = 'create';
-		    }
-
-		    // If no validator designated
-		    if ($valideur < 1)
-		    {
-		        setEventMessages($langs->transnoentitiesnoconv('InvalidValidatorCP'), null, 'errors');
-		        $error++;
-		    }
-
-		    $result = 0;
-
-		    if (!$error)
-		    {
-	    	    $object->fk_user = $fuserid;
-	    	    $object->description = $description;
-	    	    $object->fk_validator = $valideur;
-	    		$object->fk_type = $type;
-	    		$object->date_debut = $date_debut;
-	    		$object->date_fin = $date_fin;
-	    		$object->halfday = $halfday;
-
-	    		$result = $object->create($user);
-	    		if ($result <= 0)
-	    		{
-	    			setEventMessages($object->error, $object->errors, 'errors');
-	    			$error++;
-	    		}
-		    }
-
-		    // If no SQL error we redirect to the request card
-		    if (!$error)
-		    {
+		if (!$error)
+		{
+			$object = new Holiday($db);
+
+			$db->begin();
+
+			$date_debut = dol_mktime(0, 0, 0, GETPOST('date_debut_month'), GETPOST('date_debut_day'), GETPOST('date_debut_year'));
+			$date_fin = dol_mktime(0, 0, 0, GETPOST('date_fin_month'), GETPOST('date_fin_day'), GETPOST('date_fin_year'));
+			$date_debut_gmt = dol_mktime(0, 0, 0, GETPOST('date_debut_month'), GETPOST('date_debut_day'), GETPOST('date_debut_year'), 1);
+			$date_fin_gmt = dol_mktime(0, 0, 0, GETPOST('date_fin_month'), GETPOST('date_fin_day'), GETPOST('date_fin_year'), 1);
+			$starthalfday = GETPOST('starthalfday');
+			$endhalfday = GETPOST('endhalfday');
+			$type = GETPOST('type');
+			$halfday = 0;
+			if ($starthalfday == 'afternoon' && $endhalfday == 'morning') $halfday = 2;
+			elseif ($starthalfday == 'afternoon') $halfday = -1;
+			elseif ($endhalfday == 'morning') $halfday = 1;
+
+			$valideur = GETPOST('valideur', 'int');
+			$description = trim(GETPOST('description', 'none'));
+
+			// If no type
+			if ($type <= 0)
+			{
+				setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
+				$error++;
+				$action = 'create';
+			}
+
+			// If no start date
+			if (empty($date_debut))
+			{
+				setEventMessages($langs->trans("NoDateDebut"), null, 'errors');
+				$error++;
+				$action = 'create';
+			}
+			// If no end date
+			if (empty($date_fin))
+			{
+				setEventMessages($langs->trans("NoDateFin"), null, 'errors');
+				$error++;
+				$action = 'create';
+			}
+			// If start date after end date
+			if ($date_debut > $date_fin)
+			{
+				setEventMessages($langs->trans("ErrorEndDateCP"), null, 'errors');
+				$error++;
+				$action = 'create';
+			}
+
+			// Check if there is already holiday for this period
+			$verifCP = $object->verifDateHolidayCP($fuserid, $date_debut, $date_fin, $halfday);
+			if (!$verifCP)
+			{
+				setEventMessages($langs->trans("alreadyCPexist"), null, 'errors');
+				$error++;
+				$action = 'create';
+			}
+
+			// If there is no Business Days within request
+			$nbopenedday = num_open_day($date_debut_gmt, $date_fin_gmt, 0, 1, $halfday);
+			if ($nbopenedday < 0.5)
+			{
+				setEventMessages($langs->trans("ErrorDureeCP"), null, 'errors');
+				$error++;
+				$action = 'create';
+			}
+
+			// If no validator designated
+			if ($valideur < 1)
+			{
+				setEventMessages($langs->transnoentitiesnoconv('InvalidValidatorCP'), null, 'errors');
+				$error++;
+			}
+
+			$result = 0;
+
+			if (!$error)
+			{
+				$object->fk_user = $fuserid;
+				$object->description = $description;
+				$object->fk_validator = $valideur;
+				$object->fk_type = $type;
+				$object->date_debut = $date_debut;
+				$object->date_fin = $date_fin;
+				$object->halfday = $halfday;
+
+				$result = $object->create($user);
+				if ($result <= 0)
+				{
+					setEventMessages($object->error, $object->errors, 'errors');
+					$error++;
+				}
+			}
+
+			// If no SQL error we redirect to the request card
+			if (!$error)
+			{
 				$db->commit();
 
-		    	header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
-		        exit;
-		    } else {
-		    	$db->rollback();
-		    }
-	    }
+				header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
+				exit;
+			} else {
+				$db->rollback();
+			}
+		}
 	}
 
 	if ($action == 'update' && GETPOSTISSET('savevalidator') && !empty($user->rights->holiday->approve))
 	{
-	    $object->fetch($id);
+		$object->fetch($id);
 
-	    $object->oldcopy = dol_clone($object);
+		$object->oldcopy = dol_clone($object);
 
-	    $object->fk_validator = GETPOST('valideur', 'int');
+		$object->fk_validator = GETPOST('valideur', 'int');
 
-	    if ($object->fk_validator != $object->oldcopy->fk_validator)
-	    {
-	        $verif = $object->update($user);
+		if ($object->fk_validator != $object->oldcopy->fk_validator)
+		{
+			$verif = $object->update($user);
 
-	        if ($verif <= 0)
-	        {
-	            setEventMessages($object->error, $object->errors, 'warnings');
-	            $action = 'editvalidator';
-	        } else {
-	            header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
-	            exit;
-	        }
-	    }
+			if ($verif <= 0)
+			{
+				setEventMessages($object->error, $object->errors, 'warnings');
+				$action = 'editvalidator';
+			} else {
+				header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
+				exit;
+			}
+		}
 
-	    $action = '';
+		$action = '';
 	}
 
 	if ($action == 'update' && !GETPOSTISSET('savevalidator'))

+ 2 - 2
htdocs/index.php

@@ -450,14 +450,14 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) {
 	if (!empty($conf->expensereport->enabled) && $user->rights->expensereport->approve) {
 		include_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
 		$board = new ExpenseReport($db);
-		$dashboardlines[$board->element . '_toapprove'] = $board->load_board($user, 'toapprove');
+		$dashboardlines[$board->element.'_toapprove'] = $board->load_board($user, 'toapprove');
 	}
 
 	// Number of expense reports to pay
 	if (!empty($conf->expensereport->enabled) && $user->rights->expensereport->to_paid) {
 		include_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
 		$board = new ExpenseReport($db);
-		$dashboardlines[$board->element . '_topay'] = $board->load_board($user, 'topay');
+		$dashboardlines[$board->element.'_topay'] = $board->load_board($user, 'topay');
 	}
 
 	// Number of holidays to approve

+ 87 - 87
htdocs/loan/class/paymentloan.class.php

@@ -41,63 +41,63 @@ class PaymentLoan extends CommonObject
 	 */
 	public $table_element = 'payment_loan';
 
-    /**
-     * @var string String with name of icon for PaymentLoan
-     */
-    public $picto = 'money-bill-alt';
+	/**
+	 * @var string String with name of icon for PaymentLoan
+	 */
+	public $picto = 'money-bill-alt';
 
-    /**
-     * @var int Loan ID
-     */
-    public $fk_loan;
+	/**
+	 * @var int Loan ID
+	 */
+	public $fk_loan;
 
-    /**
-     * @var string Create date
-     */
-    public $datec = '';
+	/**
+	 * @var string Create date
+	 */
+	public $datec = '';
 
-    public $tms = '';
+	public $tms = '';
 
-    /**
-     * @var string Payment date
-     */
-    public $datep = '';
+	/**
+	 * @var string Payment date
+	 */
+	public $datep = '';
 
-    public $amounts = array(); // Array of amounts
+	public $amounts = array(); // Array of amounts
 
-    public $amount_capital; // Total amount of payment
+	public $amount_capital; // Total amount of payment
 
-    public $amount_insurance;
+	public $amount_insurance;
 
-    public $amount_interest;
+	public $amount_interest;
 
-    /**
-     * @var int Payment mode ID
-     */
-    public $fk_typepayment;
+	/**
+	 * @var int Payment mode ID
+	 */
+	public $fk_typepayment;
 
-    /**
-     * @var int Payment ID
-     */
-    public $num_payment;
+	/**
+	 * @var int Payment ID
+	 */
+	public $num_payment;
 
-    /**
-     * @var int Bank ID
-     */
-    public $fk_bank;
+	/**
+	 * @var int Bank ID
+	 */
+	public $fk_bank;
 
-    /**
-     * @var int User ID
-     */
-    public $fk_user_creat;
+	/**
+	 * @var int User ID
+	 */
+	public $fk_user_creat;
 
-    /**
-     * @var int user ID
-     */
-    public $fk_user_modif;
+	/**
+	 * @var int user ID
+	 */
+	public $fk_user_modif;
 
-    public $type_code;
-    public $type_label;
+	public $type_code;
+	public $type_label;
 
 
 	/**
@@ -367,23 +367,23 @@ class PaymentLoan extends CommonObject
 			if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
 		}
 
-        // Set loan unpaid if loan has no other payment
-        if (!$error)
-        {
-            require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
-            $loan = new Loan($this->db);
-            $loan->fetch($this->fk_loan);
-            $sum_payment = $loan->getSumPayment();
-            if ($sum_payment == 0)
-            {
-                dol_syslog(get_class($this)."::delete : set loan to unpaid", LOG_DEBUG);
-                if ($loan->set_unpaid($user) < 1)
-                {
-                    $error++;
-                    dol_print_error($this->db);
-                }
-            }
-        }
+		// Set loan unpaid if loan has no other payment
+		if (!$error)
+		{
+			require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
+			$loan = new Loan($this->db);
+			$loan->fetch($this->fk_loan);
+			$sum_payment = $loan->getSumPayment();
+			if ($sum_payment == 0)
+			{
+				dol_syslog(get_class($this)."::delete : set loan to unpaid", LOG_DEBUG);
+				if ($loan->set_unpaid($user) < 1)
+				{
+					$error++;
+					dol_print_error($this->db);
+				}
+			}
+		}
 
 		//if (! $error)
 		//{
@@ -435,7 +435,7 @@ class PaymentLoan extends CommonObject
 		global $conf;
 
 		$error = 0;
-        $this->db->begin();
+		$this->db->begin();
 
 		if (!empty($conf->banque->enabled))
 		{
@@ -448,9 +448,9 @@ class PaymentLoan extends CommonObject
 			if ($mode == 'payment_loan') $total = -$total;
 
 			// Insert payment into llx_bank
-            $bank_line_id = $acc->addline(
+			$bank_line_id = $acc->addline(
 				$this->datep,
-            	$this->fk_typepayment, // Payment mode ID or code ("CHQ or VIR for example")
+				$this->fk_typepayment, // Payment mode ID or code ("CHQ or VIR for example")
 				$label,
 				$total,
 				$this->num_payment,
@@ -498,36 +498,36 @@ class PaymentLoan extends CommonObject
 		}
 
 
-        // Set loan payment started if no set
-        if (!$error)
-        {
-            require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
-            $loan = new Loan($this->db);
-            $loan->fetch($fk_loan);
-            if ($loan->paid == $loan::STATUS_UNPAID)
-            {
-                dol_syslog(get_class($this)."::addPaymentToBank : set loan payment to started", LOG_DEBUG);
-                if ($loan->set_started($user) < 1)
-                {
-                    $error++;
-                    dol_print_error($this->db);
-                }
-            }
-        }
+		// Set loan payment started if no set
+		if (!$error)
+		{
+			require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
+			$loan = new Loan($this->db);
+			$loan->fetch($fk_loan);
+			if ($loan->paid == $loan::STATUS_UNPAID)
+			{
+				dol_syslog(get_class($this)."::addPaymentToBank : set loan payment to started", LOG_DEBUG);
+				if ($loan->set_started($user) < 1)
+				{
+					$error++;
+					dol_print_error($this->db);
+				}
+			}
+		}
 
 		if (!$error)
 		{
-            $this->db->commit();
+			$this->db->commit();
 			return 1;
 		}
 		else {
-            $this->db->rollback();
+			$this->db->rollback();
 			return -1;
 		}
 	}
 
 
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
 	/**
 	 *  Update link between loan's payment and the line generate in llx_bank
 	 *
@@ -536,14 +536,14 @@ class PaymentLoan extends CommonObject
 	 */
 	public function update_fk_bank($id_bank)
 	{
-        // phpcs:enable
+		// phpcs:enable
 		$sql = "UPDATE ".MAIN_DB_PREFIX."payment_loan SET fk_bank = ".$id_bank." WHERE rowid = ".$this->id;
 
 		dol_syslog(get_class($this)."::update_fk_bank", LOG_DEBUG);
 		$result = $this->db->query($sql);
 		if ($result)
 		{
-		    $this->fk_bank = $id_bank;
+			$this->fk_bank = $id_bank;
 			return 1;
 		} else {
 			$this->error = $this->db->error();
@@ -556,9 +556,9 @@ class PaymentLoan extends CommonObject
 	 *
 	 *	@param	int		$withpicto					0=No picto, 1=Include picto into link, 2=No picto
 	 * 	@param	int		$maxlen						Max length label
-     *	@param	int  	$notooltip					1=Disable tooltip
-     *	@param	string	$moretitle					Add more text to title tooltip
-     *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
+	 *	@param	int  	$notooltip					1=Disable tooltip
+	 *	@param	string	$moretitle					Add more text to title tooltip
+	 *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
 	 *	@return	string								String with URL
 	 */
 	public function getNomUrl($withpicto = 0, $maxlen = 0, $notooltip = 0, $moretitle = '', $save_lastsearch_value = -1)

+ 123 - 123
htdocs/opensurvey/card.php

@@ -49,8 +49,8 @@ $object = new Opensurveysondage($db);
 $result = $object->fetch(0, $numsondage);
 if ($result <= 0)
 {
-    dol_print_error($db, $object->error);
-    exit;
+	dol_print_error($db, $object->error);
+	exit;
 }
 
 $expiredate = dol_mktime(0, 0, 0, GETPOST('expiremonth'), GETPOST('expireday'), GETPOST('expireyear'));
@@ -67,112 +67,112 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e
 
 if (empty($reshook))
 {
-    if ($cancel) $action = '';
-
-    // Delete
-    if ($action == 'delete_confirm')
-    {
-    	// Security check
-    	if (!$user->rights->opensurvey->write) accessforbidden();
-
-    	$result = $object->delete($user, '', $numsondage);
-
-    	header('Location: '.dol_buildpath('/opensurvey/list.php', 1));
-    	exit();
-    }
-
-    // Close
-    if ($action == 'close')
-    {
-        $object->status = Opensurveysondage::STATUS_CLOSED;
-        $object->update($user);
-    }
-
-    // Reopend
-    if ($action == 'reopen')
-    {
-        $object->status = Opensurveysondage::STATUS_VALIDATED;
-        $object->update($user);
-    }
-
-    // Update
-    if ($action == 'update')
-    {
-    	// Security check
-    	if (!$user->rights->opensurvey->write) accessforbidden();
-
-    	$error = 0;
-
-    	if (!GETPOST('nouveautitre'))
-    	{
-    		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Title")), null, 'errors');
-    		$error++;
-    		$action = 'edit';
-    	}
-
-    	if (!$error)
-    	{
-    		$object->title = GETPOST('nouveautitre', 'nohtml');
-    		$object->description = GETPOST('nouveauxcommentaires', 'restricthtml');
-    		$object->mail_admin = GETPOST('nouvelleadresse', 'alpha');
-    		$object->date_fin = $expiredate;
-    		$object->allow_comments = GETPOST('cancomment', 'alpha') == 'on' ? 1 : 0;
-    		$object->allow_spy = GETPOST('canseeothersvote', 'alpha') == 'on' ? 1 : 0;
-    		$object->mailsonde = GETPOST('mailsonde', 'alpha') == 'on' ? true : false;
-
-    		$res = $object->update($user);
-    		if ($res < 0)
-    		{
-    			setEventMessages($object->error, $object->errors, 'errors');
-    			$action = 'edit';
-    		}
-    	}
-    }
-
-    // Add comment
-    if (GETPOST('ajoutcomment'))
-    {
-    	$error = 0;
-
-    	if (!GETPOST('comment'))
-    	{
-    		$error++;
-    		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Comment")), null, 'errors');
-    	}
-    	if (!GETPOST('commentuser'))
-    	{
-    		$error++;
-    		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("User")), null, 'errors');
-    	}
-
-    	if (!$error)
-    	{
-    		$comment = GETPOST("comment");
-    		$comment_user = GETPOST('commentuser');
-
-    		$resql = $object->addComment($comment, $comment_user);
-
-    		if (!$resql)
-    		{
-    			setEventMessages($langs->trans('ErrorInsertingComment'), null, 'errors');
-    		}
-    	}
-    }
-
-    // Delete comment
-    $idcomment = GETPOST('deletecomment', 'int');
-    if ($idcomment)
-    {
-    	// Security check
-    	if (!$user->rights->opensurvey->write) accessforbidden();
-
-    	$resql = $object->deleteComment($idcomment);
-    }
-
-    if ($action == 'edit') {
-    	// Security check
-    	if (!$user->rights->opensurvey->write) accessforbidden();
-    }
+	if ($cancel) $action = '';
+
+	// Delete
+	if ($action == 'delete_confirm')
+	{
+		// Security check
+		if (!$user->rights->opensurvey->write) accessforbidden();
+
+		$result = $object->delete($user, '', $numsondage);
+
+		header('Location: '.dol_buildpath('/opensurvey/list.php', 1));
+		exit();
+	}
+
+	// Close
+	if ($action == 'close')
+	{
+		$object->status = Opensurveysondage::STATUS_CLOSED;
+		$object->update($user);
+	}
+
+	// Reopend
+	if ($action == 'reopen')
+	{
+		$object->status = Opensurveysondage::STATUS_VALIDATED;
+		$object->update($user);
+	}
+
+	// Update
+	if ($action == 'update')
+	{
+		// Security check
+		if (!$user->rights->opensurvey->write) accessforbidden();
+
+		$error = 0;
+
+		if (!GETPOST('nouveautitre'))
+		{
+			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Title")), null, 'errors');
+			$error++;
+			$action = 'edit';
+		}
+
+		if (!$error)
+		{
+			$object->title = GETPOST('nouveautitre', 'nohtml');
+			$object->description = GETPOST('nouveauxcommentaires', 'restricthtml');
+			$object->mail_admin = GETPOST('nouvelleadresse', 'alpha');
+			$object->date_fin = $expiredate;
+			$object->allow_comments = GETPOST('cancomment', 'alpha') == 'on' ? 1 : 0;
+			$object->allow_spy = GETPOST('canseeothersvote', 'alpha') == 'on' ? 1 : 0;
+			$object->mailsonde = GETPOST('mailsonde', 'alpha') == 'on' ? true : false;
+
+			$res = $object->update($user);
+			if ($res < 0)
+			{
+				setEventMessages($object->error, $object->errors, 'errors');
+				$action = 'edit';
+			}
+		}
+	}
+
+	// Add comment
+	if (GETPOST('ajoutcomment'))
+	{
+		$error = 0;
+
+		if (!GETPOST('comment'))
+		{
+			$error++;
+			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Comment")), null, 'errors');
+		}
+		if (!GETPOST('commentuser'))
+		{
+			$error++;
+			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("User")), null, 'errors');
+		}
+
+		if (!$error)
+		{
+			$comment = GETPOST("comment");
+			$comment_user = GETPOST('commentuser');
+
+			$resql = $object->addComment($comment, $comment_user);
+
+			if (!$resql)
+			{
+				setEventMessages($langs->trans('ErrorInsertingComment'), null, 'errors');
+			}
+		}
+	}
+
+	// Delete comment
+	$idcomment = GETPOST('deletecomment', 'int');
+	if ($idcomment)
+	{
+		// Security check
+		if (!$user->rights->opensurvey->write) accessforbidden();
+
+		$resql = $object->deleteComment($idcomment);
+	}
+
+	if ($action == 'edit') {
+		// Security check
+		if (!$user->rights->opensurvey->write) accessforbidden();
+	}
 }
 
 
@@ -302,8 +302,8 @@ print '</td></tr>';
 print '<tr><td>'.$langs->trans('ExpireDate').'</td><td colspan="2">';
 if ($action == 'edit') print $form->selectDate($expiredate ? $expiredate : $object->date_fin, 'expire', 0, 0, 0, '', 1, 0);
 else {
-    print dol_print_date($object->date_fin, 'day');
-    if ($object->date_fin && $object->date_fin < dol_now() && $object->status == Opensurveysondage::STATUS_VALIDATED) print img_warning($langs->trans("Expired"));
+	print dol_print_date($object->date_fin, 'day');
+	if ($object->date_fin && $object->date_fin < dol_now() && $object->status == Opensurveysondage::STATUS_VALIDATED) print img_warning($langs->trans("Expired"));
 }
 print '</td></tr>';
 
@@ -356,19 +356,19 @@ print '</form>'."\n";
 print '<div class="tabsAction">';
 
 if ($action != 'edit' && $user->rights->opensurvey->write) {
-    //Modify button
-    print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit&id='.$numsondage.'">'.$langs->trans("Modify").'</a>';
-
-    if ($object->status == Opensurveysondage::STATUS_VALIDATED)
-    {
-        //Close button
-        print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=close&id='.$numsondage.'">'.$langs->trans("Close").'</a>';
-    }
-    if ($object->status == Opensurveysondage::STATUS_CLOSED)
-    {
-        //Opened button
-        print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=reopen&id='.$numsondage.'">'.$langs->trans("ReOpen").'</a>';
-    }
+	//Modify button
+	print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit&id='.$numsondage.'">'.$langs->trans("Modify").'</a>';
+
+	if ($object->status == Opensurveysondage::STATUS_VALIDATED)
+	{
+		//Close button
+		print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=close&id='.$numsondage.'">'.$langs->trans("Close").'</a>';
+	}
+	if ($object->status == Opensurveysondage::STATUS_CLOSED)
+	{
+		//Opened button
+		print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=reopen&id='.$numsondage.'">'.$langs->trans("ReOpen").'</a>';
+	}
 
 	//Delete button
 	print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?suppressionsondage=1&id='.$numsondage.'&amp;action=delete">'.$langs->trans('Delete').'</a>';

+ 612 - 612
htdocs/opensurvey/class/opensurveysondage.class.php

@@ -34,616 +34,616 @@ require_once DOL_DOCUMENT_ROOT."/core/class/commonobject.class.php";
  */
 class Opensurveysondage extends CommonObject
 {
-    /**
-     * @var string ID to identify managed object
-     */
-    public $element = 'opensurvey_sondage';
-
-    /**
-     * @var string Name of table without prefix where object is stored
-     */
-    public $table_element = 'opensurvey_sondage';
-
-    /**
-     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
-     */
-    public $picto = 'poll';
-
-
-    /**
-     * @var string	ID survey
-     */
-    public $id_sondage;
-
-    /**
-     * @var string description
-     */
-    public $description;
-
-    public $mail_admin;
-    public $nom_admin;
-
-    /**
-     * Id of user author of the poll
-     * @var int
-     */
-    public $fk_user_creat;
-
-    /**
-     * @var string	Title
-     */
-    public $title;
-
-    public $date_fin = '';
-    public $status = 1;
-    public $format;
-    public $mailsonde;
-
-    public $sujet;
-
-    /**
-     * @var int		Allow comments on this poll
-     */
-    public $allow_comments;
-
-    /**
-     * @var int		Allow users see others vote
-     */
-    public $allow_spy;
-
-
-    /**
-     * Draft status (not used)
-     */
-    const STATUS_DRAFT = 0;
-    /**
-     * Validated/Opened status
-     */
-    const STATUS_VALIDATED = 1;
-    /**
-     * Closed
-     */
-    const STATUS_CLOSED = 2;
-
-
-
-    /**
-     *  Constructor
-     *
-     *  @param	DoliDb		$db      Database handler
-     */
-    public function __construct($db)
-    {
-        $this->db = $db;
-    }
-
-
-    /**
-     *  Create object into database
-     *
-     *  @param	User    $user        User that creates
-     *  @param  int     $notrigger   0=launch triggers after, 1=disable triggers
-     *  @return int                  <0 if KO, Id of created object if OK
-     */
-    public function create(User $user, $notrigger = 0)
-    {
-        $error = 0;
-
-        // Clean parameters
-        $this->cleanParameters();
-
-        // Check parameters
-        if (!$this->date_fin > 0)
-        {
-            $this->error = 'BadValueForEndDate';
-            dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
-            return -1;
-        }
-
-        // Insert request
-        $sql = "INSERT INTO ".MAIN_DB_PREFIX."opensurvey_sondage(";
-        $sql .= "id_sondage,";
-        $sql .= "commentaires,";
-        $sql .= "fk_user_creat,";
-        $sql .= "titre,";
-        $sql .= "date_fin,";
-        $sql .= "status,";
-        $sql .= "format,";
-        $sql .= "mailsonde,";
-        $sql .= "allow_comments,";
-        $sql .= "allow_spy,";
-        $sql .= "sujet";
-        $sql .= ") VALUES (";
-        $sql .= "'".$this->db->escape($this->id_sondage)."',";
-        $sql .= " ".(empty($this->description) ? 'NULL' : "'".$this->db->escape($this->description)."'").",";
-        $sql .= " ".$user->id.",";
-        $sql .= " '".$this->db->escape($this->title)."',";
-        $sql .= " '".$this->db->idate($this->date_fin)."',";
-        $sql .= " ".$this->status.",";
-        $sql .= " '".$this->db->escape($this->format)."',";
-        $sql .= " ".$this->db->escape($this->mailsonde).",";
-        $sql .= " ".$this->db->escape($this->allow_comments).",";
-        $sql .= " ".$this->db->escape($this->allow_spy).",";
-        $sql .= " '".$this->db->escape($this->sujet)."'";
-        $sql .= ")";
-
-        $this->db->begin();
-
-           dol_syslog(get_class($this)."::create", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
-
-        if (!$error)
-        {
-            if (!$notrigger)
-            {
-                global $langs, $conf;
-
-                // Call trigger
-                $result = $this->call_trigger('OPENSURVEY_CREATE', $user);
-                if ($result < 0) $error++;
-                // End call triggers
-            }
-        }
-
-        // Commit or rollback
-        if ($error)
-        {
-            foreach ($this->errors as $errmsg)
-            {
-                dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
-                $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
-            }
-            $this->db->rollback();
-            return -1 * $error;
-        } else {
-            $this->db->commit();
-            return $this->id;
-        }
-    }
-
-
-    /**
-     *  Load object in memory from the database
-     *
-     *  @param	int		$id    				Id object
-     *  @param	string	$numsurvey			Ref of survey (admin or not)
-     *  @return int          				<0 if KO, >0 if OK
-     */
-    public function fetch($id, $numsurvey = '')
-    {
-        $sql = "SELECT";
-        $sql .= " t.id_sondage,";
-        $sql .= " t.titre as title,";
-        $sql .= " t.commentaires as description,";
-        $sql .= " t.mail_admin,";
-        $sql .= " t.nom_admin,";
-        $sql .= " t.fk_user_creat,";
-        $sql .= " t.date_fin,";
-        $sql .= " t.status,";
-        $sql .= " t.format,";
-        $sql .= " t.mailsonde,";
-        $sql .= " t.allow_comments,";
-        $sql .= " t.allow_spy,";
-        $sql .= " t.sujet,";
-        $sql .= " t.tms";
-        $sql .= " FROM ".MAIN_DB_PREFIX."opensurvey_sondage as t";
-        $sql .= " WHERE t.id_sondage = '".$this->db->escape($id ? $id : $numsurvey)."'";
-
-        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            if ($this->db->num_rows($resql))
-            {
-                $obj = $this->db->fetch_object($resql);
-
-                $this->id_sondage = $obj->id_sondage;
-                $this->ref = $this->id_sondage; //For compatibility
-
-                $this->description = $obj->description;
-                $this->mail_admin = $obj->mail_admin;
-                $this->nom_admin = $obj->nom_admin;
-                $this->title = $obj->title;
-                $this->date_fin = $this->db->jdate($obj->date_fin);
-                $this->status = $obj->status;
-                $this->format = $obj->format;
-                $this->mailsonde = $obj->mailsonde;
-                $this->allow_comments = $obj->allow_comments;
-                $this->allow_spy = $obj->allow_spy;
-                $this->sujet = $obj->sujet;
-                $this->fk_user_creat = $obj->fk_user_creat;
-
-                $this->date_m = $this->db->jdate($obj->tls);
-                $ret = 1;
-            } else {
-                $sondage = ($id ? 'id='.$id : 'sondageid='.$numsurvey);
-                $this->error = 'Fetch no poll found for '.$sondage;
-                dol_syslog($this->error, LOG_ERR);
-                $ret = 0;
-            }
-
-            $this->db->free($resql);
-        } else {
-              $this->error = "Error ".$this->db->lasterror();
-            $ret = -1;
-        }
-
-        return $ret;
-    }
-
-
-    /**
-     *  Update object into database
-     *
-     *  @param	User    $user        User that modifies
-     *  @param  int     $notrigger	 0=launch triggers after, 1=disable triggers
-     *  @return int     		   	 <0 if KO, >0 if OK
-     */
-    public function update(User $user, $notrigger = 0)
-    {
-        global $conf, $langs;
-        $error = 0;
-
-        // Clean parameters
-        $this->cleanParameters();
-
-        // Check parameters
-        // Put here code to add a control on parameters values
-
-        // Update request
-        $sql = "UPDATE ".MAIN_DB_PREFIX."opensurvey_sondage SET";
-        $sql .= " id_sondage=".(isset($this->id_sondage) ? "'".$this->db->escape($this->id_sondage)."'" : "null").",";
-        $sql .= " commentaires=".(isset($this->description) ? "'".$this->db->escape($this->description)."'" : "null").",";
-        $sql .= " mail_admin=".(isset($this->mail_admin) ? "'".$this->db->escape($this->mail_admin)."'" : "null").",";
-        $sql .= " nom_admin=".(isset($this->nom_admin) ? "'".$this->db->escape($this->nom_admin)."'" : "null").",";
-        $sql .= " titre=".(isset($this->title) ? "'".$this->db->escape($this->title)."'" : "null").",";
-        $sql .= " date_fin=".(dol_strlen($this->date_fin) != 0 ? "'".$this->db->idate($this->date_fin)."'" : 'null').",";
-        $sql .= " status=".(isset($this->status) ? "'".$this->db->escape($this->status)."'" : "null").",";
-        $sql .= " format=".(isset($this->format) ? "'".$this->db->escape($this->format)."'" : "null").",";
-        $sql .= " mailsonde=".(isset($this->mailsonde) ? $this->db->escape($this->mailsonde) : "null").",";
-        $sql .= " allow_comments=".$this->db->escape($this->allow_comments).",";
-        $sql .= " allow_spy=".$this->db->escape($this->allow_spy);
-        $sql .= " WHERE id_sondage='".$this->db->escape($this->id_sondage)."'";
-
-        $this->db->begin();
-
-        dol_syslog(get_class($this)."::update", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
-
-        if (!$error && !$notrigger)
-        {
-        	// Call trigger
-        	$result = $this->call_trigger('OPENSURVEY_MODIFY', $user);
-        	if ($result < 0) $error++;
-        	// End call triggers
-        }
-
-        // Commit or rollback
-        if ($error)
-        {
-            foreach ($this->errors as $errmsg)
-            {
-                dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
-                $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
-            }
-            $this->db->rollback();
-            return -1 * $error;
-        } else {
-            $this->db->commit();
-            return 1;
-        }
-    }
-
-    /**
-     *  Delete object in database
-     *
-     *	@param  User	$user        		User that deletes
-     *  @param  int		$notrigger	 		0=launch triggers after, 1=disable triggers
-     *  @param	string	$numsondage			Num sondage admin to delete
-     *  @return	int					 		<0 if KO, >0 if OK
-     */
-    public function delete(User $user, $notrigger = 0, $numsondage = '')
-    {
-        global $conf, $langs;
-        $error = 0;
-
-        if (empty($numsondage))
-        {
-            $numsondage = $this->id_sondage;
-        }
-
-        $this->db->begin();
-
-        if (!$error)
-        {
-            if (!$notrigger)
-            {
-                // Call trigger
-                $result = $this->call_trigger('OPENSURVEY_DELETE', $user);
-                if ($result < 0) $error++;
-                // End call triggers
-            }
-        }
-
-        if (!$error)
-        {
-            $sql = 'DELETE FROM '.MAIN_DB_PREFIX."opensurvey_comments WHERE id_sondage = '".$this->db->escape($numsondage)."'";
-            dol_syslog(get_class($this)."::delete", LOG_DEBUG);
-            $resql = $this->db->query($sql);
-            $sql = 'DELETE FROM '.MAIN_DB_PREFIX."opensurvey_user_studs WHERE id_sondage = '".$this->db->escape($numsondage)."'";
-            dol_syslog(get_class($this)."::delete", LOG_DEBUG);
-            $resql = $this->db->query($sql);
-
-            $sql = "DELETE FROM ".MAIN_DB_PREFIX."opensurvey_sondage";
-            $sql .= " WHERE id_sondage = '".$this->db->escape($numsondage)."'";
-
-            dol_syslog(get_class($this)."::delete", LOG_DEBUG);
-            $resql = $this->db->query($sql);
-            if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
-        }
-
-        // Commit or rollback
-        if ($error)
-        {
-            foreach ($this->errors as $errmsg)
-            {
-                dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
-                $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
-            }
-            $this->db->rollback();
-            return -1 * $error;
-        } else {
-            $this->db->commit();
-            return 1;
-        }
-    }
-
-    /**
-     *  Return a link to the object card (with optionaly the picto)
-     *
-     *	@param	int		$withpicto					Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
-     *  @param	int  	$notooltip					1=Disable tooltip
-     *  @param  string  $morecss            		Add more css on link
-     *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
-     *	@return	string								String with URL
-     */
-    public function getNomUrl($withpicto = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
-    {
-        global $db, $conf, $langs;
-        global $dolibarr_main_authentication, $dolibarr_main_demo;
-        global $menumanager;
-
-        if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
-
-        $result = '';
-        $companylink = '';
-
-        $label = '<u>'.$langs->trans("ShowSurvey").'</u>';
-        $label .= '<br>';
-        $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref.'<br>';
-        $label .= '<b>'.$langs->trans('Title').':</b> '.$this->title.'<br>';
-
-        $url = DOL_URL_ROOT.'/opensurvey/card.php?id='.$this->id;
-
-        // Add param to save lastsearch_values or not
-        $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
-        if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
-        if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
-
-        $linkclose = '';
-        if (empty($notooltip))
-        {
-            if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
-            {
-                $label = $langs->trans("ShowMyObject");
-                $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
-            }
-            $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
-            $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
-        } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
-
-        $linkstart = '<a href="'.$url.'"';
-        $linkstart .= $linkclose.'>';
-        $linkend = '</a>';
-
-        $result .= $linkstart;
-        if ($withpicto) $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
-        if ($withpicto != 2) $result .= $this->ref;
-        $result .= $linkend;
-
-        return $result;
-    }
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     * Return array of lines
-     *
-     * @return 	int		<0 if KO, >0 if OK
-     */
-    public function fetch_lines()
-    {
-        // phpcs:enable
-        $ret = array();
-
-        $sql = "SELECT id_users, nom as name, reponses FROM ".MAIN_DB_PREFIX."opensurvey_user_studs";
-        $sql .= " WHERE id_sondage = '".$this->db->escape($this->id_sondage)."'";
-        $resql = $this->db->query($sql);
-
-        if ($resql)
-        {
-            $num = $this->db->num_rows($resql);
-            $i = 0;
-            while ($i < $num)
-            {
-                $obj = $this->db->fetch_object($resql);
-                $tmp = array('id_users'=>$obj->id_users, 'nom'=>$obj->name, 'reponses'=>$obj->reponses);
-
-                $ret[] = $tmp;
-                $i++;
-            }
-        } else dol_print_error($this->db);
-
-        $this->lines = $ret;
-
-        return count($this->lines);
-    }
-
-    /**
-     *	Initialise object with example values
-     *	Id must be 0 if object instance is a specimen
-     *
-     *	@return	void
-     */
-    public function initAsSpecimen()
-    {
-        $this->id = 0;
-
-        $this->id_sondage = '';
-        $this->description = 'Description of the specimen survey';
-        $this->mail_admin = '';
-        $this->nom_admin = '';
-        $this->title = 'This is a specimen survey';
-        $this->date_fin = dol_now() + 3600 * 24 * 10;
-        $this->status = 1;
-        $this->format = 'classic';
-        $this->mailsonde = '';
-    }
-
-    /**
-     * Returns all comments for the current opensurvey poll
-     *
-     * @return Object[]
-     */
-    public function getComments()
-    {
-        $comments = array();
-
-        $sql = 'SELECT id_comment, usercomment, comment';
-        $sql .= ' FROM '.MAIN_DB_PREFIX.'opensurvey_comments';
-        $sql .= " WHERE id_sondage='".$this->db->escape($this->id_sondage)."'";
-        $sql .= " ORDER BY id_comment";
-        $resql = $this->db->query($sql);
-
-        if ($resql)
-        {
-            $num_rows = $this->db->num_rows($resql);
-
-            if ($num_rows > 0)
-            {
-                while ($obj = $this->db->fetch_object($resql))
-                {
-                    $comments[] = $obj;
-                }
-            }
-        }
-
-        return $comments;
-    }
-
-    /**
-     * Adds a comment to the poll
-     *
-     * @param string $comment Comment content
-     * @param string $comment_user Comment author
-     * @return boolean False in case of the query fails, true if it was successful
-     */
-    public function addComment($comment, $comment_user)
-    {
-        $sql = "INSERT INTO ".MAIN_DB_PREFIX."opensurvey_comments (id_sondage, comment, usercomment)";
-        $sql .= " VALUES ('".$this->db->escape($this->id_sondage)."','".$this->db->escape($comment)."','".$this->db->escape($comment_user)."')";
-        $resql = $this->db->query($sql);
-
-        if (!$resql) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Deletes a comment of the poll
-     *
-     * @param int $id_comment Id of the comment
-     * @return boolean False in case of the query fails, true if it was successful
-     */
-    public function deleteComment($id_comment)
-    {
-        $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'opensurvey_comments WHERE id_comment = '.$id_comment.' AND id_sondage = "'.$this->db->escape($this->id_sondage).'"';
-        $resql = $this->db->query($sql);
-
-        if (!$resql) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Cleans all the class variables before doing an update or an insert
-     *
-     * @return void
-     */
-    private function cleanParameters()
-    {
-        $this->id_sondage = trim($this->id_sondage);
-        $this->description = trim($this->description);
-        $this->mail_admin = trim($this->mail_admin);
-        $this->nom_admin = trim($this->nom_admin);
-        $this->title = trim($this->title);
-        $this->status = trim($this->status);
-        $this->format = trim($this->format);
-        $this->mailsonde = ($this->mailsonde ? 1 : 0);
-        $this->allow_comments = ($this->allow_comments ? 1 : 0);
-        $this->allow_spy = ($this->allow_spy ? 1 : 0);
-        $this->sujet = trim($this->sujet);
-    }
-
-
-    /**
-     *	Return status label of Order
-     *
-     *	@param      int     $mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
-     *	@return     string              Libelle
-     */
-    public function getLibStatut($mode)
-    {
-        return $this->LibStatut($this->status, $mode);
-    }
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *  Return label of status
-     *
-     *  @param		int		$status      	  Id statut
-     *  @param      int		$mode        	  0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
-     *  @return     string					  Label of status
-     */
-    public function LibStatut($status, $mode)
-    {
-        // phpcs:enable
-        global $langs, $conf;
-
-        if (empty($this->labelStatus) || empty($this->labelStatusShort))
-        {
-            global $langs;
-            //$langs->load("mymodule");
-            $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft');
-            $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Opened');
-            $this->labelStatus[self::STATUS_CLOSED] = $langs->trans('Closed');
-            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft');
-            $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Opened');
-            $this->labelStatusShort[self::STATUS_CLOSED] = $langs->trans('Closed');
-        }
-
-        $statusType = 'status'.$status;
-        if ($status == self::STATUS_VALIDATED) {
-            if (0) $statusType = 'status1';
-            else $statusType = 'status4';
-        }
-        if ($status == self::STATUS_CLOSED) $statusType = 'status6';
-
-        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
-    }
+	/**
+	 * @var string ID to identify managed object
+	 */
+	public $element = 'opensurvey_sondage';
+
+	/**
+	 * @var string Name of table without prefix where object is stored
+	 */
+	public $table_element = 'opensurvey_sondage';
+
+	/**
+	 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
+	 */
+	public $picto = 'poll';
+
+
+	/**
+	 * @var string	ID survey
+	 */
+	public $id_sondage;
+
+	/**
+	 * @var string description
+	 */
+	public $description;
+
+	public $mail_admin;
+	public $nom_admin;
+
+	/**
+	 * Id of user author of the poll
+	 * @var int
+	 */
+	public $fk_user_creat;
+
+	/**
+	 * @var string	Title
+	 */
+	public $title;
+
+	public $date_fin = '';
+	public $status = 1;
+	public $format;
+	public $mailsonde;
+
+	public $sujet;
+
+	/**
+	 * @var int		Allow comments on this poll
+	 */
+	public $allow_comments;
+
+	/**
+	 * @var int		Allow users see others vote
+	 */
+	public $allow_spy;
+
+
+	/**
+	 * Draft status (not used)
+	 */
+	const STATUS_DRAFT = 0;
+	/**
+	 * Validated/Opened status
+	 */
+	const STATUS_VALIDATED = 1;
+	/**
+	 * Closed
+	 */
+	const STATUS_CLOSED = 2;
+
+
+
+	/**
+	 *  Constructor
+	 *
+	 *  @param	DoliDb		$db      Database handler
+	 */
+	public function __construct($db)
+	{
+		$this->db = $db;
+	}
+
+
+	/**
+	 *  Create object into database
+	 *
+	 *  @param	User    $user        User that creates
+	 *  @param  int     $notrigger   0=launch triggers after, 1=disable triggers
+	 *  @return int                  <0 if KO, Id of created object if OK
+	 */
+	public function create(User $user, $notrigger = 0)
+	{
+		$error = 0;
+
+		// Clean parameters
+		$this->cleanParameters();
+
+		// Check parameters
+		if (!$this->date_fin > 0)
+		{
+			$this->error = 'BadValueForEndDate';
+			dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
+			return -1;
+		}
+
+		// Insert request
+		$sql = "INSERT INTO ".MAIN_DB_PREFIX."opensurvey_sondage(";
+		$sql .= "id_sondage,";
+		$sql .= "commentaires,";
+		$sql .= "fk_user_creat,";
+		$sql .= "titre,";
+		$sql .= "date_fin,";
+		$sql .= "status,";
+		$sql .= "format,";
+		$sql .= "mailsonde,";
+		$sql .= "allow_comments,";
+		$sql .= "allow_spy,";
+		$sql .= "sujet";
+		$sql .= ") VALUES (";
+		$sql .= "'".$this->db->escape($this->id_sondage)."',";
+		$sql .= " ".(empty($this->description) ? 'NULL' : "'".$this->db->escape($this->description)."'").",";
+		$sql .= " ".$user->id.",";
+		$sql .= " '".$this->db->escape($this->title)."',";
+		$sql .= " '".$this->db->idate($this->date_fin)."',";
+		$sql .= " ".$this->status.",";
+		$sql .= " '".$this->db->escape($this->format)."',";
+		$sql .= " ".$this->db->escape($this->mailsonde).",";
+		$sql .= " ".$this->db->escape($this->allow_comments).",";
+		$sql .= " ".$this->db->escape($this->allow_spy).",";
+		$sql .= " '".$this->db->escape($this->sujet)."'";
+		$sql .= ")";
+
+		$this->db->begin();
+
+		   dol_syslog(get_class($this)."::create", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
+
+		if (!$error)
+		{
+			if (!$notrigger)
+			{
+				global $langs, $conf;
+
+				// Call trigger
+				$result = $this->call_trigger('OPENSURVEY_CREATE', $user);
+				if ($result < 0) $error++;
+				// End call triggers
+			}
+		}
+
+		// Commit or rollback
+		if ($error)
+		{
+			foreach ($this->errors as $errmsg)
+			{
+				dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
+				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
+			}
+			$this->db->rollback();
+			return -1 * $error;
+		} else {
+			$this->db->commit();
+			return $this->id;
+		}
+	}
+
+
+	/**
+	 *  Load object in memory from the database
+	 *
+	 *  @param	int		$id    				Id object
+	 *  @param	string	$numsurvey			Ref of survey (admin or not)
+	 *  @return int          				<0 if KO, >0 if OK
+	 */
+	public function fetch($id, $numsurvey = '')
+	{
+		$sql = "SELECT";
+		$sql .= " t.id_sondage,";
+		$sql .= " t.titre as title,";
+		$sql .= " t.commentaires as description,";
+		$sql .= " t.mail_admin,";
+		$sql .= " t.nom_admin,";
+		$sql .= " t.fk_user_creat,";
+		$sql .= " t.date_fin,";
+		$sql .= " t.status,";
+		$sql .= " t.format,";
+		$sql .= " t.mailsonde,";
+		$sql .= " t.allow_comments,";
+		$sql .= " t.allow_spy,";
+		$sql .= " t.sujet,";
+		$sql .= " t.tms";
+		$sql .= " FROM ".MAIN_DB_PREFIX."opensurvey_sondage as t";
+		$sql .= " WHERE t.id_sondage = '".$this->db->escape($id ? $id : $numsurvey)."'";
+
+		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			if ($this->db->num_rows($resql))
+			{
+				$obj = $this->db->fetch_object($resql);
+
+				$this->id_sondage = $obj->id_sondage;
+				$this->ref = $this->id_sondage; //For compatibility
+
+				$this->description = $obj->description;
+				$this->mail_admin = $obj->mail_admin;
+				$this->nom_admin = $obj->nom_admin;
+				$this->title = $obj->title;
+				$this->date_fin = $this->db->jdate($obj->date_fin);
+				$this->status = $obj->status;
+				$this->format = $obj->format;
+				$this->mailsonde = $obj->mailsonde;
+				$this->allow_comments = $obj->allow_comments;
+				$this->allow_spy = $obj->allow_spy;
+				$this->sujet = $obj->sujet;
+				$this->fk_user_creat = $obj->fk_user_creat;
+
+				$this->date_m = $this->db->jdate($obj->tls);
+				$ret = 1;
+			} else {
+				$sondage = ($id ? 'id='.$id : 'sondageid='.$numsurvey);
+				$this->error = 'Fetch no poll found for '.$sondage;
+				dol_syslog($this->error, LOG_ERR);
+				$ret = 0;
+			}
+
+			$this->db->free($resql);
+		} else {
+			  $this->error = "Error ".$this->db->lasterror();
+			$ret = -1;
+		}
+
+		return $ret;
+	}
+
+
+	/**
+	 *  Update object into database
+	 *
+	 *  @param	User    $user        User that modifies
+	 *  @param  int     $notrigger	 0=launch triggers after, 1=disable triggers
+	 *  @return int     		   	 <0 if KO, >0 if OK
+	 */
+	public function update(User $user, $notrigger = 0)
+	{
+		global $conf, $langs;
+		$error = 0;
+
+		// Clean parameters
+		$this->cleanParameters();
+
+		// Check parameters
+		// Put here code to add a control on parameters values
+
+		// Update request
+		$sql = "UPDATE ".MAIN_DB_PREFIX."opensurvey_sondage SET";
+		$sql .= " id_sondage=".(isset($this->id_sondage) ? "'".$this->db->escape($this->id_sondage)."'" : "null").",";
+		$sql .= " commentaires=".(isset($this->description) ? "'".$this->db->escape($this->description)."'" : "null").",";
+		$sql .= " mail_admin=".(isset($this->mail_admin) ? "'".$this->db->escape($this->mail_admin)."'" : "null").",";
+		$sql .= " nom_admin=".(isset($this->nom_admin) ? "'".$this->db->escape($this->nom_admin)."'" : "null").",";
+		$sql .= " titre=".(isset($this->title) ? "'".$this->db->escape($this->title)."'" : "null").",";
+		$sql .= " date_fin=".(dol_strlen($this->date_fin) != 0 ? "'".$this->db->idate($this->date_fin)."'" : 'null').",";
+		$sql .= " status=".(isset($this->status) ? "'".$this->db->escape($this->status)."'" : "null").",";
+		$sql .= " format=".(isset($this->format) ? "'".$this->db->escape($this->format)."'" : "null").",";
+		$sql .= " mailsonde=".(isset($this->mailsonde) ? $this->db->escape($this->mailsonde) : "null").",";
+		$sql .= " allow_comments=".$this->db->escape($this->allow_comments).",";
+		$sql .= " allow_spy=".$this->db->escape($this->allow_spy);
+		$sql .= " WHERE id_sondage='".$this->db->escape($this->id_sondage)."'";
+
+		$this->db->begin();
+
+		dol_syslog(get_class($this)."::update", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
+
+		if (!$error && !$notrigger)
+		{
+			// Call trigger
+			$result = $this->call_trigger('OPENSURVEY_MODIFY', $user);
+			if ($result < 0) $error++;
+			// End call triggers
+		}
+
+		// Commit or rollback
+		if ($error)
+		{
+			foreach ($this->errors as $errmsg)
+			{
+				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
+				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
+			}
+			$this->db->rollback();
+			return -1 * $error;
+		} else {
+			$this->db->commit();
+			return 1;
+		}
+	}
+
+	/**
+	 *  Delete object in database
+	 *
+	 *	@param  User	$user        		User that deletes
+	 *  @param  int		$notrigger	 		0=launch triggers after, 1=disable triggers
+	 *  @param	string	$numsondage			Num sondage admin to delete
+	 *  @return	int					 		<0 if KO, >0 if OK
+	 */
+	public function delete(User $user, $notrigger = 0, $numsondage = '')
+	{
+		global $conf, $langs;
+		$error = 0;
+
+		if (empty($numsondage))
+		{
+			$numsondage = $this->id_sondage;
+		}
+
+		$this->db->begin();
+
+		if (!$error)
+		{
+			if (!$notrigger)
+			{
+				// Call trigger
+				$result = $this->call_trigger('OPENSURVEY_DELETE', $user);
+				if ($result < 0) $error++;
+				// End call triggers
+			}
+		}
+
+		if (!$error)
+		{
+			$sql = 'DELETE FROM '.MAIN_DB_PREFIX."opensurvey_comments WHERE id_sondage = '".$this->db->escape($numsondage)."'";
+			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
+			$resql = $this->db->query($sql);
+			$sql = 'DELETE FROM '.MAIN_DB_PREFIX."opensurvey_user_studs WHERE id_sondage = '".$this->db->escape($numsondage)."'";
+			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
+			$resql = $this->db->query($sql);
+
+			$sql = "DELETE FROM ".MAIN_DB_PREFIX."opensurvey_sondage";
+			$sql .= " WHERE id_sondage = '".$this->db->escape($numsondage)."'";
+
+			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
+			$resql = $this->db->query($sql);
+			if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); }
+		}
+
+		// Commit or rollback
+		if ($error)
+		{
+			foreach ($this->errors as $errmsg)
+			{
+				dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
+				$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
+			}
+			$this->db->rollback();
+			return -1 * $error;
+		} else {
+			$this->db->commit();
+			return 1;
+		}
+	}
+
+	/**
+	 *  Return a link to the object card (with optionaly the picto)
+	 *
+	 *	@param	int		$withpicto					Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
+	 *  @param	int  	$notooltip					1=Disable tooltip
+	 *  @param  string  $morecss            		Add more css on link
+	 *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
+	 *	@return	string								String with URL
+	 */
+	public function getNomUrl($withpicto = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
+	{
+		global $db, $conf, $langs;
+		global $dolibarr_main_authentication, $dolibarr_main_demo;
+		global $menumanager;
+
+		if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
+
+		$result = '';
+		$companylink = '';
+
+		$label = '<u>'.$langs->trans("ShowSurvey").'</u>';
+		$label .= '<br>';
+		$label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref.'<br>';
+		$label .= '<b>'.$langs->trans('Title').':</b> '.$this->title.'<br>';
+
+		$url = DOL_URL_ROOT.'/opensurvey/card.php?id='.$this->id;
+
+		// Add param to save lastsearch_values or not
+		$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
+		if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
+		if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
+
+		$linkclose = '';
+		if (empty($notooltip))
+		{
+			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
+			{
+				$label = $langs->trans("ShowMyObject");
+				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
+			}
+			$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
+			$linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
+		} else $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
+
+		$linkstart = '<a href="'.$url.'"';
+		$linkstart .= $linkclose.'>';
+		$linkend = '</a>';
+
+		$result .= $linkstart;
+		if ($withpicto) $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
+		if ($withpicto != 2) $result .= $this->ref;
+		$result .= $linkend;
+
+		return $result;
+	}
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 * Return array of lines
+	 *
+	 * @return 	int		<0 if KO, >0 if OK
+	 */
+	public function fetch_lines()
+	{
+		// phpcs:enable
+		$ret = array();
+
+		$sql = "SELECT id_users, nom as name, reponses FROM ".MAIN_DB_PREFIX."opensurvey_user_studs";
+		$sql .= " WHERE id_sondage = '".$this->db->escape($this->id_sondage)."'";
+		$resql = $this->db->query($sql);
+
+		if ($resql)
+		{
+			$num = $this->db->num_rows($resql);
+			$i = 0;
+			while ($i < $num)
+			{
+				$obj = $this->db->fetch_object($resql);
+				$tmp = array('id_users'=>$obj->id_users, 'nom'=>$obj->name, 'reponses'=>$obj->reponses);
+
+				$ret[] = $tmp;
+				$i++;
+			}
+		} else dol_print_error($this->db);
+
+		$this->lines = $ret;
+
+		return count($this->lines);
+	}
+
+	/**
+	 *	Initialise object with example values
+	 *	Id must be 0 if object instance is a specimen
+	 *
+	 *	@return	void
+	 */
+	public function initAsSpecimen()
+	{
+		$this->id = 0;
+
+		$this->id_sondage = '';
+		$this->description = 'Description of the specimen survey';
+		$this->mail_admin = '';
+		$this->nom_admin = '';
+		$this->title = 'This is a specimen survey';
+		$this->date_fin = dol_now() + 3600 * 24 * 10;
+		$this->status = 1;
+		$this->format = 'classic';
+		$this->mailsonde = '';
+	}
+
+	/**
+	 * Returns all comments for the current opensurvey poll
+	 *
+	 * @return Object[]
+	 */
+	public function getComments()
+	{
+		$comments = array();
+
+		$sql = 'SELECT id_comment, usercomment, comment';
+		$sql .= ' FROM '.MAIN_DB_PREFIX.'opensurvey_comments';
+		$sql .= " WHERE id_sondage='".$this->db->escape($this->id_sondage)."'";
+		$sql .= " ORDER BY id_comment";
+		$resql = $this->db->query($sql);
+
+		if ($resql)
+		{
+			$num_rows = $this->db->num_rows($resql);
+
+			if ($num_rows > 0)
+			{
+				while ($obj = $this->db->fetch_object($resql))
+				{
+					$comments[] = $obj;
+				}
+			}
+		}
+
+		return $comments;
+	}
+
+	/**
+	 * Adds a comment to the poll
+	 *
+	 * @param string $comment Comment content
+	 * @param string $comment_user Comment author
+	 * @return boolean False in case of the query fails, true if it was successful
+	 */
+	public function addComment($comment, $comment_user)
+	{
+		$sql = "INSERT INTO ".MAIN_DB_PREFIX."opensurvey_comments (id_sondage, comment, usercomment)";
+		$sql .= " VALUES ('".$this->db->escape($this->id_sondage)."','".$this->db->escape($comment)."','".$this->db->escape($comment_user)."')";
+		$resql = $this->db->query($sql);
+
+		if (!$resql) {
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Deletes a comment of the poll
+	 *
+	 * @param int $id_comment Id of the comment
+	 * @return boolean False in case of the query fails, true if it was successful
+	 */
+	public function deleteComment($id_comment)
+	{
+		$sql = 'DELETE FROM '.MAIN_DB_PREFIX.'opensurvey_comments WHERE id_comment = '.$id_comment.' AND id_sondage = "'.$this->db->escape($this->id_sondage).'"';
+		$resql = $this->db->query($sql);
+
+		if (!$resql) {
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Cleans all the class variables before doing an update or an insert
+	 *
+	 * @return void
+	 */
+	private function cleanParameters()
+	{
+		$this->id_sondage = trim($this->id_sondage);
+		$this->description = trim($this->description);
+		$this->mail_admin = trim($this->mail_admin);
+		$this->nom_admin = trim($this->nom_admin);
+		$this->title = trim($this->title);
+		$this->status = trim($this->status);
+		$this->format = trim($this->format);
+		$this->mailsonde = ($this->mailsonde ? 1 : 0);
+		$this->allow_comments = ($this->allow_comments ? 1 : 0);
+		$this->allow_spy = ($this->allow_spy ? 1 : 0);
+		$this->sujet = trim($this->sujet);
+	}
+
+
+	/**
+	 *	Return status label of Order
+	 *
+	 *	@param      int     $mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
+	 *	@return     string              Libelle
+	 */
+	public function getLibStatut($mode)
+	{
+		return $this->LibStatut($this->status, $mode);
+	}
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *  Return label of status
+	 *
+	 *  @param		int		$status      	  Id statut
+	 *  @param      int		$mode        	  0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
+	 *  @return     string					  Label of status
+	 */
+	public function LibStatut($status, $mode)
+	{
+		// phpcs:enable
+		global $langs, $conf;
+
+		if (empty($this->labelStatus) || empty($this->labelStatusShort))
+		{
+			global $langs;
+			//$langs->load("mymodule");
+			$this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft');
+			$this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Opened');
+			$this->labelStatus[self::STATUS_CLOSED] = $langs->trans('Closed');
+			$this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft');
+			$this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Opened');
+			$this->labelStatusShort[self::STATUS_CLOSED] = $langs->trans('Closed');
+		}
+
+		$statusType = 'status'.$status;
+		if ($status == self::STATUS_VALIDATED) {
+			if (0) $statusType = 'status1';
+			else $statusType = 'status4';
+		}
+		if ($status == self::STATUS_CLOSED) $statusType = 'status6';
+
+		return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
+	}
 }

+ 7 - 7
htdocs/product/class/product.class.php

@@ -2210,7 +2210,7 @@ class Product extends CommonObject
                             }
                             }*/
 						} else {
-							$this->error=$this->db->lasterror;
+							$this->error = $this->db->lasterror;
 							return -1;
 						}
 					}
@@ -2255,12 +2255,12 @@ class Product extends CommonObject
 								}
 								$this->prices_by_qty_list[0] = $resultat;
 							} else {
-								$this->error=$this->db->lasterror;
+								$this->error = $this->db->lasterror;
 								return -1;
 							}
 						}
 					} else {
-						$this->error=$this->db->lasterror;
+						$this->error = $this->db->lasterror;
 						return -1;
 					}
 				} elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES) && empty($ignore_price_load))    // prices per customer and quantity
@@ -2314,12 +2314,12 @@ class Product extends CommonObject
 									}
 									$this->prices_by_qty_list[$i] = $resultat;
 								} else {
-									$this->error=$this->db->lasterror;
+									$this->error = $this->db->lasterror;
 									return -1;
 								}
 							}
 						} else {
-							$this->error=$this->db->lasterror;
+							$this->error = $this->db->lasterror;
 							return -1;
 						}
 					}
@@ -2346,7 +2346,7 @@ class Product extends CommonObject
 				return 0;
 			}
 		} else {
-			$this->error=$this->db->lasterror;
+			$this->error = $this->db->lasterror;
 			return -1;
 		}
 	}
@@ -4769,7 +4769,7 @@ class Product extends CommonObject
 			if ($result < 0) dol_print_error($this->db, $this->error);
 			$stock_sending_client = $this->stats_expedition['qty'];
 		}
-		if (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || ! empty($conf->supplier_order->enabled))
+		if (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled))
 		{
 			$filterStatus = '1,2,3,4';
 			if (isset($includedraftpoforvirtual)) $filterStatus = '0,'.$filterStatus;

+ 4 - 4
htdocs/product/inventory/card.php

@@ -447,11 +447,11 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 		// Documents
 		if ($includedocgeneration) {
 			$objref = dol_sanitizeFileName($object->ref);
-			$relativepath = $objref . '/' . $objref . '.pdf';
+			$relativepath = $objref.'/'.$objref.'.pdf';
 			$filedir = $conf->mymodule->dir_output.'/'.$object->element.'/'.$objref;
-			$urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id;
-			$genallowed = $user->rights->mymodule->myobject->read;	// If you can read, you can build the PDF to read content
-			$delallowed = $user->rights->mymodule->myobject->write;	// If you can create/edit, you can remove a file on card
+			$urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
+			$genallowed = $user->rights->mymodule->myobject->read; // If you can read, you can build the PDF to read content
+			$delallowed = $user->rights->mymodule->myobject->write; // If you can create/edit, you can remove a file on card
 			print $formfile->showdocuments('mymodule:MyObject', $object->element.'/'.$objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang);
 		}
 

+ 40 - 40
htdocs/product/inventory/inventory.php

@@ -133,7 +133,7 @@ if (empty($reshook))
 			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
 		}
 
-		if (! $error && ! empty($conf->productbatch->enabled)) {
+		if (!$error && !empty($conf->productbatch->enabled)) {
 			$tmpproduct = new Product($db);
 			$result = $tmpproduct->fetch($fk_product);
 
@@ -320,53 +320,53 @@ if ($object->id > 0)
 		print '<br>';
 		print '</form>';
 	} else {
-    	print '<div class="tabsAction">'."\n";
-    	$parameters = array();
-    	$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
-    	if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
-
-    	if (empty($reshook))
-    	{
-    		if ($object->status == Inventory::STATUS_DRAFT)
-    		{
-    			if ($permissiontoadd)
-    			{
-    				print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_validate&confirm=yes">'.$langs->trans("Validate").' ('.$langs->trans("Start").')</a>'."\n";
-    			} else {
-    				print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Validate').' ('.$langs->trans("Start").')</a>'."\n";
-    			}
-    		}
-
-    		if ($object->status == Inventory::STATUS_VALIDATED)
-    		{
-    			if ($permissiontoadd)
-    			{
-    				/*
+		print '<div class="tabsAction">'."\n";
+		$parameters = array();
+		$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
+		if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+
+		if (empty($reshook))
+		{
+			if ($object->status == Inventory::STATUS_DRAFT)
+			{
+				if ($permissiontoadd)
+				{
+					print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_validate&confirm=yes">'.$langs->trans("Validate").' ('.$langs->trans("Start").')</a>'."\n";
+				} else {
+					print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Validate').' ('.$langs->trans("Start").')</a>'."\n";
+				}
+			}
+
+			if ($object->status == Inventory::STATUS_VALIDATED)
+			{
+				if ($permissiontoadd)
+				{
+					/*
     				if ($conf->barcode->enabled) {
     					print '<a href="#" class="butAction">'.$langs->trans("UpdateByScaningProductBarcode").'</a>';
     				}
     				if ($conf->productbatch->enabled) {
     					print '<a href="#" class="butAction">'.$langs->trans('UpdateByScaningLot').'</a>';
     				}*/
-    				if ($conf->barcode->enabled || $conf->productbatch->enabled) {
-    					print '<a href="#" class="butAction">'.$langs->trans("UpdateByScaning").'</a>';
-    				}
-    			} else {
-    				print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Save').'</a>'."\n";
-    			}
-    		}
+					if ($conf->barcode->enabled || $conf->productbatch->enabled) {
+						print '<a href="#" class="butAction">'.$langs->trans("UpdateByScaning").'</a>';
+					}
+				} else {
+					print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Save').'</a>'."\n";
+				}
+			}
 
-    		if ($object->status == Inventory::STATUS_VALIDATED)
-    		{
-	        	if ($permissiontoadd)
-	    		{
-	    			print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=record">'.$langs->trans("Finish").'</a>'."\n";
-	    		} else {
-	    			print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Finish').'</a>'."\n";
-	    		}
-    		}
+			if ($object->status == Inventory::STATUS_VALIDATED)
+			{
+				if ($permissiontoadd)
+				{
+					print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=record">'.$langs->trans("Finish").'</a>'."\n";
+				} else {
+					print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Finish').'</a>'."\n";
+				}
+			}
 
-    		/*if ($object->status == Inventory::STATUS_VALIDATED)
+			/*if ($object->status == Inventory::STATUS_VALIDATED)
     		{
 	    		if ($permissiontoadd)
 	    		{

+ 4 - 4
htdocs/product/list.php

@@ -219,7 +219,7 @@ $arrayfields = array(
 );
 
 // MultiPrices
-if ($conf->global->PRODUIT_MULTIPRICES){
+if ($conf->global->PRODUIT_MULTIPRICES) {
 	for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++)
 	{
 		$keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$i;
@@ -753,7 +753,7 @@ if ($resql)
 	}
 
 	// Multiprice
-	if ($conf->global->PRODUIT_MULTIPRICES){
+	if ($conf->global->PRODUIT_MULTIPRICES) {
 		foreach ($arraypricelevel as $key => $value)
 		{
 			if (!empty($arrayfields['p.sellprice'.$key]['checked']))
@@ -905,7 +905,7 @@ if ($resql)
 	}
 
 	// Multiprices
-	if ($conf->global->PRODUIT_MULTIPRICES){
+	if ($conf->global->PRODUIT_MULTIPRICES) {
 		foreach ($arraypricelevel as $key => $value)
 		{
 			if (!empty($arrayfields['p.sellprice'.$key]['checked']))
@@ -1265,7 +1265,7 @@ if ($resql)
 
 
 		// Multiprices
-		if ($conf->global->PRODUIT_MULTIPRICES){
+		if ($conf->global->PRODUIT_MULTIPRICES) {
 			foreach ($arraypricelevel as $key => $value)
 			{
 				if (!empty($arrayfields['p.sellprice'.$key]['checked']))

+ 1 - 1
htdocs/product/stock/class/entrepot.class.php

@@ -736,7 +736,7 @@ class Entrepot extends CommonObject
 
 		$result .= $linkstart;
 		if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
-		if ($withpicto != 2) $result .= (($showfullpath || !empty($conf->global->STOCK_ALWAYS_SHOW_FULL_ARBO)) ? $this->get_full_arbo() : (empty($this->label)?$this->libelle:$this->label));
+		if ($withpicto != 2) $result .= (($showfullpath || !empty($conf->global->STOCK_ALWAYS_SHOW_FULL_ARBO)) ? $this->get_full_arbo() : (empty($this->label) ? $this->libelle : $this->label));
 		$result .= $linkend;
 
 		global $action;

+ 107 - 107
htdocs/product/stock/product.php

@@ -39,7 +39,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productstockentrepot.class.php';
 if (!empty($conf->productbatch->enabled)) {
-    require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
+	require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
 }
 if (!empty($conf->projet->enabled)) {
 	require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
@@ -88,7 +88,7 @@ $extrafields->fetch_name_optionals_label($object->table_element);
 
 if ($id > 0 || !empty($ref))
 {
-    $result = $object->fetch($id, $ref);
+	$result = $object->fetch($id, $ref);
 }
 
 if (empty($id) && !empty($object->id)) $id = $object->id;
@@ -100,9 +100,9 @@ $canvas = !empty($object->canvas) ? $object->canvas : GETPOST("canvas");
 $objcanvas = null;
 if (!empty($canvas))
 {
-    require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
-    $objcanvas = new Canvas($db, $action);
-    $objcanvas->getCanvas('stockproduct', 'card', $canvas);
+	require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
+	$objcanvas = new Canvas($db, $action);
+	$objcanvas->getCanvas('stockproduct', 'card', $canvas);
 }
 
 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
@@ -168,27 +168,27 @@ if ($action == 'delete_productstockwarehouse' && !empty($user->rights->produit->
 // Set stock limit
 if ($action == 'setseuil_stock_alerte' && !empty($user->rights->produit->creer))
 {
-    $object = new Product($db);
-    $result = $object->fetch($id);
-    $object->seuil_stock_alerte = $stocklimit;
-    $result = $object->update($object->id, $user, 0, 'update');
-    if ($result < 0)
-    	setEventMessages($object->error, $object->errors, 'errors');
-    //else
-    //	setEventMessages($lans->trans("SavedRecordSuccessfully"), null, 'mesgs');
-    $action = '';
+	$object = new Product($db);
+	$result = $object->fetch($id);
+	$object->seuil_stock_alerte = $stocklimit;
+	$result = $object->update($object->id, $user, 0, 'update');
+	if ($result < 0)
+		setEventMessages($object->error, $object->errors, 'errors');
+	//else
+	//	setEventMessages($lans->trans("SavedRecordSuccessfully"), null, 'mesgs');
+	$action = '';
 }
 
 // Set desired stock
 if ($action == 'setdesiredstock' && !empty($user->rights->produit->creer))
 {
-    $object = new Product($db);
-    $result = $object->fetch($id);
-    $object->desiredstock = $desiredstock;
-    $result = $object->update($object->id, $user, 0, 'update');
-    if ($result < 0)
-    	setEventMessages($object->error, $object->errors, 'errors');
-    $action = '';
+	$object = new Product($db);
+	$result = $object->fetch($id);
+	$object->desiredstock = $desiredstock;
+	$result = $object->update($object->id, $user, 0, 'update');
+	if ($result < 0)
+		setEventMessages($object->error, $object->errors, 'errors');
+	$action = '';
 }
 
 
@@ -258,12 +258,12 @@ if ($action == "correct_stock" && !$cancel)
 				); // We do not change value of stock for a correction
 			} else {
 				$result = $object->correct_stock(
-		    		$user,
-		    		GETPOST("id_entrepot", 'int'),
+					$user,
+					GETPOST("id_entrepot", 'int'),
 					$nbpiece,
-		    		GETPOST("mouvement", 'int'),
-		    		GETPOST("label", 'alphanohtml'),
-		    		$priceunit,
+					GETPOST("mouvement", 'int'),
+					GETPOST("label", 'alphanohtml'),
+					$priceunit,
 					GETPOST('inventorycode', 'alphanohtml'),
 					$origin_element,
 					$origin_id
@@ -277,12 +277,12 @@ if ($action == "correct_stock" && !$cancel)
 					header("Location: ".$backtopage);
 					exit;
 				} else {
-	            	header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
+					header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id);
 					exit;
 				}
 			} else {
-			    setEventMessages($object->error, $object->errors, 'errors');
-			    $action = 'correction';
+				setEventMessages($object->error, $object->errors, 'errors');
+				$action = 'correction';
 			}
 		}
 	}
@@ -311,15 +311,15 @@ if ($action == "transfert_stock" && !$cancel)
 	}
 	if (!empty($conf->productbatch->enabled))
 	{
-	    $object = new Product($db);
-	    $result = $object->fetch($id);
-
-	    if ($object->hasbatch() && !$batchnumber)
-	    {
-	        setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("batch_number")), null, 'errors');
-	        $error++;
-	        $action = 'transfert';
-	    }
+		$object = new Product($db);
+		$result = $object->fetch($id);
+
+		if ($object->hasbatch() && !$batchnumber)
+		{
+			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("batch_number")), null, 'errors');
+			$error++;
+			$action = 'transfert';
+		}
 	}
 
 	if (!$error)
@@ -399,31 +399,31 @@ if ($action == "transfert_stock" && !$cancel)
 			} else {
 				if (!$error)
 				{
-    			    // Remove stock
-    				$result1 = $object->correct_stock(
-    					$user,
-    					GETPOST("id_entrepot", 'int'),
-    					$nbpiece,
-    					1,
-    					GETPOST("label", 'alphanohtml'),
-    					$pricesrc,
-    					GETPOST('inventorycode', 'alphanohtml')
-    				);
-    				if ($result1 < 0) $error++;
+					// Remove stock
+					$result1 = $object->correct_stock(
+						$user,
+						GETPOST("id_entrepot", 'int'),
+						$nbpiece,
+						1,
+						GETPOST("label", 'alphanohtml'),
+						$pricesrc,
+						GETPOST('inventorycode', 'alphanohtml')
+					);
+					if ($result1 < 0) $error++;
 				}
 				if (!$error)
 				{
-    				// Add stock
-    				$result2 = $object->correct_stock(
-    					$user,
-    					GETPOST("id_entrepot_destination", 'int'),
-    					$nbpiece,
-    					0,
-    					GETPOST("label", 'alphanohtml'),
-    					$pricedest,
-    					GETPOST('inventorycode', 'alphanohtml')
-    				);
-    				if ($result2 < 0) $error++;
+					// Add stock
+					$result2 = $object->correct_stock(
+						$user,
+						GETPOST("id_entrepot_destination", 'int'),
+						$nbpiece,
+						0,
+						GETPOST("label", 'alphanohtml'),
+						$pricedest,
+						GETPOST('inventorycode', 'alphanohtml')
+					);
+					if ($result2 < 0) $error++;
 				}
 			}
 
@@ -452,35 +452,35 @@ if ($action == "transfert_stock" && !$cancel)
 // Update batch information
 if ($action == 'updateline' && GETPOST('save') == $langs->trans('Save'))
 {
-    $pdluo = new Productbatch($db);
-    $result = $pdluo->fetch(GETPOST('pdluoid', 'int'));
-
-    if ($result > 0)
-    {
-        if ($pdluo->id)
-        {
-            if ((!GETPOST("sellby")) && (!GETPOST("eatby")) && (!$batchnumber)) {
-                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("atleast1batchfield")), null, 'errors');
-            } else {
-                $d_eatby = dol_mktime(0, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']);
-                $d_sellby = dol_mktime(0, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']);
-                $pdluo->batch = $batchnumber;
-                $pdluo->eatby = $d_eatby;
-                $pdluo->sellby = $d_sellby;
-                $result = $pdluo->update($user);
-                if ($result < 0)
-                {
-                    setEventMessages($pdluo->error, $pdluo->errors, 'errors');
-                }
-            }
-        } else {
-            setEventMessages($langs->trans('BatchInformationNotfound'), null, 'errors');
-        }
-    } else {
-        setEventMessages($pdluo->error, null, 'errors');
-    }
-    header("Location: product.php?id=".$id);
-    exit;
+	$pdluo = new Productbatch($db);
+	$result = $pdluo->fetch(GETPOST('pdluoid', 'int'));
+
+	if ($result > 0)
+	{
+		if ($pdluo->id)
+		{
+			if ((!GETPOST("sellby")) && (!GETPOST("eatby")) && (!$batchnumber)) {
+				setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("atleast1batchfield")), null, 'errors');
+			} else {
+				$d_eatby = dol_mktime(0, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']);
+				$d_sellby = dol_mktime(0, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']);
+				$pdluo->batch = $batchnumber;
+				$pdluo->eatby = $d_eatby;
+				$pdluo->sellby = $d_sellby;
+				$result = $pdluo->update($user);
+				if ($result < 0)
+				{
+					setEventMessages($pdluo->error, $pdluo->errors, 'errors');
+				}
+			}
+		} else {
+			setEventMessages($langs->trans('BatchInformationNotfound'), null, 'errors');
+		}
+	} else {
+		setEventMessages($pdluo->error, null, 'errors');
+	}
+	header("Location: product.php?id=".$id);
+	exit;
 }
 
 
@@ -528,17 +528,17 @@ if ($id > 0 || $ref)
 
 		dol_htmloutput_events();
 
-        $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
+		$linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
 
-        $shownav = 1;
-        if ($user->socid && !in_array('stock', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) $shownav = 0;
+		$shownav = 1;
+		if ($user->socid && !in_array('stock', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) $shownav = 0;
 
-        dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
+		dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
 
-        print '<div class="fichecenter">';
+		print '<div class="fichecenter">';
 
-        print '<div class="underbanner clearboth"></div>';
-        print '<table class="border tableforfield" width="100%">';
+		print '<div class="underbanner clearboth"></div>';
+		print '<table class="border tableforfield" width="100%">';
 
 		if (!$variants) {
 			if ($conf->productbatch->enabled) {
@@ -629,7 +629,7 @@ if ($id > 0 || $ref)
 			$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL) ? $langs->trans("ReStockOnBill").'<br>' : '');
 			$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? $langs->trans("ReStockOnValidateOrder").'<br>' : '');
 			$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? $langs->trans("ReStockOnDispatchOrder").'<br>' : '');
-       		$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? $langs->trans("StockOnReception").'<br>' : '');
+	   		$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? $langs->trans("StockOnReception").'<br>' : '');
 
 			print '<tr><td>';
 			print $form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1);
@@ -656,13 +656,13 @@ if ($id > 0 || $ref)
 
 			// Number of product from customer order already sent (partial shipping)
 			if (!empty($conf->expedition->enabled)) {
-                require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
-                $filterShipmentStatus = '';
-                if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) {
-                    $filterShipmentStatus = Expedition::STATUS_VALIDATED.','.Expedition::STATUS_CLOSED;
-                } elseif (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) {
-                    $filterShipmentStatus = Expedition::STATUS_CLOSED;
-                }
+				require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
+				$filterShipmentStatus = '';
+				if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) {
+					$filterShipmentStatus = Expedition::STATUS_VALIDATED.','.Expedition::STATUS_CLOSED;
+				} elseif (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) {
+					$filterShipmentStatus = Expedition::STATUS_CLOSED;
+				}
 				if ($found) $helpondiff .= '<br>'; else $found = 1;
 				$result = $object->load_stats_sending(0, '2', 1, $filterShipmentStatus);
 				$helpondiff .= $langs->trans("ProductQtyInShipmentAlreadySent").': '.$object->stats_expedition['qty'];
@@ -730,8 +730,8 @@ if ($id > 0 || $ref)
 		}
 		print "</table>";
 
-        print '</div>';
-        print '<div style="clear:both"></div>';
+		print '</div>';
+		print '<div style="clear:both"></div>';
 
 		dol_fiche_end();
 	}
@@ -763,7 +763,7 @@ if (empty($reshook))
 {
 	if (empty($action) && $object->id)
 	{
-	    print "<div class=\"tabsAction\">\n";
+		print "<div class=\"tabsAction\">\n";
 
 		if ($user->rights->stock->mouvement->creer)
 		{

+ 1 - 1
htdocs/projet/class/project.class.php

@@ -492,7 +492,7 @@ class Project extends CommonObject
 			$sql .= " WHERE entity IN (".getEntity('project').")";
 			if (!empty($ref)) {
 				$sql .= " AND ref = '".$this->db->escape($ref)."'";
-			} elseif (! empty($ref_ext)) {
+			} elseif (!empty($ref_ext)) {
 				$sql .= " AND ref_ext = '".$this->db->escape($ref_ext)."'";
 			} else {
 				$sql .= " AND email_msgid = '".$this->db->escape($email_msgid)."'";

+ 16 - 16
htdocs/recruitment/recruitmentindex.php

@@ -321,14 +321,14 @@ $NBMAX = 3;
 $max = 3;
 
 // Last modified job position
-if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->recruitmentjobposition->read)
+if (!empty($conf->recruitment->enabled) && $user->rights->recruitment->recruitmentjobposition->read)
 {
 	$sql = "SELECT s.rowid, s.ref, s.label, s.date_creation, s.tms, s.status";
-	$sql.= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as s";
-	if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
-	$sql.= " WHERE s.entity IN (".getEntity($staticrecruitmentjobposition->element).")";
-	if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
-	if ($socid)	$sql.= " AND s.fk_soc = $socid";
+	$sql .= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as s";
+	if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
+	$sql .= " WHERE s.entity IN (".getEntity($staticrecruitmentjobposition->element).")";
+	if (!$user->rights->societe->client->voir && !$socid) $sql .= " AND s.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
+	if ($socid)	$sql .= " AND s.fk_soc = $socid";
 	$sql .= " ORDER BY s.tms DESC";
 	$sql .= $db->plimit($max, 0);
 
@@ -379,15 +379,15 @@ if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->recruitm
 }
 
 // Last modified job position
-if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->recruitmentjobposition->read)
+if (!empty($conf->recruitment->enabled) && $user->rights->recruitment->recruitmentjobposition->read)
 {
 	$sql = "SELECT rc.rowid, rc.ref, rc.email, rc.lastname, rc.firstname, rc.date_creation, rc.tms, rc.status";
-	$sql.= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentcandidature as rc";
-	$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as s ON rc.fk_recruitmentjobposition = s.rowid";
-	if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
-	$sql.= " WHERE rc.entity IN (".getEntity($staticrecruitmentjobposition->element).")";
-	if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
-	if ($socid)	$sql.= " AND s.fk_soc = $socid";
+	$sql .= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentcandidature as rc";
+	$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as s ON rc.fk_recruitmentjobposition = s.rowid";
+	if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
+	$sql .= " WHERE rc.entity IN (".getEntity($staticrecruitmentjobposition->element).")";
+	if (!$user->rights->societe->client->voir && !$socid) $sql .= " AND s.fk_soc = sc.fk_soc AND sc.fk_user = ".$user->id;
+	if ($socid)	$sql .= " AND s.fk_soc = $socid";
 	$sql .= " ORDER BY rc.tms DESC";
 	$sql .= $db->plimit($max, 0);
 
@@ -409,9 +409,9 @@ if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->recruitm
 			while ($i < $num)
 			{
 				$objp = $db->fetch_object($resql);
-				$staticrecruitmentcandidature->id=$objp->rowid;
-				$staticrecruitmentcandidature->ref=$objp->ref;
-				$staticrecruitmentcandidature->email=$objp->email;
+				$staticrecruitmentcandidature->id = $objp->rowid;
+				$staticrecruitmentcandidature->ref = $objp->ref;
+				$staticrecruitmentcandidature->email = $objp->email;
 				$staticrecruitmentcandidature->status = $objp->status;
 				$staticrecruitmentcandidature->date_creation = $objp->date_creation;
 				$staticrecruitmentcandidature->firstname = $objp->firstname;

+ 182 - 182
htdocs/stripe/class/stripe.class.php

@@ -36,11 +36,11 @@ class Stripe extends CommonObject
 	/**
 	 * @var int Thirdparty ID
 	 */
-    public $fk_soc;
+	public $fk_soc;
 
-    /**
-     * @var int ID
-     */
+	/**
+	 * @var int ID
+	 */
 	public $fk_key;
 
 	/**
@@ -62,9 +62,9 @@ class Stripe extends CommonObject
 	public $code;
 	public $declinecode;
 
-    /**
-     * @var string Message
-     */
+	/**
+	 * @var string Message
+	 */
 	public $message;
 
 	/**
@@ -102,21 +102,21 @@ class Stripe extends CommonObject
 
 		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
 		$result = $this->db->query($sql);
-    	if ($result) {
+		if ($result) {
 			if ($this->db->num_rows($result)) {
 				$obj = $this->db->fetch_object($result);
-    			$tokenstring = $obj->tokenstring;
-
-    			$tmparray = dol_json_decode($tokenstring);
-    			$key = $tmparray->stripe_user_id;
-    		} else {
-    			$tokenstring = '';
-    		}
-    	} else {
-    		dol_print_error($this->db);
-    	}
-
-    	dol_syslog("No dedicated Stripe Connect account available for entity ".$conf->entity);
+				$tokenstring = $obj->tokenstring;
+
+				$tmparray = dol_json_decode($tokenstring);
+				$key = $tmparray->stripe_user_id;
+			} else {
+				$tokenstring = '';
+			}
+		} else {
+			dol_print_error($this->db);
+		}
+
+		dol_syslog("No dedicated Stripe Connect account available for entity ".$conf->entity);
 		return $key;
 	}
 
@@ -194,7 +194,7 @@ class Stripe extends CommonObject
 				}
 			} elseif ($createifnotlinkedtostripe)
 			{
-			    $ipaddress = getUserRemoteIP();
+				$ipaddress = getUserRemoteIP();
 
 				$dataforcustomer = array(
 					"email" => $object->email,
@@ -291,9 +291,9 @@ class Stripe extends CommonObject
 		return $stripepaymentmethod;
 	}
 
-    /**
+	/**
 	 * Get the Stripe payment intent. Create it with confirmnow=false
-     * Warning. If a payment was tried and failed, a payment intent was created.
+	 * Warning. If a payment was tried and failed, a payment intent was created.
 	 * But if we change something on object to pay (amount or other), reusing same payment intent is not allowed by Stripe.
 	 * Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay),
 	 * that's why i comment the part of code to retreive a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used)
@@ -333,9 +333,9 @@ class Stripe extends CommonObject
 
 		$fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
 		if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
-		    $fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
+			$fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
 		} elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
-		    $fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
+			$fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
 		}
 		if (!in_array($currency_code, $arrayzerounitcurrency)) {
 			$stripefee = round($fee * 100);
@@ -345,7 +345,7 @@ class Stripe extends CommonObject
 
 		$paymentintent = null;
 
-		if (is_object($object) && ! empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND))
+		if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND))
 		{
 			// Warning. If a payment was tried and failed, a payment intent was created.
 			// But if we change something on object to pay (amount or other that does not change the idempotency key), reusing same payment intent is not allowed by Stripe.
@@ -354,167 +354,167 @@ class Stripe extends CommonObject
 			// That's why we can comment the part of code to retreive a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used)
 
 			$sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site";
-    		$sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi";
-    		$sql.= " WHERE pi.fk_facture = " . $object->id;
-    		$sql.= " AND pi.sourcetype = '" . $object->element . "'";
-    		$sql.= " AND pi.entity IN (".getEntity('societe').")";
-    		$sql.= " AND pi.ext_payment_site = '" . $service . "'";
-
-    		dol_syslog(get_class($this) . "::getPaymentIntent search stripe payment intent for object id = ".$object->id, LOG_DEBUG);
-    		$resql = $this->db->query($sql);
-    		if ($resql) {
-    			$num = $this->db->num_rows($resql);
-    			if ($num)
-    			{
-    				$obj = $this->db->fetch_object($resql);
-    				$intent = $obj->ext_payment_id;
-
-    				dol_syslog(get_class($this) . "::getPaymentIntent found existing payment intent record");
-
-    				// Force to use the correct API key
-    				global $stripearrayofkeysbyenv;
-    				\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
-
-    				try {
-    					if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
-    						$paymentintent = \Stripe\PaymentIntent::retrieve($intent);
-    					} else {
-    						$paymentintent = \Stripe\PaymentIntent::retrieve($intent, array("stripe_account" => $key));
-    					}
-    				}
-    				catch (Exception $e) {
-    				    $error++;
-    					$this->error = $e->getMessage();
-    				}
-    			}
-    		}
+			$sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi";
+			$sql.= " WHERE pi.fk_facture = " . $object->id;
+			$sql.= " AND pi.sourcetype = '" . $object->element . "'";
+			$sql.= " AND pi.entity IN (".getEntity('societe').")";
+			$sql.= " AND pi.ext_payment_site = '" . $service . "'";
+
+			dol_syslog(get_class($this) . "::getPaymentIntent search stripe payment intent for object id = ".$object->id, LOG_DEBUG);
+			$resql = $this->db->query($sql);
+			if ($resql) {
+				$num = $this->db->num_rows($resql);
+				if ($num)
+				{
+					$obj = $this->db->fetch_object($resql);
+					$intent = $obj->ext_payment_id;
+
+					dol_syslog(get_class($this) . "::getPaymentIntent found existing payment intent record");
+
+					// Force to use the correct API key
+					global $stripearrayofkeysbyenv;
+					\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
+
+					try {
+						if (empty($key)) {				// If the Stripe connect account not set, we use common API usage
+							$paymentintent = \Stripe\PaymentIntent::retrieve($intent);
+						} else {
+							$paymentintent = \Stripe\PaymentIntent::retrieve($intent, array("stripe_account" => $key));
+						}
+					}
+					catch (Exception $e) {
+						$error++;
+						$this->error = $e->getMessage();
+					}
+				}
+			}
 		}
 
 		if (empty($paymentintent))
 		{
-    		$ipaddress = getUserRemoteIP();
-    		$metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress);
-            if (is_object($object))
-            {
-                $metadata['dol_type'] = $object->element;
-                $metadata['dol_id'] = $object->id;
+			$ipaddress = getUserRemoteIP();
+			$metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress);
+			if (is_object($object))
+			{
+				$metadata['dol_type'] = $object->element;
+				$metadata['dol_id'] = $object->id;
 				if (is_object($object->thirdparty) && $object->thirdparty->id > 0) $metadata['dol_thirdparty_id'] = $object->thirdparty->id;
-            }
-
-            // list of payment method types
-            $paymentmethodtypes = array("card");
-            if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT) ) $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
-            if (!empty($conf->global->STRIPE_IDEAL) ) $paymentmethodtypes[] = "ideal"; //&& ($object->thirdparty->isInEEC())
-
-    		$dataforintent = array(
-    		    "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent
-    		    "confirmation_method" => $mode,
-    		    "amount" => $stripeamount,
-    			"currency" => $currency_code,
-    			"payment_method_types" => $paymentmethodtypes,
-    		    "description" => $description,
-    		    "statement_descriptor_suffix" => dol_trunc($tag, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
-    			//"save_payment_method" => true,
+			}
+
+			// list of payment method types
+			$paymentmethodtypes = array("card");
+			if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT) ) $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
+			if (!empty($conf->global->STRIPE_IDEAL) ) $paymentmethodtypes[] = "ideal"; //&& ($object->thirdparty->isInEEC())
+
+			$dataforintent = array(
+				"confirm" => $confirmnow, // Do not confirm immediatly during creation of intent
+				"confirmation_method" => $mode,
+				"amount" => $stripeamount,
+				"currency" => $currency_code,
+				"payment_method_types" => $paymentmethodtypes,
+				"description" => $description,
+				"statement_descriptor_suffix" => dol_trunc($tag, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
+				//"save_payment_method" => true,
 				"setup_future_usage" => "on_session",
-    			"metadata" => $metadata
-    		);
-    		if (!is_null($customer)) $dataforintent["customer"] = $customer;
-    		// payment_method =
-    		// payment_method_types = array('card')
-            //var_dump($dataforintent);
-    		if ($off_session)
-    		{
-    		    unset($dataforintent['setup_future_usage']);
-    		    $dataforintent["off_session"] = true;
-    		}
-    		if (!is_null($payment_method))
-    		{
-    			$dataforintent["payment_method"] = $payment_method;
-    			$description .= ' - '.$payment_method;
-    		}
-
-    		if ($conf->entity != $conf->global->STRIPECONNECT_PRINCIPAL && $stripefee > 0)
-    		{
-    			$dataforintent["application_fee_amount"] = $stripefee;
-    		}
-    		if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email)
-    		{
-    		    $dataforintent["receipt_email"] = $object->thirdparty->email;
-    		}
-
-    		try {
-    			// Force to use the correct API key
-    			global $stripearrayofkeysbyenv;
-    			\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
-
-    			$arrayofoptions = array();
-    			if (empty($noidempotency_key)) {
-    				$arrayofoptions["idempotency_key"] = $description;
-    			}
-    			// Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent.
-    			if (!empty($key)) {				// If the Stripe connect account not set, we use common API usage
-    				$arrayofoptions["stripe_account"] = $key;
-    			}
-    			$paymentintent = \Stripe\PaymentIntent::create($dataforintent, $arrayofoptions);
-
-    			// Store the payment intent
-    			if (is_object($object))
-    			{
-    				$paymentintentalreadyexists = 0;
-    				// Check that payment intent $paymentintent->id is not already recorded.
-    				$sql = "SELECT pi.rowid";
-    				$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pi";
-    				$sql .= " WHERE pi.entity IN (".getEntity('societe').")";
-    				$sql .= " AND pi.ext_payment_site = '".$service."'";
-    				$sql .= " AND pi.ext_payment_id = '".$this->db->escape($paymentintent->id)."'";
-
-    				dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_facture_demande", LOG_DEBUG);
-    				$resql = $this->db->query($sql);
-    				if ($resql) {
-    					$num = $this->db->num_rows($resql);
-    					if ($num)
-    					{
-    						$obj = $this->db->fetch_object($resql);
-    						if ($obj) $paymentintentalreadyexists++;
-    					}
-    				} else dol_print_error($this->db);
-
-    				// If not, we create it.
-    				if (!$paymentintentalreadyexists)
-    				{
-	    				$now = dol_now();
-	    				$sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_facture_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site, amount)";
-	    				$sql .= " VALUES ('".$this->db->idate($now)."', ".$user->id.", '".$this->db->escape($paymentintent->id)."', ".$object->id.", '".$this->db->escape($object->element)."', ".$conf->entity.", '".$service."', ".$amount.")";
-	    				$resql = $this->db->query($sql);
-	    				if (!$resql)
-	    				{
-	    				    $error++;
-	    					$this->error = $this->db->lasterror();
-	                        dol_syslog(get_class($this)."::PaymentIntent failed to insert paymentintent with id=".$paymentintent->id." into database.");
-	    				}
-    				}
-    			} else {
-    			    $_SESSION["stripe_payment_intent"] = $paymentintent;
-    			}
-    		} catch (Stripe\Error\Card $e)
-    		{
-    			$error++;
-    			$this->error = $e->getMessage();
-    			$this->code = $e->getStripeCode();
-    			$this->declinecode = $e->getDeclineCode();
-    		} catch (Exception $e)
-    		{
-    		    /*var_dump($dataforintent);
+				"metadata" => $metadata
+			);
+			if (!is_null($customer)) $dataforintent["customer"] = $customer;
+			// payment_method =
+			// payment_method_types = array('card')
+			//var_dump($dataforintent);
+			if ($off_session)
+			{
+				unset($dataforintent['setup_future_usage']);
+				$dataforintent["off_session"] = true;
+			}
+			if (!is_null($payment_method))
+			{
+				$dataforintent["payment_method"] = $payment_method;
+				$description .= ' - '.$payment_method;
+			}
+
+			if ($conf->entity != $conf->global->STRIPECONNECT_PRINCIPAL && $stripefee > 0)
+			{
+				$dataforintent["application_fee_amount"] = $stripefee;
+			}
+			if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email)
+			{
+				$dataforintent["receipt_email"] = $object->thirdparty->email;
+			}
+
+			try {
+				// Force to use the correct API key
+				global $stripearrayofkeysbyenv;
+				\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
+
+				$arrayofoptions = array();
+				if (empty($noidempotency_key)) {
+					$arrayofoptions["idempotency_key"] = $description;
+				}
+				// Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent.
+				if (!empty($key)) {				// If the Stripe connect account not set, we use common API usage
+					$arrayofoptions["stripe_account"] = $key;
+				}
+				$paymentintent = \Stripe\PaymentIntent::create($dataforintent, $arrayofoptions);
+
+				// Store the payment intent
+				if (is_object($object))
+				{
+					$paymentintentalreadyexists = 0;
+					// Check that payment intent $paymentintent->id is not already recorded.
+					$sql = "SELECT pi.rowid";
+					$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pi";
+					$sql .= " WHERE pi.entity IN (".getEntity('societe').")";
+					$sql .= " AND pi.ext_payment_site = '".$service."'";
+					$sql .= " AND pi.ext_payment_id = '".$this->db->escape($paymentintent->id)."'";
+
+					dol_syslog(get_class($this)."::getPaymentIntent search if payment intent already in prelevement_facture_demande", LOG_DEBUG);
+					$resql = $this->db->query($sql);
+					if ($resql) {
+						$num = $this->db->num_rows($resql);
+						if ($num)
+						{
+							$obj = $this->db->fetch_object($resql);
+							if ($obj) $paymentintentalreadyexists++;
+						}
+					} else dol_print_error($this->db);
+
+					// If not, we create it.
+					if (!$paymentintentalreadyexists)
+					{
+						$now = dol_now();
+						$sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_facture_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site, amount)";
+						$sql .= " VALUES ('".$this->db->idate($now)."', ".$user->id.", '".$this->db->escape($paymentintent->id)."', ".$object->id.", '".$this->db->escape($object->element)."', ".$conf->entity.", '".$service."', ".$amount.")";
+						$resql = $this->db->query($sql);
+						if (!$resql)
+						{
+							$error++;
+							$this->error = $this->db->lasterror();
+							dol_syslog(get_class($this)."::PaymentIntent failed to insert paymentintent with id=".$paymentintent->id." into database.");
+						}
+					}
+				} else {
+					$_SESSION["stripe_payment_intent"] = $paymentintent;
+				}
+			} catch (Stripe\Error\Card $e)
+			{
+				$error++;
+				$this->error = $e->getMessage();
+				$this->code = $e->getStripeCode();
+				$this->declinecode = $e->getDeclineCode();
+			} catch (Exception $e)
+			{
+				/*var_dump($dataforintent);
     		    var_dump($description);
     		    var_dump($key);
     		    var_dump($paymentintent);
     		    var_dump($e->getMessage());
     		    var_dump($e);*/
-    		    $error++;
-    			$this->error = $e->getMessage();
-    			$this->code = '';
-    			$this->declinecode = '';
-    		}
+				$error++;
+				$this->error = $e->getMessage();
+				$this->code = '';
+				$this->declinecode = '';
+			}
 		}
 
 		dol_syslog("getPaymentIntent return error=".$error." this->error=".$this->error, LOG_INFO, -1);
@@ -572,7 +572,7 @@ class Stripe extends CommonObject
 
 			// list of payment method types
 			$paymentmethodtypes = array("card");
-			if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT) ) $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
+			if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT)) $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC())
 			// iDEAL not supported with setupIntent
 
 			$dataforintent = array(
@@ -933,10 +933,10 @@ class Stripe extends CommonObject
 					}
 				} elseif (preg_match('/acct_/i', $source))
 				{
-                    $charge = \Stripe\Charge::create(array(
+					$charge = \Stripe\Charge::create(array(
 						"amount" => "$stripeamount",
 						"currency" => "$currency",
-                        "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
+						"statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
 						"description" => "Stripe payment: ".$description,
 						"capture"  => $capture,
 						"metadata" => $metadata,
@@ -946,7 +946,7 @@ class Stripe extends CommonObject
 					$paymentarray = array(
 						"amount" => "$stripeamount",
 						"currency" => "$currency",
-					    "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
+						"statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description)
 						"description" => "Stripe payment: ".$description,
 						"capture"  => $capture,
 						"metadata" => $metadata,
@@ -965,9 +965,9 @@ class Stripe extends CommonObject
 				// With Stripe Connect
 				$fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE;
 				if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
-				    $fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
+					$fee = $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL;
 				} elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) {
-				    $fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
+					$fee = $conf->global->STRIPE_APPLICATION_FEE_MINIMAL;
 				}
 
 				if (!in_array($currency, $arrayzerounitcurrency)) $stripefee = round($fee * 100);

+ 1881 - 1881
htdocs/supplier_proposal/class/supplier_proposal.class.php

@@ -776,1897 +776,1897 @@ class SupplierProposal extends CommonObject
 			$this->line->multicurrency_total_tva	= $multicurrency_total_tva;
 			$this->line->multicurrency_total_ttc	= $multicurrency_total_ttc;
 
-            $result = $this->line->update();
-            if ($result > 0)
-            {
-                // Reorder if child line
-                if (!empty($fk_parent_line)) $this->line_order(true, 'DESC');
-
-                $this->update_price(1);
-
-                $this->fk_supplier_proposal = $this->id;
-
-                $this->db->commit();
-                return $result;
-            } else {
-                $this->error = $this->db->error();
-                $this->db->rollback();
-                return -1;
-            }
-        } else {
-            dol_syslog(get_class($this)."::updateline Erreur -2 SupplierProposal en mode incompatible pour cette action");
-            return -2;
-        }
-    }
-
-
-    /**
-     *  Delete detail line
-     *
-     *  @param		int		$lineid			Id of line to delete
-     *  @return     int         			>0 if OK, <0 if KO
-     */
-    public function deleteline($lineid)
-    {
-        if ($this->statut == 0)
-        {
-            $line = new SupplierProposalLine($this->db);
-
-            // For triggers
-            $line->fetch($lineid);
-
-            if ($line->delete() > 0)
-            {
-                $this->update_price(1);
-
-                return 1;
-            } else {
-                return -1;
-            }
-        } else {
-            return -2;
-        }
-    }
-
-
-    /**
-     *  Create commercial proposal into database
-     * 	this->ref can be set or empty. If empty, we will use "(PROVid)"
-     *
-     * 	@param		User	$user		User that create
-     * 	@param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
-     *  @return     int     			<0 if KO, >=0 if OK
-     */
-    public function create($user, $notrigger = 0)
-    {
-        global $langs, $conf, $mysoc, $hookmanager;
-        $error = 0;
-
-        $now = dol_now();
-
-        dol_syslog(get_class($this)."::create");
-
-        // Check parameters
-        $result = $this->fetch_thirdparty();
-        if ($result < 0)
-        {
-            $this->error = "Failed to fetch company";
-            dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
-            return -3;
-        }
-
-        // Check parameters
-        if (!empty($this->ref))	// We check that ref is not already used
-        {
-            $result = self::isExistingObject($this->element, 0, $this->ref); // Check ref is not yet used
-            if ($result > 0)
-            {
-                $this->error = 'ErrorRefAlreadyExists';
-                dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING);
-                $this->db->rollback();
-                return -1;
-            }
-        }
-
-        // Multicurrency
-        if (!empty($this->multicurrency_code)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $now);
-        if (empty($this->fk_multicurrency))
-        {
-            $this->multicurrency_code = $conf->currency;
-            $this->fk_multicurrency = 0;
-            $this->multicurrency_tx = 1;
-        }
-
-        $this->db->begin();
-
-        // Insert into database
-        $sql = "INSERT INTO ".MAIN_DB_PREFIX."supplier_proposal (";
-        $sql .= "fk_soc";
-        $sql .= ", price";
-        $sql .= ", remise";
-        $sql .= ", remise_percent";
-        $sql .= ", remise_absolue";
-        $sql .= ", tva";
-        $sql .= ", total";
-        $sql .= ", datec";
-        $sql .= ", ref";
-        $sql .= ", fk_user_author";
-        $sql .= ", note_private";
-        $sql .= ", note_public";
-        $sql .= ", model_pdf";
-        $sql .= ", fk_cond_reglement";
-        $sql .= ", fk_mode_reglement";
-        $sql .= ", fk_account";
-        $sql .= ", date_livraison";
-        $sql .= ", fk_shipping_method";
-        $sql .= ", fk_projet";
-        $sql .= ", entity";
-        $sql .= ", fk_multicurrency";
-        $sql .= ", multicurrency_code";
-        $sql .= ", multicurrency_tx";
-        $sql .= ") ";
-        $sql .= " VALUES (";
-        $sql .= $this->socid;
-        $sql .= ", 0";
-        $sql .= ", ".$this->remise;
-        $sql .= ", ".($this->remise_percent ? $this->db->escape($this->remise_percent) : 'null');
-        $sql .= ", ".($this->remise_absolue ? $this->db->escape($this->remise_absolue) : 'null');
-        $sql .= ", 0";
-        $sql .= ", 0";
-        $sql .= ", '".$this->db->idate($now)."'";
-        $sql .= ", '(PROV)'";
-        $sql .= ", ".($user->id > 0 ? "'".$user->id."'" : "null");
-        $sql .= ", '".$this->db->escape($this->note_private)."'";
-        $sql .= ", '".$this->db->escape($this->note_public)."'";
-        $sql .= ", '".$this->db->escape($this->modelpdf)."'";
-        $sql .= ", ".($this->cond_reglement_id > 0 ? $this->cond_reglement_id : 'NULL');
-        $sql .= ", ".($this->mode_reglement_id > 0 ? $this->mode_reglement_id : 'NULL');
-        $sql .= ", ".($this->fk_account > 0 ? $this->fk_account : 'NULL');
-        $sql .= ", ".($this->date_livraison != '' ? "'".$this->db->idate($this->date_livraison)."'" : "null");
-        $sql .= ", ".($this->shipping_method_id > 0 ? $this->shipping_method_id : 'NULL');
-        $sql .= ", ".($this->fk_project ? $this->fk_project : "null");
-        $sql .= ", ".$conf->entity;
-        $sql .= ", ".(int) $this->fk_multicurrency;
-        $sql .= ", '".$this->db->escape($this->multicurrency_code)."'";
-        $sql .= ", ".(double) $this->multicurrency_tx;
-        $sql .= ")";
-
-        dol_syslog(get_class($this)."::create", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."supplier_proposal");
-
-            if ($this->id)
-            {
-                $this->ref = '(PROV'.$this->id.')';
-                $sql = 'UPDATE '.MAIN_DB_PREFIX."supplier_proposal SET ref='".$this->db->escape($this->ref)."' WHERE rowid=".$this->id;
-
-                dol_syslog(get_class($this)."::create", LOG_DEBUG);
-                $resql = $this->db->query($sql);
-                if (!$resql) $error++;
-
-                if (!empty($this->linkedObjectsIds) && empty($this->linked_objects))	// To use new linkedObjectsIds instead of old linked_objects
-                {
-                    $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
-                }
-
-                // Add object linked
-                if (!$error && $this->id && is_array($this->linked_objects) && !empty($this->linked_objects))
-                {
-                    foreach ($this->linked_objects as $origin => $tmp_origin_id)
-                    {
-                        if (is_array($tmp_origin_id))       // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
-                        {
-                            foreach ($tmp_origin_id as $origin_id)
-                            {
-                                $ret = $this->add_object_linked($origin, $origin_id);
-                                if (!$ret)
-                                {
-                                    dol_print_error($this->db);
-                                    $error++;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                /*
+			$result = $this->line->update();
+			if ($result > 0)
+			{
+				// Reorder if child line
+				if (!empty($fk_parent_line)) $this->line_order(true, 'DESC');
+
+				$this->update_price(1);
+
+				$this->fk_supplier_proposal = $this->id;
+
+				$this->db->commit();
+				return $result;
+			} else {
+				$this->error = $this->db->error();
+				$this->db->rollback();
+				return -1;
+			}
+		} else {
+			dol_syslog(get_class($this)."::updateline Erreur -2 SupplierProposal en mode incompatible pour cette action");
+			return -2;
+		}
+	}
+
+
+	/**
+	 *  Delete detail line
+	 *
+	 *  @param		int		$lineid			Id of line to delete
+	 *  @return     int         			>0 if OK, <0 if KO
+	 */
+	public function deleteline($lineid)
+	{
+		if ($this->statut == 0)
+		{
+			$line = new SupplierProposalLine($this->db);
+
+			// For triggers
+			$line->fetch($lineid);
+
+			if ($line->delete() > 0)
+			{
+				$this->update_price(1);
+
+				return 1;
+			} else {
+				return -1;
+			}
+		} else {
+			return -2;
+		}
+	}
+
+
+	/**
+	 *  Create commercial proposal into database
+	 * 	this->ref can be set or empty. If empty, we will use "(PROVid)"
+	 *
+	 * 	@param		User	$user		User that create
+	 * 	@param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
+	 *  @return     int     			<0 if KO, >=0 if OK
+	 */
+	public function create($user, $notrigger = 0)
+	{
+		global $langs, $conf, $mysoc, $hookmanager;
+		$error = 0;
+
+		$now = dol_now();
+
+		dol_syslog(get_class($this)."::create");
+
+		// Check parameters
+		$result = $this->fetch_thirdparty();
+		if ($result < 0)
+		{
+			$this->error = "Failed to fetch company";
+			dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
+			return -3;
+		}
+
+		// Check parameters
+		if (!empty($this->ref))	// We check that ref is not already used
+		{
+			$result = self::isExistingObject($this->element, 0, $this->ref); // Check ref is not yet used
+			if ($result > 0)
+			{
+				$this->error = 'ErrorRefAlreadyExists';
+				dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING);
+				$this->db->rollback();
+				return -1;
+			}
+		}
+
+		// Multicurrency
+		if (!empty($this->multicurrency_code)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $now);
+		if (empty($this->fk_multicurrency))
+		{
+			$this->multicurrency_code = $conf->currency;
+			$this->fk_multicurrency = 0;
+			$this->multicurrency_tx = 1;
+		}
+
+		$this->db->begin();
+
+		// Insert into database
+		$sql = "INSERT INTO ".MAIN_DB_PREFIX."supplier_proposal (";
+		$sql .= "fk_soc";
+		$sql .= ", price";
+		$sql .= ", remise";
+		$sql .= ", remise_percent";
+		$sql .= ", remise_absolue";
+		$sql .= ", tva";
+		$sql .= ", total";
+		$sql .= ", datec";
+		$sql .= ", ref";
+		$sql .= ", fk_user_author";
+		$sql .= ", note_private";
+		$sql .= ", note_public";
+		$sql .= ", model_pdf";
+		$sql .= ", fk_cond_reglement";
+		$sql .= ", fk_mode_reglement";
+		$sql .= ", fk_account";
+		$sql .= ", date_livraison";
+		$sql .= ", fk_shipping_method";
+		$sql .= ", fk_projet";
+		$sql .= ", entity";
+		$sql .= ", fk_multicurrency";
+		$sql .= ", multicurrency_code";
+		$sql .= ", multicurrency_tx";
+		$sql .= ") ";
+		$sql .= " VALUES (";
+		$sql .= $this->socid;
+		$sql .= ", 0";
+		$sql .= ", ".$this->remise;
+		$sql .= ", ".($this->remise_percent ? $this->db->escape($this->remise_percent) : 'null');
+		$sql .= ", ".($this->remise_absolue ? $this->db->escape($this->remise_absolue) : 'null');
+		$sql .= ", 0";
+		$sql .= ", 0";
+		$sql .= ", '".$this->db->idate($now)."'";
+		$sql .= ", '(PROV)'";
+		$sql .= ", ".($user->id > 0 ? "'".$user->id."'" : "null");
+		$sql .= ", '".$this->db->escape($this->note_private)."'";
+		$sql .= ", '".$this->db->escape($this->note_public)."'";
+		$sql .= ", '".$this->db->escape($this->modelpdf)."'";
+		$sql .= ", ".($this->cond_reglement_id > 0 ? $this->cond_reglement_id : 'NULL');
+		$sql .= ", ".($this->mode_reglement_id > 0 ? $this->mode_reglement_id : 'NULL');
+		$sql .= ", ".($this->fk_account > 0 ? $this->fk_account : 'NULL');
+		$sql .= ", ".($this->date_livraison != '' ? "'".$this->db->idate($this->date_livraison)."'" : "null");
+		$sql .= ", ".($this->shipping_method_id > 0 ? $this->shipping_method_id : 'NULL');
+		$sql .= ", ".($this->fk_project ? $this->fk_project : "null");
+		$sql .= ", ".$conf->entity;
+		$sql .= ", ".(int) $this->fk_multicurrency;
+		$sql .= ", '".$this->db->escape($this->multicurrency_code)."'";
+		$sql .= ", ".(double) $this->multicurrency_tx;
+		$sql .= ")";
+
+		dol_syslog(get_class($this)."::create", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."supplier_proposal");
+
+			if ($this->id)
+			{
+				$this->ref = '(PROV'.$this->id.')';
+				$sql = 'UPDATE '.MAIN_DB_PREFIX."supplier_proposal SET ref='".$this->db->escape($this->ref)."' WHERE rowid=".$this->id;
+
+				dol_syslog(get_class($this)."::create", LOG_DEBUG);
+				$resql = $this->db->query($sql);
+				if (!$resql) $error++;
+
+				if (!empty($this->linkedObjectsIds) && empty($this->linked_objects))	// To use new linkedObjectsIds instead of old linked_objects
+				{
+					$this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
+				}
+
+				// Add object linked
+				if (!$error && $this->id && is_array($this->linked_objects) && !empty($this->linked_objects))
+				{
+					foreach ($this->linked_objects as $origin => $tmp_origin_id)
+					{
+						if (is_array($tmp_origin_id))       // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
+						{
+							foreach ($tmp_origin_id as $origin_id)
+							{
+								$ret = $this->add_object_linked($origin, $origin_id);
+								if (!$ret)
+								{
+									dol_print_error($this->db);
+									$error++;
+								}
+							}
+						}
+					}
+				}
+
+				/*
                  *  Insertion du detail des produits dans la base
                  */
-                if (!$error)
-                {
-                    $fk_parent_line = 0;
-                    $num = count($this->lines);
-
-                    for ($i = 0; $i < $num; $i++)
-                    {
-                        // Reset fk_parent_line for no child products and special product
-                        if (($this->lines[$i]->product_type != 9 && empty($this->lines[$i]->fk_parent_line)) || $this->lines[$i]->product_type == 9) {
-                            $fk_parent_line = 0;
-                        }
-
-                        $result = $this->addline(
-                            $this->lines[$i]->desc,
-                            $this->lines[$i]->subprice,
-                            $this->lines[$i]->qty,
-                            $this->lines[$i]->tva_tx,
-                            $this->lines[$i]->localtax1_tx,
-                            $this->lines[$i]->localtax2_tx,
-                            $this->lines[$i]->fk_product,
-                            $this->lines[$i]->remise_percent,
-                            'HT',
-                            0,
-                            0,
-                            $this->lines[$i]->product_type,
-                            $this->lines[$i]->rang,
-                            $this->lines[$i]->special_code,
-                            $fk_parent_line,
-                            $this->lines[$i]->fk_fournprice,
-                            $this->lines[$i]->pa_ht,
-                            $this->lines[$i]->label,
-                            $this->lines[$i]->array_options,
-                            $this->lines[$i]->ref_fourn,
-                            $this->lines[$i]->fk_unit,
-                            'supplier_proposal',
-                            $this->lines[$i]->rowid
-                        );
-
-                        if ($result < 0)
-                        {
-                            $error++;
-                            $this->error = $this->db->error;
-                            dol_print_error($this->db);
-                            break;
-                        }
-                        // Defined the new fk_parent_line
-                        if ($result > 0 && $this->lines[$i]->product_type == 9) {
-                            $fk_parent_line = $result;
-                        }
-                    }
-                }
-
-                if (!$error)
-                {
-                    // Mise a jour infos denormalisees
-                    $resql = $this->update_price(1);
-                    if ($resql)
-                    {
-                        $action = 'update';
-
-                        // Actions on extra fields
-                        if (!$error)
-                        {
-                            $result = $this->insertExtraFields();
-                            if ($result < 0)
-                            {
-                                $error++;
-                            }
-                        }
-
-                        if (!$error && !$notrigger)
-                        {
-                            // Call trigger
-                            $result = $this->call_trigger('PROPOSAL_SUPPLIER_CREATE', $user);
-                            if ($result < 0) { $error++; }
-                            // End call triggers
-                        }
-                    } else {
-                        $this->error = $this->db->lasterror();
-                        $error++;
-                    }
-                }
-            } else {
-                $this->error = $this->db->lasterror();
-                $error++;
-            }
-
-            if (!$error)
-            {
-                $this->db->commit();
-                dol_syslog(get_class($this)."::create done id=".$this->id);
-                return $this->id;
-            } else {
-                $this->db->rollback();
-                return -2;
-            }
-        } else {
-            $this->error = $this->db->lasterror();
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *	Insert into DB a supplier_proposal object completely defined by its data members (ex, results from copy).
-     *
-     *	@param 		User	$user	User that create
-     *	@return    	int				Id of the new object if ok, <0 if ko
-     *	@see       	create()
-     */
-    public function create_from($user)
-    {
-        // phpcs:enable
-        $this->products = $this->lines;
-
-        return $this->create($user);
-    }
-
-    /**
-     *		Load an object from its id and create a new one in database
-     *
+				if (!$error)
+				{
+					$fk_parent_line = 0;
+					$num = count($this->lines);
+
+					for ($i = 0; $i < $num; $i++)
+					{
+						// Reset fk_parent_line for no child products and special product
+						if (($this->lines[$i]->product_type != 9 && empty($this->lines[$i]->fk_parent_line)) || $this->lines[$i]->product_type == 9) {
+							$fk_parent_line = 0;
+						}
+
+						$result = $this->addline(
+							$this->lines[$i]->desc,
+							$this->lines[$i]->subprice,
+							$this->lines[$i]->qty,
+							$this->lines[$i]->tva_tx,
+							$this->lines[$i]->localtax1_tx,
+							$this->lines[$i]->localtax2_tx,
+							$this->lines[$i]->fk_product,
+							$this->lines[$i]->remise_percent,
+							'HT',
+							0,
+							0,
+							$this->lines[$i]->product_type,
+							$this->lines[$i]->rang,
+							$this->lines[$i]->special_code,
+							$fk_parent_line,
+							$this->lines[$i]->fk_fournprice,
+							$this->lines[$i]->pa_ht,
+							$this->lines[$i]->label,
+							$this->lines[$i]->array_options,
+							$this->lines[$i]->ref_fourn,
+							$this->lines[$i]->fk_unit,
+							'supplier_proposal',
+							$this->lines[$i]->rowid
+						);
+
+						if ($result < 0)
+						{
+							$error++;
+							$this->error = $this->db->error;
+							dol_print_error($this->db);
+							break;
+						}
+						// Defined the new fk_parent_line
+						if ($result > 0 && $this->lines[$i]->product_type == 9) {
+							$fk_parent_line = $result;
+						}
+					}
+				}
+
+				if (!$error)
+				{
+					// Mise a jour infos denormalisees
+					$resql = $this->update_price(1);
+					if ($resql)
+					{
+						$action = 'update';
+
+						// Actions on extra fields
+						if (!$error)
+						{
+							$result = $this->insertExtraFields();
+							if ($result < 0)
+							{
+								$error++;
+							}
+						}
+
+						if (!$error && !$notrigger)
+						{
+							// Call trigger
+							$result = $this->call_trigger('PROPOSAL_SUPPLIER_CREATE', $user);
+							if ($result < 0) { $error++; }
+							// End call triggers
+						}
+					} else {
+						$this->error = $this->db->lasterror();
+						$error++;
+					}
+				}
+			} else {
+				$this->error = $this->db->lasterror();
+				$error++;
+			}
+
+			if (!$error)
+			{
+				$this->db->commit();
+				dol_syslog(get_class($this)."::create done id=".$this->id);
+				return $this->id;
+			} else {
+				$this->db->rollback();
+				return -2;
+			}
+		} else {
+			$this->error = $this->db->lasterror();
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *	Insert into DB a supplier_proposal object completely defined by its data members (ex, results from copy).
+	 *
+	 *	@param 		User	$user	User that create
+	 *	@return    	int				Id of the new object if ok, <0 if ko
+	 *	@see       	create()
+	 */
+	public function create_from($user)
+	{
+		// phpcs:enable
+		$this->products = $this->lines;
+
+		return $this->create($user);
+	}
+
+	/**
+	 *		Load an object from its id and create a new one in database
+	 *
 	 *      @param	    User	$user		    User making the clone
-     *		@param		int		$fromid			Id of thirdparty
-     * 	 	@return		int						New id of clone
-     */
-    public function createFromClone(User $user, $fromid = 0)
-    {
-        global $conf, $hookmanager;
-
-        $error = 0;
-        $now = dol_now();
-
-        $this->db->begin();
-
-        // get extrafields so they will be clone
-        foreach ($this->lines as $line)
-            $line->fetch_optionals();
-
-        // Load source object
-        $objFrom = clone $this;
-
-        $objsoc = new Societe($this->db);
-
-        // Change socid if needed
-        if (!empty($fromid) && $fromid != $this->socid)
-        {
-            if ($objsoc->fetch($fromid) > 0)
-            {
-                $this->socid = $objsoc->id;
-                $this->cond_reglement_id	= (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
-                $this->mode_reglement_id	= (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
-                $this->fk_project = '';
-            }
-
-            // TODO Change product price if multi-prices
-        } else {
-            $objsoc->fetch($this->socid);
-        }
-
-        $this->id = 0;
-        $this->statut = 0;
-
-        if (empty($conf->global->SUPPLIER_PROPOSAL_ADDON) || !is_readable(DOL_DOCUMENT_ROOT."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.".php"))
-        {
-            $this->error = 'ErrorSetupNotComplete';
-            return -1;
-        }
-
-        // Clear fields
-        $this->user_author = $user->id;
-        $this->user_valid = '';
-        $this->date = $now;
-
-        // Set ref
-        require_once DOL_DOCUMENT_ROOT."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.'.php';
-        $obj = $conf->global->SUPPLIER_PROPOSAL_ADDON;
-        $modSupplierProposal = new $obj;
-        $this->ref = $modSupplierProposal->getNextValue($objsoc, $this);
-
-        // Create clone
-        $this->context['createfromclone'] = 'createfromclone';
-        $result = $this->create($user);
-        if ($result < 0) $error++;
-
-        if (!$error)
-        {
-            // Hook of thirdparty module
-            if (is_object($hookmanager))
-            {
-                $parameters = array('objFrom'=>$objFrom);
-                $action = '';
-                $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
-                if ($reshook < 0) $error++;
-            }
-        }
-
-        unset($this->context['createfromclone']);
-
-        // End
-        if (!$error)
-        {
-            $this->db->commit();
-            return $this->id;
-        } else {
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-    /**
-     *	Load a proposal from database and its ligne array
-     *
-     *	@param      int			$rowid		id of object to load
-     *	@param		string		$ref		Ref of proposal
-     *	@return     int         			>0 if OK, <0 if KO
-     */
-    public function fetch($rowid, $ref = '')
-    {
-        global $conf;
-
-        $sql = "SELECT p.rowid, p.entity, p.ref, p.remise, p.remise_percent, p.remise_absolue, p.fk_soc";
-        $sql .= ", p.total, p.tva, p.localtax1, p.localtax2, p.total_ht";
-        $sql .= ", p.datec";
-        $sql .= ", p.date_valid as datev";
-        $sql .= ", p.date_livraison as date_livraison";
-        $sql .= ", p.model_pdf, p.extraparams";
-        $sql .= ", p.note_private, p.note_public";
-        $sql .= ", p.fk_projet as fk_project, p.fk_statut";
-        $sql .= ", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
-        $sql .= ", p.fk_cond_reglement";
-        $sql .= ", p.fk_mode_reglement";
-        $sql .= ', p.fk_account';
-        $sql .= ", p.fk_shipping_method";
-        $sql .= ", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
-        $sql .= ", c.label as statut_label";
-        $sql .= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc";
-        $sql .= ", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
-        $sql .= " FROM ".MAIN_DB_PREFIX."c_propalst as c, ".MAIN_DB_PREFIX."supplier_proposal as p";
-        $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as cp ON p.fk_mode_reglement = cp.id';
-        $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as cr ON p.fk_cond_reglement = cr.rowid';
-        $sql .= " WHERE p.fk_statut = c.id";
-        $sql .= " AND p.entity IN (".getEntity('supplier_proposal').")";
-        if ($ref) $sql .= " AND p.ref='".$ref."'";
-        else $sql .= " AND p.rowid=".$rowid;
-
-        dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            if ($this->db->num_rows($resql))
-            {
-                $obj = $this->db->fetch_object($resql);
-
-                $this->id                   = $obj->rowid;
-                $this->entity               = $obj->entity;
-
-                $this->ref                  = $obj->ref;
-                $this->remise               = $obj->remise;
-                $this->remise_percent       = $obj->remise_percent;
-                $this->remise_absolue       = $obj->remise_absolue;
-                $this->total                = $obj->total; // TODO deprecated
-                $this->total_ht             = $obj->total_ht;
-                $this->total_tva            = $obj->tva;
-                $this->total_localtax1		= $obj->localtax1;
-                $this->total_localtax2		= $obj->localtax2;
-                $this->total_ttc            = $obj->total;
-                $this->socid                = $obj->fk_soc;
-                $this->fk_project           = $obj->fk_project;
-                $this->model_pdf            = $obj->model_pdf;
-                $this->modelpdf             = $obj->model_pdf;
-                $this->note                 = $obj->note_private; // TODO deprecated
-                $this->note_private         = $obj->note_private;
-                $this->note_public          = $obj->note_public;
-                $this->statut               = (int) $obj->fk_statut;
-                $this->statut_libelle       = $obj->statut_label;
-                $this->datec                = $this->db->jdate($obj->datec); // TODO deprecated
-                $this->datev                = $this->db->jdate($obj->datev); // TODO deprecated
-                $this->date_creation = $this->db->jdate($obj->datec); //Creation date
-                $this->date_validation = $this->db->jdate($obj->datev); //Validation date
-                $this->date_livraison       = $this->db->jdate($obj->date_livraison);
-                $this->shipping_method_id   = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method : null;
-
-                $this->mode_reglement_id    = $obj->fk_mode_reglement;
-                $this->mode_reglement_code  = $obj->mode_reglement_code;
-                $this->mode_reglement       = $obj->mode_reglement;
-                $this->fk_account           = ($obj->fk_account > 0) ? $obj->fk_account : null;
-                $this->cond_reglement_id    = $obj->fk_cond_reglement;
-                $this->cond_reglement_code  = $obj->cond_reglement_code;
-                $this->cond_reglement       = $obj->cond_reglement;
-                $this->cond_reglement_doc   = $obj->cond_reglement_libelle_doc;
-
-                $this->extraparams = (array) json_decode($obj->extraparams, true);
-
-                $this->user_author_id = $obj->fk_user_author;
-                $this->user_valid_id  = $obj->fk_user_valid;
-                $this->user_close_id  = $obj->fk_user_cloture;
-
-                // Multicurrency
-                $this->fk_multicurrency 		= $obj->fk_multicurrency;
-                $this->multicurrency_code = $obj->multicurrency_code;
-                $this->multicurrency_tx 		= $obj->multicurrency_tx;
-                $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
-                $this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
-                $this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
-
-                if ($obj->fk_statut == 0)
-                {
-                    $this->brouillon = 1;
-                }
-
-                // Retreive all extrafield
-                // fetch optionals attributes and labels
-                $this->fetch_optionals();
-
-                $this->db->free($resql);
-
-                $this->lines = array();
-
-                // Lines of supplier proposals
-                $sql = "SELECT d.rowid, d.fk_supplier_proposal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,";
-                $sql .= " d.info_bits, d.total_ht, d.total_tva, d.total_localtax1, d.total_localtax2, d.total_ttc, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht, d.special_code, d.rang, d.product_type,";
-                $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label,';
-                $sql .= ' d.ref_fourn as ref_produit_fourn,';
-                $sql .= ' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc, d.fk_unit';
-                $sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposaldet as d";
-                $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON d.fk_product = p.rowid";
-                $sql .= " WHERE d.fk_supplier_proposal = ".$this->id;
-                $sql .= " ORDER by d.rang";
-
-                $result = $this->db->query($sql);
-                if ($result)
-                {
-                    $num = $this->db->num_rows($result);
-                    $i = 0;
-
-                    while ($i < $num)
-                    {
-                        $objp                   = $this->db->fetch_object($result);
-
-                        $line                   = new SupplierProposalLine($this->db);
-
-                        $line->rowid = $objp->rowid; // deprecated
-                        $line->id = $objp->rowid;
-                        $line->fk_supplier_proposal = $objp->fk_supplier_proposal;
-                        $line->fk_parent_line = $objp->fk_parent_line;
-                        $line->product_type     = $objp->product_type;
-                        $line->label            = $objp->custom_label;
-                        $line->desc             = $objp->description; // Description ligne
-                        $line->qty              = $objp->qty;
-                        $line->tva_tx           = $objp->tva_tx;
-                        $line->localtax1_tx		= $objp->localtax1_tx;
-                        $line->localtax2_tx		= $objp->localtax2_tx;
-                        $line->subprice         = $objp->subprice;
-                        $line->fk_remise_except = $objp->fk_remise_except;
-                        $line->remise_percent   = $objp->remise_percent;
-
-                        $line->info_bits        = $objp->info_bits;
-                        $line->total_ht         = $objp->total_ht;
-                        $line->total_tva        = $objp->total_tva;
-                        $line->total_localtax1	= $objp->total_localtax1;
-                        $line->total_localtax2	= $objp->total_localtax2;
-                        $line->total_ttc        = $objp->total_ttc;
-                          $line->fk_fournprice 	= $objp->fk_fournprice;
-                        $marginInfos = getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
-                        $line->pa_ht = $marginInfos[0];
-                        $line->marge_tx			= $marginInfos[1];
-                        $line->marque_tx		= $marginInfos[2];
-                        $line->special_code     = $objp->special_code;
-                        $line->rang             = $objp->rang;
-
-                        $line->fk_product       = $objp->fk_product;
-
-                        $line->ref = $objp->product_ref; // deprecated
-                        $line->product_ref = $objp->product_ref;
-                        $line->libelle = $objp->product_label; // deprecated
-                        $line->product_label = $objp->product_label;
-                        $line->product_desc     = $objp->product_desc; // Description produit
-                        $line->fk_product_type  = $objp->fk_product_type;
-
-                        $line->ref_fourn = $objp->ref_produit_fourn;
-
-                        // Multicurrency
-                        $line->fk_multicurrency = $objp->fk_multicurrency;
-                        $line->multicurrency_code = $objp->multicurrency_code;
-                        $line->multicurrency_subprice 	= $objp->multicurrency_subprice;
-                        $line->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
-                        $line->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
-                        $line->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
-                        $line->fk_unit = $objp->fk_unit;
-
-                        $this->lines[$i] = $line;
-
-                        $i++;
-                    }
-                    $this->db->free($result);
-                } else {
-                    $this->error = $this->db->error();
-                    return -1;
-                }
-
-                // Retreive all extrafield
-                // fetch optionals attributes and labels
-                $this->fetch_optionals();
-
-                return 1;
-            }
-
-            $this->error = "Record Not Found";
-            return 0;
-        } else {
-            $this->error = $this->db->error();
-            return -1;
-        }
-    }
-
-    /**
-     *  Set status to validated
-     *
-     *  @param	User	$user       Object user that validate
-     *  @param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
-     *  @return int         		<0 if KO, >=0 if OK
-     */
-    public function valid($user, $notrigger = 0)
-    {
-        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
-
-        global $conf, $langs;
-
-        $error = 0;
-        $now = dol_now();
-
-        if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->supplier_proposal->creer))
-           || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->supplier_proposal->validate_advance)))
-        {
-            $this->db->begin();
-
-            // Numbering module definition
-            $soc = new Societe($this->db);
-            $soc->fetch($this->socid);
-
-            // Define new ref
-            if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
-            {
-                $num = $this->getNextNumRef($soc);
-            } else {
-                $num = $this->ref;
-            }
-            $this->newref = dol_sanitizeFileName($num);
-
-            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
-            $sql .= " SET ref = '".$this->db->escape($num)."',";
-            $sql .= " fk_statut = 1, date_valid='".$this->db->idate($now)."', fk_user_valid=".$user->id;
-            $sql .= " WHERE rowid = ".$this->id." AND fk_statut = 0";
-
-            dol_syslog(get_class($this)."::valid", LOG_DEBUG);
-            $resql = $this->db->query($sql);
-            if (!$resql)
-            {
-                dol_print_error($this->db);
-                $error++;
-            }
-
-               // Trigger calls
-            if (!$error && !$notrigger)
-            {
-                // Call trigger
-                $result = $this->call_trigger('PROPOSAL_SUPPLIER_VALIDATE', $user);
-                if ($result < 0) { $error++; }
-                // End call triggers
-            }
-
-            if (!$error)
-            {
-                $this->oldref = $this->ref;
-
-                // Rename directory if dir was a temporary ref
-                if (preg_match('/^[\(]?PROV/i', $this->ref))
-                {
-                	// Now we rename also files into index
-                	$sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'supplier_proposal/".$this->db->escape($this->newref)."'";
-                	$sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'supplier_proposal/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
-                	$resql = $this->db->query($sql);
-                	if (!$resql) { $error++; $this->error = $this->db->lasterror(); }
-
-                	// We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
-                	$oldref = dol_sanitizeFileName($this->ref);
-                    $newref = dol_sanitizeFileName($num);
-                    $dirsource = $conf->supplier_proposal->dir_output.'/'.$oldref;
-                    $dirdest = $conf->supplier_proposal->dir_output.'/'.$newref;
-                    if (!$error && file_exists($dirsource))
-                    {
-                        dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
-                        if (@rename($dirsource, $dirdest))
-                        {
-                            dol_syslog("Rename ok");
-                            // Rename docs starting with $oldref with $newref
-                            $listoffiles = dol_dir_list($conf->supplier_proposal->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
-                            foreach ($listoffiles as $fileentry)
-                            {
-                                $dirsource = $fileentry['name'];
-                                $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
-                                $dirsource = $fileentry['path'].'/'.$dirsource;
-                                $dirdest = $fileentry['path'].'/'.$dirdest;
-                                @rename($dirsource, $dirdest);
-                            }
-                        }
-                    }
-                }
-
-                $this->ref = $num;
-                $this->brouillon = 0;
-                $this->statut = 1;
-                $this->user_valid_id = $user->id;
-                $this->datev = $now;
-
-                $this->db->commit();
-                return 1;
-            } else {
-                $this->db->rollback();
-                return -1;
-            }
-        } else {
-            dol_syslog("You don't have permission to validate supplier proposal", LOG_WARNING);
-            return -2;
-        }
-    }
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *	Set delivery date
-     *
-     *	@param      User 		$user        		Object user that modify
-     *	@param      int			$date_livraison     Delivery date
-     *	@return     int         					<0 if ko, >0 if ok
-     */
-    public function set_date_livraison($user, $date_livraison)
-    {
-        // phpcs:enable
-        if (!empty($user->rights->supplier_proposal->creer))
-        {
-            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
-            $sql .= " SET date_livraison = ".($date_livraison != '' ? "'".$this->db->idate($date_livraison)."'" : 'null');
-            $sql .= " WHERE rowid = ".$this->id;
-
-            if ($this->db->query($sql))
-            {
-                $this->date_livraison = $date_livraison;
-                return 1;
-            } else {
-                $this->error = $this->db->error();
-                dol_syslog(get_class($this)."::set_date_livraison Erreur SQL");
-                return -1;
-            }
-        }
-    }
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *	Set an overall discount on the proposal
-     *
-     *	@param      User	$user       Object user that modify
-     *	@param      double	$remise      Amount discount
-     *	@return     int         		<0 if ko, >0 if ok
-     */
-    public function set_remise_percent($user, $remise)
-    {
-        // phpcs:enable
-        $remise = trim($remise) ?trim($remise) : 0;
-
-        if (!empty($user->rights->supplier_proposal->creer))
-        {
-            $remise = price2num($remise);
-
-            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal SET remise_percent = ".$remise;
-            $sql .= " WHERE rowid = ".$this->id." AND fk_statut = 0";
-
-            if ($this->db->query($sql))
-            {
-                $this->remise_percent = $remise;
-                $this->update_price(1);
-                return 1;
-            } else {
-                $this->error = $this->db->error();
-                return -1;
-            }
-        }
-    }
-
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *	Set an absolute overall discount on the proposal
-     *
-     *	@param      User	$user        Object user that modify
-     *	@param      double	$remise      Amount discount
-     *	@return     int         		<0 if ko, >0 if ok
-     */
-    public function set_remise_absolue($user, $remise)
-    {
-        // phpcs:enable
-        $remise = trim($remise) ?trim($remise) : 0;
-
-        if (!empty($user->rights->supplier_proposal->creer))
-        {
-            $remise = price2num($remise);
-
-            $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
-            $sql .= " SET remise_absolue = ".$remise;
-            $sql .= " WHERE rowid = ".$this->id." AND fk_statut = 0";
-
-            if ($this->db->query($sql))
-            {
-                $this->remise_absolue = $remise;
-                $this->update_price(1);
-                return 1;
-            } else {
-                $this->error = $this->db->error();
-                return -1;
-            }
-        }
-    }
-
-
-
-    /**
-     *	Reopen the commercial proposal
-     *
-     *	@param      User	$user		Object user that close
-     *	@param      int		$statut		Statut
-     *	@param      string	$note		Comment
-     *  @param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
-     *	@return     int         		<0 if KO, >0 if OK
-     */
-    public function reopen($user, $statut, $note = '', $notrigger = 0)
-    {
-        global $langs, $conf;
-
-        $this->statut = $statut;
-        $error = 0;
-
-        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
-        $sql .= " SET fk_statut = ".$this->statut.",";
-        if (!empty($note)) $sql .= " note_private = '".$this->db->escape($note)."',";
-        $sql .= " date_cloture=NULL, fk_user_cloture=NULL";
-        $sql .= " WHERE rowid = ".$this->id;
-
-        $this->db->begin();
-
-        dol_syslog(get_class($this)."::reopen", LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if (!$resql) {
-            $error++; $this->errors[] = "Error ".$this->db->lasterror();
-        }
-        if (!$error)
-        {
-            if (!$notrigger)
-            {
-                // Call trigger
-                $result = $this->call_trigger('PROPOSAL_SUPPLIER_REOPEN', $user);
-                if ($result < 0) { $error++; }
-                // End call triggers
-            }
-        }
-
-        // Commit or rollback
-        if ($error)
-        {
-            if (!empty($this->errors))
-            {
-                foreach ($this->errors as $errmsg)
-                {
-                    dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
-                    $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
-                }
-            }
-            $this->db->rollback();
-            return -1 * $error;
-        } else {
-            $this->db->commit();
-            return 1;
-        }
-    }
-
-
-    /**
-     *	Close the askprice
-     *
-     *	@param      User	$user		Object user that close
-     *	@param      int		$status		Status
-     *	@param      string	$note		Comment
-     *	@return     int         		<0 if KO, >0 if OK
-     */
-    public function cloture($user, $status, $note)
-    {
-        global $langs, $conf;
-
-        $this->statut = $status;
-        $error = 0;
-        $now = dol_now();
-
-        $this->db->begin();
-
-        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
-        $sql .= " SET fk_statut = ".$status.", note_private = '".$this->db->escape($note)."', date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
-        $sql .= " WHERE rowid = ".$this->id;
-
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            $modelpdf = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED ? $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED : $this->modelpdf;
-            $triggerName = 'PROPOSAL_SUPPLIER_CLOSE_REFUSED';
-
-            if ($status == 2)
-            {
-                $triggerName = 'PROPOSAL_SUPPLIER_CLOSE_SIGNED';
-                $modelpdf = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL ? $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL : $this->modelpdf;
-
-                if (!empty($conf->global->SUPPLIER_PROPOSAL_UPDATE_PRICE_ON_SUPPlIER_PROPOSAL))     // TODO This option was not tested correctly. Error if product ref does not exists
-                {
-                    $result = $this->updateOrCreatePriceFournisseur($user);
-                }
-            }
-            if ($status == 4)
-            {
-                $triggerName = 'PROPOSAL_SUPPLIER_CLASSIFY_BILLED';
-            }
-
-            if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
-            {
-                // Define output language
-                $outputlangs = $langs;
-                if (!empty($conf->global->MAIN_MULTILANGS)) {
-                    $outputlangs = new Translate("", $conf);
-                    $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
-                    $outputlangs->setDefaultLang($newlang);
-                }
-                //$ret=$object->fetch($id);    // Reload to get new records
-                $this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
-            }
-
-            // Call trigger
-            $result = $this->call_trigger($triggerName, $user);
-            if ($result < 0) { $error++; }
-            // End call triggers
-
-            if (!$error)
-            {
-                $this->db->commit();
-                return 1;
-            } else {
-                $this->db->rollback();
-                return -1;
-            }
-        } else {
-            $this->error = $this->db->lasterror();
-            $this->errors[] = $this->db->lasterror();
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-    /**
-     *	Add or update supplier price according to result of proposal
-     *
-     *	@param     User	    $user       Object user
-     *  @return    int                  > 0 if OK
-     */
-    public function updateOrCreatePriceFournisseur($user)
-    {
-        global $conf;
-
-        dol_syslog(get_class($this)."::updateOrCreatePriceFournisseur", LOG_DEBUG);
-        foreach ($this->lines as $product)
-        {
-            if ($product->subprice <= 0) continue;
-            $productsupplier = new ProductFournisseur($this->db);
-
-            $multicurrency_tx = 1;
-            $fk_multicurrency = 0;
-
-            if (empty($this->thirdparty)) $this->fetch_thirdparty();
-
-            $ref_fourn = $product->ref_fourn;
-            if (empty($ref_fourn)) $ref_fourn = $product->ref_supplier;
-            if (!empty($conf->multicurrency->enabled) && !empty($product->multicurrency_code)) list($fk_multicurrency, $multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $product->multicurrency_code);
-            $productsupplier->id = $product->fk_product;
-
-            $productsupplier->update_buyprice($product->qty, $product->total_ht, $user, 'HT', $this->thirdparty, '', $ref_fourn, $product->tva_tx, 0, 0, 0, $product->info_bits, '', '', array(), '', $product->multicurrency_total_ht, 'HT', $multicurrency_tx, $product->multicurrency_code, '', '', '');
-        }
-
-        return 1;
-    }
-
-    /**
-     *	Upate ProductFournisseur
-     *
-     * 	@param		int 	$idProductFournPrice	id of llx_product_fournisseur_price
-     * 	@param		Product $product				contain informations to update
-     *	@param      User	$user					Object user
-     *	@return     int         					<0 if KO, >0 if OK
-     */
-    public function updatePriceFournisseur($idProductFournPrice, $product, $user)
-    {
-        $price = price2num($product->subprice * $product->qty, 'MU');
-        $unitPrice = price2num($product->subprice, 'MU');
-
-        $sql = 'UPDATE '.MAIN_DB_PREFIX.'product_fournisseur_price SET '.(!empty($product->ref_fourn) ? 'ref_fourn = "'.$product->ref_fourn.'", ' : '').' price ='.$price.', unitprice ='.$unitPrice.' WHERE rowid = '.$idProductFournPrice;
-
-        $resql = $this->db->query($sql);
-        if (!$resql) {
-            $this->error = $this->db->error();
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-     /**
-     *	Create ProductFournisseur
-     *
-     *	@param		Product 	$product	Object Product
-     *	@param      User		$user		Object user
-     *	@return     int         			<0 if KO, >0 if OK
-     */
-    public function createPriceFournisseur($product, $user)
-    {
-    	global $conf;
-
-        $price = price2num($product->subprice * $product->qty, 'MU');
-        $qty = price2num($product->qty);
-        $unitPrice = price2num($product->subprice, 'MU');
-
-        $now = dol_now();
-
-        $values = array(
-            "'".$this->db->idate($now)."'",
-            $product->fk_product,
-            $this->thirdparty->id,
-            "'".$product->ref_fourn."'",
-            $price,
-            $qty,
-            $unitPrice,
-            $product->tva_tx,
-            $user->id
-        );
-        if (!empty($conf->multicurrency->enabled)) {
-            if (!empty($product->multicurrency_code)) {
+	 *		@param		int		$fromid			Id of thirdparty
+	 * 	 	@return		int						New id of clone
+	 */
+	public function createFromClone(User $user, $fromid = 0)
+	{
+		global $conf, $hookmanager;
+
+		$error = 0;
+		$now = dol_now();
+
+		$this->db->begin();
+
+		// get extrafields so they will be clone
+		foreach ($this->lines as $line)
+			$line->fetch_optionals();
+
+		// Load source object
+		$objFrom = clone $this;
+
+		$objsoc = new Societe($this->db);
+
+		// Change socid if needed
+		if (!empty($fromid) && $fromid != $this->socid)
+		{
+			if ($objsoc->fetch($fromid) > 0)
+			{
+				$this->socid = $objsoc->id;
+				$this->cond_reglement_id	= (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
+				$this->mode_reglement_id	= (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
+				$this->fk_project = '';
+			}
+
+			// TODO Change product price if multi-prices
+		} else {
+			$objsoc->fetch($this->socid);
+		}
+
+		$this->id = 0;
+		$this->statut = 0;
+
+		if (empty($conf->global->SUPPLIER_PROPOSAL_ADDON) || !is_readable(DOL_DOCUMENT_ROOT."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.".php"))
+		{
+			$this->error = 'ErrorSetupNotComplete';
+			return -1;
+		}
+
+		// Clear fields
+		$this->user_author = $user->id;
+		$this->user_valid = '';
+		$this->date = $now;
+
+		// Set ref
+		require_once DOL_DOCUMENT_ROOT."/core/modules/supplier_proposal/".$conf->global->SUPPLIER_PROPOSAL_ADDON.'.php';
+		$obj = $conf->global->SUPPLIER_PROPOSAL_ADDON;
+		$modSupplierProposal = new $obj;
+		$this->ref = $modSupplierProposal->getNextValue($objsoc, $this);
+
+		// Create clone
+		$this->context['createfromclone'] = 'createfromclone';
+		$result = $this->create($user);
+		if ($result < 0) $error++;
+
+		if (!$error)
+		{
+			// Hook of thirdparty module
+			if (is_object($hookmanager))
+			{
+				$parameters = array('objFrom'=>$objFrom);
+				$action = '';
+				$reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+				if ($reshook < 0) $error++;
+			}
+		}
+
+		unset($this->context['createfromclone']);
+
+		// End
+		if (!$error)
+		{
+			$this->db->commit();
+			return $this->id;
+		} else {
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	/**
+	 *	Load a proposal from database and its ligne array
+	 *
+	 *	@param      int			$rowid		id of object to load
+	 *	@param		string		$ref		Ref of proposal
+	 *	@return     int         			>0 if OK, <0 if KO
+	 */
+	public function fetch($rowid, $ref = '')
+	{
+		global $conf;
+
+		$sql = "SELECT p.rowid, p.entity, p.ref, p.remise, p.remise_percent, p.remise_absolue, p.fk_soc";
+		$sql .= ", p.total, p.tva, p.localtax1, p.localtax2, p.total_ht";
+		$sql .= ", p.datec";
+		$sql .= ", p.date_valid as datev";
+		$sql .= ", p.date_livraison as date_livraison";
+		$sql .= ", p.model_pdf, p.extraparams";
+		$sql .= ", p.note_private, p.note_public";
+		$sql .= ", p.fk_projet as fk_project, p.fk_statut";
+		$sql .= ", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
+		$sql .= ", p.fk_cond_reglement";
+		$sql .= ", p.fk_mode_reglement";
+		$sql .= ', p.fk_account';
+		$sql .= ", p.fk_shipping_method";
+		$sql .= ", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
+		$sql .= ", c.label as statut_label";
+		$sql .= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc";
+		$sql .= ", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
+		$sql .= " FROM ".MAIN_DB_PREFIX."c_propalst as c, ".MAIN_DB_PREFIX."supplier_proposal as p";
+		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as cp ON p.fk_mode_reglement = cp.id';
+		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as cr ON p.fk_cond_reglement = cr.rowid';
+		$sql .= " WHERE p.fk_statut = c.id";
+		$sql .= " AND p.entity IN (".getEntity('supplier_proposal').")";
+		if ($ref) $sql .= " AND p.ref='".$ref."'";
+		else $sql .= " AND p.rowid=".$rowid;
+
+		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			if ($this->db->num_rows($resql))
+			{
+				$obj = $this->db->fetch_object($resql);
+
+				$this->id                   = $obj->rowid;
+				$this->entity               = $obj->entity;
+
+				$this->ref                  = $obj->ref;
+				$this->remise               = $obj->remise;
+				$this->remise_percent       = $obj->remise_percent;
+				$this->remise_absolue       = $obj->remise_absolue;
+				$this->total                = $obj->total; // TODO deprecated
+				$this->total_ht             = $obj->total_ht;
+				$this->total_tva            = $obj->tva;
+				$this->total_localtax1		= $obj->localtax1;
+				$this->total_localtax2		= $obj->localtax2;
+				$this->total_ttc            = $obj->total;
+				$this->socid                = $obj->fk_soc;
+				$this->fk_project           = $obj->fk_project;
+				$this->model_pdf            = $obj->model_pdf;
+				$this->modelpdf             = $obj->model_pdf;
+				$this->note                 = $obj->note_private; // TODO deprecated
+				$this->note_private         = $obj->note_private;
+				$this->note_public          = $obj->note_public;
+				$this->statut               = (int) $obj->fk_statut;
+				$this->statut_libelle       = $obj->statut_label;
+				$this->datec                = $this->db->jdate($obj->datec); // TODO deprecated
+				$this->datev                = $this->db->jdate($obj->datev); // TODO deprecated
+				$this->date_creation = $this->db->jdate($obj->datec); //Creation date
+				$this->date_validation = $this->db->jdate($obj->datev); //Validation date
+				$this->date_livraison       = $this->db->jdate($obj->date_livraison);
+				$this->shipping_method_id   = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method : null;
+
+				$this->mode_reglement_id    = $obj->fk_mode_reglement;
+				$this->mode_reglement_code  = $obj->mode_reglement_code;
+				$this->mode_reglement       = $obj->mode_reglement;
+				$this->fk_account           = ($obj->fk_account > 0) ? $obj->fk_account : null;
+				$this->cond_reglement_id    = $obj->fk_cond_reglement;
+				$this->cond_reglement_code  = $obj->cond_reglement_code;
+				$this->cond_reglement       = $obj->cond_reglement;
+				$this->cond_reglement_doc   = $obj->cond_reglement_libelle_doc;
+
+				$this->extraparams = (array) json_decode($obj->extraparams, true);
+
+				$this->user_author_id = $obj->fk_user_author;
+				$this->user_valid_id  = $obj->fk_user_valid;
+				$this->user_close_id  = $obj->fk_user_cloture;
+
+				// Multicurrency
+				$this->fk_multicurrency 		= $obj->fk_multicurrency;
+				$this->multicurrency_code = $obj->multicurrency_code;
+				$this->multicurrency_tx 		= $obj->multicurrency_tx;
+				$this->multicurrency_total_ht = $obj->multicurrency_total_ht;
+				$this->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
+				$this->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
+
+				if ($obj->fk_statut == 0)
+				{
+					$this->brouillon = 1;
+				}
+
+				// Retreive all extrafield
+				// fetch optionals attributes and labels
+				$this->fetch_optionals();
+
+				$this->db->free($resql);
+
+				$this->lines = array();
+
+				// Lines of supplier proposals
+				$sql = "SELECT d.rowid, d.fk_supplier_proposal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,";
+				$sql .= " d.info_bits, d.total_ht, d.total_tva, d.total_localtax1, d.total_localtax2, d.total_ttc, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht, d.special_code, d.rang, d.product_type,";
+				$sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label,';
+				$sql .= ' d.ref_fourn as ref_produit_fourn,';
+				$sql .= ' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc, d.fk_unit';
+				$sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposaldet as d";
+				$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON d.fk_product = p.rowid";
+				$sql .= " WHERE d.fk_supplier_proposal = ".$this->id;
+				$sql .= " ORDER by d.rang";
+
+				$result = $this->db->query($sql);
+				if ($result)
+				{
+					$num = $this->db->num_rows($result);
+					$i = 0;
+
+					while ($i < $num)
+					{
+						$objp                   = $this->db->fetch_object($result);
+
+						$line                   = new SupplierProposalLine($this->db);
+
+						$line->rowid = $objp->rowid; // deprecated
+						$line->id = $objp->rowid;
+						$line->fk_supplier_proposal = $objp->fk_supplier_proposal;
+						$line->fk_parent_line = $objp->fk_parent_line;
+						$line->product_type     = $objp->product_type;
+						$line->label            = $objp->custom_label;
+						$line->desc             = $objp->description; // Description ligne
+						$line->qty              = $objp->qty;
+						$line->tva_tx           = $objp->tva_tx;
+						$line->localtax1_tx		= $objp->localtax1_tx;
+						$line->localtax2_tx		= $objp->localtax2_tx;
+						$line->subprice         = $objp->subprice;
+						$line->fk_remise_except = $objp->fk_remise_except;
+						$line->remise_percent   = $objp->remise_percent;
+
+						$line->info_bits        = $objp->info_bits;
+						$line->total_ht         = $objp->total_ht;
+						$line->total_tva        = $objp->total_tva;
+						$line->total_localtax1	= $objp->total_localtax1;
+						$line->total_localtax2	= $objp->total_localtax2;
+						$line->total_ttc        = $objp->total_ttc;
+						  $line->fk_fournprice 	= $objp->fk_fournprice;
+						$marginInfos = getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
+						$line->pa_ht = $marginInfos[0];
+						$line->marge_tx			= $marginInfos[1];
+						$line->marque_tx		= $marginInfos[2];
+						$line->special_code     = $objp->special_code;
+						$line->rang             = $objp->rang;
+
+						$line->fk_product       = $objp->fk_product;
+
+						$line->ref = $objp->product_ref; // deprecated
+						$line->product_ref = $objp->product_ref;
+						$line->libelle = $objp->product_label; // deprecated
+						$line->product_label = $objp->product_label;
+						$line->product_desc     = $objp->product_desc; // Description produit
+						$line->fk_product_type  = $objp->fk_product_type;
+
+						$line->ref_fourn = $objp->ref_produit_fourn;
+
+						// Multicurrency
+						$line->fk_multicurrency = $objp->fk_multicurrency;
+						$line->multicurrency_code = $objp->multicurrency_code;
+						$line->multicurrency_subprice 	= $objp->multicurrency_subprice;
+						$line->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
+						$line->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
+						$line->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
+						$line->fk_unit = $objp->fk_unit;
+
+						$this->lines[$i] = $line;
+
+						$i++;
+					}
+					$this->db->free($result);
+				} else {
+					$this->error = $this->db->error();
+					return -1;
+				}
+
+				// Retreive all extrafield
+				// fetch optionals attributes and labels
+				$this->fetch_optionals();
+
+				return 1;
+			}
+
+			$this->error = "Record Not Found";
+			return 0;
+		} else {
+			$this->error = $this->db->error();
+			return -1;
+		}
+	}
+
+	/**
+	 *  Set status to validated
+	 *
+	 *  @param	User	$user       Object user that validate
+	 *  @param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
+	 *  @return int         		<0 if KO, >=0 if OK
+	 */
+	public function valid($user, $notrigger = 0)
+	{
+		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+
+		global $conf, $langs;
+
+		$error = 0;
+		$now = dol_now();
+
+		if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->supplier_proposal->creer))
+		   || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->supplier_proposal->validate_advance)))
+		{
+			$this->db->begin();
+
+			// Numbering module definition
+			$soc = new Societe($this->db);
+			$soc->fetch($this->socid);
+
+			// Define new ref
+			if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
+			{
+				$num = $this->getNextNumRef($soc);
+			} else {
+				$num = $this->ref;
+			}
+			$this->newref = dol_sanitizeFileName($num);
+
+			$sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
+			$sql .= " SET ref = '".$this->db->escape($num)."',";
+			$sql .= " fk_statut = 1, date_valid='".$this->db->idate($now)."', fk_user_valid=".$user->id;
+			$sql .= " WHERE rowid = ".$this->id." AND fk_statut = 0";
+
+			dol_syslog(get_class($this)."::valid", LOG_DEBUG);
+			$resql = $this->db->query($sql);
+			if (!$resql)
+			{
+				dol_print_error($this->db);
+				$error++;
+			}
+
+			   // Trigger calls
+			if (!$error && !$notrigger)
+			{
+				// Call trigger
+				$result = $this->call_trigger('PROPOSAL_SUPPLIER_VALIDATE', $user);
+				if ($result < 0) { $error++; }
+				// End call triggers
+			}
+
+			if (!$error)
+			{
+				$this->oldref = $this->ref;
+
+				// Rename directory if dir was a temporary ref
+				if (preg_match('/^[\(]?PROV/i', $this->ref))
+				{
+					// Now we rename also files into index
+					$sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'supplier_proposal/".$this->db->escape($this->newref)."'";
+					$sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'supplier_proposal/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
+					$resql = $this->db->query($sql);
+					if (!$resql) { $error++; $this->error = $this->db->lasterror(); }
+
+					// We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
+					$oldref = dol_sanitizeFileName($this->ref);
+					$newref = dol_sanitizeFileName($num);
+					$dirsource = $conf->supplier_proposal->dir_output.'/'.$oldref;
+					$dirdest = $conf->supplier_proposal->dir_output.'/'.$newref;
+					if (!$error && file_exists($dirsource))
+					{
+						dol_syslog(get_class($this)."::valid rename dir ".$dirsource." into ".$dirdest);
+						if (@rename($dirsource, $dirdest))
+						{
+							dol_syslog("Rename ok");
+							// Rename docs starting with $oldref with $newref
+							$listoffiles = dol_dir_list($conf->supplier_proposal->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
+							foreach ($listoffiles as $fileentry)
+							{
+								$dirsource = $fileentry['name'];
+								$dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
+								$dirsource = $fileentry['path'].'/'.$dirsource;
+								$dirdest = $fileentry['path'].'/'.$dirdest;
+								@rename($dirsource, $dirdest);
+							}
+						}
+					}
+				}
+
+				$this->ref = $num;
+				$this->brouillon = 0;
+				$this->statut = 1;
+				$this->user_valid_id = $user->id;
+				$this->datev = $now;
+
+				$this->db->commit();
+				return 1;
+			} else {
+				$this->db->rollback();
+				return -1;
+			}
+		} else {
+			dol_syslog("You don't have permission to validate supplier proposal", LOG_WARNING);
+			return -2;
+		}
+	}
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *	Set delivery date
+	 *
+	 *	@param      User 		$user        		Object user that modify
+	 *	@param      int			$date_livraison     Delivery date
+	 *	@return     int         					<0 if ko, >0 if ok
+	 */
+	public function set_date_livraison($user, $date_livraison)
+	{
+		// phpcs:enable
+		if (!empty($user->rights->supplier_proposal->creer))
+		{
+			$sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
+			$sql .= " SET date_livraison = ".($date_livraison != '' ? "'".$this->db->idate($date_livraison)."'" : 'null');
+			$sql .= " WHERE rowid = ".$this->id;
+
+			if ($this->db->query($sql))
+			{
+				$this->date_livraison = $date_livraison;
+				return 1;
+			} else {
+				$this->error = $this->db->error();
+				dol_syslog(get_class($this)."::set_date_livraison Erreur SQL");
+				return -1;
+			}
+		}
+	}
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *	Set an overall discount on the proposal
+	 *
+	 *	@param      User	$user       Object user that modify
+	 *	@param      double	$remise      Amount discount
+	 *	@return     int         		<0 if ko, >0 if ok
+	 */
+	public function set_remise_percent($user, $remise)
+	{
+		// phpcs:enable
+		$remise = trim($remise) ?trim($remise) : 0;
+
+		if (!empty($user->rights->supplier_proposal->creer))
+		{
+			$remise = price2num($remise);
+
+			$sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal SET remise_percent = ".$remise;
+			$sql .= " WHERE rowid = ".$this->id." AND fk_statut = 0";
+
+			if ($this->db->query($sql))
+			{
+				$this->remise_percent = $remise;
+				$this->update_price(1);
+				return 1;
+			} else {
+				$this->error = $this->db->error();
+				return -1;
+			}
+		}
+	}
+
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *	Set an absolute overall discount on the proposal
+	 *
+	 *	@param      User	$user        Object user that modify
+	 *	@param      double	$remise      Amount discount
+	 *	@return     int         		<0 if ko, >0 if ok
+	 */
+	public function set_remise_absolue($user, $remise)
+	{
+		// phpcs:enable
+		$remise = trim($remise) ?trim($remise) : 0;
+
+		if (!empty($user->rights->supplier_proposal->creer))
+		{
+			$remise = price2num($remise);
+
+			$sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal ";
+			$sql .= " SET remise_absolue = ".$remise;
+			$sql .= " WHERE rowid = ".$this->id." AND fk_statut = 0";
+
+			if ($this->db->query($sql))
+			{
+				$this->remise_absolue = $remise;
+				$this->update_price(1);
+				return 1;
+			} else {
+				$this->error = $this->db->error();
+				return -1;
+			}
+		}
+	}
+
+
+
+	/**
+	 *	Reopen the commercial proposal
+	 *
+	 *	@param      User	$user		Object user that close
+	 *	@param      int		$statut		Statut
+	 *	@param      string	$note		Comment
+	 *  @param		int		$notrigger	1=Does not execute triggers, 0= execute triggers
+	 *	@return     int         		<0 if KO, >0 if OK
+	 */
+	public function reopen($user, $statut, $note = '', $notrigger = 0)
+	{
+		global $langs, $conf;
+
+		$this->statut = $statut;
+		$error = 0;
+
+		$sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
+		$sql .= " SET fk_statut = ".$this->statut.",";
+		if (!empty($note)) $sql .= " note_private = '".$this->db->escape($note)."',";
+		$sql .= " date_cloture=NULL, fk_user_cloture=NULL";
+		$sql .= " WHERE rowid = ".$this->id;
+
+		$this->db->begin();
+
+		dol_syslog(get_class($this)."::reopen", LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if (!$resql) {
+			$error++; $this->errors[] = "Error ".$this->db->lasterror();
+		}
+		if (!$error)
+		{
+			if (!$notrigger)
+			{
+				// Call trigger
+				$result = $this->call_trigger('PROPOSAL_SUPPLIER_REOPEN', $user);
+				if ($result < 0) { $error++; }
+				// End call triggers
+			}
+		}
+
+		// Commit or rollback
+		if ($error)
+		{
+			if (!empty($this->errors))
+			{
+				foreach ($this->errors as $errmsg)
+				{
+					dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
+					$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
+				}
+			}
+			$this->db->rollback();
+			return -1 * $error;
+		} else {
+			$this->db->commit();
+			return 1;
+		}
+	}
+
+
+	/**
+	 *	Close the askprice
+	 *
+	 *	@param      User	$user		Object user that close
+	 *	@param      int		$status		Status
+	 *	@param      string	$note		Comment
+	 *	@return     int         		<0 if KO, >0 if OK
+	 */
+	public function cloture($user, $status, $note)
+	{
+		global $langs, $conf;
+
+		$this->statut = $status;
+		$error = 0;
+		$now = dol_now();
+
+		$this->db->begin();
+
+		$sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
+		$sql .= " SET fk_statut = ".$status.", note_private = '".$this->db->escape($note)."', date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
+		$sql .= " WHERE rowid = ".$this->id;
+
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			$modelpdf = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED ? $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_CLOSED : $this->modelpdf;
+			$triggerName = 'PROPOSAL_SUPPLIER_CLOSE_REFUSED';
+
+			if ($status == 2)
+			{
+				$triggerName = 'PROPOSAL_SUPPLIER_CLOSE_SIGNED';
+				$modelpdf = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL ? $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF_ODT_TOBILL : $this->modelpdf;
+
+				if (!empty($conf->global->SUPPLIER_PROPOSAL_UPDATE_PRICE_ON_SUPPlIER_PROPOSAL))     // TODO This option was not tested correctly. Error if product ref does not exists
+				{
+					$result = $this->updateOrCreatePriceFournisseur($user);
+				}
+			}
+			if ($status == 4)
+			{
+				$triggerName = 'PROPOSAL_SUPPLIER_CLASSIFY_BILLED';
+			}
+
+			if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
+			{
+				// Define output language
+				$outputlangs = $langs;
+				if (!empty($conf->global->MAIN_MULTILANGS)) {
+					$outputlangs = new Translate("", $conf);
+					$newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
+					$outputlangs->setDefaultLang($newlang);
+				}
+				//$ret=$object->fetch($id);    // Reload to get new records
+				$this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
+			}
+
+			// Call trigger
+			$result = $this->call_trigger($triggerName, $user);
+			if ($result < 0) { $error++; }
+			// End call triggers
+
+			if (!$error)
+			{
+				$this->db->commit();
+				return 1;
+			} else {
+				$this->db->rollback();
+				return -1;
+			}
+		} else {
+			$this->error = $this->db->lasterror();
+			$this->errors[] = $this->db->lasterror();
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	/**
+	 *	Add or update supplier price according to result of proposal
+	 *
+	 *	@param     User	    $user       Object user
+	 *  @return    int                  > 0 if OK
+	 */
+	public function updateOrCreatePriceFournisseur($user)
+	{
+		global $conf;
+
+		dol_syslog(get_class($this)."::updateOrCreatePriceFournisseur", LOG_DEBUG);
+		foreach ($this->lines as $product)
+		{
+			if ($product->subprice <= 0) continue;
+			$productsupplier = new ProductFournisseur($this->db);
+
+			$multicurrency_tx = 1;
+			$fk_multicurrency = 0;
+
+			if (empty($this->thirdparty)) $this->fetch_thirdparty();
+
+			$ref_fourn = $product->ref_fourn;
+			if (empty($ref_fourn)) $ref_fourn = $product->ref_supplier;
+			if (!empty($conf->multicurrency->enabled) && !empty($product->multicurrency_code)) list($fk_multicurrency, $multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $product->multicurrency_code);
+			$productsupplier->id = $product->fk_product;
+
+			$productsupplier->update_buyprice($product->qty, $product->total_ht, $user, 'HT', $this->thirdparty, '', $ref_fourn, $product->tva_tx, 0, 0, 0, $product->info_bits, '', '', array(), '', $product->multicurrency_total_ht, 'HT', $multicurrency_tx, $product->multicurrency_code, '', '', '');
+		}
+
+		return 1;
+	}
+
+	/**
+	 *	Upate ProductFournisseur
+	 *
+	 * 	@param		int 	$idProductFournPrice	id of llx_product_fournisseur_price
+	 * 	@param		Product $product				contain informations to update
+	 *	@param      User	$user					Object user
+	 *	@return     int         					<0 if KO, >0 if OK
+	 */
+	public function updatePriceFournisseur($idProductFournPrice, $product, $user)
+	{
+		$price = price2num($product->subprice * $product->qty, 'MU');
+		$unitPrice = price2num($product->subprice, 'MU');
+
+		$sql = 'UPDATE '.MAIN_DB_PREFIX.'product_fournisseur_price SET '.(!empty($product->ref_fourn) ? 'ref_fourn = "'.$product->ref_fourn.'", ' : '').' price ='.$price.', unitprice ='.$unitPrice.' WHERE rowid = '.$idProductFournPrice;
+
+		$resql = $this->db->query($sql);
+		if (!$resql) {
+			$this->error = $this->db->error();
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	 /**
+	  *	Create ProductFournisseur
+	  *
+	  *	@param		Product 	$product	Object Product
+	  *	@param      User		$user		Object user
+	  *	@return     int         			<0 if KO, >0 if OK
+	  */
+	public function createPriceFournisseur($product, $user)
+	{
+		global $conf;
+
+		$price = price2num($product->subprice * $product->qty, 'MU');
+		$qty = price2num($product->qty);
+		$unitPrice = price2num($product->subprice, 'MU');
+
+		$now = dol_now();
+
+		$values = array(
+			"'".$this->db->idate($now)."'",
+			$product->fk_product,
+			$this->thirdparty->id,
+			"'".$product->ref_fourn."'",
+			$price,
+			$qty,
+			$unitPrice,
+			$product->tva_tx,
+			$user->id
+		);
+		if (!empty($conf->multicurrency->enabled)) {
+			if (!empty($product->multicurrency_code)) {
 				include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
-	            $multicurrency = new MultiCurrency($this->db); //need to fetch because empty fk_multicurrency and rate
-                $multicurrency->fetch(0, $product->multicurrency_code);
-                if (!empty($multicurrency->id)) {
-                    $values[] = $multicurrency->id;
-                    $values[] = "'".$product->multicurrency_code."'";
-                    $values[] = $product->multicurrency_subprice;
-                    $values[] = $product->multicurrency_total_ht;
-                    $values[] = $multicurrency->rate->rate;
-                } else {
-                    for ($i = 0; $i < 5; $i++) $values[] = 'NULL';
-                }
-            }
-        }
-
-        $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_fournisseur_price ';
-        $sql .= '(datec, fk_product, fk_soc, ref_fourn, price, quantity, unitprice, tva_tx, fk_user';
-        if (!empty($conf->multicurrency->enabled) && !empty($product->multicurrency_code)) $sql .= ',fk_multicurrency, multicurrency_code, multicurrency_unitprice, multicurrency_price, multicurrency_tx';
-        $sql .= ')  VALUES ('.implode(',', $values).')';
-
-        $resql = $this->db->query($sql);
-        if (!$resql) {
-            $this->error = $this->db->error();
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *  Set draft status
-     *
-     *	@param		User	$user		Object user that modify
-     *	@return		int					<0 if KO, >0 if OK
-     */
-    public function setDraft($user)
-    {
-        // phpcs:enable
-        global $conf, $langs;
-
-        $error = 0;
-
-        if ($this->statut == self::STATUS_DRAFT)
-        {
-            dol_syslog(get_class($this)."::setDraft already draft status", LOG_WARNING);
-            return 0;
-        }
-
-        $sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
-        $sql .= " SET fk_statut = ".self::STATUS_DRAFT;
-        $sql .= " WHERE rowid = ".$this->id;
-
-        if ($this->db->query($sql))
-        {
-            if (!$error) {
-                $this->oldcopy = clone $this;
-            }
-
-            if (!$error) {
-                // Call trigger
-                $result = $this->call_trigger('PROPOSAL_SUPPLIER_UNVALIDATE', $user);
-                if ($result < 0) $error++;
-            }
-
-            if (!$error) {
-                $this->statut = self::STATUS_DRAFT;
-                $this->brouillon = 1;
-                $this->db->commit();
-                return 1;
-            } else {
-                $this->db->rollback();
-                return -1;
-            }
-        } else {
-            return -1;
-        }
-    }
-
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *    Return list of askprice (eventually filtered on user) into an array
-     *
-     *    @param	int		$shortlist			0=Return array[id]=ref, 1=Return array[](id=>id,ref=>ref,name=>name)
-     *    @param	int		$draft				0=not draft, 1=draft
-     *    @param	int		$notcurrentuser		0=all user, 1=not current user
-     *    @param    int		$socid				Id third pary
-     *    @param    int		$limit				For pagination
-     *    @param    int		$offset				For pagination
-     *    @param    string	$sortfield			Sort criteria
-     *    @param    string	$sortorder			Sort order
-     *    @return	int		       				-1 if KO, array with result if OK
-     */
-    public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield = 'p.datec', $sortorder = 'DESC')
-    {
-        // phpcs:enable
-        global $conf, $user;
-
-        $ga = array();
-
-        $sql = "SELECT s.rowid, s.nom as name, s.client,";
-        $sql .= " p.rowid as supplier_proposalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
-        $sql .= " p.datep as dp, p.fin_validite as datelimite";
-        if (!$user->rights->societe->client->voir && !$socid) $sql .= ", sc.fk_soc, sc.fk_user";
-        $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as p, ".MAIN_DB_PREFIX."c_propalst as c";
-        if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
-        $sql .= " WHERE p.entity IN (".getEntity('supplier_proposal').")";
-        $sql .= " AND p.fk_soc = s.rowid";
-        $sql .= " AND p.fk_statut = c.id";
-        if (!$user->rights->societe->client->voir && !$socid) //restriction
-        {
-            $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;
-        }
-        if ($socid) $sql .= " AND s.rowid = ".$socid;
-        if ($draft)	$sql .= " AND p.fk_statut = 0";
-        if ($notcurrentuser > 0) $sql .= " AND p.fk_user_author <> ".$user->id;
-        $sql .= $this->db->order($sortfield, $sortorder);
-        $sql .= $this->db->plimit($limit, $offset);
-
-        $result = $this->db->query($sql);
-        if ($result)
-        {
-            $num = $this->db->num_rows($result);
-            if ($num)
-            {
-                $i = 0;
-                while ($i < $num)
-                {
-                    $obj = $this->db->fetch_object($result);
-
-                    if ($shortlist == 1)
-                    {
-                        $ga[$obj->supplier_proposalid] = $obj->ref;
-                    } elseif ($shortlist == 2)
-                    {
-                        $ga[$obj->supplier_proposalid] = $obj->ref.' ('.$obj->name.')';
-                    } else {
-                        $ga[$i]['id'] = $obj->supplier_proposalid;
-                        $ga[$i]['ref'] 	= $obj->ref;
-                        $ga[$i]['name'] = $obj->name;
-                    }
-
-                    $i++;
-                }
-            }
-            return $ga;
-        } else {
-            dol_print_error($this->db);
-            return -1;
-        }
-    }
-
-    /**
-     *	Delete askprice
-     *
-     *	@param	User	$user        	Object user that delete
-     *	@param	int		$notrigger		1=Does not execute triggers, 0= execute triggers
-     *	@return	int						1 if ok, otherwise if error
-     */
-    public function delete($user, $notrigger = 0)
-    {
-        global $conf, $langs;
-        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
-
-        $error = 0;
-
-        $this->db->begin();
-
-        if (!$notrigger)
-        {
-            // Call trigger
-            $result = $this->call_trigger('PROPOSAL_SUPPLIER_DELETE', $user);
-            if ($result < 0) { $error++; }
-            // End call triggers
-        }
-
-        if (!$error)
-        {
-            $main = MAIN_DB_PREFIX.'supplier_proposaldet';
-            $ef = $main."_extrafields";
-            $sqlef = "DELETE FROM $ef WHERE fk_object IN (SELECT rowid FROM $main WHERE fk_supplier_proposal = ".$this->id.")";
-            $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposaldet WHERE fk_supplier_proposal = ".$this->id;
-            if ($this->db->query($sql))
-            {
-                $sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposal WHERE rowid = ".$this->id;
-                if ($this->db->query($sqlef) && $this->db->query($sql))
-                {
-                    // Delete linked object
-                    $res = $this->deleteObjectLinked();
-                    if ($res < 0) $error++;
-
-                    if (!$error)
-                    {
-                        // We remove directory
-                        $ref = dol_sanitizeFileName($this->ref);
-                        if ($conf->supplier_proposal->dir_output && !empty($this->ref))
-                        {
-                            $dir = $conf->supplier_proposal->dir_output."/".$ref;
-                            $file = $dir."/".$ref.".pdf";
-                            if (file_exists($file))
-                            {
-                                dol_delete_preview($this);
-
-                                if (!dol_delete_file($file, 0, 0, 0, $this)) // For triggers
-                                {
-                                    $this->error = 'ErrorFailToDeleteFile';
-                                    $this->errors = array('ErrorFailToDeleteFile');
-                                    $this->db->rollback();
-                                    return 0;
-                                }
-                            }
-                            if (file_exists($dir))
-                            {
-                                $res = @dol_delete_dir_recursive($dir);
-                                if (!$res)
-                                {
-                                    $this->error = 'ErrorFailToDeleteDir';
-                                    $this->errors = array('ErrorFailToDeleteDir');
-                                    $this->db->rollback();
-                                    return 0;
-                                }
-                            }
-                        }
-                    }
-
-                    // Removed extrafields
-                    if (!$error)
-                    {
-                    	$result = $this->deleteExtraFields();
-                    	if ($result < 0)
-                    	{
-                    		$error++;
-                    		$errorflag = -4;
-                    		dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
-                    	}
-                    }
-
-                    if (!$error)
-                    {
-                        dol_syslog(get_class($this)."::delete ".$this->id." by ".$user->id, LOG_DEBUG);
-                        $this->db->commit();
-                        return 1;
-                    } else {
-                        $this->error = $this->db->lasterror();
-                        $this->db->rollback();
-                        return 0;
-                    }
-                } else {
-                    $this->error = $this->db->lasterror();
-                    $this->db->rollback();
-                    return -3;
-                }
-            } else {
-                $this->error = $this->db->lasterror();
-                $this->db->rollback();
-                return -2;
-            }
-        } else {
-            $this->db->rollback();
-            return -1;
-        }
-    }
-
-    /**
-     *	Object SupplierProposal Information
-     *
-     * 	@param	int		$id		Proposal id
-     *  @return	void
-     */
-    public function info($id)
-    {
-        $sql = "SELECT c.rowid, ";
-        $sql .= " c.datec, c.date_valid as datev, c.date_cloture as dateo,";
-        $sql .= " c.fk_user_author, c.fk_user_valid, c.fk_user_cloture";
-        $sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal as c";
-        $sql .= " WHERE c.rowid = ".$id;
-
-        $result = $this->db->query($sql);
-
-        if ($result)
-        {
-            if ($this->db->num_rows($result))
-            {
-                $obj = $this->db->fetch_object($result);
-
-                $this->id                = $obj->rowid;
-
-                $this->date_creation     = $this->db->jdate($obj->datec);
-                $this->date_validation   = $this->db->jdate($obj->datev);
-                $this->date_cloture      = $this->db->jdate($obj->dateo);
-
-                $cuser = new User($this->db);
-                $cuser->fetch($obj->fk_user_author);
-                $this->user_creation = $cuser;
-
-                if ($obj->fk_user_valid)
-                {
-                    $vuser = new User($this->db);
-                    $vuser->fetch($obj->fk_user_valid);
-                    $this->user_validation = $vuser;
-                }
-
-                if ($obj->fk_user_cloture)
-                {
-                    $cluser = new User($this->db);
-                    $cluser->fetch($obj->fk_user_cloture);
-                    $this->user_cloture = $cluser;
-                }
-            }
-            $this->db->free($result);
-        } else {
-            dol_print_error($this->db);
-        }
-    }
-
-
-    /**
-     *    	Return label of status of proposal (draft, validated, ...)
-     *
-     *    	@param      int			$mode        0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
-     *    	@return     string		Label
-     */
-    public function getLibStatut($mode = 0)
-    {
-        return $this->LibStatut((isset($this->statut) ? $this->statut : $this->status), $mode);
-    }
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *  Return label of a status (draft, validated, ...)
-     *
-     *  @param      int			$status		Id status
+				$multicurrency = new MultiCurrency($this->db); //need to fetch because empty fk_multicurrency and rate
+				$multicurrency->fetch(0, $product->multicurrency_code);
+				if (!empty($multicurrency->id)) {
+					$values[] = $multicurrency->id;
+					$values[] = "'".$product->multicurrency_code."'";
+					$values[] = $product->multicurrency_subprice;
+					$values[] = $product->multicurrency_total_ht;
+					$values[] = $multicurrency->rate->rate;
+				} else {
+					for ($i = 0; $i < 5; $i++) $values[] = 'NULL';
+				}
+			}
+		}
+
+		$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_fournisseur_price ';
+		$sql .= '(datec, fk_product, fk_soc, ref_fourn, price, quantity, unitprice, tva_tx, fk_user';
+		if (!empty($conf->multicurrency->enabled) && !empty($product->multicurrency_code)) $sql .= ',fk_multicurrency, multicurrency_code, multicurrency_unitprice, multicurrency_price, multicurrency_tx';
+		$sql .= ')  VALUES ('.implode(',', $values).')';
+
+		$resql = $this->db->query($sql);
+		if (!$resql) {
+			$this->error = $this->db->error();
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *  Set draft status
+	 *
+	 *	@param		User	$user		Object user that modify
+	 *	@return		int					<0 if KO, >0 if OK
+	 */
+	public function setDraft($user)
+	{
+		// phpcs:enable
+		global $conf, $langs;
+
+		$error = 0;
+
+		if ($this->statut == self::STATUS_DRAFT)
+		{
+			dol_syslog(get_class($this)."::setDraft already draft status", LOG_WARNING);
+			return 0;
+		}
+
+		$sql = "UPDATE ".MAIN_DB_PREFIX."supplier_proposal";
+		$sql .= " SET fk_statut = ".self::STATUS_DRAFT;
+		$sql .= " WHERE rowid = ".$this->id;
+
+		if ($this->db->query($sql))
+		{
+			if (!$error) {
+				$this->oldcopy = clone $this;
+			}
+
+			if (!$error) {
+				// Call trigger
+				$result = $this->call_trigger('PROPOSAL_SUPPLIER_UNVALIDATE', $user);
+				if ($result < 0) $error++;
+			}
+
+			if (!$error) {
+				$this->statut = self::STATUS_DRAFT;
+				$this->brouillon = 1;
+				$this->db->commit();
+				return 1;
+			} else {
+				$this->db->rollback();
+				return -1;
+			}
+		} else {
+			return -1;
+		}
+	}
+
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *    Return list of askprice (eventually filtered on user) into an array
+	 *
+	 *    @param	int		$shortlist			0=Return array[id]=ref, 1=Return array[](id=>id,ref=>ref,name=>name)
+	 *    @param	int		$draft				0=not draft, 1=draft
+	 *    @param	int		$notcurrentuser		0=all user, 1=not current user
+	 *    @param    int		$socid				Id third pary
+	 *    @param    int		$limit				For pagination
+	 *    @param    int		$offset				For pagination
+	 *    @param    string	$sortfield			Sort criteria
+	 *    @param    string	$sortorder			Sort order
+	 *    @return	int		       				-1 if KO, array with result if OK
+	 */
+	public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield = 'p.datec', $sortorder = 'DESC')
+	{
+		// phpcs:enable
+		global $conf, $user;
+
+		$ga = array();
+
+		$sql = "SELECT s.rowid, s.nom as name, s.client,";
+		$sql .= " p.rowid as supplier_proposalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
+		$sql .= " p.datep as dp, p.fin_validite as datelimite";
+		if (!$user->rights->societe->client->voir && !$socid) $sql .= ", sc.fk_soc, sc.fk_user";
+		$sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as p, ".MAIN_DB_PREFIX."c_propalst as c";
+		if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
+		$sql .= " WHERE p.entity IN (".getEntity('supplier_proposal').")";
+		$sql .= " AND p.fk_soc = s.rowid";
+		$sql .= " AND p.fk_statut = c.id";
+		if (!$user->rights->societe->client->voir && !$socid) //restriction
+		{
+			$sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;
+		}
+		if ($socid) $sql .= " AND s.rowid = ".$socid;
+		if ($draft)	$sql .= " AND p.fk_statut = 0";
+		if ($notcurrentuser > 0) $sql .= " AND p.fk_user_author <> ".$user->id;
+		$sql .= $this->db->order($sortfield, $sortorder);
+		$sql .= $this->db->plimit($limit, $offset);
+
+		$result = $this->db->query($sql);
+		if ($result)
+		{
+			$num = $this->db->num_rows($result);
+			if ($num)
+			{
+				$i = 0;
+				while ($i < $num)
+				{
+					$obj = $this->db->fetch_object($result);
+
+					if ($shortlist == 1)
+					{
+						$ga[$obj->supplier_proposalid] = $obj->ref;
+					} elseif ($shortlist == 2)
+					{
+						$ga[$obj->supplier_proposalid] = $obj->ref.' ('.$obj->name.')';
+					} else {
+						$ga[$i]['id'] = $obj->supplier_proposalid;
+						$ga[$i]['ref'] 	= $obj->ref;
+						$ga[$i]['name'] = $obj->name;
+					}
+
+					$i++;
+				}
+			}
+			return $ga;
+		} else {
+			dol_print_error($this->db);
+			return -1;
+		}
+	}
+
+	/**
+	 *	Delete askprice
+	 *
+	 *	@param	User	$user        	Object user that delete
+	 *	@param	int		$notrigger		1=Does not execute triggers, 0= execute triggers
+	 *	@return	int						1 if ok, otherwise if error
+	 */
+	public function delete($user, $notrigger = 0)
+	{
+		global $conf, $langs;
+		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+
+		$error = 0;
+
+		$this->db->begin();
+
+		if (!$notrigger)
+		{
+			// Call trigger
+			$result = $this->call_trigger('PROPOSAL_SUPPLIER_DELETE', $user);
+			if ($result < 0) { $error++; }
+			// End call triggers
+		}
+
+		if (!$error)
+		{
+			$main = MAIN_DB_PREFIX.'supplier_proposaldet';
+			$ef = $main."_extrafields";
+			$sqlef = "DELETE FROM $ef WHERE fk_object IN (SELECT rowid FROM $main WHERE fk_supplier_proposal = ".$this->id.")";
+			$sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposaldet WHERE fk_supplier_proposal = ".$this->id;
+			if ($this->db->query($sql))
+			{
+				$sql = "DELETE FROM ".MAIN_DB_PREFIX."supplier_proposal WHERE rowid = ".$this->id;
+				if ($this->db->query($sqlef) && $this->db->query($sql))
+				{
+					// Delete linked object
+					$res = $this->deleteObjectLinked();
+					if ($res < 0) $error++;
+
+					if (!$error)
+					{
+						// We remove directory
+						$ref = dol_sanitizeFileName($this->ref);
+						if ($conf->supplier_proposal->dir_output && !empty($this->ref))
+						{
+							$dir = $conf->supplier_proposal->dir_output."/".$ref;
+							$file = $dir."/".$ref.".pdf";
+							if (file_exists($file))
+							{
+								dol_delete_preview($this);
+
+								if (!dol_delete_file($file, 0, 0, 0, $this)) // For triggers
+								{
+									$this->error = 'ErrorFailToDeleteFile';
+									$this->errors = array('ErrorFailToDeleteFile');
+									$this->db->rollback();
+									return 0;
+								}
+							}
+							if (file_exists($dir))
+							{
+								$res = @dol_delete_dir_recursive($dir);
+								if (!$res)
+								{
+									$this->error = 'ErrorFailToDeleteDir';
+									$this->errors = array('ErrorFailToDeleteDir');
+									$this->db->rollback();
+									return 0;
+								}
+							}
+						}
+					}
+
+					// Removed extrafields
+					if (!$error)
+					{
+						$result = $this->deleteExtraFields();
+						if ($result < 0)
+						{
+							$error++;
+							$errorflag = -4;
+							dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
+						}
+					}
+
+					if (!$error)
+					{
+						dol_syslog(get_class($this)."::delete ".$this->id." by ".$user->id, LOG_DEBUG);
+						$this->db->commit();
+						return 1;
+					} else {
+						$this->error = $this->db->lasterror();
+						$this->db->rollback();
+						return 0;
+					}
+				} else {
+					$this->error = $this->db->lasterror();
+					$this->db->rollback();
+					return -3;
+				}
+			} else {
+				$this->error = $this->db->lasterror();
+				$this->db->rollback();
+				return -2;
+			}
+		} else {
+			$this->db->rollback();
+			return -1;
+		}
+	}
+
+	/**
+	 *	Object SupplierProposal Information
+	 *
+	 * 	@param	int		$id		Proposal id
+	 *  @return	void
+	 */
+	public function info($id)
+	{
+		$sql = "SELECT c.rowid, ";
+		$sql .= " c.datec, c.date_valid as datev, c.date_cloture as dateo,";
+		$sql .= " c.fk_user_author, c.fk_user_valid, c.fk_user_cloture";
+		$sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal as c";
+		$sql .= " WHERE c.rowid = ".$id;
+
+		$result = $this->db->query($sql);
+
+		if ($result)
+		{
+			if ($this->db->num_rows($result))
+			{
+				$obj = $this->db->fetch_object($result);
+
+				$this->id                = $obj->rowid;
+
+				$this->date_creation     = $this->db->jdate($obj->datec);
+				$this->date_validation   = $this->db->jdate($obj->datev);
+				$this->date_cloture      = $this->db->jdate($obj->dateo);
+
+				$cuser = new User($this->db);
+				$cuser->fetch($obj->fk_user_author);
+				$this->user_creation = $cuser;
+
+				if ($obj->fk_user_valid)
+				{
+					$vuser = new User($this->db);
+					$vuser->fetch($obj->fk_user_valid);
+					$this->user_validation = $vuser;
+				}
+
+				if ($obj->fk_user_cloture)
+				{
+					$cluser = new User($this->db);
+					$cluser->fetch($obj->fk_user_cloture);
+					$this->user_cloture = $cluser;
+				}
+			}
+			$this->db->free($result);
+		} else {
+			dol_print_error($this->db);
+		}
+	}
+
+
+	/**
+	 *    	Return label of status of proposal (draft, validated, ...)
+	 *
+	 *    	@param      int			$mode        0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
+	 *    	@return     string		Label
+	 */
+	public function getLibStatut($mode = 0)
+	{
+		return $this->LibStatut((isset($this->statut) ? $this->statut : $this->status), $mode);
+	}
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *  Return label of a status (draft, validated, ...)
+	 *
+	 *  @param      int			$status		Id status
 	 *  @param  	int			$mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
-     *  @return     string      Label
-     */
-    public function LibStatut($status, $mode = 1)
-    {
-        // phpcs:enable
-
-    	// Init/load array of translation of status
-    	if (empty($this->labelStatus) || empty($this->labelStatusShort))
-    	{
-    		global $langs;
-    		$langs->load("supplier_proposal");
-    		$this->labelStatus[self::STATUS_DRAFT] = $langs->trans("SupplierProposalStatusDraft");
-    		$this->labelStatus[self::STATUS_VALIDATED] = $langs->trans("SupplierProposalStatusValidated");
-    		$this->labelStatus[self::STATUS_SIGNED] = $langs->trans("SupplierProposalStatusSigned");
-    		$this->labelStatus[self::STATUS_NOTSIGNED] = $langs->trans("SupplierProposalStatusNotSigned");
-    		$this->labelStatus[self::STATUS_CLOSE] = $langs->trans("SupplierProposalStatusClosed");
-    		$this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans("SupplierProposalStatusDraftShort");
-    		$this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans("Opened");
-    		$this->labelStatusShort[self::STATUS_SIGNED] = $langs->trans("SupplierProposalStatusSignedShort");
-    		$this->labelStatusShort[self::STATUS_NOTSIGNED] = $langs->trans("SupplierProposalStatusNotSignedShort");
-    		$this->labelStatusShort[self::STATUS_CLOSE] = $langs->trans("SupplierProposalStatusClosedShort");
-    	}
-
-    	$statusnew = '';
-    	if ($status == self::STATUS_DRAFT) $statusnew = 'status0';
-    	elseif ($status == self::STATUS_VALIDATED) $statusnew = 'status1';
-    	elseif ($status == self::STATUS_SIGNED) $statusnew = 'status4';
-    	elseif ($status == self::STATUS_NOTSIGNED) $statusnew = 'status9';
-    	elseif ($status == self::STATUS_CLOSE) $statusnew = 'status6';
-
-    	return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusnew, $mode);
-    }
-
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
-     *
-     *      @param          User	$user   Object user
-     *      @param          int		$mode   "opened" for askprice to close, "signed" for proposal to invoice
-     *      @return         int             <0 if KO, >0 if OK
-     */
-    public function load_board($user, $mode)
-    {
-        // phpcs:enable
-        global $conf, $user, $langs;
-
-        $now = dol_now();
-
-        $this->nbtodo = $this->nbtodolate = 0;
-        $clause = " WHERE";
-
-        $sql = "SELECT p.rowid, p.ref, p.datec as datec";
-        $sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
-        if (!$user->rights->societe->client->voir && !$user->socid)
-        {
-            $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
-            $sql .= " WHERE sc.fk_user = ".$user->id;
-            $clause = " AND";
-        }
-        $sql .= $clause." p.entity IN (".getEntity('supplier_proposal').")";
-        if ($mode == 'opened') $sql .= " AND p.fk_statut = 1";
-        if ($mode == 'signed') $sql .= " AND p.fk_statut = 2";
-        if ($user->socid) $sql .= " AND p.fk_soc = ".$user->socid;
-
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
+	 *  @return     string      Label
+	 */
+	public function LibStatut($status, $mode = 1)
+	{
+		// phpcs:enable
+
+		// Init/load array of translation of status
+		if (empty($this->labelStatus) || empty($this->labelStatusShort))
+		{
+			global $langs;
+			$langs->load("supplier_proposal");
+			$this->labelStatus[self::STATUS_DRAFT] = $langs->trans("SupplierProposalStatusDraft");
+			$this->labelStatus[self::STATUS_VALIDATED] = $langs->trans("SupplierProposalStatusValidated");
+			$this->labelStatus[self::STATUS_SIGNED] = $langs->trans("SupplierProposalStatusSigned");
+			$this->labelStatus[self::STATUS_NOTSIGNED] = $langs->trans("SupplierProposalStatusNotSigned");
+			$this->labelStatus[self::STATUS_CLOSE] = $langs->trans("SupplierProposalStatusClosed");
+			$this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans("SupplierProposalStatusDraftShort");
+			$this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans("Opened");
+			$this->labelStatusShort[self::STATUS_SIGNED] = $langs->trans("SupplierProposalStatusSignedShort");
+			$this->labelStatusShort[self::STATUS_NOTSIGNED] = $langs->trans("SupplierProposalStatusNotSignedShort");
+			$this->labelStatusShort[self::STATUS_CLOSE] = $langs->trans("SupplierProposalStatusClosedShort");
+		}
+
+		$statusnew = '';
+		if ($status == self::STATUS_DRAFT) $statusnew = 'status0';
+		elseif ($status == self::STATUS_VALIDATED) $statusnew = 'status1';
+		elseif ($status == self::STATUS_SIGNED) $statusnew = 'status4';
+		elseif ($status == self::STATUS_NOTSIGNED) $statusnew = 'status9';
+		elseif ($status == self::STATUS_CLOSE) $statusnew = 'status6';
+
+		return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusnew, $mode);
+	}
+
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
+	 *
+	 *      @param          User	$user   Object user
+	 *      @param          int		$mode   "opened" for askprice to close, "signed" for proposal to invoice
+	 *      @return         int             <0 if KO, >0 if OK
+	 */
+	public function load_board($user, $mode)
+	{
+		// phpcs:enable
+		global $conf, $user, $langs;
+
+		$now = dol_now();
+
+		$this->nbtodo = $this->nbtodolate = 0;
+		$clause = " WHERE";
+
+		$sql = "SELECT p.rowid, p.ref, p.datec as datec";
+		$sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
+		if (!$user->rights->societe->client->voir && !$user->socid)
+		{
+			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
+			$sql .= " WHERE sc.fk_user = ".$user->id;
+			$clause = " AND";
+		}
+		$sql .= $clause." p.entity IN (".getEntity('supplier_proposal').")";
+		if ($mode == 'opened') $sql .= " AND p.fk_statut = 1";
+		if ($mode == 'signed') $sql .= " AND p.fk_statut = 2";
+		if ($user->socid) $sql .= " AND p.fk_soc = ".$user->socid;
+
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
 			$label = $labelShort = '';
 			$status = '';
-            if ($mode == 'opened') {
-                $delay_warning = $conf->supplier_proposal->cloture->warning_delay;
-                $status = self::STATUS_VALIDATED;
-                $label = $langs->trans("SupplierProposalsToClose");
-                $labelShort = $langs->trans("ToAcceptRefuse");
-            }
-            if ($mode == 'signed') {
-                $delay_warning = $conf->supplier_proposal->facturation->warning_delay;
-                $status = self::STATUS_SIGNED;
-                $label = $langs->trans("SupplierProposalsToProcess"); // May be billed or ordered
+			if ($mode == 'opened') {
+				$delay_warning = $conf->supplier_proposal->cloture->warning_delay;
+				$status = self::STATUS_VALIDATED;
+				$label = $langs->trans("SupplierProposalsToClose");
+				$labelShort = $langs->trans("ToAcceptRefuse");
+			}
+			if ($mode == 'signed') {
+				$delay_warning = $conf->supplier_proposal->facturation->warning_delay;
+				$status = self::STATUS_SIGNED;
+				$label = $langs->trans("SupplierProposalsToProcess"); // May be billed or ordered
 				$labelShort = $langs->trans("ToClose");
-            }
-
-            $response = new WorkboardResponse();
-            $response->warning_delay = $delay_warning / 60 / 60 / 24;
-            $response->label = $label;
-            $response->labelShort = $labelShort;
-            $response->url = DOL_URL_ROOT.'/supplier_proposal/list.php?search_status='.$status;
-            $response->img = img_object('', "propal");
-
-            // This assignment in condition is not a bug. It allows walking the results.
-            while ($obj = $this->db->fetch_object($resql))
-            {
-                $response->nbtodo++;
-                if ($mode == 'opened')
-                {
-                    $datelimit = $this->db->jdate($obj->datefin);
-                    if ($datelimit < ($now - $delay_warning))
-                    {
-                        $response->nbtodolate++;
-                    }
-                }
-                // TODO Definir regle des propales a facturer en retard
-                // if ($mode == 'signed' && ! count($this->FactureListeArray($obj->rowid))) $this->nbtodolate++;
-            }
-            return $response;
-        } else {
-            $this->error = $this->db->lasterror();
-            return -1;
-        }
-    }
-
-
-    /**
-     *  Initialise an instance with random values.
-     *  Used to build previews or test instances.
-     *	id must be 0 if object instance is a specimen.
-     *
-     *  @return	void
-     */
-    public function initAsSpecimen()
-    {
-        global $user, $langs, $conf;
-
-        // Load array of products prodids
-        $num_prods = 0;
-        $prodids = array();
-        $sql = "SELECT rowid";
-        $sql .= " FROM ".MAIN_DB_PREFIX."product";
-        $sql .= " WHERE entity IN (".getEntity('product').")";
-        $sql .= $this->db->plimit(100);
-
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            $num_prods = $this->db->num_rows($resql);
-            $i = 0;
-            while ($i < $num_prods)
-            {
-                $i++;
-                $row = $this->db->fetch_row($resql);
-                $prodids[$i] = $row[0];
-            }
-        }
-
-        // Initialise parametres
-        $this->id = 0;
-        $this->ref = 'SPECIMEN';
-        $this->specimen = 1;
-        $this->socid = 1;
-        $this->date = time();
-        $this->cond_reglement_id   = 1;
-        $this->cond_reglement_code = 'RECEP';
-        $this->mode_reglement_id   = 7;
-        $this->mode_reglement_code = 'CHQ';
-        $this->note_public = 'This is a comment (public)';
-        $this->note_private = 'This is a comment (private)';
-        // Lines
-        $nbp = 5;
-        $xnbp = 0;
-        while ($xnbp < $nbp)
-        {
-            $line = new SupplierProposalLine($this->db);
-            $line->desc = $langs->trans("Description")." ".$xnbp;
-            $line->qty = 1;
-            $line->subprice = 100;
-            $line->tva_tx = 19.6;
-            $line->localtax1_tx = 0;
-            $line->localtax2_tx = 0;
-            if ($xnbp == 2)
-            {
-                $line->total_ht = 50;
-                $line->total_ttc = 59.8;
-                $line->total_tva = 9.8;
-                $line->remise_percent = 50;
-            } else {
-                $line->total_ht = 100;
-                $line->total_ttc = 119.6;
-                $line->total_tva = 19.6;
-                $line->remise_percent = 00;
-            }
-
-            if ($num_prods > 0)
-            {
-                $prodid = mt_rand(1, $num_prods);
-                $line->fk_product = $prodids[$prodid];
-            }
-
-            $this->lines[$xnbp] = $line;
-
-            $this->total_ht       += $line->total_ht;
-            $this->total_tva      += $line->total_tva;
-            $this->total_ttc      += $line->total_ttc;
-
-            $xnbp++;
-        }
-    }
-
-    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
-    /**
-     *      Load indicator this->nb of global stats widget
-     *
-     *      @return     int         <0 if ko, >0 if ok
-     */
-    public function load_state_board()
-    {
-        // phpcs:enable
-        global $conf, $user;
-
-        $this->nb = array();
-        $clause = "WHERE";
-
-        $sql = "SELECT count(p.rowid) as nb";
-        $sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
-        $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
-        if (!$user->rights->societe->client->voir && !$user->socid)
-        {
-            $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
-            $sql .= " WHERE sc.fk_user = ".$user->id;
-            $clause = "AND";
-        }
-        $sql .= " ".$clause." p.entity IN (".getEntity('supplier_proposal').")";
-
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            // This assignment in condition is not a bug. It allows walking the results.
-            while ($obj = $this->db->fetch_object($resql))
-            {
-                $this->nb["supplier_proposals"] = $obj->nb;
-            }
-            $this->db->free($resql);
-            return 1;
-        } else {
-            dol_print_error($this->db);
-            $this->error = $this->db->lasterror();
-            return -1;
-        }
-    }
-
-
-    /**
-     *  Returns the reference to the following non used Proposal used depending on the active numbering module
-     *  defined into SUPPLIER_PROPOSAL_ADDON
-     *
-     *  @param	Societe		$soc  	Object thirdparty
-     *  @return string      		Reference libre pour la propale
-     */
-    public function getNextNumRef($soc)
-    {
-        global $conf, $db, $langs;
-        $langs->load("supplier_proposal");
-
-        if (!empty($conf->global->SUPPLIER_PROPOSAL_ADDON))
-        {
-            $mybool = false;
-
-            $file = $conf->global->SUPPLIER_PROPOSAL_ADDON.".php";
-            $classname = $conf->global->SUPPLIER_PROPOSAL_ADDON;
-
-            // Include file with class
-            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
-            foreach ($dirmodels as $reldir) {
-                $dir = dol_buildpath($reldir."core/modules/supplier_proposal/");
-
-                // Load file with numbering class (if found)
-                $mybool |= @include_once $dir.$file;
-            }
-
-            if (!$mybool)
-            {
-                dol_print_error('', "Failed to include file ".$file);
-                return '';
-            }
-
-            $obj = new $classname();
-            $numref = "";
-            $numref = $obj->getNextValue($soc, $this);
-
-            if ($numref != "")
-            {
-                return $numref;
-            } else {
-                $this->error = $obj->error;
-                return "";
-            }
-        } else {
-            $langs->load("errors");
-            print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("SupplierProposal"));
-            return "";
-        }
-    }
-
-    /**
-     *	Return clicable link of object (with eventually picto)
-     *
-     *	@param      int		$withpicto					Add picto into link
-     *	@param      string	$option						Where point the link ('compta', 'expedition', 'document', ...)
-     *	@param      string	$get_params    				Parametres added to url
-     *  @param	    int   	$notooltip					1=Disable tooltip
-     *  @param      int     $save_lastsearch_value		-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
-     *  @param		int		$addlinktonotes				Add link to show notes
-     *	@return     string          					String with URL
-     */
-    public function getNomUrl($withpicto = 0, $option = '', $get_params = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0)
-    {
-        global $langs, $conf, $user;
-
-        if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
-
-        $url = '';
-        $result = '';
-
-        $label = '<u>'.$langs->trans("SupplierProposal").'</u>';
-        if (!empty($this->ref)) $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
-        if (!empty($this->ref_fourn)) $label .= '<br><b>'.$langs->trans('RefSupplier').':</b> '.$this->ref_fourn;
-        if (!empty($this->total_ht)) $label .= '<br><b>'.$langs->trans('AmountHT').':</b> '.price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
-        if (!empty($this->total_tva)) $label .= '<br><b>'.$langs->trans('VAT').':</b> '.price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
-        if (!empty($this->total_ttc)) $label .= '<br><b>'.$langs->trans('AmountTTC').':</b> '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
-        if (isset($this->status)) {
-           	$label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
-        }
-
-        if ($option == '') {
-            $url = DOL_URL_ROOT.'/supplier_proposal/card.php?id='.$this->id.$get_params;
-        }
-        if ($option == 'document') {
-            $url = DOL_URL_ROOT.'/supplier_proposal/document.php?id='.$this->id.$get_params;
-        }
-
-        if ($option !== 'nolink')
-        {
-            // Add param to save lastsearch_values or not
-            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
-            if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
-            if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
-        }
-
-        $linkclose = '';
-        if (empty($notooltip) && $user->rights->propal->lire)
-        {
-            if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
-            {
-                $label = $langs->trans("ShowSupplierProposal");
-                $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
-            }
-            $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
-            $linkclose .= ' class="classfortooltip"';
-        }
-
-        $linkstart = '<a href="'.$url.'"';
-        $linkstart .= $linkclose.'>';
-        $linkend = '</a>';
-
-        $result .= $linkstart;
-        if ($withpicto) $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
-        if ($withpicto != 2) $result .= $this->ref;
-        $result .= $linkend;
-
-        if ($addlinktonotes)
-        {
-        	$txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
-        	if ($txttoshow)
-        	{
-        		$notetoshow = $langs->trans("ViewPrivateNote").':<br>'.dol_string_nohtmltag($txttoshow, 1);
-        		$result .= ' <span class="note inline-block">';
-        		$result .= '<a href="'.DOL_URL_ROOT.'/supplier_proposal/note.php?id='.$this->id.'" class="classfortooltip" title="'.dol_escape_htmltag($notetoshow).'">';
-        		$result .= img_picto('', 'note');
-        		$result .= '</a>';
-        		//$result.=img_picto($langs->trans("ViewNote"),'object_generic');
-        		//$result.='</a>';
-        		$result .= '</span>';
-        	}
-        }
-
-        return $result;
-    }
-
-    /**
-     * 	Retrieve an array of supplier proposal lines
-     *
-     * 	@return int		>0 if OK, <0 if KO
-     */
-    public function getLinesArray()
-    {
-        // For other object, here we call fetch_lines. But fetch_lines does not exists on supplier proposal
-
-        $sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,';
-        $sql .= ' pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,';
-        $sql .= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code, pt.localtax1_tx, pt.localtax2_tx,';
-        $sql .= ' pt.product_type, pt.rang, pt.fk_parent_line,';
-        $sql .= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid,';
-        $sql .= ' p.description as product_desc, pt.ref_fourn as ref_supplier,';
-        $sql .= ' pt.fk_multicurrency, pt.multicurrency_code, pt.multicurrency_subprice, pt.multicurrency_total_ht, pt.multicurrency_total_tva, pt.multicurrency_total_ttc, pt.fk_unit';
-        $sql .= ' FROM '.MAIN_DB_PREFIX.'supplier_proposaldet as pt';
-        $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pt.fk_product=p.rowid';
-        $sql .= ' WHERE pt.fk_supplier_proposal = '.$this->id;
-        $sql .= ' ORDER BY pt.rang ASC, pt.rowid';
-
-        dol_syslog(get_class($this).'::getLinesArray', LOG_DEBUG);
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            $num = $this->db->num_rows($resql);
-            $i = 0;
-
-            while ($i < $num)
-            {
-                $obj = $this->db->fetch_object($resql);
-
-                $this->lines[$i] = new SupplierProposalLine($this->db);
-                $this->lines[$i]->id = $obj->rowid; // for backward compatibility
-                $this->lines[$i]->rowid				= $obj->rowid;
-                $this->lines[$i]->label 			= $obj->custom_label;
-                $this->lines[$i]->description = $obj->description;
-                $this->lines[$i]->fk_product = $obj->fk_product;
-                $this->lines[$i]->ref = $obj->ref;
-                $this->lines[$i]->product_label = $obj->product_label;
-                $this->lines[$i]->product_desc		= $obj->product_desc;
-                $this->lines[$i]->fk_product_type = $obj->fk_product_type; // deprecated
-                $this->lines[$i]->product_type		= $obj->product_type;
-                $this->lines[$i]->qty = $obj->qty;
-                $this->lines[$i]->subprice = $obj->subprice;
-                $this->lines[$i]->fk_remise_except = $obj->fk_remise_except;
-                $this->lines[$i]->remise_percent = $obj->remise_percent;
-                $this->lines[$i]->tva_tx = $obj->tva_tx;
-                $this->lines[$i]->info_bits			= $obj->info_bits;
-                $this->lines[$i]->total_ht = $obj->total_ht;
-                $this->lines[$i]->total_tva			= $obj->total_tva;
-                $this->lines[$i]->total_ttc			= $obj->total_ttc;
-                $this->lines[$i]->fk_fournprice = $obj->fk_fournprice;
-                $marginInfos = getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->lines[$i]->fk_fournprice, $obj->pa_ht);
-                $this->lines[$i]->pa_ht = $marginInfos[0];
-                $this->lines[$i]->marge_tx = $marginInfos[1];
-                $this->lines[$i]->marque_tx = $marginInfos[2];
-                $this->lines[$i]->fk_parent_line = $obj->fk_parent_line;
-                $this->lines[$i]->special_code = $obj->special_code;
-                $this->lines[$i]->rang = $obj->rang;
-
-                $this->lines[$i]->ref_fourn = $obj->ref_supplier; // deprecated
-                $this->lines[$i]->ref_supplier = $obj->ref_supplier;
-
-                // Multicurrency
-                $this->lines[$i]->fk_multicurrency = $obj->fk_multicurrency;
-                $this->lines[$i]->multicurrency_code = $obj->multicurrency_code;
-                $this->lines[$i]->multicurrency_subprice 	= $obj->multicurrency_subprice;
-                $this->lines[$i]->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
-                $this->lines[$i]->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
-                $this->lines[$i]->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
-                $this->lines[$i]->fk_unit = $obj->fk_unit;
-
-                $i++;
-            }
-            $this->db->free($resql);
-
-            return 1;
-        } else {
-            $this->error = $this->db->error();
-            return -1;
-        }
-    }
-
-    /**
-     *  Create a document onto disk according to template module.
-     *
-     * 	@param	    string		$modele			Force model to use ('' to not force)
-     * 	@param		Translate	$outputlangs	Object langs to use for output
-     *  @param      int			$hidedetails    Hide details of lines
-     *  @param      int			$hidedesc       Hide description
-     *  @param      int			$hideref        Hide ref
-         *  @param   null|array  $moreparams     Array to provide more information
-     * 	@return     int         				0 if KO, 1 if OK
-     */
-    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
-    {
-        global $conf, $langs;
-
-        $langs->load("supplier_proposal");
+			}
+
+			$response = new WorkboardResponse();
+			$response->warning_delay = $delay_warning / 60 / 60 / 24;
+			$response->label = $label;
+			$response->labelShort = $labelShort;
+			$response->url = DOL_URL_ROOT.'/supplier_proposal/list.php?search_status='.$status;
+			$response->img = img_object('', "propal");
+
+			// This assignment in condition is not a bug. It allows walking the results.
+			while ($obj = $this->db->fetch_object($resql))
+			{
+				$response->nbtodo++;
+				if ($mode == 'opened')
+				{
+					$datelimit = $this->db->jdate($obj->datefin);
+					if ($datelimit < ($now - $delay_warning))
+					{
+						$response->nbtodolate++;
+					}
+				}
+				// TODO Definir regle des propales a facturer en retard
+				// if ($mode == 'signed' && ! count($this->FactureListeArray($obj->rowid))) $this->nbtodolate++;
+			}
+			return $response;
+		} else {
+			$this->error = $this->db->lasterror();
+			return -1;
+		}
+	}
+
+
+	/**
+	 *  Initialise an instance with random values.
+	 *  Used to build previews or test instances.
+	 *	id must be 0 if object instance is a specimen.
+	 *
+	 *  @return	void
+	 */
+	public function initAsSpecimen()
+	{
+		global $user, $langs, $conf;
+
+		// Load array of products prodids
+		$num_prods = 0;
+		$prodids = array();
+		$sql = "SELECT rowid";
+		$sql .= " FROM ".MAIN_DB_PREFIX."product";
+		$sql .= " WHERE entity IN (".getEntity('product').")";
+		$sql .= $this->db->plimit(100);
+
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			$num_prods = $this->db->num_rows($resql);
+			$i = 0;
+			while ($i < $num_prods)
+			{
+				$i++;
+				$row = $this->db->fetch_row($resql);
+				$prodids[$i] = $row[0];
+			}
+		}
+
+		// Initialise parametres
+		$this->id = 0;
+		$this->ref = 'SPECIMEN';
+		$this->specimen = 1;
+		$this->socid = 1;
+		$this->date = time();
+		$this->cond_reglement_id   = 1;
+		$this->cond_reglement_code = 'RECEP';
+		$this->mode_reglement_id   = 7;
+		$this->mode_reglement_code = 'CHQ';
+		$this->note_public = 'This is a comment (public)';
+		$this->note_private = 'This is a comment (private)';
+		// Lines
+		$nbp = 5;
+		$xnbp = 0;
+		while ($xnbp < $nbp)
+		{
+			$line = new SupplierProposalLine($this->db);
+			$line->desc = $langs->trans("Description")." ".$xnbp;
+			$line->qty = 1;
+			$line->subprice = 100;
+			$line->tva_tx = 19.6;
+			$line->localtax1_tx = 0;
+			$line->localtax2_tx = 0;
+			if ($xnbp == 2)
+			{
+				$line->total_ht = 50;
+				$line->total_ttc = 59.8;
+				$line->total_tva = 9.8;
+				$line->remise_percent = 50;
+			} else {
+				$line->total_ht = 100;
+				$line->total_ttc = 119.6;
+				$line->total_tva = 19.6;
+				$line->remise_percent = 00;
+			}
+
+			if ($num_prods > 0)
+			{
+				$prodid = mt_rand(1, $num_prods);
+				$line->fk_product = $prodids[$prodid];
+			}
+
+			$this->lines[$xnbp] = $line;
+
+			$this->total_ht       += $line->total_ht;
+			$this->total_tva      += $line->total_tva;
+			$this->total_ttc      += $line->total_ttc;
+
+			$xnbp++;
+		}
+	}
+
+	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+	/**
+	 *      Load indicator this->nb of global stats widget
+	 *
+	 *      @return     int         <0 if ko, >0 if ok
+	 */
+	public function load_state_board()
+	{
+		// phpcs:enable
+		global $conf, $user;
+
+		$this->nb = array();
+		$clause = "WHERE";
+
+		$sql = "SELECT count(p.rowid) as nb";
+		$sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal as p";
+		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
+		if (!$user->rights->societe->client->voir && !$user->socid)
+		{
+			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
+			$sql .= " WHERE sc.fk_user = ".$user->id;
+			$clause = "AND";
+		}
+		$sql .= " ".$clause." p.entity IN (".getEntity('supplier_proposal').")";
+
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			// This assignment in condition is not a bug. It allows walking the results.
+			while ($obj = $this->db->fetch_object($resql))
+			{
+				$this->nb["supplier_proposals"] = $obj->nb;
+			}
+			$this->db->free($resql);
+			return 1;
+		} else {
+			dol_print_error($this->db);
+			$this->error = $this->db->lasterror();
+			return -1;
+		}
+	}
+
+
+	/**
+	 *  Returns the reference to the following non used Proposal used depending on the active numbering module
+	 *  defined into SUPPLIER_PROPOSAL_ADDON
+	 *
+	 *  @param	Societe		$soc  	Object thirdparty
+	 *  @return string      		Reference libre pour la propale
+	 */
+	public function getNextNumRef($soc)
+	{
+		global $conf, $db, $langs;
+		$langs->load("supplier_proposal");
+
+		if (!empty($conf->global->SUPPLIER_PROPOSAL_ADDON))
+		{
+			$mybool = false;
+
+			$file = $conf->global->SUPPLIER_PROPOSAL_ADDON.".php";
+			$classname = $conf->global->SUPPLIER_PROPOSAL_ADDON;
+
+			// Include file with class
+			$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
+			foreach ($dirmodels as $reldir) {
+				$dir = dol_buildpath($reldir."core/modules/supplier_proposal/");
+
+				// Load file with numbering class (if found)
+				$mybool |= @include_once $dir.$file;
+			}
+
+			if (!$mybool)
+			{
+				dol_print_error('', "Failed to include file ".$file);
+				return '';
+			}
+
+			$obj = new $classname();
+			$numref = "";
+			$numref = $obj->getNextValue($soc, $this);
+
+			if ($numref != "")
+			{
+				return $numref;
+			} else {
+				$this->error = $obj->error;
+				return "";
+			}
+		} else {
+			$langs->load("errors");
+			print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("SupplierProposal"));
+			return "";
+		}
+	}
+
+	/**
+	 *	Return clicable link of object (with eventually picto)
+	 *
+	 *	@param      int		$withpicto					Add picto into link
+	 *	@param      string	$option						Where point the link ('compta', 'expedition', 'document', ...)
+	 *	@param      string	$get_params    				Parametres added to url
+	 *  @param	    int   	$notooltip					1=Disable tooltip
+	 *  @param      int     $save_lastsearch_value		-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
+	 *  @param		int		$addlinktonotes				Add link to show notes
+	 *	@return     string          					String with URL
+	 */
+	public function getNomUrl($withpicto = 0, $option = '', $get_params = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0)
+	{
+		global $langs, $conf, $user;
+
+		if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
+
+		$url = '';
+		$result = '';
+
+		$label = '<u>'.$langs->trans("SupplierProposal").'</u>';
+		if (!empty($this->ref)) $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
+		if (!empty($this->ref_fourn)) $label .= '<br><b>'.$langs->trans('RefSupplier').':</b> '.$this->ref_fourn;
+		if (!empty($this->total_ht)) $label .= '<br><b>'.$langs->trans('AmountHT').':</b> '.price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
+		if (!empty($this->total_tva)) $label .= '<br><b>'.$langs->trans('VAT').':</b> '.price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
+		if (!empty($this->total_ttc)) $label .= '<br><b>'.$langs->trans('AmountTTC').':</b> '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
+		if (isset($this->status)) {
+		   	$label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
+		}
+
+		if ($option == '') {
+			$url = DOL_URL_ROOT.'/supplier_proposal/card.php?id='.$this->id.$get_params;
+		}
+		if ($option == 'document') {
+			$url = DOL_URL_ROOT.'/supplier_proposal/document.php?id='.$this->id.$get_params;
+		}
+
+		if ($option !== 'nolink')
+		{
+			// Add param to save lastsearch_values or not
+			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
+			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
+			if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
+		}
+
+		$linkclose = '';
+		if (empty($notooltip) && $user->rights->propal->lire)
+		{
+			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
+			{
+				$label = $langs->trans("ShowSupplierProposal");
+				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
+			}
+			$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
+			$linkclose .= ' class="classfortooltip"';
+		}
+
+		$linkstart = '<a href="'.$url.'"';
+		$linkstart .= $linkclose.'>';
+		$linkend = '</a>';
+
+		$result .= $linkstart;
+		if ($withpicto) $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
+		if ($withpicto != 2) $result .= $this->ref;
+		$result .= $linkend;
+
+		if ($addlinktonotes)
+		{
+			$txttoshow = ($user->socid > 0 ? $this->note_public : $this->note_private);
+			if ($txttoshow)
+			{
+				$notetoshow = $langs->trans("ViewPrivateNote").':<br>'.dol_string_nohtmltag($txttoshow, 1);
+				$result .= ' <span class="note inline-block">';
+				$result .= '<a href="'.DOL_URL_ROOT.'/supplier_proposal/note.php?id='.$this->id.'" class="classfortooltip" title="'.dol_escape_htmltag($notetoshow).'">';
+				$result .= img_picto('', 'note');
+				$result .= '</a>';
+				//$result.=img_picto($langs->trans("ViewNote"),'object_generic');
+				//$result.='</a>';
+				$result .= '</span>';
+			}
+		}
+
+		return $result;
+	}
+
+	/**
+	 * 	Retrieve an array of supplier proposal lines
+	 *
+	 * 	@return int		>0 if OK, <0 if KO
+	 */
+	public function getLinesArray()
+	{
+		// For other object, here we call fetch_lines. But fetch_lines does not exists on supplier proposal
+
+		$sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,';
+		$sql .= ' pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,';
+		$sql .= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code, pt.localtax1_tx, pt.localtax2_tx,';
+		$sql .= ' pt.product_type, pt.rang, pt.fk_parent_line,';
+		$sql .= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid,';
+		$sql .= ' p.description as product_desc, pt.ref_fourn as ref_supplier,';
+		$sql .= ' pt.fk_multicurrency, pt.multicurrency_code, pt.multicurrency_subprice, pt.multicurrency_total_ht, pt.multicurrency_total_tva, pt.multicurrency_total_ttc, pt.fk_unit';
+		$sql .= ' FROM '.MAIN_DB_PREFIX.'supplier_proposaldet as pt';
+		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON pt.fk_product=p.rowid';
+		$sql .= ' WHERE pt.fk_supplier_proposal = '.$this->id;
+		$sql .= ' ORDER BY pt.rang ASC, pt.rowid';
+
+		dol_syslog(get_class($this).'::getLinesArray', LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			$num = $this->db->num_rows($resql);
+			$i = 0;
+
+			while ($i < $num)
+			{
+				$obj = $this->db->fetch_object($resql);
+
+				$this->lines[$i] = new SupplierProposalLine($this->db);
+				$this->lines[$i]->id = $obj->rowid; // for backward compatibility
+				$this->lines[$i]->rowid				= $obj->rowid;
+				$this->lines[$i]->label 			= $obj->custom_label;
+				$this->lines[$i]->description = $obj->description;
+				$this->lines[$i]->fk_product = $obj->fk_product;
+				$this->lines[$i]->ref = $obj->ref;
+				$this->lines[$i]->product_label = $obj->product_label;
+				$this->lines[$i]->product_desc		= $obj->product_desc;
+				$this->lines[$i]->fk_product_type = $obj->fk_product_type; // deprecated
+				$this->lines[$i]->product_type		= $obj->product_type;
+				$this->lines[$i]->qty = $obj->qty;
+				$this->lines[$i]->subprice = $obj->subprice;
+				$this->lines[$i]->fk_remise_except = $obj->fk_remise_except;
+				$this->lines[$i]->remise_percent = $obj->remise_percent;
+				$this->lines[$i]->tva_tx = $obj->tva_tx;
+				$this->lines[$i]->info_bits			= $obj->info_bits;
+				$this->lines[$i]->total_ht = $obj->total_ht;
+				$this->lines[$i]->total_tva			= $obj->total_tva;
+				$this->lines[$i]->total_ttc			= $obj->total_ttc;
+				$this->lines[$i]->fk_fournprice = $obj->fk_fournprice;
+				$marginInfos = getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->lines[$i]->fk_fournprice, $obj->pa_ht);
+				$this->lines[$i]->pa_ht = $marginInfos[0];
+				$this->lines[$i]->marge_tx = $marginInfos[1];
+				$this->lines[$i]->marque_tx = $marginInfos[2];
+				$this->lines[$i]->fk_parent_line = $obj->fk_parent_line;
+				$this->lines[$i]->special_code = $obj->special_code;
+				$this->lines[$i]->rang = $obj->rang;
+
+				$this->lines[$i]->ref_fourn = $obj->ref_supplier; // deprecated
+				$this->lines[$i]->ref_supplier = $obj->ref_supplier;
+
+				// Multicurrency
+				$this->lines[$i]->fk_multicurrency = $obj->fk_multicurrency;
+				$this->lines[$i]->multicurrency_code = $obj->multicurrency_code;
+				$this->lines[$i]->multicurrency_subprice 	= $obj->multicurrency_subprice;
+				$this->lines[$i]->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
+				$this->lines[$i]->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
+				$this->lines[$i]->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
+				$this->lines[$i]->fk_unit = $obj->fk_unit;
+
+				$i++;
+			}
+			$this->db->free($resql);
+
+			return 1;
+		} else {
+			$this->error = $this->db->error();
+			return -1;
+		}
+	}
+
+	/**
+	 *  Create a document onto disk according to template module.
+	 *
+	 * 	@param	    string		$modele			Force model to use ('' to not force)
+	 * 	@param		Translate	$outputlangs	Object langs to use for output
+	 *  @param      int			$hidedetails    Hide details of lines
+	 *  @param      int			$hidedesc       Hide description
+	 *  @param      int			$hideref        Hide ref
+	 *  @param   null|array  $moreparams     Array to provide more information
+	 * 	@return     int         				0 if KO, 1 if OK
+	 */
+	public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
+	{
+		global $conf, $langs;
+
+		$langs->load("supplier_proposal");
 		$outputlangs->load("products");
 
-        if (!dol_strlen($modele)) {
-            $modele = 'aurore';
-
-            if ($this->modelpdf) {
-                $modele = $this->modelpdf;
-            } elseif (!empty($conf->global->SUPPLIER_PROPOSAL_ADDON_PDF)) {
-                $modele = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF;
-            }
-        }
-
-        $modelpath = "core/modules/supplier_proposal/doc/";
-
-        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
-    }
-
-
-    /**
-     * Function used to replace a thirdparty id with another one.
-     *
-     * @param DoliDB $db Database handler
-     * @param int $origin_id Old thirdparty id
-     * @param int $dest_id New thirdparty id
-     * @return bool
-     */
-    public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
-    {
-        $tables = array(
-            'supplier_proposal'
-        );
-
-        return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
-    }
+		if (!dol_strlen($modele)) {
+			$modele = 'aurore';
+
+			if ($this->modelpdf) {
+				$modele = $this->modelpdf;
+			} elseif (!empty($conf->global->SUPPLIER_PROPOSAL_ADDON_PDF)) {
+				$modele = $conf->global->SUPPLIER_PROPOSAL_ADDON_PDF;
+			}
+		}
+
+		$modelpath = "core/modules/supplier_proposal/doc/";
+
+		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
+	}
+
+
+	/**
+	 * Function used to replace a thirdparty id with another one.
+	 *
+	 * @param DoliDB $db Database handler
+	 * @param int $origin_id Old thirdparty id
+	 * @param int $dest_id New thirdparty id
+	 * @return bool
+	 */
+	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
+	{
+		$tables = array(
+			'supplier_proposal'
+		);
+
+		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
+	}
 }
 
 

+ 63 - 63
htdocs/takepos/invoice.php

@@ -369,38 +369,38 @@ if ($action == "freezone") {
 		$tva_tx = get_default_tva($mysoc, $customer);
 	}
 
-    // Local Taxes
-    $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
-    $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
+	// Local Taxes
+	$localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
+	$localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
 
-    $invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', 'TTC', $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0);
-    $invoice->fetch($placeid);
+	$invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', 'TTC', $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0);
+	$invoice->fetch($placeid);
 }
 
 if ($action == "addnote") {
-    foreach ($invoice->lines as $line)
-    {
-        if ($line->id == $number)
+	foreach ($invoice->lines as $line)
+	{
+		if ($line->id == $number)
 		{
 			$line->array_options['order_notes'] = $desc;
 			$result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
-        }
-    }
-    $invoice->fetch($placeid);
+		}
+	}
+	$invoice->fetch($placeid);
 }
 
 if ($action == "deleteline") {
-    if ($idline > 0 and $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
-        $invoice->deleteline($idline);
-        $invoice->fetch($placeid);
-    } elseif ($placeid > 0) {             // If invoice exists but no line selected, proceed to delete last line.
-        $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture='".$placeid."' order by rowid DESC";
-        $resql = $db->query($sql);
-        $row = $db->fetch_array($resql);
-        $deletelineid = $row[0];
-        $invoice->deleteline($deletelineid);
-        $invoice->fetch($placeid);
-    }
+	if ($idline > 0 and $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
+		$invoice->deleteline($idline);
+		$invoice->fetch($placeid);
+	} elseif ($placeid > 0) {             // If invoice exists but no line selected, proceed to delete last line.
+		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture='".$placeid."' order by rowid DESC";
+		$resql = $db->query($sql);
+		$row = $db->fetch_array($resql);
+		$deletelineid = $row[0];
+		$invoice->deleteline($deletelineid);
+		$invoice->fetch($placeid);
+	}
 	if (count($invoice->lines) == 0) $invoice->delete($user);
 }
 
@@ -830,7 +830,7 @@ $( document ).ready(function() {
 				$s .= '<br>'.$langs->trans("SubscriptionNotReceived");
 				if ($adh->statut > 0) $s .= " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
 			}
-      		if (empty($adh->statut)) { $s .= "</s>"; }
+	  		if (empty($adh->statut)) { $s .= "</s>"; }
 		} else {
 			$s .= '<br>'.$langs->trans("ThirdpartyNotLinkedToMember");
 		}
@@ -1011,47 +1011,47 @@ if ($placeid > 0)
 				$htmlsupplements[$line->fk_parent_line] .= '</tr>'."\n";
 				continue;
 			}
-            $htmlforlines = '';
-
-            $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
-            if ($line->special_code == "4") {
-                $htmlforlines .= ' order';
-            }
-            $htmlforlines .= '" id="'.$line->id.'">';
-            $htmlforlines .= '<td class="left">';
+			$htmlforlines = '';
+
+			$htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
+			if ($line->special_code == "4") {
+				$htmlforlines .= ' order';
+			}
+			$htmlforlines .= '" id="'.$line->id.'">';
+			$htmlforlines .= '<td class="left">';
 			if ($_SESSION["basiclayout"] == 1) $htmlforlines .= '<span class="phoneqty">'.$line->qty."</span> x ";
-            if (isset($line->product_type))
-            {
-                if (empty($line->product_type)) $htmlforlines .= img_object('', 'product').' ';
-                else $htmlforlines .= img_object('', 'service').' ';
-            }
-            if (empty($conf->global->TAKEPOS_SHOW_N_FIRST_LINES)) {
-            	$tooltiptext = '';
-            	if ($line->product_ref) {
-            		$tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
-            		$tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
-	            	if ($line->product_label != $line->desc) {
-	            		if ($line->desc) $tooltiptext .= '<br>';
-	    	        	$tooltiptext .= $line->desc;
-	            	}
-            	}
-            	$htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
-            } else {
-            	if ($line->product_label) $htmlforlines .= $line->product_label;
-            	if ($line->product_label != $line->desc)
-	            {
-	            	if ($line->product_label && $line->desc) $htmlforlines .= '<br>';
-	            	$firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
-	                if ($firstline != $line->desc)
-	                {
-	                    $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
-	                } else {
-	                    $htmlforlines .= $line->desc;
-	                }
-	            }
-            }
-            if (!empty($line->array_options['options_order_notes'])) $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
-            if ($_SESSION["basiclayout"] == 1) $htmlforlines .= '</td><td class="right phonetable"><button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty - 1).');" class="publicphonebutton2 phonered">-</button>&nbsp;&nbsp;<button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty + 1).');" class="publicphonebutton2 phonegreen">+</button>';
+			if (isset($line->product_type))
+			{
+				if (empty($line->product_type)) $htmlforlines .= img_object('', 'product').' ';
+				else $htmlforlines .= img_object('', 'service').' ';
+			}
+			if (empty($conf->global->TAKEPOS_SHOW_N_FIRST_LINES)) {
+				$tooltiptext = '';
+				if ($line->product_ref) {
+					$tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
+					$tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
+					if ($line->product_label != $line->desc) {
+						if ($line->desc) $tooltiptext .= '<br>';
+						$tooltiptext .= $line->desc;
+					}
+				}
+				$htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
+			} else {
+				if ($line->product_label) $htmlforlines .= $line->product_label;
+				if ($line->product_label != $line->desc)
+				{
+					if ($line->product_label && $line->desc) $htmlforlines .= '<br>';
+					$firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
+					if ($firstline != $line->desc)
+					{
+						$htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
+					} else {
+						$htmlforlines .= $line->desc;
+					}
+				}
+			}
+			if (!empty($line->array_options['options_order_notes'])) $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
+			if ($_SESSION["basiclayout"] == 1) $htmlforlines .= '</td><td class="right phonetable"><button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty - 1).');" class="publicphonebutton2 phonered">-</button>&nbsp;&nbsp;<button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty + 1).');" class="publicphonebutton2 phonegreen">+</button>';
 			if ($_SESSION["basiclayout"] != 1)
 			{
 				$moreinfo = '';

+ 43 - 43
htdocs/ticket/card.php

@@ -138,7 +138,7 @@ if (empty($reshook)) {
 
 	if ($cancel) {
 		if (!empty($backtopage)) {
-			header("Location: " . $backtopage);
+			header("Location: ".$backtopage);
 			exit;
 		}
 
@@ -254,10 +254,10 @@ if (empty($reshook)) {
 				if (!empty($backtopage)) {
 					$url = $backtopage;
 				} else {
-					$url = 'card.php?track_id=' . $object->track_id;
+					$url = 'card.php?track_id='.$object->track_id;
 				}
 
-				header("Location: " . $url);
+				header("Location: ".$url);
 				exit;
 			} else {
 				$db->rollback();
@@ -325,7 +325,7 @@ if (empty($reshook)) {
 		if ($object->markAsRead($user) > 0) {
 			setEventMessages($langs->trans('TicketMarkedAsRead'), null, 'mesgs');
 
-			header("Location: card.php?track_id=" . $object->track_id . "&action=view");
+			header("Location: card.php?track_id=".$object->track_id."&action=view");
 			exit;
 		} else {
 			setEventMessages($object->error, $object->errors, 'errors');
@@ -376,7 +376,7 @@ if (empty($reshook)) {
 
 			setEventMessages($langs->trans('TicketAssigned'), null, 'mesgs');
 
-			header("Location: card.php?track_id=" . $object->track_id . "&action=view");
+			header("Location: card.php?track_id=".$object->track_id."&action=view");
 			exit;
 		} else {
 			array_push($object->errors, $object->error);
@@ -392,10 +392,10 @@ if (empty($reshook)) {
 			if (!empty($backtopage)) {
 				$url = $backtopage;
 			} else {
-				$url = 'card.php?action=view&track_id=' . $object->track_id;
+				$url = 'card.php?action=view&track_id='.$object->track_id;
 			}
 
-			header("Location: " . $url);
+			header("Location: ".$url);
 			exit;
 		} else {
 			setEventMessages($object->error, null, 'errors');
@@ -409,8 +409,8 @@ if (empty($reshook)) {
 		if ($object->close($user)) {
 			setEventMessages($langs->trans('TicketMarkedAsClosed'), null, 'mesgs');
 
-			$url = 'card.php?action=view&track_id=' . GETPOST('track_id', 'alpha');
-			header("Location: " . $url);
+			$url = 'card.php?action=view&track_id='.GETPOST('track_id', 'alpha');
+			header("Location: ".$url);
 		} else {
 			$action = '';
 			setEventMessages($object->error, $object->errors, 'errors');
@@ -425,10 +425,10 @@ if (empty($reshook)) {
 			// Log action in ticket logs table
 			$log_action = $langs->trans('TicketLogClosedBy', $_SESSION['email_customer']);
 
-			setEventMessages('<div class="confirm">' . $langs->trans('TicketMarkedAsClosed') . '</div>', null, 'mesgs');
+			setEventMessages('<div class="confirm">'.$langs->trans('TicketMarkedAsClosed').'</div>', null, 'mesgs');
 
-			$url = 'card.php?action=view_ticket&track_id=' . GETPOST('track_id', 'alpha');
-			header("Location: " . $url);
+			$url = 'card.php?action=view_ticket&track_id='.GETPOST('track_id', 'alpha');
+			header("Location: ".$url);
 		} else {
 			setEventMessages($object->error, $object->errors, 'errors');
 			$action = '';
@@ -438,12 +438,12 @@ if (empty($reshook)) {
 	if ($action == 'confirm_delete_ticket' && GETPOST('confirm', 'alpha') == "yes" && $user->rights->ticket->delete) {
 		if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) {
 			if ($object->delete($user) > 0) {
-				setEventMessages('<div class="confirm">' . $langs->trans('TicketDeletedSuccess') . '</div>', null, 'mesgs');
-				Header("Location: " . DOL_URL_ROOT . "/ticket/list.php");
+				setEventMessages('<div class="confirm">'.$langs->trans('TicketDeletedSuccess').'</div>', null, 'mesgs');
+				Header("Location: ".DOL_URL_ROOT."/ticket/list.php");
 				exit;
 			} else {
 				$langs->load("errors");
-				$mesg = '<div class="error">' . $langs->trans($object->error) . '</div>';
+				$mesg = '<div class="error">'.$langs->trans($object->error).'</div>';
 				$action = '';
 			}
 		}
@@ -453,8 +453,8 @@ if (empty($reshook)) {
 	if ($action == 'set_thirdparty' && $user->rights->societe->creer) {
 		if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) {
 			$result = $object->setCustomer(GETPOST('editcustomer', 'int'));
-			$url = 'card.php?action=view&track_id=' . GETPOST('track_id', 'alpha');
-			header("Location: " . $url);
+			$url = 'card.php?action=view&track_id='.GETPOST('track_id', 'alpha');
+			header("Location: ".$url);
 			exit();
 		}
 	}
@@ -463,8 +463,8 @@ if (empty($reshook)) {
 		if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) {
 			$result = $object->setProgression(GETPOST('progress', 'alpha'));
 
-			$url = 'card.php?action=view&track_id=' . $object->track_id;
-			header("Location: " . $url);
+			$url = 'card.php?action=view&track_id='.$object->track_id;
+			header("Location: ".$url);
 			exit();
 		}
 	}
@@ -476,12 +476,12 @@ if (empty($reshook)) {
 			}
 
 			if ($action == 'setsubject' && empty($object->subject)) {
-				$mesg .= ($mesg ? '<br>' : '') . $langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject"));
+				$mesg .= ($mesg ? '<br>' : '').$langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject"));
 			}
 
 			if (!$mesg) {
 				if ($object->update($user) >= 0) {
-					header("Location: " . $_SERVER['PHP_SELF'] . "?track_id=" . $object->track_id);
+					header("Location: ".$_SERVER['PHP_SELF']."?track_id=".$object->track_id);
 					exit;
 				}
 				$mesg = $object->error;
@@ -498,8 +498,8 @@ if (empty($reshook)) {
 					// Log action in ticket logs table
 					$log_action = $langs->trans('TicketLogReopen');
 
-					$url = 'card.php?action=view&track_id=' . $object->track_id;
-					header("Location: " . $url);
+					$url = 'card.php?action=view&track_id='.$object->track_id;
+					header("Location: ".$url);
 					exit();
 				}
 			}
@@ -508,16 +508,16 @@ if (empty($reshook)) {
 	elseif ($action == 'classin' && $user->rights->ticket->write) {
 		if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) {
 			$object->setProject(GETPOST('projectid', 'int'));
-			$url = 'card.php?action=view&track_id=' . $object->track_id;
-			header("Location: " . $url);
+			$url = 'card.php?action=view&track_id='.$object->track_id;
+			header("Location: ".$url);
 			exit();
 		}
 	} // Categorisation dans contrat
 	elseif ($action == 'setcontract' && $user->rights->ticket->write) {
 		if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) {
 			$object->setContract(GETPOST('contractid', 'int'));
-			$url = 'card.php?action=view&track_id=' . $object->track_id;
-			header("Location: " . $url);
+			$url = 'card.php?action=view&track_id='.$object->track_id;
+			header("Location: ".$url);
 			exit();
 		}
 	} elseif ($action == "set_message" && $user->rights->ticket->manage) {
@@ -530,7 +530,7 @@ if (empty($reshook)) {
 			$object->message = $fieldtomodify;
 			$ret = $object->update($user);
 			if ($ret > 0) {
-				$log_action = $langs->trans('TicketInitialMessageModified') . " \n";
+				$log_action = $langs->trans('TicketInitialMessageModified')." \n";
 				// include the Diff class
 				dol_include_once('/ticket/class/utils_diff.class.php');
 				// output the result of comparing two files as plain text
@@ -551,8 +551,8 @@ if (empty($reshook)) {
 				// Log action in ticket logs table
 				$log_action = $langs->trans('TicketLogStatusChanged', $langs->transnoentities($object->statuts_short[$old_status]), $langs->transnoentities($object->statuts_short[$new_status]));
 
-				$url = 'card.php?action=view&track_id=' . $object->track_id;
-				header("Location: " . $url);
+				$url = 'card.php?action=view&track_id='.$object->track_id;
+				header("Location: ".$url);
 				exit();
 			}
 		}
@@ -597,19 +597,19 @@ if (empty($reshook)) {
 
 
 	$permissiondellink = $user->rights->ticket->write;
-	include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be include, not include_once
+	include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
 
 	// Actions to build doc
 	$upload_dir = $conf->ticket->dir_output;
 	$permissiontoadd = $user->rights->ticket->write;
-	include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
+	include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
 
 	// Actions to send emails
 	$triggersendname = 'TICKET_SENTBYMAIL';
 	$paramname = 'id';
 	$autocopy = 'MAIN_MAIL_AUTOCOPY_TICKET_TO'; // used to know the automatic BCC to add
-	$trackid = 'tic' . $object->id;
-	include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
+	$trackid = 'tic'.$object->id;
+	include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
 
 	// Set $action to correct value for the case we used presend action to add a message
 	if (GETPOSTISSET('actionbis') && $action == 'presend') $action = 'presend_addmessage';
@@ -1027,15 +1027,15 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd
 		} else {
 			// Type
 			print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td>';
-			print $langs->getLabelFromKey($db, 'TicketTypeShort' . $object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
+			print $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
 			print '</td></tr>';
 			// Group
 			print '<tr><td>'.$langs->trans("TicketCategory").'</td><td>';
-			print $langs->getLabelFromKey($db, 'TicketCategoryShort' . $object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
+			print $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
 			print '</td></tr>';
 			// Severity
 			print '<tr><td>'.$langs->trans("TicketSeverity").'</td><td>';
-			print $langs->getLabelFromKey($db, 'TicketSeverityShort' . $object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
+			print $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
 			print '</td></tr>';
 		}
 		print '</table>'; // End table actions
@@ -1299,7 +1299,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd
 		}
 
 		// Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab)
-		if (! empty($conf->global->TICKET_SHOW_MESSAGES_ON_CARD)) {
+		if (!empty($conf->global->TICKET_SHOW_MESSAGES_ON_CARD)) {
 			$param = '&id='.$object->id;
 			if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.$contextpage;
 			if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.$limit;
@@ -1308,17 +1308,17 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd
 
 			$morehtmlright = '';
 
-			$messagingUrl = DOL_URL_ROOT . '/ticket/agenda.php?track_id=' . $object->track_id;
+			$messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id;
 			$morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fal fa-list-alt imgforviewmode', $messagingUrl, '', 1);
 
 			// Show link to add a message (if read and not closed)
 			$btnstatus = $object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
-			$url = 'card.php?track_id=' . $object->track_id . '&action=presend_addmessage&mode=init';
+			$url = 'card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init';
 			$morehtmlright .= dolGetButtonTitle($langs->trans('TicketAddMessage'), '', 'fal fa-comment-dots', $url, 'add-new-ticket-title-button', $btnstatus);
 
 			// Show link to add event (if read and not closed)
-			$btnstatus = $object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";;
-			$url = dol_buildpath('/comm/action/card.php', 1) . '?action=create&datep=' . date('YmdHi') . '&origin=ticket&originid=' . $object->id . '&projectid=' . $object->fk_project . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?track_id=' . $object->track_id);
+			$btnstatus = $object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message"; ;
+			$url = dol_buildpath('/comm/action/card.php', 1).'?action=create&datep='.date('YmdHi').'&origin=ticket&originid='.$object->id.'&projectid='.$object->fk_project.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?track_id='.$object->track_id);
 			$morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fal fa-plus-circle', $url, 'add-new-ticket-even-button', $btnstatus);
 
 			print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1);
@@ -1352,7 +1352,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd
 				$morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-list-alt imgforviewmode', DOL_URL_ROOT.'/ticket/agenda.php?id='.$object->id);
 
 				// List of actions on element
-				include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
+				include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
 				$formactions = new FormActions($db);
 				$somethingshown = $formactions->showactions($object, 'ticket', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
 

+ 23 - 23
htdocs/ticket/class/ticket.class.php

@@ -1701,7 +1701,7 @@ class Ticket extends CommonObject
 				$error = 0;
 
 				// Valid and close fichinter linked
-				if (!empty($conf->ficheinter->enabled) && ! empty($conf->global->WORKFLOW_TICKET_CLOSE_INTERVENTION)) {
+				if (!empty($conf->ficheinter->enabled) && !empty($conf->global->WORKFLOW_TICKET_CLOSE_INTERVENTION)) {
 					dol_syslog("We have closed the ticket, so we close all linked interventions");
 					$this->fetchObjectLinked($this->id, $this->element, null, 'fichinter');
 					if ($this->linkedObjectsIds)
@@ -2549,23 +2549,23 @@ class Ticket extends CommonObject
 							// Customer company infos
 							$message .= '<br><br>';
 							$message .= "==============================================";
-							$message .= !empty($object->thirdparty->name) ? '<br>' . $langs->trans('Thirdparty') . " : " . $object->thirdparty->name : '';
-							$message .= !empty($object->thirdparty->town) ? '<br>' . $langs->trans('Town') . " : " . $object->thirdparty->town : '';
-							$message .= !empty($object->thirdparty->phone) ? '<br>' . $langs->trans('Phone') . " : " . $object->thirdparty->phone : '';
+							$message .= !empty($object->thirdparty->name) ? '<br>'.$langs->trans('Thirdparty')." : ".$object->thirdparty->name : '';
+							$message .= !empty($object->thirdparty->town) ? '<br>'.$langs->trans('Town')." : ".$object->thirdparty->town : '';
+							$message .= !empty($object->thirdparty->phone) ? '<br>'.$langs->trans('Phone')." : ".$object->thirdparty->phone : '';
 
 							// Email send to
 							$message .= '<br><br>';
 							if (!empty($assigned_user_dont_have_email)) {
-								$message .= '<br>' . $langs->trans('NoEMail') . ' : ' . $assigned_user_dont_have_email;
+								$message .= '<br>'.$langs->trans('NoEMail').' : '.$assigned_user_dont_have_email;
 							}
 							foreach ($sendto as $val) {
-								$message .= '<br>' . $langs->trans('TicketNotificationRecipient') . ' : ' . $val;
+								$message .= '<br>'.$langs->trans('TicketNotificationRecipient').' : '.$val;
 							}
 
 							// URL ticket
-							$url_internal_ticket = dol_buildpath('/ticket/card.php', 2) . '?track_id=' . $object->track_id;
+							$url_internal_ticket = dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id;
 							$message .= '<br><br>';
-							$message .= $langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal') . ' : <a href="' . $url_internal_ticket . '">' . $object->track_id . '</a>';
+							$message .= $langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal').' : <a href="'.$url_internal_ticket.'">'.$object->track_id.'</a>';
 
 							$this->sendTicketMessageByEmail($subject, $message, '', $sendto, $listofpaths, $listofmimes, $listofnames);
 						}
@@ -2602,9 +2602,9 @@ class Ticket extends CommonObject
 							//  Coordonnées client
 							$message .= '<br><br>';
 							$message .= "==============================================<br>";
-							$message .= !empty($object->thirdparty->name) ? $langs->trans('Thirdparty') . " : " . $object->thirdparty->name : '';
-							$message .= !empty($object->thirdparty->town) ? '<br>' . $langs->trans('Town') . " : " . $object->thirdparty->town : '';
-							$message .= !empty($object->thirdparty->phone) ? '<br>' . $langs->trans('Phone') . " : " . $object->thirdparty->phone : '';
+							$message .= !empty($object->thirdparty->name) ? $langs->trans('Thirdparty')." : ".$object->thirdparty->name : '';
+							$message .= !empty($object->thirdparty->town) ? '<br>'.$langs->trans('Town')." : ".$object->thirdparty->town : '';
+							$message .= !empty($object->thirdparty->phone) ? '<br>'.$langs->trans('Phone')." : ".$object->thirdparty->phone : '';
 
 							// Build array to display recipient list
 							foreach ($internal_contacts as $key => $info_sendto) {
@@ -2614,19 +2614,19 @@ class Ticket extends CommonObject
 								}
 
 								if ($info_sendto['email'] != '') {
-									if (!empty($info_sendto['email'])) $sendto[] = trim($info_sendto['firstname'] . " " . $info_sendto['lastname']) . " <" . $info_sendto['email'] . ">";
+									if (!empty($info_sendto['email'])) $sendto[] = trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">";
 
 									//Contact type
-									$recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1') . ' (' . strtolower($info_sendto['libelle']) . ')';
-									$message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient') . ' : ' . $recipient . '<br>' : '');
+									$recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1').' ('.strtolower($info_sendto['libelle']).')';
+									$message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient').' : '.$recipient.'<br>' : '');
 								}
 							}
 							$message .= '<br>';
 							// URL ticket
-							$url_internal_ticket = dol_buildpath('/ticket/card.php', 2) . '?track_id=' . $object->track_id;
+							$url_internal_ticket = dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id;
 
 							// altairis: make html link on url
-							$message .= '<br>' . $langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal') . ' : <a href="' . $url_internal_ticket . '">' . $object->track_id . '</a><br>';
+							$message .= '<br>'.$langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal').' : <a href="'.$url_internal_ticket.'">'.$object->track_id.'</a><br>';
 
 							// Add global email address recipient
 							if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !in_array($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)) {
@@ -2688,23 +2688,23 @@ class Ticket extends CommonObject
 									}
 
 									if ($info_sendto['email'] != '' && $info_sendto['email'] != $object->origin_email) {
-										if (!empty($info_sendto['email'])) $sendto[] = trim($info_sendto['firstname'] . " " . $info_sendto['lastname']) . " <" . $info_sendto['email'] . ">";
+										if (!empty($info_sendto['email'])) $sendto[] = trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">";
 
-										$recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1') . ' (' . strtolower($info_sendto['libelle']) . ')';
-										$message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient') . ' : ' . $recipient . '<br>' : '');
+										$recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1').' ('.strtolower($info_sendto['libelle']).')';
+										$message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient').' : '.$recipient.'<br>' : '');
 									}
 								}
 
 								// If public interface is not enable, use link to internal page into mail
 								$url_public_ticket = (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE) ?
-										(!empty($conf->global->TICKET_URL_PUBLIC_INTERFACE) ? $conf->global->TICKET_URL_PUBLIC_INTERFACE . '/view.php' : dol_buildpath('/public/ticket/view.php', 2)) : dol_buildpath('/ticket/card.php', 2)) . '?track_id=' . $object->track_id;
-								$message .= '<br>' . $langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer') . ' : <a href="' . $url_public_ticket . '">' . $object->track_id . '</a><br>';
+										(!empty($conf->global->TICKET_URL_PUBLIC_INTERFACE) ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)) : dol_buildpath('/ticket/card.php', 2)).'?track_id='.$object->track_id;
+								$message .= '<br>'.$langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer').' : <a href="'.$url_public_ticket.'">'.$object->track_id.'</a><br>';
 
 								// Build final message
-								$message = $message_intro . '<br><br>' . $message;
+								$message = $message_intro.'<br><br>'.$message;
 
 								// Add signature
-								$message .= '<br>' . $message_signature;
+								$message .= '<br>'.$message_signature;
 
 								if (!empty($object->origin_email)) {
 									$sendto[] = $object->origin_email;

+ 6 - 6
htdocs/ticket/list.php

@@ -100,9 +100,9 @@ foreach ($object->fields as $key => $val)
 {
 	if ($val['searchall']) $fieldstosearchall['t.'.$key] = $val['label'];
 }
-$fieldstosearchall['s.name_alias']="AliasNameShort";
-$fieldstosearchall['s.zip']="Zip";
-$fieldstosearchall['s.town']="Town";
+$fieldstosearchall['s.name_alias'] = "AliasNameShort";
+$fieldstosearchall['s.zip'] = "Zip";
+$fieldstosearchall['s.town'] = "Town";
 
 // Definition of fields for list
 $arrayfields = array();
@@ -755,13 +755,13 @@ while ($i < min($num, $limit))
 			print '>';
 			if ($key == 'fk_statut') print $object->getLibStatut(5);
 			elseif ($key == 'type_code') {
-				$s = $langs->getLabelFromKey($db, 'TicketTypeShort' . $object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
+				$s = $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
 				print '<span title="'.$s.'">';
 				print $s;
 				print '</span>';
 			}
-			elseif ($key == 'category_code') print $langs->getLabelFromKey($db, 'TicketCategoryShort' . $object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
-			elseif ($key == 'severity_code') print $langs->getLabelFromKey($db, 'TicketSeverityShort' . $object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
+			elseif ($key == 'category_code') print $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
+			elseif ($key == 'severity_code') print $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
 			elseif ($key == 'tms') print dol_print_date($db->jdate($obj->$key), 'dayhour', 'tzuser');
 			elseif ($key == 'fk_user_create') {
 				if ($object->fk_user_create > 0) {

+ 3 - 3
htdocs/user/class/user.class.php

@@ -3233,9 +3233,9 @@ class User extends CommonObject
 			}
 			return $num;
 		} else {
-            $this->errors[] = $this->db->lasterror();
-            return -1;
-        }
+			$this->errors[] = $this->db->lasterror();
+			return -1;
+		}
 	}
 
 	/**

+ 1 - 1
htdocs/user/group/perms.php

@@ -303,7 +303,7 @@ if ($object->id > 0)
 				print '<td colspan="2">&nbsp;</td>';
 
 				// Module id
-				if ($user->admin) print '<td class="right">'. $objMod->numero.'</td>';
+				if ($user->admin) print '<td class="right">'.$objMod->numero.'</td>';
 
 				print '</tr>';
 			}

+ 1 - 1
htdocs/user/perms.php

@@ -365,7 +365,7 @@ if ($result)
 			print '<td>&nbsp;</td>';
 
 			// Module Id
-			if ($user->admin) print '<td class="right">'. $objMod->numero.'</td>';
+			if ($user->admin) print '<td class="right">'.$objMod->numero.'</td>';
 
 			print '</tr>'."\n";
 		}

+ 6 - 6
htdocs/variants/class/ProductCombination.class.php

@@ -165,11 +165,11 @@ class ProductCombination
 			/**
 			 * for auto retrocompatibility with last behavior
 			 */
-			if ($fk_price_level>0){
+			if ($fk_price_level > 0) {
 				$combination_price_levels[$fk_price_level] = ProductCombinationLevel::createFromParent($this->db, $this, $fk_price_level);
 			}
 			else {
-				for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++){
+				for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) {
 					$combination_price_levels[$i] = ProductCombinationLevel::createFromParent($this->db, $this, $i);
 				}
 			}
@@ -783,16 +783,16 @@ class ProductCombination
 		$newcomb->variation_weight = $weight_impact;
 
 		// Init price level
-		if ($conf->global->PRODUIT_MULTIPRICES){
-			for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++){
+		if ($conf->global->PRODUIT_MULTIPRICES) {
+			for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) {
 				$productCombinationLevel = new ProductCombinationLevel($this->db);
 				$productCombinationLevel->fk_product_attribute_combination = $newcomb->id;
 				$productCombinationLevel->fk_price_level = $i;
 				$productCombinationLevel->variation_price = $price_impact[$i];
 
-				if (is_array($price_var_percent)){
+				if (is_array($price_var_percent)) {
 					$productCombinationLevel->variation_price_percentage = (empty($price_var_percent[$i]) ? false : $price_var_percent[$i]);
-				}else {
+				} else {
 					$productCombinationLevel->variation_price_percentage = $price_var_percent;
 				}
 

Some files were not shown because too many files changed in this diff