浏览代码

Merge branch 'develop' into new_branch_24_04

Philippe Grand 8 年之前
父节点
当前提交
b5b79bc36b
共有 100 个文件被更改,包括 3111 次插入933 次删除
  1. 3 1
      ChangeLog
  2. 22 7
      build/debian/README.howto
  3. 1 1
      build/debian/install.forced.php.install
  4. 2 1
      build/makepack-dolibarr.pl
  5. 3 4
      htdocs/accountancy/admin/accountmodel.php
  6. 1 1
      htdocs/accountancy/admin/export.php
  7. 2 2
      htdocs/accountancy/admin/index.php
  8. 1 1
      htdocs/accountancy/admin/journals.php
  9. 6 2
      htdocs/accountancy/bookkeeping/card.php
  10. 2 2
      htdocs/accountancy/bookkeeping/list.php
  11. 26 22
      htdocs/accountancy/bookkeeping/listbyaccount.php
  12. 12 3
      htdocs/accountancy/class/bookkeeping.class.php
  13. 12 4
      htdocs/accountancy/customer/lines.php
  14. 9 4
      htdocs/accountancy/customer/list.php
  15. 6 3
      htdocs/accountancy/index.php
  16. 153 138
      htdocs/accountancy/journal/bankjournal.php
  17. 146 104
      htdocs/accountancy/journal/expensereportsjournal.php
  18. 153 106
      htdocs/accountancy/journal/purchasesjournal.php
  19. 139 97
      htdocs/accountancy/journal/sellsjournal.php
  20. 7 2
      htdocs/accountancy/supplier/lines.php
  21. 7 2
      htdocs/accountancy/supplier/list.php
  22. 3 3
      htdocs/adherents/subscription.php
  23. 1 1
      htdocs/adherents/subscription/card.php
  24. 1 1
      htdocs/admin/agenda.php
  25. 1 1
      htdocs/admin/agenda_extrafields.php
  26. 1 1
      htdocs/admin/agenda_extsites.php
  27. 1 1
      htdocs/admin/agenda_other.php
  28. 1 1
      htdocs/admin/agenda_xcal.php
  29. 7 1
      htdocs/admin/chequereceipts.php
  30. 2 1
      htdocs/admin/clicktodial.php
  31. 7 6
      htdocs/admin/commande.php
  32. 9 2
      htdocs/admin/contract.php
  33. 84 20
      htdocs/admin/defaultvalues.php
  34. 20 14
      htdocs/admin/dict.php
  35. 8 2
      htdocs/admin/expedition.php
  36. 9 3
      htdocs/admin/expensereport.php
  37. 1 1
      htdocs/admin/expensereport_extrafields.php
  38. 10 6
      htdocs/admin/external_rss.php
  39. 7 6
      htdocs/admin/facture.php
  40. 10 3
      htdocs/admin/fichinter.php
  41. 7 1
      htdocs/admin/livraison.php
  42. 1 3
      htdocs/admin/loan.php
  43. 19 12
      htdocs/admin/mails_templates.php
  44. 2 4
      htdocs/admin/modules.php
  45. 4 9
      htdocs/admin/oauth.php
  46. 1 1
      htdocs/admin/payment.php
  47. 42 3
      htdocs/admin/pdf.php
  48. 1 3
      htdocs/admin/perms.php
  49. 8 7
      htdocs/admin/propal.php
  50. 1 1
      htdocs/admin/salaries.php
  51. 56 0
      htdocs/admin/stock.php
  52. 9 4
      htdocs/admin/supplier_invoice.php
  53. 10 4
      htdocs/admin/supplier_order.php
  54. 1 2
      htdocs/admin/supplier_payment.php
  55. 9 2
      htdocs/admin/supplier_proposal.php
  56. 14 8
      htdocs/admin/syslog.php
  57. 5 5
      htdocs/admin/taxes.php
  58. 21 5
      htdocs/admin/translation.php
  59. 17 34
      htdocs/admin/websites.php
  60. 1 2
      htdocs/admin/workflow.php
  61. 2 0
      htdocs/api/class/api.class.php
  62. 1 1
      htdocs/api/class/api_login.class.php
  63. 8 4
      htdocs/comm/card.php
  64. 27 24
      htdocs/comm/mailing/cibles.php
  65. 1 1
      htdocs/comm/mailing/class/mailing.class.php
  66. 5 4
      htdocs/comm/propal/class/api_proposals.class.php
  67. 2 2
      htdocs/comm/propal/contact.php
  68. 1 0
      htdocs/commande/class/commande.class.php
  69. 3 2
      htdocs/commande/contact.php
  70. 1 1
      htdocs/compta/bank/card.php
  71. 1 1
      htdocs/compta/facture/admin/facture_cust_extrafields.php
  72. 1 1
      htdocs/compta/facture/admin/facturedet_cust_extrafields.php
  73. 11 22
      htdocs/compta/facture/card.php
  74. 2 1
      htdocs/compta/facture/fiche-rec.php
  75. 19 19
      htdocs/compta/paiement.php
  76. 55 5
      htdocs/compta/paiement/class/paiement.class.php
  77. 6 1
      htdocs/core/ajax/check_notifications.php
  78. 5 2
      htdocs/core/boxes/box_external_rss.php
  79. 2 1
      htdocs/core/class/commoninvoice.class.php
  80. 367 56
      htdocs/core/class/commonobject.class.php
  81. 3 3
      htdocs/core/class/conf.class.php
  82. 440 0
      htdocs/core/class/coreobject.class.php
  83. 500 0
      htdocs/core/class/ctyperesource.class.php
  84. 4 0
      htdocs/core/class/extrafields.class.php
  85. 4 3
      htdocs/core/class/html.form.class.php
  86. 14 5
      htdocs/core/class/html.formmail.class.php
  87. 7 7
      htdocs/core/class/html.formmailing.class.php
  88. 12 5
      htdocs/core/db/DoliDB.class.php
  89. 7 5
      htdocs/core/js/lib_notification.js.php
  90. 166 0
      htdocs/core/js/listview.js
  91. 92 0
      htdocs/core/lib/accounting.lib.php
  92. 1 1
      htdocs/core/lib/ajax.lib.php
  93. 49 0
      htdocs/core/lib/company.lib.php
  94. 24 6
      htdocs/core/lib/files.lib.php
  95. 82 34
      htdocs/core/lib/functions.lib.php
  96. 2 1
      htdocs/core/lib/functions2.lib.php
  97. 28 5
      htdocs/core/lib/pdf.lib.php
  98. 14 14
      htdocs/core/lib/report.lib.php
  99. 2 2
      htdocs/core/lib/security2.lib.php
  100. 15 3
      htdocs/core/menus/standard/eldy.lib.php

+ 3 - 1
ChangeLog

@@ -13,7 +13,9 @@ Following changes may create regression for some external modules, but were nece
 * The page compta/facture.php was renamed into compta/facture/card.php to match page naming conventions.
 * The page compta/facture.php was renamed into compta/facture/card.php to match page naming conventions.
 * The signature of method ->delete() of class Product and PriceExpression was changed from 
 * The signature of method ->delete() of class Product and PriceExpression was changed from 
   ->delete($id, notrigger) to ->delete(User, notrigger) to match standard dev rules.
   ->delete($id, notrigger) to ->delete(User, notrigger) to match standard dev rules.
-
+* Removed CommonObject::displayMarginInfos (was deprecated in 3.8). Use same method into
+  html.formmargin.class.php
+* Removed Societe::set_commnucation_level (was deprecated in 4.0). Was not used.
 
 
 ***** ChangeLog for 5.0.1 compared to 5.0.0 *****
 ***** ChangeLog for 5.0.1 compared to 5.0.0 *****
 FIX: #6503: SQL error in "Last pending payment invoices"
 FIX: #6503: SQL error in "Last pending payment invoices"

+ 22 - 7
build/debian/README.howto

@@ -385,13 +385,14 @@ http://packages.qa.debian.org
 * Package will be into release when test will be moved as stable.
 * Package will be into release when test will be moved as stable.
 
 
 
 
-##### Send an unblock request 
+
+##### Send an unblock request to make a full update of a stable package 
 
 
 Use this to move from unstable to testing.
 Use this to move from unstable to testing.
 
 
 reportbug -B debian --smtphost=smtp.gmail.com:587 --smtpuser=xxxx --smtppasswd=yyyy --tls
 reportbug -B debian --smtphost=smtp.gmail.com:587 --smtpuser=xxxx --smtppasswd=yyyy --tls
 Choose package "release.debian.org"
 Choose package "release.debian.org"
-Then "unblock"
+Then usertag "unblock"
 Then name of package "dolibarr"
 Then name of package "dolibarr"
 Fill message, for example:
 Fill message, for example:
 "Please unblock package dolibarr
 "Please unblock package dolibarr
@@ -400,12 +401,11 @@ Note that package 3.5.7 contains not only fixed for bugs reported to debian. It
 so it is a better solution to validate this maintenance release than applying a patch of the only CVE-2015-3935. 
 so it is a better solution to validate this maintenance release than applying a patch of the only CVE-2015-3935. 
 After discussion with ..., it appears that security holes are enough to request this unblock request."
 After discussion with ..., it appears that security holes are enough to request this unblock request."
 
 
-
-Use this to request an update of a stable package
+Use this to request an full update of a stable package
 
 
 reportbug -B debian --smtphost=smtp.gmail.com:587 --smtpuser=xxxx --smtppasswd=yyyy --tls
 reportbug -B debian --smtphost=smtp.gmail.com:587 --smtpuser=xxxx --smtppasswd=yyyy --tls
 Choose package "release.debian.org"
 Choose package "release.debian.org"
-Then "unblock"
+Then usertag "unblock"
 Then name of package "dolibarr"
 Then name of package "dolibarr"
 Fill message, for example:
 Fill message, for example:
 "
 "
@@ -417,11 +417,26 @@ Pro are:
 - It fixes also stability bugs
 - It fixes also stability bugs
 - Patches were already tested because deployed and used by several thousands of users.
 - Patches were already tested because deployed and used by several thousands of users.
 - It is easier for package maintener to include this official set of fixes than applying one patch after one patch for each debian report or backported each patch into a dedicated version.
 - It is easier for package maintener to include this official set of fixes than applying one patch after one patch for each debian report or backported each patch into a dedicated version.
-- Debian maintenance version matches with official project maintenance version (better when all fixes are not related to the way the software is packaged)
+- Debian maintenance version is inline with official project maintenance version (better when all fixes are not related to the way the software is packaged)
 Cons are: 
 Cons are: 
-- The patch include more than the only one security reported fxes
+- The patch include more than the only one security reported fixes
 
 
 So I just need to know if it's ok to push such a version 3.5.7 (fixes for 3.5.* branch) instead of only one fix for only the few (the only) reported debian bugs,
 So I just need to know if it's ok to push such a version 3.5.7 (fixes for 3.5.* branch) instead of only one fix for only the few (the only) reported debian bugs,
 since it provides more stability and is for me a more secured process.
 since it provides more stability and is for me a more secured process.
 "
 "
 
 
+##### Send an request to ask a simple fix of a stable package 
+
+Use this to ask to apply patches on a stable version.
+
+reportbug -B debian --smtphost=smtp.gmail.com:587 --smtpuser=xxxx --smtppasswd=yyyy --tls
+Choose package "release.debian.org"
+Then usertag "jessie-pu"
+Then name of package "dolibarr"
+Fill message, for example:
+"Please unblock package dolibarr
+A security error CVE-2015-3935 was reported and is fixed into package 3.5.7.
+Note that package 3.5.7 contains not only fixed for bugs reported to debian. It includes other fixes, but they are all related to stability or security,
+so it is a better solution to validate this maintenance release than applying a patch of the only CVE-2015-3935. 
+After discussion with ..., it appears that security holes are enough to request this unblock request."
+

+ 1 - 1
build/debian/install.forced.php.install

@@ -7,7 +7,7 @@
 //
 //
 
 
 $force_install_packager='deb';
 $force_install_packager='deb';
-$force_install_noedit=2;
+$force_install_noedit=1;
 $force_install_message='KeepDefaultValuesDeb';
 $force_install_message='KeepDefaultValuesDeb';
 #$force_install_main_data_root='/usr/share/dolibarr/documents';
 #$force_install_main_data_root='/usr/share/dolibarr/documents';
 $force_install_main_data_root='/var/lib/dolibarr/documents';
 $force_install_main_data_root='/var/lib/dolibarr/documents';

+ 2 - 1
build/makepack-dolibarr.pl

@@ -509,7 +509,7 @@ if ($nboftargetok) {
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/documents`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/documents`;
 
 
 		# Removed known external modules to avoid any error when packaging from env where external modules are tested 
 		# Removed known external modules to avoid any error when packaging from env where external modules are tested 
-	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/custom/*`;	# For custom we want to keep dir
+	    #$ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type d -exec rm -fr {} \;`;	# For custom we want to keep dir
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/allscreens*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/allscreens*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/ancotec*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/ancotec*`;
 	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/cabinetmed*`;
 	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/cabinetmed*`;
@@ -550,6 +550,7 @@ if ($nboftargetok) {
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/doc`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/doc`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/example`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/example`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/test`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/test`;
+        $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mobiledetect/mobiledetectlib/.gitmodules`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/lib/Mail`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/lib/Mail`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/samples`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/samples`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/php-iban/docs`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/php-iban/docs`;

+ 3 - 4
htdocs/accountancy/admin/accountmodel.php

@@ -757,8 +757,7 @@ if ($id)
         {
         {
         	print '<tr><td colspan="8">* '.$langs->trans("AvailableVariables").": ";
         	print '<tr><td colspan="8">* '.$langs->trans("AvailableVariables").": ";
         	require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
         	require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
-        	$formmail=new FormMail($db);
-        	$tmp=$formmail->getAvailableSubstitKey('form');
+        	$tmp=FormMail::getAvailableSubstitKey('formemail');
         	print implode(', ', $tmp);
         	print implode(', ', $tmp);
         	print '</td></tr>';
         	print '</td></tr>';
         }
         }
@@ -901,8 +900,8 @@ if ($id)
         if ($id == 4) print '<td></td>';
         if ($id == 4) print '<td></td>';
         print '<td class="liste_titre"></td>';
         print '<td class="liste_titre"></td>';
     	print '<td class="liste_titre" colspan="2" align="right">';
     	print '<td class="liste_titre" colspan="2" align="right">';
-    	$searchpitco=$form->showFilterAndCheckAddButtons(0);
-    	print $searchpitco;
+    	$searchpicto=$form->showFilterAndCheckAddButtons(0);
+    	print $searchpicto;
     	print '</td>';
     	print '</td>';
         print '</tr>';
         print '</tr>';
             
             

+ 1 - 1
htdocs/accountancy/admin/export.php

@@ -130,7 +130,7 @@ print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">';
 print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
 print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
 print '<input type="hidden" name="action" value="update">';
 print '<input type="hidden" name="action" value="update">';
 
 
-dol_fiche_head($head, 'export', $langs->trans("Configuration"), 0, 'cron');
+dol_fiche_head($head, 'export', $langs->trans("Configuration"), -1, 'cron');
 
 
 $var = true;
 $var = true;
 
 

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

@@ -171,7 +171,7 @@ print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">';
 print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
 print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
 print '<input type="hidden" name="action" value="update">';
 print '<input type="hidden" name="action" value="update">';
 
 
-dol_fiche_head($head, 'general', $langs->trans("Configuration"), 0, 'cron');
+dol_fiche_head($head, 'general', $langs->trans("Configuration"), -1, 'cron');
 
 
 
 
 // Default mode for calculating turnover (parameter ACCOUNTING_MODE)
 // Default mode for calculating turnover (parameter ACCOUNTING_MODE)
@@ -299,7 +299,7 @@ print '<div class="center"><input type="submit" class="button" value="' . $langs
 print '<br>';
 print '<br>';
 print '<br>';
 print '<br>';
 
 
-print $langs->trans("AccountancySetupDoneFromAccountancyMenu", $langs->transnoentitiesnoconv("Home").'-'.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy"));
+print '<div class="opacitymedium">'.$langs->trans("AccountancySetupDoneFromAccountancyMenu", $langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy")).'</div>';
 
 
 print '<br>';
 print '<br>';
 print '</form>';
 print '</form>';

+ 1 - 1
htdocs/accountancy/admin/journals.php

@@ -94,7 +94,7 @@ print load_fiche_titre($langs->trans('ConfigAccountingExpert'), $linkback, 'titl
 
 
 $head = admin_accounting_prepare_head(null);
 $head = admin_accounting_prepare_head(null);
 
 
-dol_fiche_head($head, 'journal', $langs->trans("Configuration"), 0, 'cron');
+dol_fiche_head($head, 'journal', $langs->trans("Configuration"), -1, 'cron');
 
 
 $sql = "SELECT j.rowid, j.code, j.label, j.nature, j.active";
 $sql = "SELECT j.rowid, j.code, j.label, j.nature, j.active";
 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_journal as j";
 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_journal as j";

+ 6 - 2
htdocs/accountancy/bookkeeping/card.php

@@ -305,6 +305,8 @@ if ($action == 'create') {
 
 
 		dol_fiche_head();
 		dol_fiche_head();
 		
 		
+		print '<div class="fichecenter">';
+		
 		print '<table class="border" width="100%">';
 		print '<table class="border" width="100%">';
 		print '<tr class="pair">';
 		print '<tr class="pair">';
 		print '<td class="titlefield">' . $langs->trans("NumMvts") . '</td>';
 		print '<td class="titlefield">' . $langs->trans("NumMvts") . '</td>';
@@ -328,6 +330,8 @@ if ($action == 'create') {
 		print '</tr>';
 		print '</tr>';
 		print '</table>';
 		print '</table>';
 		
 		
+		print '</div>';
+		
 		dol_fiche_end();
 		dol_fiche_end();
 
 
 		print '<br>';
 		print '<br>';
@@ -427,8 +431,8 @@ if ($action == 'create') {
 					print $formventilation->select_auxaccount($code_tiers, 'code_tiers', 1);
 					print $formventilation->select_auxaccount($code_tiers, 'code_tiers', 1);
 					print '</td>';
 					print '</td>';
 					print '<td><input type="text" size="15" name="label_compte" value="' . $label_compte . '"/></td>';
 					print '<td><input type="text" size="15" name="label_compte" value="' . $label_compte . '"/></td>';
-					print '<td align="right"><input type="text" size="6" name="debit" value="' . price($debit) . '"/></td>';
-					print '<td align="right"><input type="text" size="6" name="credit" value="' . price($credit) . '"/></td>';
+					print '<td align="right"><input type="text" class="right maxwidth50" name="debit" value="' . price($debit) . '"/></td>';
+					print '<td align="right"><input type="text" class="right maxwidth50" name="credit" value="' . price($credit) . '"/></td>';
 					print '<td></td>';
 					print '<td></td>';
 					print '<td></td>';
 					print '<td></td>';
 					print '<td><input type="submit" class="button" name="save" value="' . $langs->trans("Add") . '"></td>';
 					print '<td><input type="submit" class="button" name="save" value="' . $langs->trans("Add") . '"></td>';

+ 2 - 2
htdocs/accountancy/bookkeeping/list.php

@@ -360,7 +360,7 @@ if (count($filter)) $button.= $langs->trans("ExportFilteredList");
 else $button.= $langs->trans("ExportList");
 else $button.= $langs->trans("ExportList");
 $button.= '</a>';
 $button.= '</a>';
 
 
-$groupby = ' <a href="./listbyaccount.php">' . $langs->trans("GroupByAccountAccounting") . '</a>';
+$groupby = ' <a class="nohover" href="'.DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php"">' . $langs->trans("GroupByAccountAccounting") . '</a>';
 
 
 print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $button, $result, $nbtotalofrecords, 'title_accountancy', 0, $groupby, '', $limit);
 print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $button, $result, $nbtotalofrecords, 'title_accountancy', 0, $groupby, '', $limit);
 
 
@@ -437,7 +437,7 @@ foreach ($object->lines as $line ) {
 
 
 	print '<td><a href="./card.php?piece_num=' . $line->piece_num . '">' . $line->piece_num . '</a></td>';
 	print '<td><a href="./card.php?piece_num=' . $line->piece_num . '">' . $line->piece_num . '</a></td>';
 	print '<td align="center">' . dol_print_date($line->doc_date, 'day') . '</td>';
 	print '<td align="center">' . dol_print_date($line->doc_date, 'day') . '</td>';
-	print '<td>' . $line->doc_ref . '</td>';
+	print '<td class="nowrap">' . $line->doc_ref . '</td>';
 	print '<td>' . length_accountg($line->numero_compte) . '</td>';
 	print '<td>' . length_accountg($line->numero_compte) . '</td>';
 	print '<td>' . length_accounta($line->code_tiers) . '</td>';
 	print '<td>' . length_accounta($line->code_tiers) . '</td>';
 	print '<td>' . $line->label_compte . '</td>';
 	print '<td>' . $line->label_compte . '</td>';

+ 26 - 22
htdocs/accountancy/bookkeeping/listbyaccount.php

@@ -207,7 +207,7 @@ if ($action == 'delbookkeepingyear') {
 
 
 print '<form method="GET" id="searchFormList" action="' . $_SERVER["PHP_SELF"] . '">';
 print '<form method="GET" id="searchFormList" action="' . $_SERVER["PHP_SELF"] . '">';
 
 
-$viewflat = ' <a href="./list.php">' . $langs->trans("ViewFlatList") . '</a>';
+$viewflat = ' <a class="nohover" href="'.DOL_URL_ROOT.'/accountancy/bookkeeping/list.php">' . $langs->trans("ViewFlatList") . '</a>';
 
 
 print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result, $nbtotalofrecords,'title_accountancy',0,$viewflat,'',$limit);
 print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result, $nbtotalofrecords,'title_accountancy',0,$viewflat,'',$limit);
 
 
@@ -222,17 +222,6 @@ print '<div class="inline-block divButAction"><a class="butAction" href="./card.
 print '</div>';
 print '</div>';
 
 
 print '<table class="noborder" width="100%">';
 print '<table class="noborder" width="100%">';
-print '<tr class="liste_titre">';
-print '<td>' . $langs->trans("AccountAccounting") . '</td>';
-print_liste_field_titre($langs->trans("TransactionNumShort"), $_SERVER['PHP_SELF'], "t.piece_num", "", $options, 'align="right"', $sortfield, $sortorder);
-print_liste_field_titre($langs->trans("Docdate"), $_SERVER['PHP_SELF'], "t.doc_date", "", $options, 'align="center"', $sortfield, $sortorder);
-print_liste_field_titre($langs->trans("Docref"), $_SERVER['PHP_SELF'], "t.doc_ref", "", $options, "", $sortfield, $sortorder);
-print_liste_field_titre($langs->trans("SuppliersInvoices") . ' / ' . $langs->trans("CustomersInvoices"));
-print_liste_field_titre($langs->trans("Debit"), $_SERVER['PHP_SELF'], "t.debit", "", $options, 'align="right"', $sortfield, $sortorder);
-print_liste_field_titre($langs->trans("Credit"), $_SERVER['PHP_SELF'], "t.credit", "", $options, 'align="right"', $sortfield, $sortorder);
-print_liste_field_titre($langs->trans("Codejournal"), $_SERVER['PHP_SELF'], "t.code_journal", "", $options, 'align="right"', $sortfield, $sortorder);
-print_liste_field_titre('', $_SERVER["PHP_SELF"], "", $options, "", 'width="60" align="center"', $sortfield, $sortorder);
-print "</tr>\n";
 
 
 print '<tr class="liste_titre">';
 print '<tr class="liste_titre">';
 print '<td class="liste_titre">' . $object->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array (), 1, 1, '') . '</td>';
 print '<td class="liste_titre">' . $object->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array (), 1, 1, '') . '</td>';
@@ -254,6 +243,18 @@ $searchpitco=$form->showFilterAndCheckAddButtons(0);
 print $searchpitco;
 print $searchpitco;
 print '</td>';
 print '</td>';
 
 
+print '<tr class="liste_titre">';
+print_liste_field_titre($langs->trans("AccountAccountingShort"), $_SERVER['PHP_SELF']);
+print_liste_field_titre($langs->trans("TransactionNumShort"), $_SERVER['PHP_SELF'], "t.piece_num", "", $options, 'align="right"', $sortfield, $sortorder);
+print_liste_field_titre($langs->trans("Docdate"), $_SERVER['PHP_SELF'], "t.doc_date", "", $options, 'align="center"', $sortfield, $sortorder);
+print_liste_field_titre($langs->trans("Docref"), $_SERVER['PHP_SELF'], "t.doc_ref", "", $options, "", $sortfield, $sortorder);
+print_liste_field_titre($langs->trans("Label"));
+print_liste_field_titre($langs->trans("Debit"), $_SERVER['PHP_SELF'], "t.debit", "", $options, 'align="right"', $sortfield, $sortorder);
+print_liste_field_titre($langs->trans("Credit"), $_SERVER['PHP_SELF'], "t.credit", "", $options, 'align="right"', $sortfield, $sortorder);
+print_liste_field_titre($langs->trans("Codejournal"), $_SERVER['PHP_SELF'], "t.code_journal", "", $options, 'align="right"', $sortfield, $sortorder);
+print_liste_field_titre('', $_SERVER["PHP_SELF"], "", $options, "", 'width="60" align="center"', $sortfield, $sortorder);
+print "</tr>\n";
+
 print '</tr>';
 print '</tr>';
 
 
 $var = True;
 $var = True;
@@ -277,9 +278,10 @@ foreach ( $object->lines as $line ) {
         
         
         // Affiche un Sous-Total par compte comptable
         // Affiche un Sous-Total par compte comptable
         if (isset($displayed_account_number)) {
         if (isset($displayed_account_number)) {
-          print '<tr class="liste_total"><td align="right" colspan="4">'.$langs->trans("SubTotal").':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td>';
-          print "<td>&nbsp;</td>\n";
-          print '</tr>';
+            print '<tr class="liste_total"><td align="right" colspan="5">'.$langs->trans("SubTotal").':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td>';
+            print "<td>&nbsp;</td>\n";
+            print "<td>&nbsp;</td>\n";
+            print '</tr>';
         }
         }
         
         
         // Show the break account
         // Show the break account
@@ -299,17 +301,18 @@ foreach ( $object->lines as $line ) {
 
 
 	print '<tr class="oddeven">';
 	print '<tr class="oddeven">';
 	print '<td>&nbsp;</td>';
 	print '<td>&nbsp;</td>';
-	print '<td align="right">'.$line->piece_num.'</td>';
+	print '<td align="right"><a href="./card.php?piece_num=' . $line->piece_num . '">'.$line->piece_num.'</a></td>';
 	print '<td align="center">' . dol_print_date($line->doc_date, 'day') . '</td>';
 	print '<td align="center">' . dol_print_date($line->doc_date, 'day') . '</td>';
-	print '<td><a href="./card.php?piece_num=' . $line->piece_num . '">' . $line->doc_ref . '</a></td>';
+	
+	// TODO Add a link according to doc_type and fk_doc
+	print '<td class="nowrap">';
+    //if ($line->doc_type == 'supplier_invoice')
+    //if ($line->doc_type == 'customer_invoice')
+	print $line->doc_ref;
+    print '</td>';
     
     
     // Affiche un lien vers la facture client/fournisseur
     // Affiche un lien vers la facture client/fournisseur
     $doc_ref = preg_replace('/\(.*\)/', '', $line->doc_ref);
     $doc_ref = preg_replace('/\(.*\)/', '', $line->doc_ref);
-    if ($line->doc_type == 'supplier_invoice')
-     print strlen(length_accounta($line->code_tiers)) == 0 ? '<td><a href="/fourn/facture/list.php?search_ref_supplier=' . $doc_ref . '">' . $line->label_compte . '</a></td>' : '<td><a href="/fourn/facture/list.php?search_ref_supplier=' . $doc_ref . '">' . $line->label_compte . '</a><br /><span style="font-size:0.8em">(' . length_accounta($line->code_tiers) . ')</span></td>';
-    elseif ($line->doc_type == 'customer_invoice')
-    print strlen(length_accounta($line->code_tiers)) == 0 ? '<td><a href="/compta/facture/list.php?search_ref=' . $doc_ref . '">' . $line->label_compte . '</a></td>' : '<td><a href="/compta/facture/list.php?search_ref=' . $doc_ref . '">' . $line->label_compte . '</a><br /><span style="font-size:0.8em">(' . length_accounta($line->code_tiers) . ')</span></td>';
-    else
     print strlen(length_accounta($line->code_tiers)) == 0 ? '<td>' . $line->label_compte . '</td>' : '<td>' . $line->label_compte . '<br /><span style="font-size:0.8em">(' . length_accounta($line->code_tiers) . ')</span></td>';
     print strlen(length_accounta($line->code_tiers)) == 0 ? '<td>' . $line->label_compte . '</td>' : '<td>' . $line->label_compte . '<br /><span style="font-size:0.8em">(' . length_accounta($line->code_tiers) . ')</span></td>';
 
 
 
 
@@ -332,6 +335,7 @@ foreach ( $object->lines as $line ) {
 print '<tr class="liste_total">';
 print '<tr class="liste_total">';
 print '<td align="right" colspan="5">'.$langs->trans("SubTotal").':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td>';
 print '<td align="right" colspan="5">'.$langs->trans("SubTotal").':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td>';
 print "<td>&nbsp;</td>\n";
 print "<td>&nbsp;</td>\n";
+print "<td>&nbsp;</td>\n";
 print '</tr>';
 print '</tr>';
 
 
 
 

+ 12 - 3
htdocs/accountancy/class/bookkeeping.class.php

@@ -169,7 +169,15 @@ class BookKeeping extends CommonObject
 		if (empty($this->numero_compte) || $this->numero_compte == '-1')
 		if (empty($this->numero_compte) || $this->numero_compte == '-1')
 		{
 		{
 		    $langs->load("errors");
 		    $langs->load("errors");
-            $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForBankLine', $this->fk_docdet);		    
+            if (in_array($this->doc_type, array('bank', 'expense_report')))
+            {
+		        $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForBankLine', $this->fk_docdet,  $this->doc_type);
+            }
+            else
+            {
+                $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForInvoiceLine', $this->fk_doc,  $this->doc_type);		    
+            }
+		    
 		    return -1;
 		    return -1;
 		}
 		}
 		
 		
@@ -178,11 +186,12 @@ class BookKeeping extends CommonObject
 		
 		
 		$this->piece_num = 0;
 		$this->piece_num = 0;
 		
 		
-		// first check if line not yet in bookkeeping
+		// First check if line not yet already in bookkeeping
 		$sql = "SELECT count(*) as nb";
 		$sql = "SELECT count(*) as nb";
 		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
 		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
 		$sql .= " WHERE doc_type = '" . $this->doc_type . "'";
 		$sql .= " WHERE doc_type = '" . $this->doc_type . "'";
-		$sql .= " AND fk_docdet = " . $this->fk_docdet;
+		$sql .= " AND fk_doc = " . $this->fk_doc;
+		$sql .= " AND fk_docdet = " . $this->fk_docdet;                   // This field can be 0 is record is for several lines 
 		$sql .= " AND numero_compte = '" . $this->numero_compte . "'";
 		$sql .= " AND numero_compte = '" . $this->numero_compte . "'";
 	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		

+ 12 - 4
htdocs/accountancy/customer/lines.php

@@ -43,6 +43,7 @@ $langs->load("productbatch");
 $account_parent = GETPOST('account_parent');
 $account_parent = GETPOST('account_parent');
 $changeaccount = GETPOST('changeaccount');
 $changeaccount = GETPOST('changeaccount');
 // Search Getpost
 // Search Getpost
+$search_lineid = GETPOST('search_lineid', 'int');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
@@ -86,6 +87,7 @@ $formventilation = new FormVentilation($db);
 // Purge search criteria
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 {
 {
+    $search_lineid = '';
 	$search_ref = '';
 	$search_ref = '';
 	$search_invoice = '';
 	$search_invoice = '';
 	$search_label = '';
 	$search_label = '';
@@ -151,7 +153,7 @@ print '<script type="text/javascript">
  * Customer Invoice lines
  * Customer Invoice lines
  */
  */
 $sql = "SELECT f.rowid, f.facnumber, f.type, f.datef, f.ref_client,";
 $sql = "SELECT f.rowid, f.facnumber, f.type, f.datef, f.ref_client,";
-$sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.tva_tx, fd.total_ttc,";
+$sql .= " fd.rowid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.tva_tx, fd.total_ttc,";
 $sql .= " s.rowid as socid, s.nom as name, s.code_compta, s.code_client,";
 $sql .= " s.rowid as socid, s.nom as name, s.code_compta, s.code_client,";
 $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.accountancy_code_sell, aa.rowid as fk_compte, aa.account_number, aa.label as label_compte,";
 $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.accountancy_code_sell, aa.rowid as fk_compte, aa.account_number, aa.label as label_compte,";
 $sql .= " fd.situation_percent, co.label as country, s.tva_intra";
 $sql .= " fd.situation_percent, co.label as country, s.tva_intra";
@@ -169,6 +171,9 @@ if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
 } else {
 } else {
 	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_STANDARD . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
 	$sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_STANDARD . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")";
 }
 }
+if ($search_lineid) {
+    $sql .= natural_search("fd.rowid", $search_lineid, 1);
+}
 if (strlen(trim($search_invoice))) {
 if (strlen(trim($search_invoice))) {
 	$sql .= natural_search("f.facnumber", $search_invoice);
 	$sql .= natural_search("f.facnumber", $search_invoice);
 }
 }
@@ -257,7 +262,7 @@ if ($result) {
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	
 	
 	print '<tr class="liste_titre_filter">';
 	print '<tr class="liste_titre_filter">';
-	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_lineid" value="' . dol_escape_htmltag($search_lineid) . '""></td>';
 	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"><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
 	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
@@ -328,13 +333,16 @@ if ($result) {
 		print '<td align="right">' . price($objp->total_ht) . '</td>';
 		print '<td align="right">' . price($objp->total_ht) . '</td>';
 		print '<td align="center">' . price($objp->tva_tx) . '</td>';
 		print '<td align="center">' . price($objp->tva_tx) . '</td>';
 		print '<td>';
 		print '<td>';
-		print $codecompta . ' <a href="./card.php?id=' . $objp->fdid . '">';
+		print $codecompta . ' <a href="./card.php?id=' . $objp->rowid . '">';
 		print img_edit();
 		print img_edit();
 		print '</a>';
 		print '</a>';
 		print '</td>';
 		print '</td>';
+		
 		print '<td>' . $objp->country .'</td>';
 		print '<td>' . $objp->country .'</td>';
+		
 		print '<td>' . $objp->tva_intra . '</td>';
 		print '<td>' . $objp->tva_intra . '</td>';
-		print '<td class="center"><input type="checkbox" class="checkforaction" name="changeaccount[]" value="' . $objp->fdid . '"/></td>';
+		
+		print '<td class="center"><input type="checkbox" class="checkforaction" name="changeaccount[]" value="' . $objp->rowid . '"/></td>';
 
 
 		print "</tr>";
 		print "</tr>";
 		$i ++;
 		$i ++;

+ 9 - 4
htdocs/accountancy/customer/list.php

@@ -52,6 +52,7 @@ $toselect = GETPOST('toselect', 'array');
 $mesCasesCochees = GETPOST('toselect', 'array');
 $mesCasesCochees = GETPOST('toselect', 'array');
 
 
 // Search Getpost
 // Search Getpost
+$search_lineid = GETPOST('search_lineid', 'int');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
@@ -100,6 +101,7 @@ if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction !=
 // Purge search criteria
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 {
 {
+    $search_lineid = '';
 	$search_ref = '';
 	$search_ref = '';
 	$search_invoice = '';
 	$search_invoice = '';
 	$search_label = '';
 	$search_label = '';
@@ -177,7 +179,7 @@ llxHeader('', $langs->trans("Ventilation"));
 
 
 // Customer Invoice lines
 // Customer Invoice lines
 $sql = "SELECT f.facnumber, f.rowid as facid, f.datef, f.type as ftype,";
 $sql = "SELECT f.facnumber, f.rowid as facid, f.datef, f.type as ftype,";
-$sql .= " l.fk_product, l.description, l.total_ht, l.rowid, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line,";
+$sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line,";
 $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_sell as code_sell, p.tva_tx as tva_tx_prod,";
 $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_sell as code_sell, p.tva_tx as tva_tx_prod,";
 $sql .= " aa.rowid as aarowid";
 $sql .= " aa.rowid as aarowid";
 $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
 $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
@@ -189,6 +191,9 @@ $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0";
 $sql .= " AND product_type <= 2";
 $sql .= " AND product_type <= 2";
 $sql .= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_sell IS NULL OR p.accountancy_code_sell ='')";
 $sql .= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_sell IS NULL OR p.accountancy_code_sell ='')";
 // Add search filter like
 // Add search filter like
+if ($search_lineid) {
+    $sql .= natural_search("l.rowid", $search_lineid, 1);
+}
 if (strlen(trim($search_invoice))) {
 if (strlen(trim($search_invoice))) {
     $sql .= natural_search("f.facnumber",$search_invoice);
     $sql .= natural_search("f.facnumber",$search_invoice);
 }
 }
@@ -274,7 +279,7 @@ if ($result) {
 
 
 	// We add search filter
 	// We add search filter
 	print '<tr class="liste_titre_filter">';
 	print '<tr class="liste_titre_filter">';
-	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_lineid" value="' . dol_escape_htmltag($search_lineid) . '""></td>';
 	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"><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
 	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
@@ -285,7 +290,7 @@ if ($result) {
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td align="center" class="liste_titre">';
 	print '<td align="center" class="liste_titre">';
-	$searchpicto=$form->showFilterAndCheckAddButtons($massactionbutton?1:0, 'checkforselect', 1);
+	$searchpicto=$form->showFilterButtons();
 	print $searchpicto;
 	print $searchpicto;
 	print '</td>';
 	print '</td>';
 	print '</tr>';
 	print '</tr>';
@@ -303,7 +308,7 @@ if ($result) {
 	print_liste_field_titre($langs->trans("IntoAccount"), '', '', '', '', 'align="center"');
 	print_liste_field_titre($langs->trans("IntoAccount"), '', '', '', '', 'align="center"');
 	$checkpicto='';
 	$checkpicto='';
 	if ($massactionbutton) $checkpicto=$form->showCheckAddButtons('checkforselect', 1);
 	if ($massactionbutton) $checkpicto=$form->showCheckAddButtons('checkforselect', 1);
-	print_liste_field_titre($checkpitco, '', '', '', '', 'align="center"');
+	print_liste_field_titre($checkpicto, '', '', '', '', 'align="center"');
 	print "</tr>\n";
 	print "</tr>\n";
 	
 	
 	$facture_static = new Facture($db);
 	$facture_static = new Facture($db);

+ 6 - 3
htdocs/accountancy/index.php

@@ -129,15 +129,18 @@ if (! empty($conf->don->enabled))
     print "<br>\n";
     print "<br>\n";
     print "<br>\n";
     print "<br>\n";
 }*/
 }*/
+
 $step++;
 $step++;
-$textlink='<strong>'.$langs->transnoentitiesnoconv("Home").'-'.$langs->transnoentitiesnoconv("MenuBankCash").'</strong>';
-print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBank", $step, $textlink);
+print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescProd", $step, '<strong>'.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("ProductsBinding").'</strong>');
 print "<br>\n";
 print "<br>\n";
 print "<br>\n";
 print "<br>\n";
 
 
 $step++;
 $step++;
-print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescProd", $step, '<strong>'.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("ProductsBinding").'</strong>')."<br>\n";
+$textlink='<strong>'.$langs->transnoentitiesnoconv("MenuBankCash").'</strong>';
+print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBank", $step, $textlink);
 print "<br>\n";
 print "<br>\n";
+print "<br>\n";
+
 
 
 print "<br>\n";
 print "<br>\n";
 print_fiche_titre($langs->trans("AccountancyAreaDescActionFreq"), '', 'object_calendarweek');
 print_fiche_titre($langs->trans("AccountancyAreaDescActionFreq"), '', 'object_calendarweek');

+ 153 - 138
htdocs/accountancy/journal/bankjournal.php

@@ -106,7 +106,7 @@ if (empty($date_start) || empty($date_end)) // We define date_start and date_end
 $p = explode(":", $conf->global->MAIN_INFO_SOCIETE_COUNTRY);
 $p = explode(":", $conf->global->MAIN_INFO_SOCIETE_COUNTRY);
 $idpays = $p[0];
 $idpays = $p[0];
 
 
-$sql  = "SELECT b.rowid , b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type,";
+$sql  = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type,";
 $sql .= " ba.courant, ba.ref as baref, ba.account_number,";
 $sql .= " ba.courant, ba.ref as baref, ba.account_number,";
 $sql .= " soc.code_compta, soc.code_compta_fournisseur, soc.rowid as socid, soc.nom as name, bu1.type as typeop,";
 $sql .= " soc.code_compta, soc.code_compta_fournisseur, soc.rowid as socid, soc.nom as name, bu1.type as typeop,";
 $sql .= " u.accountancy_code, u.rowid as userid, u.lastname as name, u.firstname as firstname, bu2.type as typeop";
 $sql .= " u.accountancy_code, u.rowid as userid, u.lastname as name, u.firstname as firstname, bu2.type as typeop";
@@ -341,79 +341,81 @@ if (! $error && $action == 'writebookkeeping') {
 		    // Line into bank account
 		    // Line into bank account
     		foreach ( $tabbq[$key] as $k => $mt ) 
     		foreach ( $tabbq[$key] as $k => $mt ) 
     		{
     		{
-    			$bookkeeping = new BookKeeping($db);
-    			$bookkeeping->doc_date = $val["date"];
-    			$bookkeeping->doc_ref = $val["ref"];
-    			$bookkeeping->doc_type = 'bank';
-    			$bookkeeping->fk_doc = $key;
-    			$bookkeeping->fk_docdet = $val["fk_bank"];
-    			$bookkeeping->numero_compte = $k;
-    			$bookkeeping->label_compte = $compte->label;
-    			$bookkeeping->montant = ($mt < 0 ? - $mt : $mt);
-    			$bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
-    			$bookkeeping->debit = ($mt >= 0 ? $mt : 0);
-    			$bookkeeping->credit = ($mt < 0 ? - $mt : 0);
-    			$bookkeeping->code_journal = $journal;
-    			$bookkeeping->fk_user_author = $user->id;
-    			$bookkeeping->date_create = $now;
+    			if ($mt) {
+        		    $bookkeeping = new BookKeeping($db);
+        			$bookkeeping->doc_date = $val["date"];
+        			$bookkeeping->doc_ref = $val["ref"];
+        			$bookkeeping->doc_type = 'bank';
+        			$bookkeeping->fk_doc = $key;
+        			$bookkeeping->fk_docdet = $val["fk_bank"];
+        			$bookkeeping->numero_compte = $k;
+        			$bookkeeping->label_compte = $compte->label;
+        			$bookkeeping->montant = ($mt < 0 ? - $mt : $mt);
+        			$bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
+        			$bookkeeping->debit = ($mt >= 0 ? $mt : 0);
+        			$bookkeeping->credit = ($mt < 0 ? - $mt : 0);
+        			$bookkeeping->code_journal = $journal;
+        			$bookkeeping->fk_user_author = $user->id;
+        			$bookkeeping->date_create = $now;
+        
+        			if ($tabtype[$key] == 'payment') {
+        			    $bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
     
     
-    			if ($tabtype[$key] == 'payment') {
-    			    $bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
-
-    				$sqlmid = 'SELECT fac.facnumber';
-    				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture fac";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement_facture as payfac ON payfac.fk_facture=fac.rowid";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement as pay ON  payfac.fk_paiement=pay.rowid";
-    				$sqlmid .= " WHERE pay.fk_bank=" . $key;
-    				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
-    				$resultmid = $db->query($sqlmid);
-    				if ($resultmid) {
-    					$objmid = $db->fetch_object($resultmid);
-    					$bookkeeping->doc_ref = $objmid->facnumber;    // Ref of invoice
-    				}
-    			} else if ($tabtype[$key] == 'payment_supplier') {
-    			    $bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
-
-    				$sqlmid = 'SELECT facf.ref_supplier, facf.ref';
-    				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture_fourn facf";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn_facturefourn as payfacf ON payfacf.fk_facturefourn=facf.rowid";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn as payf ON  payfacf.fk_paiementfourn=payf.rowid";
-    				$sqlmid .= " WHERE payf.fk_bank=" . $key;
-    				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
-    				$resultmid = $db->query($sqlmid);
-    				if ($resultmid) {
-    					$objmid = $db->fetch_object($resultmid);
-    					$bookkeeping->doc_ref = $objmid->ref_supplier . ' (' . $objmid->ref . ')'; // Ref on invoice
-    				}
-    			} else if ($tabtype[$key] == 'payment_expensereport') {
-    			    $bookkeeping->code_tiers = $tabuser[$key]['accountancy_code'];
-
-    				$sqlmid = 'SELECT e.ref';
-    				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "expensereport as e";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "payment_expensereport as payer ON payer.fk_expensereport=e.rowid";
-    				$sqlmid .= " WHERE payer.fk_expensereport=" . $val["fk_expensereport"];
-    				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
-    				$resultmid = $db->query($sqlmid);
-    				if ($resultmid) {
-    					$objmid = $db->fetch_object($resultmid);
-    					$bookkeeping->doc_ref = $objmid->ref; // Ref of expensereport
-    				}
-    			}
+        				$sqlmid = 'SELECT fac.facnumber';
+        				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture fac";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement_facture as payfac ON payfac.fk_facture=fac.rowid";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement as pay ON  payfac.fk_paiement=pay.rowid";
+        				$sqlmid .= " WHERE pay.fk_bank=" . $key;
+        				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+        				$resultmid = $db->query($sqlmid);
+        				if ($resultmid) {
+        					$objmid = $db->fetch_object($resultmid);
+        					$bookkeeping->doc_ref = $objmid->facnumber;    // Ref of invoice
+        				}
+        			} else if ($tabtype[$key] == 'payment_supplier') {
+        			    $bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
+    
+        				$sqlmid = 'SELECT facf.ref_supplier, facf.ref';
+        				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture_fourn facf";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn_facturefourn as payfacf ON payfacf.fk_facturefourn=facf.rowid";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn as payf ON  payfacf.fk_paiementfourn=payf.rowid";
+        				$sqlmid .= " WHERE payf.fk_bank=" . $key;
+        				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+        				$resultmid = $db->query($sqlmid);
+        				if ($resultmid) {
+        					$objmid = $db->fetch_object($resultmid);
+        					$bookkeeping->doc_ref = $objmid->ref_supplier . ' (' . $objmid->ref . ')'; // Ref on invoice
+        				}
+        			} else if ($tabtype[$key] == 'payment_expensereport') {
+        			    $bookkeeping->code_tiers = $tabuser[$key]['accountancy_code'];
     
     
-    			$result = $bookkeeping->create($user);
-    			if ($result < 0) {
-    				if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
-    				{
-    					$error++;
-    					$errorforline++;
-    					//setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
-    				}
-    				else
-    				{
-	    				$error++;
-	    				$errorforline++;
-	    				setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
-    				}
+        				$sqlmid = 'SELECT e.ref';
+        				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "expensereport as e";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "payment_expensereport as payer ON payer.fk_expensereport=e.rowid";
+        				$sqlmid .= " WHERE payer.fk_expensereport=" . $val["fk_expensereport"];
+        				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+        				$resultmid = $db->query($sqlmid);
+        				if ($resultmid) {
+        					$objmid = $db->fetch_object($resultmid);
+        					$bookkeeping->doc_ref = $objmid->ref; // Ref of expensereport
+        				}
+        			}
+        
+        			$result = $bookkeeping->create($user);
+        			if ($result < 0) {
+        				if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+        				{
+        					$error++;
+        					$errorforline++;
+        					//setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+        				}
+        				else
+        				{
+    	    				$error++;
+    	    				$errorforline++;
+    	    				setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+        				}
+        			}
     			}
     			}
     		}
     		}
 		}
 		}
@@ -423,65 +425,76 @@ if (! $error && $action == 'writebookkeeping') {
 		{
 		{
 		    // Line into thirdparty account
 		    // Line into thirdparty account
     		foreach ( $tabtp[$key] as $k => $mt ) {
     		foreach ( $tabtp[$key] as $k => $mt ) {
-    			$bookkeeping = new BookKeeping($db);
-    			$bookkeeping->doc_date = $val["date"];
-    			$bookkeeping->doc_ref = $val["ref"];
-    			$bookkeeping->doc_type = 'bank';
-    			$bookkeeping->fk_doc = $key;
-    			$bookkeeping->fk_docdet = $val["fk_bank"];
-    			$bookkeeping->label_compte = $tabcompany[$key]['name'];
-    			$bookkeeping->montant = ($mt < 0 ? - $mt : $mt);
-    			$bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
-    			$bookkeeping->debit = ($mt < 0 ? - $mt : 0);
-    			$bookkeeping->credit = ($mt >= 0) ? $mt : 0;
-    			$bookkeeping->code_journal = $journal;
-    			$bookkeeping->fk_user_author = $user->id;
-    			$bookkeeping->date_create = $now;
-    
-    			if (in_array($tabtype[$key], array('sc', 'payment_sc'))) {   // If payment is payment of social contribution
-    				$bookkeeping->code_tiers = '';
-    				$bookkeeping->numero_compte = $k;
-    			} else if ($tabtype[$key] == 'payment') {    // If payment is payment of customer invoice, we get ref of invoice
-    				$sqlmid = 'SELECT fac.facnumber';
-    				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture fac ";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement_facture as payfac ON  payfac.fk_facture=fac.rowid";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement as pay ON  payfac.fk_paiement=pay.rowid";
-    				$sqlmid .= " WHERE pay.fk_bank=" . $key;
-    				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
-    				$resultmid = $db->query($sqlmid);
-    				if ($resultmid) {
-    					$objmid = $db->fetch_object($resultmid);
-    					$bookkeeping->doc_ref = $objmid->facnumber;
-    				}
-    				$bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
-    				$bookkeeping->numero_compte = $k;
-    			} else if ($tabtype[$key] == 'payment_supplier') {           // If payment is payment of supplier invoice, we get ref of invoice
-    
-    				$sqlmid = 'SELECT facf.ref_supplier,facf.ref';
-    				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture_fourn facf ";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn_facturefourn as payfacf ON  payfacf.fk_facturefourn=facf.rowid";
-    				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn as payf ON  payfacf.fk_paiementfourn=payf.rowid";
-    				$sqlmid .= " WHERE payf.fk_bank=" . $key;
-    				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
-    				$resultmid = $db->query($sqlmid);
-    				if ($resultmid) {
-    					$objmid = $db->fetch_object($resultmid);
-    					$bookkeeping->doc_ref = $objmid->ref_supplier . ' (' . $objmid->ref . ')';
-    				}
-                    $bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
-    				$bookkeeping->numero_compte = $k;
-    			} else {
-    			    // FIXME Should be a temporary account ???
-    				$bookkeeping->doc_ref = $k;
-    				//$bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
-    				$bookkeeping->numero_compte = 'CodeNotDef';
-    			}
-    
-    			$result = $bookkeeping->create($user);
-    			if ($result < 0) {
-    				$error++;
-    				$errorforline++;
-    				setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+    			if ($mt) {
+        		    $bookkeeping = new BookKeeping($db);
+        			$bookkeeping->doc_date = $val["date"];
+        			$bookkeeping->doc_ref = $val["ref"];
+        			$bookkeeping->doc_type = 'bank';
+        			$bookkeeping->fk_doc = $key;
+        			$bookkeeping->fk_docdet = $val["fk_bank"];
+        			$bookkeeping->label_compte = $tabcompany[$key]['name'];
+        			$bookkeeping->montant = ($mt < 0 ? - $mt : $mt);
+        			$bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
+        			$bookkeeping->debit = ($mt < 0 ? - $mt : 0);
+        			$bookkeeping->credit = ($mt >= 0) ? $mt : 0;
+        			$bookkeeping->code_journal = $journal;
+        			$bookkeeping->fk_user_author = $user->id;
+        			$bookkeeping->date_create = $now;
+        
+        			if (in_array($tabtype[$key], array('sc', 'payment_sc'))) {   // If payment is payment of social contribution
+        				$bookkeeping->code_tiers = '';
+        				$bookkeeping->numero_compte = $k;
+        			} else if ($tabtype[$key] == 'payment') {    // If payment is payment of customer invoice, we get ref of invoice
+        				$sqlmid = 'SELECT fac.facnumber';
+        				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture fac ";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement_facture as payfac ON  payfac.fk_facture=fac.rowid";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiement as pay ON  payfac.fk_paiement=pay.rowid";
+        				$sqlmid .= " WHERE pay.fk_bank=" . $key;
+        				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+        				$resultmid = $db->query($sqlmid);
+        				if ($resultmid) {
+        					$objmid = $db->fetch_object($resultmid);
+        					$bookkeeping->doc_ref = $objmid->facnumber;
+        				}
+        				$bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
+        				$bookkeeping->numero_compte = $k;
+        			} else if ($tabtype[$key] == 'payment_supplier') {           // If payment is payment of supplier invoice, we get ref of invoice
+        
+        				$sqlmid = 'SELECT facf.ref_supplier,facf.ref';
+        				$sqlmid .= " FROM " . MAIN_DB_PREFIX . "facture_fourn facf ";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn_facturefourn as payfacf ON  payfacf.fk_facturefourn=facf.rowid";
+        				$sqlmid .= " INNER JOIN " . MAIN_DB_PREFIX . "paiementfourn as payf ON  payfacf.fk_paiementfourn=payf.rowid";
+        				$sqlmid .= " WHERE payf.fk_bank=" . $key;
+        				dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+        				$resultmid = $db->query($sqlmid);
+        				if ($resultmid) {
+        					$objmid = $db->fetch_object($resultmid);
+        					$bookkeeping->doc_ref = $objmid->ref_supplier . ' (' . $objmid->ref . ')';
+        				}
+                        $bookkeeping->code_tiers = $tabcompany[$key]['code_compta'];
+        				$bookkeeping->numero_compte = $k;
+        			} else {
+        			    // FIXME Should be a temporary account ???
+        				$bookkeeping->doc_ref = $k;
+        				//$bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
+        				$bookkeeping->numero_compte = 'CodeNotDef';
+        			}
+        
+        			$result = $bookkeeping->create($user);
+        			if ($result < 0) {
+        				if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+        				{
+        					$error++;
+        					$errorforline++;
+        					//setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+        				}
+        				else
+        				{
+    	    				$error++;
+    	    				$errorforline++;
+    	    				setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+        				}
+        			}
     			}
     			}
     		}
     		}
 		}
 		}
@@ -512,6 +525,7 @@ if (! $error && $action == 'writebookkeeping') {
 }
 }
 
 
 // Export
 // Export
+/*
 if ($action == 'export_csv') {
 if ($action == 'export_csv') {
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 
 
@@ -678,7 +692,7 @@ if ($action == 'export_csv') {
 		}
 		}
 	}
 	}
 }
 }
-
+*/
 
 
 
 
 
 
@@ -702,18 +716,19 @@ if (empty($action) || $action == 'view') {
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
 
 
 	$varlink = 'id_account=' . $id_bank_account;
 	$varlink = 'id_account=' . $id_bank_account;
-	report_header($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array (
-			'action' => ''
-	), '', $varlink);
+	
+	journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
 
 
-	if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
+	/*if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans('Export') . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans('Export') . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 	} else {
 	} else {
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
-	}
+	}*/
 
 
+    print '<div class="tabsAction">';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-
+    print '</div>';
+    
 	// TODO Avoid using js. We can use a direct link with $param
 	// TODO Avoid using js. We can use a direct link with $param
 	print '
 	print '
 	<script type="text/javascript">
 	<script type="text/javascript">

+ 146 - 104
htdocs/accountancy/journal/expensereportsjournal.php

@@ -157,100 +157,140 @@ if ($action == 'writebookkeeping') {
 	{
 	{
 		$errorforline = 0;
 		$errorforline = 0;
 
 
-		foreach ( $tabttc[$key] as $k => $mt ) {
-			// get compte id and label
-
-			$bookkeeping = new BookKeeping($db);
-			$bookkeeping->doc_date = $val["date"];
-			$bookkeeping->doc_ref = $val["ref"];
-			$bookkeeping->date_create = $now;
-			$bookkeeping->doc_type = 'expense_report';
-			$bookkeeping->fk_doc = $key;
-			$bookkeeping->fk_docdet = $val["fk_expensereportdet"];
-			$bookkeeping->code_tiers = $tabuser[$key]['user_accountancy_code'];
-			$bookkeeping->label_compte = $tabuser[$key]['name'];
-			$bookkeeping->numero_compte = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT;
-			$bookkeeping->montant = $mt;
-			$bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
-			$bookkeeping->debit = ($mt <= 0) ? $mt : 0;
-			$bookkeeping->credit = ($mt > 0) ? $mt : 0;
-			$bookkeeping->code_journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
-			$bookkeeping->fk_user_author = $user->id;
-
-			$result = $bookkeeping->create($user);
-			if ($result < 0) {
-				$error++;
-				$errorforline++;
-				setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
-			}
-		}
-
-		// Fees
-		foreach ( $tabht[$key] as $k => $mt ) {
-			$accountingaccount = new AccountingAccount($db);
-			$accountingaccount->fetch(null, $k, true);
-			if ($mt) {
-				// get compte id and label
-				$accountingaccount = new AccountingAccount($db);
-				if ($accountingaccount->fetch(null, $k, true)) {
-					$bookkeeping = new BookKeeping($db);
-					$bookkeeping->doc_date = $val["date"];
-					$bookkeeping->doc_ref = $val["ref"];
-					$bookkeeping->date_create = $now;
-					$bookkeeping->doc_type = 'expense_report';
-					$bookkeeping->fk_doc = $key;
-					$bookkeeping->fk_docdet = $val["fk_expensereportdet"];
-					$bookkeeping->code_tiers = '';
-					$bookkeeping->label_compte = $accountingaccount->label;
-					$bookkeeping->numero_compte = $k;
-					$bookkeeping->montant = $mt;
-					$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
-					$bookkeeping->debit = ($mt > 0) ? $mt : 0;
-					$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
-					$bookkeeping->code_journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
-					$bookkeeping->fk_user_author = $user->id;
-
-					$result = $bookkeeping->create($user);
-					if ($result < 0) {
-						$error++;
-						$errorforline++;
-						setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
-					}
-				}
-			}
-		}
-
-		// VAT
-		// var_dump($tabtva);
-		foreach ( $tabtva[$key] as $k => $mt ) {
-			if ($mt) {
-				// get compte id and label
-				$bookkeeping = new BookKeeping($db);
-				$bookkeeping->doc_date = $val["date"];
-				$bookkeeping->doc_ref = $val["ref"];
-				$bookkeeping->date_create = $now;
-				$bookkeeping->doc_type = 'expense_report';
-				$bookkeeping->fk_doc = $key;
-				$bookkeeping->fk_docdet = $val["fk_expensereportdet"];
-				$bookkeeping->code_tiers = '';
-				$bookkeeping->label_compte = $langs->trans("VAT"). ' '.$def_tva[$key];
-				$bookkeeping->numero_compte = $k;
-				$bookkeeping->montant = $mt;
-				$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
-				$bookkeeping->debit = ($mt > 0) ? $mt : 0;
-				$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
-				$bookkeeping->code_journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
-				$bookkeeping->fk_user_author = $user->id;
-
-				$result = $bookkeeping->create($user);
-				if ($result < 0) {
-					$error++;
-					$errorforline++;
-					setEventMessages($object->error, $object->errors, 'errors');
-				}
-			}
-		}
-
+	    $db->begin();
+	     
+        if (! $errorforline)
+        {
+    	    foreach ( $tabttc[$key] as $k => $mt ) {
+    			if ($mt) {
+        	        // get compte id and label
+        
+        			$bookkeeping = new BookKeeping($db);
+        			$bookkeeping->doc_date = $val["date"];
+        			$bookkeeping->doc_ref = $val["ref"];
+        			$bookkeeping->date_create = $now;
+        			$bookkeeping->doc_type = 'expense_report';
+        			$bookkeeping->fk_doc = $key;
+        			$bookkeeping->fk_docdet = $val["fk_expensereportdet"];
+        			$bookkeeping->code_tiers = $tabuser[$key]['user_accountancy_code'];
+        			$bookkeeping->label_compte = $tabuser[$key]['name'];
+        			$bookkeeping->numero_compte = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT;
+        			$bookkeeping->montant = $mt;
+        			$bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
+        			$bookkeeping->debit = ($mt <= 0) ? $mt : 0;
+        			$bookkeeping->credit = ($mt > 0) ? $mt : 0;
+        			$bookkeeping->code_journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
+        			$bookkeeping->fk_user_author = $user->id;
+        
+        			$result = $bookkeeping->create($user);
+        			if ($result < 0) {
+        			    if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+        			    {
+        			        $error++;
+        			        $errorforline++;
+        			        //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+        			    }
+        			    else
+        			    {
+        			        $error++;
+        			        $errorforline++;
+        			        setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+        			    }
+        			}
+    			}
+    		}
+        }
+        
+        if (! $errorforline)
+        {
+            // Fees
+    		foreach ( $tabht[$key] as $k => $mt ) {
+    			$accountingaccount = new AccountingAccount($db);
+    			$accountingaccount->fetch(null, $k, true);
+    			if ($mt) {
+    				// get compte id and label
+    				$accountingaccount = new AccountingAccount($db);
+    				if ($accountingaccount->fetch(null, $k, true)) {
+    					$bookkeeping = new BookKeeping($db);
+    					$bookkeeping->doc_date = $val["date"];
+    					$bookkeeping->doc_ref = $val["ref"];
+    					$bookkeeping->date_create = $now;
+    					$bookkeeping->doc_type = 'expense_report';
+    					$bookkeeping->fk_doc = $key;
+    					$bookkeeping->fk_docdet = $val["fk_expensereportdet"];
+    					$bookkeeping->code_tiers = '';
+    					$bookkeeping->label_compte = $accountingaccount->label;
+    					$bookkeeping->numero_compte = $k;
+    					$bookkeeping->montant = $mt;
+    					$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
+    					$bookkeeping->debit = ($mt > 0) ? $mt : 0;
+    					$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
+    					$bookkeeping->code_journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
+    					$bookkeeping->fk_user_author = $user->id;
+    
+    					$result = $bookkeeping->create($user);
+	        			if ($result < 0) {
+            			    if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+            			    {
+            			        $error++;
+            			        $errorforline++;
+            			        //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+            			    }
+            			    else
+            			    {
+            			        $error++;
+            			        $errorforline++;
+            			        setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+            			    }
+	        			}
+    				}
+    			}
+    		}
+        }
+        
+        if (! $errorforline)
+        {
+            // VAT
+    		// var_dump($tabtva);
+    		foreach ( $tabtva[$key] as $k => $mt ) {
+    			if ($mt) {
+    				// get compte id and label
+    				$bookkeeping = new BookKeeping($db);
+    				$bookkeeping->doc_date = $val["date"];
+    				$bookkeeping->doc_ref = $val["ref"];
+    				$bookkeeping->date_create = $now;
+    				$bookkeeping->doc_type = 'expense_report';
+    				$bookkeeping->fk_doc = $key;
+    				$bookkeeping->fk_docdet = $val["fk_expensereportdet"];
+    				$bookkeeping->code_tiers = '';
+    				$bookkeeping->label_compte = $langs->trans("VAT"). ' '.$def_tva[$key];
+    				$bookkeeping->numero_compte = $k;
+    				$bookkeeping->montant = $mt;
+    				$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
+    				$bookkeeping->debit = ($mt > 0) ? $mt : 0;
+    				$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
+    				$bookkeeping->code_journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
+    				$bookkeeping->fk_user_author = $user->id;
+    
+    				$result = $bookkeeping->create($user);
+    				if ($result < 0) {
+           			    if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+        			    {
+        			        $error++;
+        			        $errorforline++;
+        			        //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+        			    }
+        			    else
+        			    {
+        			        $error++;
+        			        $errorforline++;
+        			        setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+        			    }
+    				}
+    			}
+    		}
+        }
+        
 		if (! $errorforline)
 		if (! $errorforline)
 		{
 		{
 		    $db->commit();
 		    $db->commit();
@@ -286,7 +326,7 @@ $form = new Form($db);
 $userstatic = new User($db);
 $userstatic = new User($db);
 
 
 // Export
 // Export
-if ($action == 'export_csv') {
+/*if ($action == 'export_csv') {
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 	$journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
 	$journal = $conf->global->ACCOUNTING_EXPENSEREPORT_JOURNAL;
 
 
@@ -393,6 +433,7 @@ if ($action == 'export_csv') {
 		}
 		}
 	}
 	}
 }
 }
+*/
 
 
 if (empty($action) || $action == 'view') {
 if (empty($action) || $action == 'view') {
 
 
@@ -406,18 +447,19 @@ if (empty($action) || $action == 'view') {
 	$description.= $langs->trans("DescJournalOnlyBindedVisible").'<br>';
 	$description.= $langs->trans("DescJournalOnlyBindedVisible").'<br>';
 
 
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
-	report_header($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array (
-			'action' => ''
-	));
 
 
-	if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
+	journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''));
+
+	/*if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans("Export") . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans("Export") . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 	} else {
 	} else {
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
-	}
+	}*/
 
 
+    print '<div class="tabsAction">';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-
+    print '</div>';
+    
 	print '
 	print '
 	<script type="text/javascript">
 	<script type="text/javascript">
 		function launch_export() {
 		function launch_export() {
@@ -511,11 +553,11 @@ if (empty($action) || $action == 'view') {
 				print "</tr>";
 				print "</tr>";
 			}
 			}
 		}
 		}
-		print '<tr class="oddeven">';
 
 
 		// Third party
 		// Third party
 		foreach ( $tabttc[$key] as $k => $mt ) {
 		foreach ( $tabttc[$key] as $k => $mt ) {
-			print "<td><!-- Thirdparty --></td>";
+		    print '<tr class="oddeven">';
+		    print "<td><!-- Thirdparty --></td>";
 		    print "<td>" . $date . "</td>";
 		    print "<td>" . $date . "</td>";
 			print "<td>" . $expensereportstatic->getNomUrl(1) . "</td>";
 			print "<td>" . $expensereportstatic->getNomUrl(1) . "</td>";
 			$userstatic->id = $tabuser[$key]['id'];
 			$userstatic->id = $tabuser[$key]['id'];
@@ -531,8 +573,8 @@ if (empty($action) || $action == 'view') {
 			print "<td>" . $userstatic->getNomUrl(0, 'user', 16) . ' - ' . $langs->trans("Code_tiers") . "</td>";
 			print "<td>" . $userstatic->getNomUrl(0, 'user', 16) . ' - ' . $langs->trans("Code_tiers") . "</td>";
 			print '<td align="right">' . ($mt < 0 ? - price(- $mt) : '') . "</td>";
 			print '<td align="right">' . ($mt < 0 ? - price(- $mt) : '') . "</td>";
 			print '<td align="right">' . ($mt >= 0 ? price($mt) : '') . "</td>";
 			print '<td align="right">' . ($mt >= 0 ? price($mt) : '') . "</td>";
+		    print "</tr>";
 		}
 		}
-		print "</tr>";
 	}
 	}
 
 
 	print "</table>";
 	print "</table>";

+ 153 - 106
htdocs/accountancy/journal/purchasesjournal.php

@@ -109,6 +109,7 @@ dol_syslog('accountancy/journal/purchasesjournal.php:: $sql=' . $sql);
 $result = $db->query($sql);
 $result = $db->query($sql);
 if ($result) {
 if ($result) {
 	$num = $db->num_rows($result);
 	$num = $db->num_rows($result);
+
 	// les variables
 	// les variables
 	$cptfour = (! empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER)) ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : $langs->trans("CodeNotDef");
 	$cptfour = (! empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER)) ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : $langs->trans("CodeNotDef");
 	$cpttva = (! empty($conf->global->ACCOUNTING_VAT_BUY_ACCOUNT)) ? $conf->global->ACCOUNTING_VAT_BUY_ACCOUNT : $langs->trans("CodeNotDef");
 	$cpttva = (! empty($conf->global->ACCOUNTING_VAT_BUY_ACCOUNT)) ? $conf->global->ACCOUNTING_VAT_BUY_ACCOUNT : $langs->trans("CodeNotDef");
@@ -123,8 +124,10 @@ if ($result) {
 	$i = 0;
 	$i = 0;
 	while ( $i < $num ) {
 	while ( $i < $num ) {
 		$obj = $db->fetch_object($result);
 		$obj = $db->fetch_object($result);
+
 		// contrôles
 		// contrôles
 		$compta_soc = (! empty($obj->code_compta_fournisseur)) ? $obj->code_compta_fournisseur : $cptfour;
 		$compta_soc = (! empty($obj->code_compta_fournisseur)) ? $obj->code_compta_fournisseur : $cptfour;
+		
 		$compta_prod = $obj->compte;
 		$compta_prod = $obj->compte;
 		if (empty($compta_prod)) {
 		if (empty($compta_prod)) {
 			if ($obj->product_type == 0)
 			if ($obj->product_type == 0)
@@ -144,14 +147,21 @@ if ($result) {
 
 
 		$tabfac[$obj->rowid]["type"] = $obj->type;
 		$tabfac[$obj->rowid]["type"] = $obj->type;
 		$tabfac[$obj->rowid]["description"] = $obj->description;
 		$tabfac[$obj->rowid]["description"] = $obj->description;
-		$tabfac[$obj->rowid]["fk_facturefourndet"] = $obj->fdid;
+		//$tabfac[$obj->rowid]["fk_facturefourndet"] = $obj->fdid;
+		
+        // Avoid warnings
+        if (! isset($tabttc[$obj->rowid][$compta_soc])) $tabttc[$obj->rowid][$compta_soc] = 0;
+        if (! isset($tabht[$obj->rowid][$compta_prod])) $tabht[$obj->rowid][$compta_prod] = 0;
+        if (! isset($tabtva[$obj->rowid][$compta_tva])) $tabtva[$obj->rowid][$compta_tva] = 0;
+
 		$tabttc[$obj->rowid][$compta_soc] += $obj->total_ttc;
 		$tabttc[$obj->rowid][$compta_soc] += $obj->total_ttc;
 		$tabht[$obj->rowid][$compta_prod] += $obj->total_ht;
 		$tabht[$obj->rowid][$compta_prod] += $obj->total_ht;
 		$tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
 		$tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
 		$tabcompany[$obj->rowid] = array (
 		$tabcompany[$obj->rowid] = array (
 				'id' => $obj->socid,
 				'id' => $obj->socid,
 				'name' => $obj->name,
 				'name' => $obj->name,
-				'code_fournisseur' => $obj->code_compta_fournisseur
+				'code_fournisseur' => $obj->code_fournisseur,
+				'code_compta_fournisseur' => $compta_soc
 		);
 		);
 
 
 		$i ++;
 		$i ++;
@@ -165,7 +175,7 @@ if ($action == 'writebookkeeping') {
 	$now = dol_now();
 	$now = dol_now();
 	$error = 0;
 	$error = 0;
 
 
-	foreach ($tabfac as $key => $val)
+	foreach ($tabfac as $key => $val)  // Loop on each invoice
 	{
 	{
 	    $errorforline = 0;
 	    $errorforline = 0;
 	     
 	     
@@ -188,101 +198,136 @@ if ($action == 'writebookkeeping') {
 		$companystatic->code_fournisseur = $tabcompany[$key]['code_fournisseur'];
 		$companystatic->code_fournisseur = $tabcompany[$key]['code_fournisseur'];
 		$companystatic->client = $tabcompany[$key]['code_client'];
 		$companystatic->client = $tabcompany[$key]['code_client'];
 
 
-		foreach ( $tabttc[$key] as $k => $mt ) {
-			// get compte id and label
-
-			$bookkeeping = new BookKeeping($db);
-			$bookkeeping->doc_date = $val["date"];
-			$bookkeeping->doc_ref = $val["ref"];
-			$bookkeeping->date_create = $now;
-			$bookkeeping->doc_type = 'supplier_invoice';
-			$bookkeeping->fk_doc = $key;
-			$bookkeeping->fk_docdet = $val["fk_facturefourndet"];
-			$bookkeeping->code_tiers = $tabcompany[$key]['code_fournisseur'];
-			$bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->refsupplier . ' - ' . $langs->trans("Code_tiers");
-			$bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
-			$bookkeeping->montant = $mt;
-			$bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
-			$bookkeeping->debit = ($mt <= 0) ? $mt : 0;
-			$bookkeeping->credit = ($mt > 0) ? $mt : 0;
-			$bookkeeping->code_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
-			$bookkeeping->fk_user_author = $user->id;
-
-			$result = $bookkeeping->create($user);
-			if ($result < 0) {
-			    $error++;
-			    $errorforline++;
-			    setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
-			}
-		}
-
+        if (! $errorforline)
+        {
+    		foreach ( $tabttc[$key] as $k => $mt ) {
+    			// get compte id and label
+    		    if ($mt) {
+        			$bookkeeping = new BookKeeping($db);
+        			$bookkeeping->doc_date = $val["date"];
+        			$bookkeeping->doc_ref = $val["ref"];
+        			$bookkeeping->date_create = $now;
+        			$bookkeeping->doc_type = 'supplier_invoice';
+        			$bookkeeping->fk_doc = $key;
+        			$bookkeeping->fk_docdet = 0;    // Useless, can be several lines that are source of this record to add
+        			$bookkeeping->code_tiers = $tabcompany[$key]['code_fournisseur'];
+        			$bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->refsupplier . ' - ' . $langs->trans("Code_tiers");
+        			$bookkeeping->numero_compte = $tabcompany[$key]['code_compta_fournisseur'];
+        			$bookkeeping->montant = $mt;
+        			$bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
+        			$bookkeeping->debit = ($mt <= 0) ? $mt : 0;
+        			$bookkeeping->credit = ($mt > 0) ? $mt : 0;
+        			$bookkeeping->code_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
+        			$bookkeeping->fk_user_author = $user->id;
+        
+        			$result = $bookkeeping->create($user);
+           			if ($result < 0) {
+                        if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+                        {
+                            $error++;
+                            $errorforline++;
+                            //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+                        }
+                        else
+                        {
+                            $error++;
+                            $errorforline++;
+                            setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+                        }
+        			}
+    		    }
+    		}
+        }
+        
 		// Product / Service
 		// Product / Service
-		foreach ( $tabht[$key] as $k => $mt ) {
-			$accountingaccount = new AccountingAccount($db);
-			$accountingaccount->fetch(null, $k, true);
-			if ($mt) {
-				// get compte id and label
-				$accountingaccount = new AccountingAccount($db);
-				if ($accountingaccount->fetch(null, $k, true)) {
-					$bookkeeping = new BookKeeping($db);
-					$bookkeeping->doc_date = $val["date"];
-					$bookkeeping->doc_ref = $val["ref"];
-					$bookkeeping->date_create = $now;
-					$bookkeeping->doc_type = 'supplier_invoice';
-					$bookkeeping->fk_doc = $key;
-					$bookkeeping->fk_docdet = $val["fk_facturefourndet"];
-					$bookkeeping->code_tiers = '';
-					$bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->refsupplier . ' - ' . $accountingaccount->label;
-					$bookkeeping->numero_compte = $k;
-					$bookkeeping->montant = $mt;
-					$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
-					$bookkeeping->debit = ($mt > 0) ? $mt : 0;
-					$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
-					$bookkeeping->code_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
-					$bookkeeping->fk_user_author = $user->id;
-
-					$result = $bookkeeping->create($user);
-					if ($result < 0) {
-						$error++;
-						$errorforline++;
-						setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
-					}
-				}
-			}
-		}
-
+        if (! $errorforline)
+        {
+            foreach ( $tabht[$key] as $k => $mt ) {
+    			$accountingaccount = new AccountingAccount($db);
+    			$accountingaccount->fetch(null, $k, true);
+    			if ($mt) {
+    				// get compte id and label
+    				$accountingaccount = new AccountingAccount($db);
+    				if ($accountingaccount->fetch(null, $k, true)) {
+    					$bookkeeping = new BookKeeping($db);
+    					$bookkeeping->doc_date = $val["date"];
+    					$bookkeeping->doc_ref = $val["ref"];
+    					$bookkeeping->date_create = $now;
+    					$bookkeeping->doc_type = 'supplier_invoice';
+    					$bookkeeping->fk_doc = $key;
+    					$bookkeeping->fk_docdet = 0;    // Useless, can be several lines that are source of this record to add
+    					$bookkeeping->code_tiers = '';
+    					$bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->refsupplier . ' - ' . $accountingaccount->label;
+    					$bookkeeping->numero_compte = $k;
+    					$bookkeeping->montant = $mt;
+    					$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
+    					$bookkeeping->debit = ($mt > 0) ? $mt : 0;
+    					$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
+    					$bookkeeping->code_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
+    					$bookkeeping->fk_user_author = $user->id;
+    
+    					$result = $bookkeeping->create($user);
+    					if ($result < 0) {
+    					    if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+            			    {
+            			        $error++;
+            			        $errorforline++;
+            			        //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+            			    }
+            			    else
+            			    {
+            			        $error++;
+            			        $errorforline++;
+            			        setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+            			    }
+    					}
+    				}
+    			}
+    		}
+        }
+        
 		// VAT
 		// VAT
 		// var_dump($tabtva);
 		// var_dump($tabtva);
-		foreach ( $tabtva[$key] as $k => $mt ) {
-			if ($mt) {
-				// get compte id and label
-				$bookkeeping = new BookKeeping($db);
-				$bookkeeping->doc_date = $val["date"];
-				$bookkeeping->doc_ref = $val["ref"];
-				$bookkeeping->date_create = $now;
-				$bookkeeping->doc_type = 'supplier_invoice';
-				$bookkeeping->fk_doc = $key;
-				$bookkeeping->fk_docdet = $val["fk_facturefourndet"];
-				$bookkeeping->code_tiers = '';
-				$bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->refsupplier . ' - ' . $langs->trans("VAT"). ' '.$def_tva[$key];
-				$bookkeeping->numero_compte = $k;
-				$bookkeeping->montant = $mt;
-				$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
-				$bookkeeping->debit = ($mt > 0) ? $mt : 0;
-				$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
-				$bookkeeping->code_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
-				$bookkeeping->fk_user_author = $user->id;
-
-				$result = $bookkeeping->create($user);
-				if ($result < 0) {
-					$error++;
-					$errorforline++;
-					setEventMessages($object->error, $object->errors, 'errors');
-				}
-			}
-		}
-		
-
+        if (! $errorforline)
+        {
+            foreach ( $tabtva[$key] as $k => $mt ) {
+    			if ($mt) {
+    				// get compte id and label
+    				$bookkeeping = new BookKeeping($db);
+    				$bookkeeping->doc_date = $val["date"];
+    				$bookkeeping->doc_ref = $val["ref"];
+    				$bookkeeping->date_create = $now;
+    				$bookkeeping->doc_type = 'supplier_invoice';
+    				$bookkeeping->fk_doc = $key;
+    				$bookkeeping->fk_docdet = 0;    // Useless, can be several lines that are source of this record to add
+    				$bookkeeping->code_tiers = '';
+    				$bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->refsupplier . ' - ' . $langs->trans("VAT"). ' '.$def_tva[$key];
+    				$bookkeeping->numero_compte = $k;
+    				$bookkeeping->montant = $mt;
+    				$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
+    				$bookkeeping->debit = ($mt > 0) ? $mt : 0;
+    				$bookkeeping->credit = ($mt <= 0) ? $mt : 0;
+    				$bookkeeping->code_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
+    				$bookkeeping->fk_user_author = $user->id;
+    
+    				$result = $bookkeeping->create($user);
+    				if ($result < 0) {
+    				    if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+    				    {
+    				        $error++;
+    				        $errorforline++;
+    				        //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+    				    }
+    				    else
+    				    {
+    				        $error++;
+    				        $errorforline++;
+    				        setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+    				    }
+    				}
+    			}
+    		}
+        }
 
 
 		if (! $errorforline)
 		if (! $errorforline)
 		{
 		{
@@ -319,7 +364,7 @@ $form = new Form($db);
 $companystatic = new Fournisseur($db);
 $companystatic = new Fournisseur($db);
 
 
 // Export
 // Export
-if ($action == 'export_csv') {
+/*if ($action == 'export_csv') {
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 	$journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
 	$journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL;
 
 
@@ -437,6 +482,7 @@ if ($action == 'export_csv') {
 		}
 		}
 	}
 	}
 }
 }
+*/
 
 
 if (empty($action) || $action == 'view') {
 if (empty($action) || $action == 'view') {
 
 
@@ -456,18 +502,19 @@ if (empty($action) || $action == 'view') {
 	}
 	}
 
 
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
-	report_header($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array (
-			'action' => ''
-	));
+	
+	journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''));
 
 
-	if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
+	/*if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans("Export") . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans("Export") . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 	} else {
 	} else {
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
-	}
+	}*/
 
 
+    print '<div class="tabsAction">';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-
+    print '</div>';
+    
 	print '
 	print '
 	<script type="text/javascript">
 	<script type="text/javascript">
 		function launch_export() {
 		function launch_export() {
@@ -485,7 +532,7 @@ if (empty($action) || $action == 'view') {
 	/*
 	/*
 	 * Show result array
 	 * Show result array
 	 */
 	 */
-	print '<br><br>';
+	print '<br>';
 
 
 	$i = 0;
 	$i = 0;
 	print "<table class=\"noborder\" width=\"100%\">";
 	print "<table class=\"noborder\" width=\"100%\">";
@@ -562,11 +609,11 @@ if (empty($action) || $action == 'view') {
 				print "</tr>";
 				print "</tr>";
 			}
 			}
 		}
 		}
-		print '<tr class="oddeven">';
 
 
 		// Third party
 		// Third party
 		foreach ( $tabttc[$key] as $k => $mt ) {
 		foreach ( $tabttc[$key] as $k => $mt ) {
-			print "<td><!-- Thirdparty --></td>";
+		    print '<tr class="oddeven">';
+		    print "<td><!-- Thirdparty --></td>";
 		    print "<td>" . $date . "</td>";
 		    print "<td>" . $date . "</td>";
 			print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
 			print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
 			$companystatic->id = $tabcompany[$key]['id'];
 			$companystatic->id = $tabcompany[$key]['id'];
@@ -585,8 +632,8 @@ if (empty($action) || $action == 'view') {
 			// print "</td>";
 			// print "</td>";
 			print '<td align="right">' . ($mt < 0 ? - price(- $mt) : '') . "</td>";
 			print '<td align="right">' . ($mt < 0 ? - price(- $mt) : '') . "</td>";
 			print '<td align="right">' . ($mt >= 0 ? price($mt) : '') . "</td>";
 			print '<td align="right">' . ($mt >= 0 ? price($mt) : '') . "</td>";
+		    print "</tr>";
 		}
 		}
-		print "</tr>";
 	}
 	}
 
 
 	print "</table>";
 	print "</table>";

+ 139 - 97
htdocs/accountancy/journal/sellsjournal.php

@@ -100,7 +100,7 @@ $sql .= " JOIN " . MAIN_DB_PREFIX . "societe as s ON s.rowid = f.fk_soc";
 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_tva as ct ON fd.tva_tx = ct.taux AND ct.fk_pays = '" . $idpays . "'";
 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_tva as ct ON fd.tva_tx = ct.taux AND ct.fk_pays = '" . $idpays . "'";
 $sql .= " WHERE fd.fk_code_ventilation > 0";
 $sql .= " WHERE fd.fk_code_ventilation > 0";
 $sql .= " AND f.entity IN (".getEntity('facture', 0).')';    // We don't share object for accountancy
 $sql .= " AND f.entity IN (".getEntity('facture', 0).')';    // We don't share object for accountancy
-$sql .= " AND f.fk_statut > 0";
+$sql .= " AND f.fk_statut > 0"; // TODO Facture annulée ?
 if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
 if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
     $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
     $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")";
 } else {
 } else {
@@ -124,10 +124,12 @@ if ($result) {
     $num = $db->num_rows($result);
     $num = $db->num_rows($result);
     $i = 0;
     $i = 0;
 
 
+    $cptcli = (! empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER)) ? $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER : $langs->trans("CodeNotDef");
+    
     while ( $i < $num ) {
     while ( $i < $num ) {
         $obj = $db->fetch_object($result);
         $obj = $db->fetch_object($result);
+        
         // les variables
         // les variables
-        $cptcli = (! empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER)) ? $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER : $langs->trans("CodeNotDef");
         $compta_soc = (! empty($obj->code_compta)) ? $obj->code_compta : $cptcli;
         $compta_soc = (! empty($obj->code_compta)) ? $obj->code_compta : $cptcli;
 
 
         $compta_prod = $obj->compte;
         $compta_prod = $obj->compte;
@@ -164,23 +166,24 @@ if ($result) {
         $tabfac[$obj->rowid]["ref"] = $obj->facnumber;
         $tabfac[$obj->rowid]["ref"] = $obj->facnumber;
         $tabfac[$obj->rowid]["type"] = $obj->type;
         $tabfac[$obj->rowid]["type"] = $obj->type;
         $tabfac[$obj->rowid]["description"] = $obj->label_compte;
         $tabfac[$obj->rowid]["description"] = $obj->label_compte;
-        $tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid;
-        if (! isset($tabttc[$obj->rowid][$compta_soc]))
-            $tabttc[$obj->rowid][$compta_soc] = 0;
-            if (! isset($tabht[$obj->rowid][$compta_prod]))
-                $tabht[$obj->rowid][$compta_prod] = 0;
-                if (! isset($tabtva[$obj->rowid][$compta_tva]))
-                    $tabtva[$obj->rowid][$compta_tva] = 0;
-                    $tabttc[$obj->rowid][$compta_soc] += $obj->total_ttc * $situation_ratio;
-                    $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio;
-                    $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio;
-                    $tabcompany[$obj->rowid] = array (
-                        'id' => $obj->socid,
-                        'name' => $obj->name,
-                        'code_client' => $obj->code_compta
-                    );
-
-                    $i ++;
+        //$tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid;
+       
+        // Avoid warnings
+        if (! isset($tabttc[$obj->rowid][$compta_soc])) $tabttc[$obj->rowid][$compta_soc] = 0;
+        if (! isset($tabht[$obj->rowid][$compta_prod])) $tabht[$obj->rowid][$compta_prod] = 0;
+        if (! isset($tabtva[$obj->rowid][$compta_tva])) $tabtva[$obj->rowid][$compta_tva] = 0;
+
+        $tabttc[$obj->rowid][$compta_soc] += $obj->total_ttc * $situation_ratio;
+        $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio;
+        $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio;
+        $tabcompany[$obj->rowid] = array (
+            'id' => $obj->socid,
+            'name' => $obj->name,
+            'code_client' => $obj->code_client,
+            'code_compta' => $compta_soc
+        );
+
+        $i ++;
     }
     }
 } else {
 } else {
     dol_print_error($db);
     dol_print_error($db);
@@ -191,7 +194,7 @@ if ($action == 'writebookkeeping') {
     $now = dol_now();
     $now = dol_now();
     $error = 0;
     $error = 0;
 
 
-    foreach ( $tabfac as $key => $val ) {
+    foreach ( $tabfac as $key => $val ) {   // Loop on each invoice
          
          
         $errorforline = 0;
         $errorforline = 0;
 
 
@@ -211,97 +214,135 @@ if ($action == 'writebookkeeping') {
         $invoicestatic->id = $key;
         $invoicestatic->id = $key;
         $invoicestatic->ref = (string) $val["ref"];
         $invoicestatic->ref = (string) $val["ref"];
 
 
-        foreach ( $tabttc[$key] as $k => $mt ) {
-            $bookkeeping = new BookKeeping($db);
-            $bookkeeping->doc_date = $val["date"];
-            $bookkeeping->doc_ref = $val["ref"];
-            $bookkeeping->date_create = $now;
-            $bookkeeping->doc_type = 'customer_invoice';
-            $bookkeeping->fk_doc = $key;
-            $bookkeeping->fk_docdet = $val["fk_facturedet"];
-            $bookkeeping->code_tiers = $tabcompany[$key]['code_client'];
-            $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
-            // $bookkeeping->label_compte = $tabcompany[$key]['name'];
-            $bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers");
-            $bookkeeping->montant = $mt;
-            $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
-            $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
-            $bookkeeping->credit = ($mt < 0) ? $mt : 0;
-            $bookkeeping->code_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
-            $bookkeeping->fk_user_author = $user->id;
-
-            $result = $bookkeeping->create($user);
-            if ($result < 0) {
-                $error++;
-                $errorforline++;
-                setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+        // Thirdparty
+        if (! $errorforline)
+        {
+            foreach ( $tabttc[$key] as $k => $mt ) {
+                if ($mt) {
+                    $bookkeeping = new BookKeeping($db);
+                    $bookkeeping->doc_date = $val["date"];
+                    $bookkeeping->doc_ref = $val["ref"];
+                    $bookkeeping->date_create = $now;
+                    $bookkeeping->doc_type = 'customer_invoice';
+                    $bookkeeping->fk_doc = $key;
+                    $bookkeeping->fk_docdet = 0;    // Useless, can be several lines that are source of this record to add
+                    $bookkeeping->code_tiers = $tabcompany[$key]['code_client'];
+                    $bookkeeping->numero_compte = $tabcompany[$key]['code_compta'];
+                    // $bookkeeping->label_compte = $tabcompany[$key]['name'];
+                    $bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers");
+                    $bookkeeping->montant = $mt;
+                    $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
+                    $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
+                    $bookkeeping->credit = ($mt < 0) ? $mt : 0;
+                    $bookkeeping->code_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
+                    $bookkeeping->fk_user_author = $user->id;
+    
+                    $result = $bookkeeping->create($user);
+           			if ($result < 0) {
+                        if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+                        {
+                            $error++;
+                            $errorforline++;
+                            //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+                        }
+                        else
+                        {
+                            $error++;
+                            $errorforline++;
+                            setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+                        }
+        			}
+                }
             }
             }
         }
         }
-
+        
         // Product / Service
         // Product / Service
-        foreach ( $tabht[$key] as $k => $mt ) {
-            if ($mt) {
-                // get compte id and label
-                $accountingaccount = new AccountingAccount($db);
-                if ($accountingaccount->fetch(null, $k, true)) {
+        if (! $errorforline)
+        {
+            foreach ( $tabht[$key] as $k => $mt ) {
+                if ($mt) {
+                    // get compte id and label
+                    $accountingaccount = new AccountingAccount($db);
+                    if ($accountingaccount->fetch(null, $k, true)) {
+                        $bookkeeping = new BookKeeping($db);
+                        $bookkeeping->doc_date = $val["date"];
+                        $bookkeeping->doc_ref = $val["ref"];
+                        $bookkeeping->date_create = $now;
+                        $bookkeeping->doc_type = 'customer_invoice';
+                        $bookkeeping->fk_doc = $key;
+                        $bookkeeping->fk_docdet = 0;    // Useless, can be several lines that are source of this record to add;
+                        $bookkeeping->code_tiers = '';
+                        $bookkeeping->numero_compte = $k;
+                        $bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $accountingaccount->label;
+                        $bookkeeping->montant = $mt;
+                        $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
+                        $bookkeeping->debit = ($mt < 0) ? $mt : 0;
+                        $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
+                        $bookkeeping->code_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
+                        $bookkeeping->fk_user_author = $user->id;
+    
+                        $result = $bookkeeping->create($user);
+            			if ($result < 0) {
+                            if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+                            {
+                                $error++;
+                                $errorforline++;
+                                //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+                            }
+                            else
+                            {
+                                $error++;
+                                $errorforline++;
+                                setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+                            }
+            			}                        
+                    }
+                }
+            }
+        }
+        
+        // VAT
+        // var_dump($tabtva);
+        if (! $errorforline)
+        {
+            foreach ( $tabtva[$key] as $k => $mt ) {
+                if ($mt) {
                     $bookkeeping = new BookKeeping($db);
                     $bookkeeping = new BookKeeping($db);
                     $bookkeeping->doc_date = $val["date"];
                     $bookkeeping->doc_date = $val["date"];
                     $bookkeeping->doc_ref = $val["ref"];
                     $bookkeeping->doc_ref = $val["ref"];
                     $bookkeeping->date_create = $now;
                     $bookkeeping->date_create = $now;
                     $bookkeeping->doc_type = 'customer_invoice';
                     $bookkeeping->doc_type = 'customer_invoice';
                     $bookkeeping->fk_doc = $key;
                     $bookkeeping->fk_doc = $key;
-                    $bookkeeping->fk_docdet = $val["fk_facturedet"];
+                    $bookkeeping->fk_docdet = 0;    // Useless, can be several lines that are source of this record to add
                     $bookkeeping->code_tiers = '';
                     $bookkeeping->code_tiers = '';
                     $bookkeeping->numero_compte = $k;
                     $bookkeeping->numero_compte = $k;
-                    $bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $accountingaccount->label;
+                    $bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("VAT").' '.$def_tva[$key];
                     $bookkeeping->montant = $mt;
                     $bookkeeping->montant = $mt;
                     $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
                     $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
                     $bookkeeping->debit = ($mt < 0) ? $mt : 0;
                     $bookkeeping->debit = ($mt < 0) ? $mt : 0;
                     $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
                     $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
                     $bookkeeping->code_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
                     $bookkeeping->code_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
                     $bookkeeping->fk_user_author = $user->id;
                     $bookkeeping->fk_user_author = $user->id;
-
+    
                     $result = $bookkeeping->create($user);
                     $result = $bookkeeping->create($user);
                     if ($result < 0) {
                     if ($result < 0) {
-                        $error++;
-                        $errorforline++;
-                        setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+           			    if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+        			    {
+        			        $error++;
+        			        $errorforline++;
+        			        //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+        			    }
+        			    else
+        			    {
+        			        $error++;
+        			        $errorforline++;
+        			        setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+        			    }
                     }
                     }
                 }
                 }
             }
             }
         }
         }
 
 
-        // VAT
-        // var_dump($tabtva);
-        foreach ( $tabtva[$key] as $k => $mt ) {
-            if ($mt) {
-                $bookkeeping = new BookKeeping($db);
-                $bookkeeping->doc_date = $val["date"];
-                $bookkeeping->doc_ref = $val["ref"];
-                $bookkeeping->date_create = $now;
-                $bookkeeping->doc_type = 'customer_invoice';
-                $bookkeeping->fk_doc = $key;
-                $bookkeeping->fk_docdet = $val["fk_facturedet"];
-                $bookkeeping->code_tiers = '';
-                $bookkeeping->numero_compte = $k;
-                $bookkeeping->label_compte = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("VAT").' '.$def_tva[$key];
-                $bookkeeping->montant = $mt;
-                $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
-                $bookkeeping->debit = ($mt < 0) ? $mt : 0;
-                $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
-                $bookkeeping->code_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
-                $bookkeeping->fk_user_author = $user->id;
-
-                $result = $bookkeeping->create($user);
-                if ($result < 0) {
-                    $error++;
-                    $errorforline++;
-                    setEventMessages($object->error, $object->errors, 'errors');
-                }
-            }
-        }
-
-
         if (! $errorforline)
         if (! $errorforline)
         {
         {
             $db->commit();
             $db->commit();
@@ -337,7 +378,7 @@ if ($action == 'writebookkeeping') {
 $form = new Form($db);
 $form = new Form($db);
 
 
 // Export
 // Export
-if ($action == 'export_csv') {
+/*if ($action == 'export_csv') {
 
 
     $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
     $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
     $sell_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
     $sell_journal = $conf->global->ACCOUNTING_SELL_JOURNAL;
@@ -457,6 +498,7 @@ if ($action == 'export_csv') {
         }
         }
     }
     }
 }
 }
+*/
 
 
 if (empty($action) || $action == 'view') {
 if (empty($action) || $action == 'view') {
 
 
@@ -474,18 +516,18 @@ if (empty($action) || $action == 'view') {
 	else
 	else
 		$description .= $langs->trans("DepositsAreIncluded");
 		$description .= $langs->trans("DepositsAreIncluded");
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
 	$period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1);
-	report_header($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array (
-			'action' => ''
-	));
+	
+	journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''));
 
 
-	if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
+	/*if ($conf->global->ACCOUNTING_EXPORT_MODELCSV != 1 && $conf->global->ACCOUNTING_EXPORT_MODELCSV != 2) {
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans("Export") . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 		print '<input type="button" class="butActionRefused" style="float: right;" value="' . $langs->trans("Export") . '" disabled="disabled" title="' . $langs->trans('ExportNotSupported') . '"/>';
 	} else {
 	} else {
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
 		print '<input type="button" class="butAction" style="float: right;" value="' . $langs->trans("Export") . '" onclick="launch_export();" />';
-	}
-
+	}*/
+    print '<div class="tabsAction">';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
 	print '<input type="button" class="butAction" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-
+    print '</div>';
+    
 	print '
 	print '
 	<script type="text/javascript">
 	<script type="text/javascript">
 		function launch_export() {
 		function launch_export() {
@@ -503,7 +545,7 @@ if (empty($action) || $action == 'view') {
 	/*
 	/*
 	 * Show result array
 	 * Show result array
 	 */
 	 */
-	print '<br><br>';
+	print '<br>';
 
 
 	$i = 0;
 	$i = 0;
 	print "<table class=\"noborder\" width=\"100%\">";
 	print "<table class=\"noborder\" width=\"100%\">";
@@ -552,8 +594,8 @@ if (empty($action) || $action == 'view') {
 			print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers") . "</td>";
 			print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers") . "</td>";
 			print "</td><td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";
 			print "</td><td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";
 			print "<td align='right'>" . ($mt < 0 ? price(- $mt) : '') . "</td>";
 			print "<td align='right'>" . ($mt < 0 ? price(- $mt) : '') . "</td>";
+		    print "</tr>";
 		}
 		}
-		print "</tr>";
 
 
 		// Product / Service
 		// Product / Service
 		foreach ( $tabht[$key] as $k => $mt ) {
 		foreach ( $tabht[$key] as $k => $mt ) {

+ 7 - 2
htdocs/accountancy/supplier/lines.php

@@ -44,6 +44,7 @@ $langs->load("productbatch");
 $account_parent = GETPOST('account_parent');
 $account_parent = GETPOST('account_parent');
 $changeaccount = GETPOST('changeaccount');
 $changeaccount = GETPOST('changeaccount');
 // Search Getpost
 // Search Getpost
+$search_lineid = GETPOST('search_lineid', 'int');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
@@ -85,6 +86,7 @@ $formventilation = new FormVentilation($db);
 // Purge search criteria
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 {
 {
+    $search_lineid = '';
 	$search_ref = '';
 	$search_ref = '';
 	$search_invoice = '';
 	$search_invoice = '';
 	$search_label = '';
 	$search_label = '';
@@ -148,7 +150,7 @@ print '<script type="text/javascript">
  * Supplier Invoice lines
  * Supplier Invoice lines
  */
  */
 $sql = "SELECT f.rowid as facid, f.ref as facnumber, f.ref_supplier, f.libelle as invoice_label, f.datef,";
 $sql = "SELECT f.rowid as facid, f.ref as facnumber, f.ref_supplier, f.libelle as invoice_label, f.datef,";
-$sql.= " l.fk_product, l.description, l.total_ht , l.qty, l.rowid, l.tva_tx, aa.label, aa.account_number, ";
+$sql.= " l.rowid, l.fk_product, l.description, l.total_ht , l.qty, l.tva_tx, aa.label, aa.account_number, ";
 $sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type";
 $sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type";
 $sql.= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
 $sql.= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
 $sql.= " , " . MAIN_DB_PREFIX . "accounting_account as aa";
 $sql.= " , " . MAIN_DB_PREFIX . "accounting_account as aa";
@@ -156,6 +158,9 @@ $sql.= " , " . MAIN_DB_PREFIX . "facture_fourn_det as l";
 $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product";
 $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product";
 $sql.= " WHERE f.rowid = l.fk_facture_fourn and f.fk_statut >= 1 AND l.fk_code_ventilation <> 0 ";
 $sql.= " WHERE f.rowid = l.fk_facture_fourn and f.fk_statut >= 1 AND l.fk_code_ventilation <> 0 ";
 $sql.= " AND aa.rowid = l.fk_code_ventilation";
 $sql.= " AND aa.rowid = l.fk_code_ventilation";
+if ($search_lineid) {
+    $sql .= natural_search("l.rowid", $search_lineid, 1);
+}
 if (strlen(trim($search_invoice))) {
 if (strlen(trim($search_invoice))) {
 	$sql .= natural_search("f.ref", $search_invoice);
 	$sql .= natural_search("f.ref", $search_invoice);
 }
 }
@@ -240,7 +245,7 @@ if ($result) {
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	
 	
 	print '<tr class="liste_titre_filter">';
 	print '<tr class="liste_titre_filter">';
-    print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_lineid" value="' . dol_escape_htmltag($search_lineid) . '""></td>';
 	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"><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';

+ 7 - 2
htdocs/accountancy/supplier/list.php

@@ -52,6 +52,7 @@ $toselect = GETPOST('toselect', 'array');
 $mesCasesCochees = GETPOST('toselect', 'array');
 $mesCasesCochees = GETPOST('toselect', 'array');
 
 
 // Search Getpost
 // Search Getpost
+$search_lineid = GETPOST('search_lineid', 'int');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_invoice = GETPOST('search_invoice', 'alpha');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_ref = GETPOST('search_ref', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
 $search_label = GETPOST('search_label', 'alpha');
@@ -101,6 +102,7 @@ if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction !=
 // Purge search criteria
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 {
 {
+    $search_lineid = '';
     $search_ref = '';
     $search_ref = '';
     $search_invoice = '';    
     $search_invoice = '';    
     $search_label = '';
     $search_label = '';
@@ -179,7 +181,7 @@ llxHeader('', $langs->trans("SuppliersVentilation"));
 
 
 // Supplier Invoice Lines
 // Supplier Invoice Lines
 $sql = "SELECT f.rowid as facid, f.ref, f.ref_supplier, f.libelle as invoice_label, f.datef,";
 $sql = "SELECT f.rowid as facid, f.ref, f.ref_supplier, f.libelle as invoice_label, f.datef,";
-$sql.= " l.fk_product, l.description, l.total_ht as price, l.rowid, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, ";
+$sql.= " l.rowid, l.fk_product, l.description, l.total_ht as price, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, ";
 $sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_buy as code_buy, p.tva_tx as tva_tx_prod,";
 $sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_buy as code_buy, p.tva_tx as tva_tx_prod,";
 $sql.= " aa.rowid as aarowid";
 $sql.= " aa.rowid as aarowid";
 $sql.= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
 $sql.= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
@@ -191,6 +193,9 @@ $sql.= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0";
 $sql.= " AND product_type <= 2";
 $sql.= " AND product_type <= 2";
 $sql.= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_buy IS NULL OR p.accountancy_code_buy ='')";
 $sql.= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_buy IS NULL OR p.accountancy_code_buy ='')";
 // Add search filter like
 // Add search filter like
+if ($search_lineid) {
+    $sql .= natural_search("l.rowid", $search_lineid, 1);
+}
 if (strlen(trim($search_invoice))) {
 if (strlen(trim($search_invoice))) {
     $sql .= natural_search("f.ref",$search_invoice);
     $sql .= natural_search("f.ref",$search_invoice);
 }
 }
@@ -272,7 +277,7 @@ if ($result) {
 
 
 	// We add search filter
 	// We add search filter
 	print '<tr class="liste_titre_filter">';
 	print '<tr class="liste_titre_filter">';
-	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_lineid" value="' . dol_escape_htmltag($search_lineid) . '""></td>';
 	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"><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';

+ 3 - 3
htdocs/adherents/subscription.php

@@ -89,14 +89,14 @@ if ($rowid)
     $caneditfieldmember=$user->rights->adherent->creer;
     $caneditfieldmember=$user->rights->adherent->creer;
 }
 }
 
 
+// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
+$hookmanager->initHooks(array('subscription'));
+
 // PDF
 // PDF
 $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
 $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
 $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
 $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
 $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
 $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
 
 
-
-
-
 /*
 /*
  * 	Actions
  * 	Actions
  */
  */

+ 1 - 1
htdocs/adherents/subscription/card.php

@@ -145,7 +145,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->adherent-
     $result=$object->delete($user);
     $result=$object->delete($user);
     if ($result > 0)
     if ($result > 0)
     {
     {
-    	header("Location: card_subscriptions.php?rowid=".$object->fk_adherent);
+    	header("Location: ".DOL_URL_ROOT."/adherents/card.php?rowid=".$object->fk_adherent);
     	exit;
     	exit;
     }
     }
     else
     else

+ 1 - 1
htdocs/admin/agenda.php

@@ -144,7 +144,7 @@ print '<input type="hidden" name="action" value="save">';
 
 
 $head=agenda_prepare_head();
 $head=agenda_prepare_head();
 
 
-dol_fiche_head($head, 'autoactions', $langs->trans("Agenda"), 0, 'action');
+dol_fiche_head($head, 'autoactions', $langs->trans("Agenda"), -1, 'action');
 
 
 print $langs->trans("AgendaAutoActionDesc")."<br>\n";
 print $langs->trans("AgendaAutoActionDesc")."<br>\n";
 print $langs->trans("OnlyActiveElementsAreShown").'<br>';
 print $langs->trans("OnlyActiveElementsAreShown").'<br>';

+ 1 - 1
htdocs/admin/agenda_extrafields.php

@@ -75,7 +75,7 @@ print "<br>\n";
 
 
 $head=agenda_prepare_head();
 $head=agenda_prepare_head();
 
 
-dol_fiche_head($head, 'attributes', $langs->trans("Agenda"), 0, 'action');
+dol_fiche_head($head, 'attributes', $langs->trans("Agenda"), -1, 'action');
 
 
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 
 

+ 1 - 1
htdocs/admin/agenda_extsites.php

@@ -137,7 +137,7 @@ print '<input type="hidden" name="action" value="save">';
 
 
 $head=agenda_prepare_head();
 $head=agenda_prepare_head();
 
 
-dol_fiche_head($head, 'extsites', $langs->trans("Agenda"), 0, 'action');
+dol_fiche_head($head, 'extsites', $langs->trans("Agenda"), -1, 'action');
 
 
 print $langs->trans("AgendaExtSitesDesc")."<br>\n";
 print $langs->trans("AgendaExtSitesDesc")."<br>\n";
 print "<br>\n";
 print "<br>\n";

+ 1 - 1
htdocs/admin/agenda_other.php

@@ -196,7 +196,7 @@ print "<br>\n";
 
 
 $head=agenda_prepare_head();
 $head=agenda_prepare_head();
 
 
-dol_fiche_head($head, 'other', $langs->trans("Agenda"), 0, 'action');
+dol_fiche_head($head, 'other', $langs->trans("Agenda"), -1, 'action');
 
 
 
 
 /*
 /*

+ 1 - 1
htdocs/admin/agenda_xcal.php

@@ -83,7 +83,7 @@ print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 
 
 $head=agenda_prepare_head();
 $head=agenda_prepare_head();
 
 
-dol_fiche_head($head, 'xcal', $langs->trans("Agenda"), 0, 'action');
+dol_fiche_head($head, 'xcal', $langs->trans("Agenda"), -1, 'action');
 
 
 print $langs->trans("AgendaSetupOtherDesc")."<br>\n";
 print $langs->trans("AgendaSetupOtherDesc")."<br>\n";
 print "<br>\n";
 print "<br>\n";

+ 7 - 1
htdocs/admin/chequereceipts.php

@@ -257,8 +257,14 @@ $var=true;
 
 
 $var=! $var;
 $var=! $var;
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnChequeReceipts").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnChequeReceipts"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='BANK_CHEQUERECEIPT_FREE_TEXT';
 $variablename='BANK_CHEQUERECEIPT_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {

+ 2 - 1
htdocs/admin/clicktodial.php

@@ -91,7 +91,8 @@ print '</td></tr>';
 
 
 print '<tr class="oddeven"><td>';
 print '<tr class="oddeven"><td>';
 print $langs->trans("DefaultLink").'</td><td>';
 print $langs->trans("DefaultLink").'</td><td>';
-print '<input style="width: 90%" type="text" name="CLICKTODIAL_URL"'.($conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS?' disabled="disabled"':'').' value="'.$conf->global->CLICKTODIAL_URL.'"><br>';
+print '<input class="quatrevingtpercent" type="text" id="CLICKTODIAL_URL" name="CLICKTODIAL_URL"'.($conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS?' disabled="disabled"':'').' value="'.$conf->global->CLICKTODIAL_URL.'"><br>';
+print ajax_autoselect('CLICKTODIAL_URL');
 print '<br>';
 print '<br>';
 print $langs->trans("ClickToDialUrlDesc").'<br>';
 print $langs->trans("ClickToDialUrlDesc").'<br>';
 print $langs->trans("Example").':<br>http://myphoneserver/mypage?login=__LOGIN__&password=__PASS__&caller=__PHONEFROM__&called=__PHONETO__';
 print $langs->trans("Example").':<br>http://myphoneserver/mypage?login=__LOGIN__&password=__PASS__&caller=__PHONEFROM__&called=__PHONETO__';

+ 7 - 6
htdocs/admin/commande.php

@@ -565,12 +565,18 @@ print "<td>&nbsp;</td>\n";
 print "</tr>\n";
 print "</tr>\n";
 $var=true;
 $var=true;
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_ORDER_FREE_TEXT">';
 print '<input type="hidden" name="action" value="set_ORDER_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnOrders").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnOrders"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='ORDER_FREE_TEXT';
 $variablename='ORDER_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -593,11 +599,6 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_COMMANDE_DRAFT_WATERMARK\">";
 print "<input type=\"hidden\" name=\"action\" value=\"set_COMMANDE_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
 print '<tr class="oddeven"><td>';
-$substitutionarray=pdf_getSubstitutionArray($langs);
-$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
-$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
-foreach($substitutionarray as $key => $val) $htmltext.=$key.'<br>';
-$htmltext.='</i>';
 print $form->textwithpicto($langs->trans("WatermarkOnDraftOrders"), $htmltext);
 print $form->textwithpicto($langs->trans("WatermarkOnDraftOrders"), $htmltext);
 print '</td><td>';
 print '</td><td>';
 print '<input class="flat minwidth200" type="text" name="COMMANDE_DRAFT_WATERMARK" value="'.$conf->global->COMMANDE_DRAFT_WATERMARK.'">';
 print '<input class="flat minwidth200" type="text" name="COMMANDE_DRAFT_WATERMARK" value="'.$conf->global->COMMANDE_DRAFT_WATERMARK.'">';

+ 9 - 2
htdocs/admin/contract.php

@@ -502,9 +502,15 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print "</tr>\n";
 print "</tr>\n";
 $var=true;
 $var=true;
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 $var=! $var;
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnContracts").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnContracts"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='CONTRACT_FREE_TEXT';
 $variablename='CONTRACT_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -521,7 +527,8 @@ print '</td></tr>'."\n";
 //Use draft Watermark
 //Use draft Watermark
 
 
 print '<tr class="oddeven"><td>';
 print '<tr class="oddeven"><td>';
-print $langs->trans("WatermarkOnDraftContractCards").'</td><td>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftContractCards"), $htmltext);
+print '</td><td>';
 print '<input size="50" class="flat" type="text" name="CONTRACT_DRAFT_WATERMARK" value="'.$conf->global->CONTRACT_DRAFT_WATERMARK.'">';
 print '<input size="50" class="flat" type="text" name="CONTRACT_DRAFT_WATERMARK" value="'.$conf->global->CONTRACT_DRAFT_WATERMARK.'">';
 print '</td></tr>'."\n";
 print '</td></tr>'."\n";
 
 

+ 84 - 20
htdocs/admin/defaultvalues.php

@@ -56,6 +56,10 @@ $defaultvalue = GETPOST('defaultvalue');
 
 
 $defaulturl=preg_replace('/^\//', '', $defaulturl);
 $defaulturl=preg_replace('/^\//', '', $defaulturl);
 
 
+$urlpage = GETPOST('urlpage');
+$key = GETPOST('key');
+$value = GETPOST('value');
+
 
 
 /*
 /*
  * Actions
  * Actions
@@ -81,25 +85,51 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
 }
 }
 
 
 
 
-if ($action == 'add' || (GETPOST('add') && $action != 'update'))
+if (($action == 'add' || (GETPOST('add') && $action != 'update')) || GETPOST('actionmodify'))
 {
 {
 	$error=0;
 	$error=0;
 
 
-	if (empty($defaulturl))
+	if (($action == 'add' || (GETPOST('add') && $action != 'update')))
 	{
 	{
-		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Url")), null, 'errors');
-		$error++;
+    	if (empty($defaulturl))
+    	{
+    		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Url")), null, 'errors');
+    		$error++;
+    	}
+    	if (empty($defaultkey))
+    	{
+    		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Field")), null, 'errors');
+    		$error++;
+    	}
 	}
 	}
-	if (empty($defaultkey))
+	if (GETPOST('actionmodify'))
 	{
 	{
-		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Key")), null, 'errors');
-		$error++;
+	    if (empty($urlpage))
+	    {
+	        setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Url")), null, 'errors');
+	        $error++;
+	    }
+	    if (empty($key))
+	    {
+	        setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Field")), null, 'errors');
+	        $error++;
+	    }
 	}
 	}
+	
 	if (! $error)
 	if (! $error)
 	{
 	{
 	    $db->begin();
 	    $db->begin();
-	     
-		$sql = "INSERT INTO ".MAIN_DB_PREFIX."default_values(type, user_id, page, param, value, entity) VALUES ('".$db->escape($mode)."', 0, '".$db->escape($defaulturl)."','".$db->escape($defaultkey)."','".$db->escape($defaultvalue)."', ".$db->escape($conf->entity).")";
+	    
+	    if ($action == 'add' || (GETPOST('add') && $action != 'update'))
+	    {
+            $sql = "INSERT INTO ".MAIN_DB_PREFIX."default_values(type, user_id, page, param, value, entity) VALUES ('".$db->escape($mode)."', 0, '".$db->escape($defaulturl)."','".$db->escape($defaultkey)."','".$db->escape($defaultvalue)."', ".$db->escape($conf->entity).")";
+	    }
+	    if (GETPOST('actionmodify'))
+	    {
+		    $sql = "UPDATE ".MAIN_DB_PREFIX."default_values SET page = '".$db->escape($urlpage)."', param = '".$db->escape($key)."', value = '".$db->escape($value)."'";
+		    $sql.= " WHERE rowid = ".$id;
+	    }
+		
 		$result = $db->query($sql);
 		$result = $db->query($sql);
 		if ($result > 0)
 		if ($result > 0)
 		{
 		{
@@ -176,6 +206,10 @@ $head=defaultvalues_prepare_head();
     
     
 dol_fiche_head($head, $mode, '', -1, '');
 dol_fiche_head($head, $mode, '', -1, '');
 
 
+if ($mode == 'sortorder')
+{
+    print info_admin($langs->trans("WarningSettingSortOrder")).'<br>';
+}
 
 
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" id="action" name="action" value="">';
 print '<input type="hidden" id="action" name="action" value="">';
@@ -187,29 +221,37 @@ $texthelp=$langs->trans("PageUrlForDefaultValues");
 if ($mode == 'createform') $texthelp.=$langs->trans("PageUrlForDefaultValuesCreate", 'societe/card.php');
 if ($mode == 'createform') $texthelp.=$langs->trans("PageUrlForDefaultValuesCreate", 'societe/card.php');
 else $texthelp.=$langs->trans("PageUrlForDefaultValuesList", 'societe/list.php');
 else $texthelp.=$langs->trans("PageUrlForDefaultValuesList", 'societe/list.php');
 $texturl=$form->textwithpicto($langs->trans("Url"), $texthelp);
 $texturl=$form->textwithpicto($langs->trans("Url"), $texthelp);
-print_liste_field_titre($texturl,$_SERVER["PHP_SELF"],'defaulturl','',$param,'',$sortfield,$sortorder);
+print_liste_field_titre($texturl,$_SERVER["PHP_SELF"],'page,param','',$param,'',$sortfield,$sortorder);
 $texthelp=$langs->trans("TheKeyIsTheNameOfHtmlField");
 $texthelp=$langs->trans("TheKeyIsTheNameOfHtmlField");
-if ($mode != 'sortorder') $textkey=$form->textwithpicto($langs->trans("Key"), $texthelp);
-else $textkey=$form->textwithpicto($langs->trans("Key"), $texthelp);
-print_liste_field_titre($textkey,$_SERVER["PHP_SELF"],'defaultkey','',$param,'',$sortfield,$sortorder);
+if ($mode != 'sortorder') 
+{
+    $textkey=$form->textwithpicto($langs->trans("Field"), $texthelp);
+}
+else 
+{
+    $texthelp='field or alias.field';
+    $textkey=$form->textwithpicto($langs->trans("Field"), $texthelp);
+}
+print_liste_field_titre($textkey,$_SERVER["PHP_SELF"],'param','',$param,'',$sortfield,$sortorder);
 if ($mode != 'sortorder')
 if ($mode != 'sortorder')
 {
 {
     $texthelp=$langs->trans("FollowingConstantsWillBeSubstituted").'<br>';
     $texthelp=$langs->trans("FollowingConstantsWillBeSubstituted").'<br>';
     // See list into GETPOST
     // See list into GETPOST
     $texthelp.='__USERID__<br>';
     $texthelp.='__USERID__<br>';
+    $texthelp.='__SUPERVISORID__<br>';
     $texthelp.='__MYCOUNTRYID__<br>';
     $texthelp.='__MYCOUNTRYID__<br>';
     $texthelp.='__DAY__<br>';
     $texthelp.='__DAY__<br>';
     $texthelp.='__MONTH__<br>';
     $texthelp.='__MONTH__<br>';
     $texthelp.='__YEAR__<br>';
     $texthelp.='__YEAR__<br>';
     if (! empty($conf->multicompany->enabled)) $texthelp.='__ENTITYID__<br>';
     if (! empty($conf->multicompany->enabled)) $texthelp.='__ENTITYID__<br>';
-    $textvalue=$form->textwithpicto($langs->trans("Value"), $texthelp);
+    $textvalue=$form->textwithpicto($langs->trans("Value"), $texthelp, 1, 'help', '', 0, 2, '');
 }
 }
 else
 else
 {
 {
     $texthelp='ASC or DESC';
     $texthelp='ASC or DESC';
     $textvalue=$form->textwithpicto($langs->trans("SortOrder"), $texthelp);
     $textvalue=$form->textwithpicto($langs->trans("SortOrder"), $texthelp);
 }
 }
-print_liste_field_titre($textvalue, $_SERVER["PHP_SELF"], 'defaultvalue', '', $param, '', $sortfield, $sortorder);
+print_liste_field_titre($textvalue, $_SERVER["PHP_SELF"], 'value', '', $param, '', $sortfield, $sortorder);
 if (! empty($conf->multicompany->enabled) && !$user->entity) print_liste_field_titre($langs->trans("Entity"),$_SERVER["PHP_SELF"],'entity,page','',$param,'',$sortfield,$sortorder);
 if (! empty($conf->multicompany->enabled) && !$user->entity) print_liste_field_titre($langs->trans("Entity"),$_SERVER["PHP_SELF"],'entity,page','',$param,'',$sortfield,$sortorder);
 print '<td align="center"></td>';
 print '<td align="center"></td>';
 print "</tr>\n";
 print "</tr>\n";
@@ -269,9 +311,17 @@ if ($result)
 
 
 		print '<tr class="oddeven">';
 		print '<tr class="oddeven">';
 		
 		
-		print '<td>'.$obj->page.'</td>'."\n";
-   	    print '<td>'.$obj->param.'</td>'."\n";
-        
+		print '<td>';
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->page;
+		else print '<input type="text" name="urlpage" value="'.dol_escape_htmltag($obj->page).'">';
+		print '</td>'."\n";
+   	    
+		// Key
+		print '<td>';
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->param;
+		else print '<input type="text" name="key" value="'.dol_escape_htmltag($obj->param).'">';
+		print '</td>'."\n";
+
 		// Value
 		// Value
 		print '<td>';
 		print '<td>';
 		/*print '<input type="hidden" name="const['.$i.'][rowid]" value="'.$obj->rowid.'">';
 		/*print '<input type="hidden" name="const['.$i.'][rowid]" value="'.$obj->rowid.'">';
@@ -279,11 +329,25 @@ if ($result)
 		print '<input type="hidden" name="const['.$i.'][name]" value="'.$obj->transkey.'">';
 		print '<input type="hidden" name="const['.$i.'][name]" value="'.$obj->transkey.'">';
 		print '<input type="text" id="value_'.$i.'" class="flat inputforupdate" size="30" name="const['.$i.'][value]" value="'.dol_escape_htmltag($obj->transvalue).'">';
 		print '<input type="text" id="value_'.$i.'" class="flat inputforupdate" size="30" name="const['.$i.'][value]" value="'.dol_escape_htmltag($obj->transvalue).'">';
 		*/
 		*/
-		print $obj->value;
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->value;
+		else print '<input type="text" name="value" value="'.dol_escape_htmltag($obj->value).'">';
 		print '</td>';
 		print '</td>';
 
 
 		print '<td align="center">';
 		print '<td align="center">';
-		print '<a href="'.$_SERVER['PHP_SELF'].'?rowid='.$obj->rowid.'&entity='.$obj->entity.'&mode='.$mode.'&action=delete'.((empty($user->entity) && $debug)?'&debug=1':'').'">'.img_delete().'</a>';
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid)
+		{
+    		print '<a href="'.$_SERVER['PHP_SELF'].'?rowid='.$obj->rowid.'&entity='.$obj->entity.'&mode='.$mode.'&action=edit'.((empty($user->entity) && $debug)?'&debug=1':'').'">'.img_edit().'</a>';
+    		print ' &nbsp; ';
+    		print '<a href="'.$_SERVER['PHP_SELF'].'?rowid='.$obj->rowid.'&entity='.$obj->entity.'&mode='.$mode.'&action=delete'.((empty($user->entity) && $debug)?'&debug=1':'').'">'.img_delete().'</a>';
+		}
+		else
+		{
+		    print '<input type="hidden" name="page" value="'.$page.'">';
+		    print '<input type="hidden" name="rowid" value="'.$id.'">';
+		    print '<div name="'.(! empty($obj->rowid)?$obj->rowid:'none').'"></div>';
+		    print '<input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
+		    print '<input type="submit" class="button" name="actioncancel" value="'.$langs->trans("Cancel").'">';
+		}
 		print '</td>';
 		print '</td>';
 		
 		
 		print "</tr>\n";
 		print "</tr>\n";

+ 20 - 14
htdocs/admin/dict.php

@@ -660,7 +660,11 @@ if (GETPOST('actionadd') || GETPOST('actionmodify'))
 	if ($_POST["accountancy_code"] <= 0) $_POST["accountancy_code"]='';	// If empty, we force to null
 	if ($_POST["accountancy_code"] <= 0) $_POST["accountancy_code"]='';	// If empty, we force to null
 	if ($_POST["accountancy_code_sell"] <= 0) $_POST["accountancy_code_sell"]='';	// If empty, we force to null
 	if ($_POST["accountancy_code_sell"] <= 0) $_POST["accountancy_code_sell"]='';	// If empty, we force to null
 	if ($_POST["accountancy_code_buy"] <= 0) $_POST["accountancy_code_buy"]='';	// If empty, we force to null
 	if ($_POST["accountancy_code_buy"] <= 0) $_POST["accountancy_code_buy"]='';	// If empty, we force to null
-
+    if ($id == 10 && isset($_POST["code"]))  // Spaces are not allowed into code 
+    {
+        $_POST["code"]=preg_replace('/\s/','',$_POST["code"]);
+    }
+    
     // Si verif ok et action add, on ajoute la ligne
     // Si verif ok et action add, on ajoute la ligne
     if ($ok && GETPOST('actionadd'))
     if ($ok && GETPOST('actionadd'))
     {
     {
@@ -914,10 +918,19 @@ if (empty($id))
 print "<br>\n";
 print "<br>\n";
 
 
 
 
+$param = '&id='.$id;
+if ($search_country_id > 0) $param.= '&search_country_id='.$search_country_id;
+if ($search_code != '')     $param.= '&search_code='.urlencode($search_country_id);
+$paramwithsearch = $param;
+if ($sortorder) $paramwithsearch.= '&sortorder='.$sortorder;
+if ($sortfield) $paramwithsearch.= '&sortfield='.$sortfield;
+if (GETPOST('from')) $paramwithsearch.= '&from='.GETPOST('from','alpha');
+
+
 // Confirmation de la suppression de la ligne
 // Confirmation de la suppression de la ligne
 if ($action == 'delete')
 if ($action == 'delete')
 {
 {
-    print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page?'page='.$page.'&':'').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.$rowid.'&code='.urlencode($_GET["code"]).'&id='.$id, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete','',0,1);
+    print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page?'page='.$page.'&':'').'rowid='.$rowid.'&code='.urlencode($_GET["code"]).$paramwithsearch, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete','',0,1);
 }
 }
 //var_dump($elementList);
 //var_dump($elementList);
 
 
@@ -1069,7 +1082,7 @@ if ($id)
         print '</tr>';
         print '</tr>';
 
 
         // Line to enter new values
         // Line to enter new values
-        print '<tr class="oddeven nodrag nodrop nohover">';
+        print '<!-- line to add new entry --><tr class="oddeven nodrag nodrop nohover">';
 
 
         $obj = new stdClass();
         $obj = new stdClass();
         // If data was already input, we define them in obj to populate input fields.
         // If data was already input, we define them in obj to populate input fields.
@@ -1130,14 +1143,6 @@ if ($id)
         $num = $db->num_rows($resql);
         $num = $db->num_rows($resql);
         $i = 0;
         $i = 0;
 
 
-        $param = '&id='.$id;
-        if ($search_country_id > 0) $param.= '&search_country_id='.$search_country_id;
-        if ($search_code != '')     $param.= '&search_code='.urlencode($search_country_id);
-        $paramwithsearch = $param;
-        if ($sortorder) $paramwithsearch.= '&sortorder='.$sortorder;
-        if ($sortfield) $paramwithsearch.= '&sortfield='.$sortfield;
-        if (GETPOST('from')) $paramwithsearch.= '&from='.GETPOST('from','alpha');
-        
         // There is several pages
         // There is several pages
         if ($num > $listlimit)
         if ($num > $listlimit)
         {
         {
@@ -1302,10 +1307,10 @@ if ($id)
                     if (empty($reshook)) fieldList($fieldlist,$obj,$tabname[$id],'edit');
                     if (empty($reshook)) fieldList($fieldlist,$obj,$tabname[$id],'edit');
 
 
                     print '<td colspan="3" align="center">';
                     print '<td colspan="3" align="center">';
+                    print '<div name="'.(! empty($obj->rowid)?$obj->rowid:$obj->code).'"></div>';
                     print '<input type="hidden" name="page" value="'.$page.'">';
                     print '<input type="hidden" name="page" value="'.$page.'">';
                     print '<input type="hidden" name="rowid" value="'.$rowid.'">';
                     print '<input type="hidden" name="rowid" value="'.$rowid.'">';
                     print '<input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
                     print '<input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
-                    print '<div name="'.(! empty($obj->rowid)?$obj->rowid:$obj->code).'"></div>';
                     print '<input type="submit" class="button" name="actioncancel" value="'.$langs->trans("Cancel").'">';
                     print '<input type="submit" class="button" name="actioncancel" value="'.$langs->trans("Cancel").'">';
                     print '</td>';
                     print '</td>';
                 }
                 }
@@ -1810,13 +1815,14 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='')
 			if ($fieldlist[$field]=='affect') $class='maxwidth50';
 			if ($fieldlist[$field]=='affect') $class='maxwidth50';
 			if ($fieldlist[$field]=='delay') $class='maxwidth50';
 			if ($fieldlist[$field]=='delay') $class='maxwidth50';
 			if ($fieldlist[$field]=='position') $class='maxwidth50';
 			if ($fieldlist[$field]=='position') $class='maxwidth50';
-			if ($fieldlist[$field]=='libelle') $class='quatrevingtpercent';
+			if ($fieldlist[$field]=='libelle' || $fieldlist[$field]=='label') $class='quatrevingtpercent';
 			if ($fieldlist[$field]=='tracking') $class='quatrevingtpercent';
 			if ($fieldlist[$field]=='tracking') $class='quatrevingtpercent';
 			if ($fieldlist[$field]=='sortorder' || $fieldlist[$field]=='sens' || $fieldlist[$field]=='category_type') $class='maxwidth50';
 			if ($fieldlist[$field]=='sortorder' || $fieldlist[$field]=='sens' || $fieldlist[$field]=='category_type') $class='maxwidth50';
 			print '<td class="'.$classtd.'">';
 			print '<td class="'.$classtd.'">';
 			$transfound=0;
 			$transfound=0;
 			if (in_array($fieldlist[$field], array('label','libelle')))
 			if (in_array($fieldlist[$field], array('label','libelle')))
 			{
 			{
+			    $transkey='';
 			    // Special case for labels
 			    // Special case for labels
 			    if ($tabname == MAIN_DB_PREFIX.'c_civility') {
 			    if ($tabname == MAIN_DB_PREFIX.'c_civility') {
 			        $transkey="Civility".strtoupper($obj->code);
 			        $transkey="Civility".strtoupper($obj->code);
@@ -1825,7 +1831,7 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='')
 			        $langs->load("bills");
 			        $langs->load("bills");
 			        $transkey="PaymentCondition".strtoupper($obj->code);
 			        $transkey="PaymentCondition".strtoupper($obj->code);
 			    }
 			    }
-			    if ($langs->trans($transkey) != $transkey)
+			    if ($transkey && $langs->trans($transkey) != $transkey)
 			    {
 			    {
 			        $transfound=1;
 			        $transfound=1;
 			        print $form->textwithpicto($langs->trans($transkey), $langs->trans("GoIntoTranslationMenuToChangeThis"));
 			        print $form->textwithpicto($langs->trans($transkey), $langs->trans("GoIntoTranslationMenuToChangeThis"));

+ 8 - 2
htdocs/admin/expedition.php

@@ -502,8 +502,14 @@ print "<tr class=\"liste_titre\">";
 print "<td>".$langs->trans("Parameter")."</td>\n";
 print "<td>".$langs->trans("Parameter")."</td>\n";
 print "</tr>";
 print "</tr>";
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr><td>';
 print '<tr><td>';
-print $langs->trans("FreeLegalTextOnShippings").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnShippings"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SHIPPING_FREE_TEXT';
 $variablename='SHIPPING_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -518,7 +524,7 @@ else
 print "</td></tr>\n";
 print "</td></tr>\n";
 
 
 print '<tr><td>';
 print '<tr><td>';
-print $langs->trans("WatermarkOnDraft").'<br>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftContractCards"), $htmltext).'<br>';
 print '<input size="50" class="flat" type="text" name="SHIPPING_DRAFT_WATERMARK" value="'.$conf->global->SHIPPING_DRAFT_WATERMARK.'">';
 print '<input size="50" class="flat" type="text" name="SHIPPING_DRAFT_WATERMARK" value="'.$conf->global->SHIPPING_DRAFT_WATERMARK.'">';
 print "</td></tr>\n";
 print "</td></tr>\n";
 
 

+ 9 - 3
htdocs/admin/expensereport.php

@@ -230,7 +230,7 @@ print load_fiche_titre($langs->trans("ExpenseReportsSetup"),$linkback,'title_set
 
 
 $head=expensereport_admin_prepare_head();
 $head=expensereport_admin_prepare_head();
 
 
-dol_fiche_head($head, 'expensereport', $langs->trans("ExpenseReports"), 0, 'trip');
+dol_fiche_head($head, 'expensereport', $langs->trans("ExpenseReports"), -1, 'trip');
 
 
 // Interventions numbering model
 // Interventions numbering model
 /*
 /*
@@ -505,9 +505,15 @@ print '<td align="center" width="60"></td>';
 print "</tr>\n";
 print "</tr>\n";
 $var=true;
 $var=true;
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 $var=! $var;
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnExpenseReports").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnExpenseReports"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='EXPENSEREPORT_FREE_TEXT';
 $variablename='EXPENSEREPORT_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -524,7 +530,7 @@ print '</td></tr>'."\n";
 //Use draft Watermark
 //Use draft Watermark
 
 
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("WatermarkOnDraftOrders").'<br>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftExpenseReports"), $htmltext).'<br>';
 print '<input size="50" class="flat" type="text" name="EXPENSEREPORT_DRAFT_WATERMARK" value="'.$conf->global->EXPENSEREPORT_DRAFT_WATERMARK.'">';
 print '<input size="50" class="flat" type="text" name="EXPENSEREPORT_DRAFT_WATERMARK" value="'.$conf->global->EXPENSEREPORT_DRAFT_WATERMARK.'">';
 print '</td></tr>'."\n";
 print '</td></tr>'."\n";
 
 

+ 1 - 1
htdocs/admin/expensereport_extrafields.php

@@ -74,7 +74,7 @@ print load_fiche_titre($langs->trans("ExpenseReportsSetup"),$linkback,'title_set
 
 
 $head = expensereport_admin_prepare_head();
 $head = expensereport_admin_prepare_head();
 
 
-dol_fiche_head($head, 'attributes', $langs->trans("ExpenseReports"), 0, 'trip');
+dol_fiche_head($head, 'attributes', $langs->trans("ExpenseReports"), -1, 'trip');
 
 
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 
 

+ 10 - 6
htdocs/admin/external_rss.php

@@ -206,13 +206,13 @@ print '<td>'.$langs->trans("Example").'</td>';
 print '</tr>';
 print '</tr>';
 print '<tr class="impair">';
 print '<tr class="impair">';
 print '<td width="100">'.$langs->trans("Title").'</td>';
 print '<td width="100">'.$langs->trans("Title").'</td>';
-print '<td><input type="text" name="external_rss_title_'.($lastexternalrss+1).'" value="'.@constant("EXTERNAL_RSS_TITLE_" . ($lastexternalrss+1)).'" size="64"></td>';
+print '<td><input type="text" class="flat minwidth300" name="external_rss_title_'.($lastexternalrss+1).'" value=""></td>';
 print '<td>'.$langs->trans('RSSUrlExample').'</td>';
 print '<td>'.$langs->trans('RSSUrlExample').'</td>';
 print '</tr>';
 print '</tr>';
 
 
 print '<tr class="pair">';
 print '<tr class="pair">';
 print '<td>'.$langs->trans('RSSUrl').'</td>';
 print '<td>'.$langs->trans('RSSUrl').'</td>';
-print '<td><input type="text" name="external_rss_urlrss_'.($lastexternalrss+1).'" value="'.@constant("EXTERNAL_RSS_URLRSS_" . ($lastexternalrss+1)).'" size="64"></td>';
+print '<td><input type="text" class="flat minwidth300" name="external_rss_urlrss_'.($lastexternalrss+1).'" value=""></td>';
 print '<td>http://news.google.com/news?ned=us&topic=h&output=rss<br>http://www.dolibarr.org/rss</td>';
 print '<td>http://news.google.com/news?ned=us&topic=h&output=rss<br>http://www.dolibarr.org/rss</td>';
 print '</tr>';
 print '</tr>';
 print '</table>';
 print '</table>';
@@ -243,10 +243,12 @@ if ($resql)
 
 
 	    preg_match('/^([0-9]+)/i',$obj->note,$reg);
 	    preg_match('/^([0-9]+)/i',$obj->note,$reg);
 		$idrss = $reg[1];
 		$idrss = $reg[1];
-		//print "x".$idrss;
+        $keyrssurl="EXTERNAL_RSS_URLRSS_".$idrss;
+        $keyrsstitle="EXTERNAL_RSS_URLRSS_".$idrss;
+        //print "x".$idrss;
 
 
         $rssparser=new RssParser($db);
         $rssparser=new RssParser($db);
-		$result = $rssparser->parser(@constant("EXTERNAL_RSS_URLRSS_".$idrss), 5, 300, $conf->externalrss->dir_temp);
+		$result = $rssparser->parser($conf->global->$keyrssurl, 5, 300, $conf->externalrss->dir_temp);
 
 
 		$var=true;
 		$var=true;
 
 
@@ -269,13 +271,13 @@ if ($resql)
 		
 		
 		print '<tr class="oddeven">';
 		print '<tr class="oddeven">';
 		print "<td width=\"100px\">".$langs->trans("Title")."</td>";
 		print "<td width=\"100px\">".$langs->trans("Title")."</td>";
-		print "<td><input type=\"text\" class=\"flat\" name=\"external_rss_title_" . $idrss . "\" value=\"" . @constant("EXTERNAL_RSS_TITLE_" . $idrss) . "\" size=\"64\"></td>";
+		print "<td><input type=\"text\" class=\"flat minwidth300\" name=\"external_rss_title_" . $idrss . "\" value=\"" . $conf->global->$keyrsstitle . "\"></td>";
 		print "</tr>";
 		print "</tr>";
 
 
 		
 		
 		print '<tr class="oddeven">';
 		print '<tr class="oddeven">';
 		print "<td>".$langs->trans("URL")."</td>";
 		print "<td>".$langs->trans("URL")."</td>";
-		print "<td><input type=\"text\" class=\"flat\" name=\"external_rss_urlrss_" . $idrss . "\" value=\"" . @constant("EXTERNAL_RSS_URLRSS_" . $idrss) . "\" size=\"64\"></td>";
+		print "<td><input type=\"text\" class=\"flat minwidth300\" name=\"external_rss_urlrss_" . $idrss . "\" value=\"" . $conf->global->$keyrssurl . "\"></td>";
 		print "</tr>";
 		print "</tr>";
 
 
 		
 		
@@ -304,6 +306,8 @@ if ($resql)
 			print "<td>".$langs->trans("Logo")."</td>";
 			print "<td>".$langs->trans("Logo")."</td>";
 			print '<td>';
 			print '<td>';
 			$imageurl=$rssparser->getImageUrl();
 			$imageurl=$rssparser->getImageUrl();
+			$linkrss=$rssparser->getLink();
+			if (! preg_match('/^http/', $imageurl)) $imageurl=$linkrss.$imageurl;
 			if ($imageurl) print '<img height="32" src="'.$imageurl.'">';
 			if ($imageurl) print '<img height="32" src="'.$imageurl.'">';
 			else print $langs->trans("None");
 			else print $langs->trans("None");
 			print '</td>';
 			print '</td>';

+ 7 - 6
htdocs/admin/facture.php

@@ -733,12 +733,18 @@ print '<input type="submit" class="button" value="'.$langs->trans("Modify").'" /
 print "</td></tr>\n";
 print "</td></tr>\n";
 print '</form>';
 print '</form>';
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
 print '<input type="hidden" name="action" value="set_INVOICE_FREE_TEXT" />';
 print '<input type="hidden" name="action" value="set_INVOICE_FREE_TEXT" />';
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnInvoices").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnInvoices"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='INVOICE_FREE_TEXT';
 $variablename='INVOICE_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -760,11 +766,6 @@ print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
 print '<input type="hidden" name="action" value="set_FACTURE_DRAFT_WATERMARK" />';
 print '<input type="hidden" name="action" value="set_FACTURE_DRAFT_WATERMARK" />';
 print '<tr class="oddeven"><td>';
 print '<tr class="oddeven"><td>';
-$substitutionarray=pdf_getSubstitutionArray($langs);
-$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
-$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
-foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
-$htmltext.='</i>';
 print $form->textwithpicto($langs->trans("WatermarkOnDraftBill"), $htmltext);
 print $form->textwithpicto($langs->trans("WatermarkOnDraftBill"), $htmltext);
 print '</td>';
 print '</td>';
 print '<td><input size="50" class="flat" type="text" name="FACTURE_DRAFT_WATERMARK" value="'.$conf->global->FACTURE_DRAFT_WATERMARK.'" />';
 print '<td><input size="50" class="flat" type="text" name="FACTURE_DRAFT_WATERMARK" value="'.$conf->global->FACTURE_DRAFT_WATERMARK.'" />';

+ 10 - 3
htdocs/admin/fichinter.php

@@ -265,7 +265,7 @@ print load_fiche_titre($langs->trans("InterventionsSetup"),$linkback,'title_setu
 
 
 $head=fichinter_admin_prepare_head();
 $head=fichinter_admin_prepare_head();
 
 
-dol_fiche_head($head, 'ficheinter', $langs->trans("Interventions"), 0, 'intervention');
+dol_fiche_head($head, 'ficheinter', $langs->trans("Interventions"), -1, 'intervention');
 
 
 // Interventions numbering model
 // Interventions numbering model
 
 
@@ -531,11 +531,17 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print "<td>&nbsp;</td>\n";
 print "<td>&nbsp;</td>\n";
 print "</tr>\n";
 print "</tr>\n";
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_FICHINTER_FREE_TEXT">';
 print '<input type="hidden" name="action" value="set_FICHINTER_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnInterventions").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnInterventions"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='FICHINTER_FREE_TEXT';
 $variablename='FICHINTER_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -558,7 +564,8 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_FICHINTER_DRAFT_WATERMARK\">";
 print "<input type=\"hidden\" name=\"action\" value=\"set_FICHINTER_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
 print '<tr class="oddeven"><td>';
-print $langs->trans("WatermarkOnDraftInterventionCards").'</td><td>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftInterventionCards"), $htmltext).'<br>';
+print '</td><td>';
 print '<input size="50" class="flat" type="text" name="FICHINTER_DRAFT_WATERMARK" value="'.$conf->global->FICHINTER_DRAFT_WATERMARK.'">';
 print '<input size="50" class="flat" type="text" name="FICHINTER_DRAFT_WATERMARK" value="'.$conf->global->FICHINTER_DRAFT_WATERMARK.'">';
 print '</td><td align="right">';
 print '</td><td align="right">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';

+ 7 - 1
htdocs/admin/livraison.php

@@ -479,12 +479,18 @@ print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 print "</tr>\n";
 $var=true;
 $var=true;
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_DELIVERY_FREE_TEXT">';
 print '<input type="hidden" name="action" value="set_DELIVERY_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnDeliveryReceipts").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnDeliveryReceipts"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='DELIVERY_FREE_TEXT';
 $variablename='DELIVERY_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {

+ 1 - 3
htdocs/admin/loan.php

@@ -96,9 +96,7 @@ print "</tr>\n";
 
 
 foreach ($list as $key)
 foreach ($list as $key)
 {
 {
-	
-
-	print '<tr '.$bc[$var].' class="value">';
+	print '<tr class="oddeven value">';
 
 
 	// Param
 	// Param
 	$label = $langs->trans($key); 
 	$label = $langs->trans($key); 

+ 19 - 12
htdocs/admin/mails_templates.php

@@ -4,7 +4,7 @@
  * Copyright (C) 2004       Benoit Mortier          <benoit.mortier@opensides.be>
  * Copyright (C) 2004       Benoit Mortier          <benoit.mortier@opensides.be>
  * Copyright (C) 2005-2012  Regis Houssin           <regis.houssin@capnetworks.com>
  * Copyright (C) 2005-2012  Regis Houssin           <regis.houssin@capnetworks.com>
  * Copyright (C) 2010-2016  Juanjo Menent           <jmenent@2byte.es>
  * Copyright (C) 2010-2016  Juanjo Menent           <jmenent@2byte.es>
- * Copyright (C) 2011-2015  Philippe Grand          <philippe.grand@atoo-net.com>
+ * Copyright (C) 2011-2017  Philippe Grand          <philippe.grand@atoo-net.com>
  * Copyright (C) 2011       Remy Younes             <ryounes@gmail.com>
  * Copyright (C) 2011       Remy Younes             <ryounes@gmail.com>
  * Copyright (C) 2012-2015  Marcos García           <marcosgdf@gmail.com>
  * Copyright (C) 2012-2015  Marcos García           <marcosgdf@gmail.com>
  * Copyright (C) 2012       Christophe Battarel     <christophe.battarel@ltairis.fr>
  * Copyright (C) 2012       Christophe Battarel     <christophe.battarel@ltairis.fr>
@@ -118,17 +118,17 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
 $formmail=new FormMail($db);
 $formmail=new FormMail($db);
 if (empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES))
 if (empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES))
 {
 {
-    $tmp=$formmail->getAvailableSubstitKey('form');
+    $tmp=FormMail::getAvailableSubstitKey('formemail');
     $tmp['__(AnyTransKey)__']='__(AnyTransKey)__';
     $tmp['__(AnyTransKey)__']='__(AnyTransKey)__';
     $helpsubstit = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
     $helpsubstit = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
     $helpsubstitforlines = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
     $helpsubstitforlines = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
 }
 }
 else
 else
 {
 {
-    $tmp=$formmail->getAvailableSubstitKey('formwithlines');
+    $tmp=FormMail::getAvailableSubstitKey('formemailwithlines');
     $tmp['__(AnyTransKey)__']='__(AnyTransKey)__';
     $tmp['__(AnyTransKey)__']='__(AnyTransKey)__';
     $helpsubstit = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
     $helpsubstit = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
-    $tmp=$formmail->getAvailableSubstitKey('formforlines');
+    $tmp=FormMail::getAvailableSubstitKey('formemailforlines');
     $helpsubstitforlines = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
     $helpsubstitforlines = $langs->trans("AvailableVariables").':<br>'.implode('<br>', $tmp);
 }
 }
 
 
@@ -484,7 +484,11 @@ if ($action != 'edit')
         {
         {
             print '<td align="'.$align.'">';
             print '<td align="'.$align.'">';
         	if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1,$valuetoshow).'</a>';
         	if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1,$valuetoshow).'</a>';
-        	else if (! empty($tabhelp[$id][$value])) print $form->textwithpicto($valuetoshow,$tabhelp[$id][$value]);
+        	else if (! empty($tabhelp[$id][$value])) 
+        	{
+        	    if (in_array($value, array('topic'))) print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, $value);   // Tooltip on click
+        	    else print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2);                             // Tooltip on hover
+        	}
         	else print $valuetoshow;
         	else print $valuetoshow;
             print '</td>';
             print '</td>';
          }
          }
@@ -539,8 +543,8 @@ if ($action != 'edit')
     foreach ($fieldsforcontent as $tmpfieldlist)
     foreach ($fieldsforcontent as $tmpfieldlist)
     {
     {
         print '<tr class="impair nodrag nodrop nohover"><td colspan="5">';
         print '<tr class="impair nodrag nodrop nohover"><td colspan="5">';
-        if ($tmpfieldlist == 'content') print '<strong>'.$form->textwithpicto($langs->trans("Content"),$tabhelp[$id][$tmpfieldlist]).'</strong><br>';
-        if ($tmpfieldlist == 'content_lines') print '<strong>'.$form->textwithpicto($langs->trans("ContentForLines"),$tabhelp[$id][$tmpfieldlist]).'</strong><br>';
+        if ($tmpfieldlist == 'content') print '<strong>'.$form->textwithpicto($langs->trans("Content"), $tabhelp[$id][$tmpfieldlist], 1, 'help', '', 0, 2, $tmpfieldlist).'</strong><br>';
+        if ($tmpfieldlist == 'content_lines') print '<strong>'.$form->textwithpicto($langs->trans("ContentForLines"), $tabhelp[$id][$tmpfieldlist], 1, 'help', '', 0, 2, $tmpfieldlist).'</strong><br>';
     
     
         if ($context != 'hide')
         if ($context != 'hide')
         {
         {
@@ -624,7 +628,11 @@ if ($resql)
         // Affiche nom du champ
         // Affiche nom du champ
         if ($showfield)
         if ($showfield)
         {
         {
-            if (! empty($tabhelp[$id][$value])) $valuetoshow = $form->textwithpicto($valuetoshow,$tabhelp[$id][$value]);
+            if (! empty($tabhelp[$id][$value])) 
+            {
+                if (in_array($value, array('topic'))) $valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2);   // Tooltip on hover
+                else $valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2);                             // Tooltip on hover
+            }
             print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable?$fieldlist[$field]:''), ($page?'page='.$page.'&':''), $param, "align=".$align, $sortfield, $sortorder);
             print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable?$fieldlist[$field]:''), ($page?'page='.$page.'&':''), $param, "align=".$align, $sortfield, $sortorder);
         }
         }
     }
     }
@@ -651,11 +659,10 @@ if ($resql)
         // Lines with values
         // Lines with values
         while ($i < $num)
         while ($i < $num)
         {
         {
-            $var = ! $var;
 
 
             $obj = $db->fetch_object($resql);
             $obj = $db->fetch_object($resql);
             //print_r($obj);
             //print_r($obj);
-            print '<tr '.$bc[$var].' id="rowid-'.$obj->rowid.'">';
+            print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
             if ($action == 'edit' && ($rowid == (! empty($obj->rowid)?$obj->rowid:$obj->code)))
             if ($action == 'edit' && ($rowid == (! empty($obj->rowid)?$obj->rowid:$obj->code)))
             {
             {
                 $tmpaction='edit';
                 $tmpaction='edit';
@@ -689,7 +696,7 @@ if ($resql)
                     // Show value for field
                     // Show value for field
                     if ($showfield) {
                     if ($showfield) {
                 
                 
-                        print '</tr><tr '.$bc[$var].' nohover tr-'.$tmpfieldlist.'-'.$rowid.' "><td colspan="5">'; // To create an artificial CR for the current tr we are on
+                        print '</tr><tr class="oddeven" nohover tr-'.$tmpfieldlist.'-'.$rowid.' "><td colspan="5">'; // To create an artificial CR for the current tr we are on
                         $okforextended = true;
                         $okforextended = true;
                         if (empty($conf->global->FCKEDITOR_ENABLE_MAIL))
                         if (empty($conf->global->FCKEDITOR_ENABLE_MAIL))
                             $okforextended = false;
                             $okforextended = false;
@@ -781,7 +788,7 @@ if ($resql)
                     // Show value for field
                     // Show value for field
                     if ($showfield) {
                     if ($showfield) {
                         
                         
-                        print '</tr><tr '.$bc[$var].' nohover tr-'.$tmpfieldlist.'-'.$i.' "><td colspan="5">'; // To create an artificial CR for the current tr we are on
+                        print '</tr><tr class="oddeven" nohover tr-'.$tmpfieldlist.'-'.$i.' "><td colspan="5">'; // To create an artificial CR for the current tr we are on
                         $okforextended = true;
                         $okforextended = true;
                         if (empty($conf->global->FCKEDITOR_ENABLE_MAIL))
                         if (empty($conf->global->FCKEDITOR_ENABLE_MAIL))
                             $okforextended = false;
                             $okforextended = false;

+ 2 - 4
htdocs/admin/modules.php

@@ -428,8 +428,6 @@ $h++;
 print "<br>\n";
 print "<br>\n";
 
 
 
 
-$var=true;
-
 if ($mode == 'common')
 if ($mode == 'common')
 {
 {
     
     
@@ -782,7 +780,7 @@ if ($mode == 'marketplace')
     print '</tr>';
     print '</tr>';
 
 
     
     
-    print "<tr ".$bc[$var].">\n";
+    print "<tr class=\"oddeven\">\n";
     $url='https://www.dolistore.com';
     $url='https://www.dolistore.com';
     print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.png"></a></td>';
     print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.png"></a></td>';
     print '<td>'.$langs->trans("DoliStoreDesc").'</td>';
     print '<td>'.$langs->trans("DoliStoreDesc").'</td>';
@@ -790,7 +788,7 @@ if ($mode == 'marketplace')
     print '</tr>';
     print '</tr>';
 
 
     
     
-    print "<tr ".$bc[$var].">\n";
+    print "<tr class=\"oddeven\">\n";
     $url='https://partners.dolibarr.org';
     $url='https://partners.dolibarr.org';
     print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner_int.png"></a></td>';
     print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner_int.png"></a></td>';
     print '<td>'.$langs->trans("DoliPartnersDesc").'</td>';
     print '<td>'.$langs->trans("DoliPartnersDesc").'</td>';

+ 4 - 9
htdocs/admin/oauth.php

@@ -93,7 +93,6 @@ print $langs->trans("ListOfSupportedOauthProviders").'<br><br>';
 
 
 print '<table class="noborder" width="100%">';
 print '<table class="noborder" width="100%">';
 
 
-$var = true;
 $i=0;
 $i=0;
 
 
 foreach ($list as $key)
 foreach ($list as $key)
@@ -116,31 +115,27 @@ foreach ($list as $key)
     if ($supported)
     if ($supported)
     {
     {
         $redirect_uri=$urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$key[0]].'_oauthcallback.php';
         $redirect_uri=$urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$key[0]].'_oauthcallback.php';
-        $var = !$var;
-        print '<tr '.$bc[$var].' class="value">';
+        print '<tr class="oddeven value">';
         print '<td>'.$langs->trans("UseTheFollowingUrlAsRedirectURI").'</td>';
         print '<td>'.$langs->trans("UseTheFollowingUrlAsRedirectURI").'</td>';
         print '<td><input style="width: 80%" type"text" name="uri'.$key[0].'" value="'.$redirect_uri.'">';
         print '<td><input style="width: 80%" type"text" name="uri'.$key[0].'" value="'.$redirect_uri.'">';
         print '</td></tr>';
         print '</td></tr>';
     }
     }
     else
     else
     {
     {
-        $var = !$var;
-        print '<tr '.$bc[$var].' class="value">';
+        print '<tr class="oddeven value">';
         print '<td>'.$langs->trans("UseTheFollowingUrlAsRedirectURI").'</td>';
         print '<td>'.$langs->trans("UseTheFollowingUrlAsRedirectURI").'</td>';
         print '<td>'.$langs->trans("FeatureNotYetSupported").'</td>';
         print '<td>'.$langs->trans("FeatureNotYetSupported").'</td>';
         print '</td></tr>';
         print '</td></tr>';
     }
     }
         
         
     // Api Id
     // Api Id
-    $var = !$var;
-    print '<tr '.$bc[$var].' class="value">';
+    print '<tr class="oddeven value">';
     print '<td><label for="'.$key[1].'">'.$langs->trans($key[1]).'</label></td>';
     print '<td><label for="'.$key[1].'">'.$langs->trans($key[1]).'</label></td>';
     print '<td><input type="text" size="100" id="'.$key[1].'" name="'.$key[1].'" value="'.$conf->global->{$key[1]}.'">';
     print '<td><input type="text" size="100" id="'.$key[1].'" name="'.$key[1].'" value="'.$conf->global->{$key[1]}.'">';
     print '</td></tr>';
     print '</td></tr>';
 
 
     // Api Secret
     // Api Secret
-    $var = !$var;
-    print '<tr '.$bc[$var].' class="value">';
+    print '<tr class="oddeven value">';
     print '<td><label for="'.$key[2].'">'.$langs->trans($key[2]).'</label></td>';
     print '<td><label for="'.$key[2].'">'.$langs->trans($key[2]).'</label></td>';
     print '<td><input type="password" size="100" id="'.$key[2].'" name="'.$key[2].'" value="'.$conf->global->{$key[2]}.'">';
     print '<td><input type="password" size="100" id="'.$key[2].'" name="'.$key[2].'" value="'.$conf->global->{$key[2]}.'">';
     print '</td></tr>';
     print '</td></tr>';

+ 1 - 1
htdocs/admin/payment.php

@@ -117,7 +117,7 @@ $linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToM
 print load_fiche_titre($langs->trans("BillsSetup"),$linkback,'title_setup');
 print load_fiche_titre($langs->trans("BillsSetup"),$linkback,'title_setup');
 
 
 $head = invoice_admin_prepare_head();
 $head = invoice_admin_prepare_head();
-dol_fiche_head($head, 'payment', $langs->trans("Invoices"), 0, 'invoice');
+dol_fiche_head($head, 'payment', $langs->trans("Invoices"), -1, 'invoice');
 
 
 /*
 /*
  *  Numbering module
  *  Numbering module

+ 42 - 3
htdocs/admin/pdf.php

@@ -42,15 +42,25 @@ $langs->load("members");
 if (! $user->admin) accessforbidden();
 if (! $user->admin) accessforbidden();
 
 
 $action = GETPOST('action','alpha');
 $action = GETPOST('action','alpha');
+$cancel = GETPOST('cancel','alpha');
+
 
 
 /*
 /*
  * Actions
  * Actions
  */
  */
 
 
+if ($cancel) {
+    $action='';
+}
+
 if ($action == 'update')
 if ($action == 'update')
 {
 {
 	dolibarr_set_const($db, "MAIN_PDF_FORMAT",    $_POST["MAIN_PDF_FORMAT"],'chaine',0,'',$conf->entity);
 	dolibarr_set_const($db, "MAIN_PDF_FORMAT",    $_POST["MAIN_PDF_FORMAT"],'chaine',0,'',$conf->entity);
-
+	
+	dolibarr_set_const($db, "MAIN_PDF_MARGIN_LEFT",    $_POST["MAIN_PDF_MARGIN_LEFT"],'chaine',0,'',$conf->entity);
+	dolibarr_set_const($db, "MAIN_PDF_MARGIN_RIGHT",   $_POST["MAIN_PDF_MARGIN_RIGHT"],'chaine',0,'',$conf->entity);
+	dolibarr_set_const($db, "MAIN_PDF_MARGIN_TOP",     $_POST["MAIN_PDF_MARGIN_TOP"],'chaine',0,'',$conf->entity);
+	dolibarr_set_const($db, "MAIN_PDF_MARGIN_BOTTOM",  $_POST["MAIN_PDF_MARGIN_BOTTOM"],'chaine',0,'',$conf->entity);
 
 
     dolibarr_set_const($db, "MAIN_PROFID1_IN_ADDRESS",    $_POST["MAIN_PROFID1_IN_ADDRESS"],'chaine',0,'',$conf->entity);
     dolibarr_set_const($db, "MAIN_PROFID1_IN_ADDRESS",    $_POST["MAIN_PROFID1_IN_ADDRESS"],'chaine',0,'',$conf->entity);
 	dolibarr_set_const($db, "MAIN_PROFID2_IN_ADDRESS",    $_POST["MAIN_PROFID2_IN_ADDRESS"],'chaine',0,'',$conf->entity);
 	dolibarr_set_const($db, "MAIN_PROFID2_IN_ADDRESS",    $_POST["MAIN_PROFID2_IN_ADDRESS"],'chaine',0,'',$conf->entity);
@@ -133,7 +143,20 @@ if ($action == 'edit')	// Edit
     print $formadmin->select_paper_format($selected,'MAIN_PDF_FORMAT');
     print $formadmin->select_paper_format($selected,'MAIN_PDF_FORMAT');
     print '</td></tr>';
     print '</td></tr>';
 
 
-	print '</table>';
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_LEFT").'</td><td>';
+    print '<input type="text" class="maxwidth50" name="MAIN_PDF_MARGIN_LEFT" value="'.(empty($conf->global->MAIN_PDF_MARGIN_LEFT)?10:$conf->global->MAIN_PDF_MARGIN_LEFT).'">';
+    print '</td></tr>';
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_RIGHT").'</td><td>';
+    print '<input type="text" class="maxwidth50" name="MAIN_PDF_MARGIN_RIGHT" value="'.(empty($conf->global->MAIN_PDF_MARGIN_RIGHT)?10:$conf->global->MAIN_PDF_MARGIN_RIGHT).'">';
+    print '</td></tr>';
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_TOP").'</td><td>';
+    print '<input type="text" class="maxwidth50" name="MAIN_PDF_MARGIN_TOP" value="'.(empty($conf->global->MAIN_PDF_MARGIN_TOP)?10:$conf->global->MAIN_PDF_MARGIN_TOP).'">';
+    print '</td></tr>';
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_BOTTOM").'</td><td>';
+    print '<input type="text" class="maxwidth50" name="MAIN_PDF_MARGIN_BOTTOM" value="'.(empty($conf->global->MAIN_PDF_MARGIN_BOTTOM)?10:$conf->global->MAIN_PDF_MARGIN_BOTTOM).'">';
+    print '</td></tr>';
+    
+    print '</table>';
 
 
 	print '<br>';
 	print '<br>';
 
 
@@ -270,7 +293,9 @@ if ($action == 'edit')	// Edit
 	print '</table>';
 	print '</table>';
 
 
     print '<br><div class="center">';
     print '<br><div class="center">';
-    print '<input class="button" type="submit" value="'.$langs->trans("Save").'">';
+    print '<input class="button" type="submit" name="save" value="'.$langs->trans("Save").'">';
+    print ' &nbsp; ';
+    print '<input class="button" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
     print '</div>';
     print '</div>';
 
 
     print '</form>';
     print '</form>';
@@ -314,6 +339,20 @@ else	// Show
     print $pdfformatlabel;
     print $pdfformatlabel;
     print '</td></tr>';
     print '</td></tr>';
 
 
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_LEFT").'</td><td>';
+    print empty($conf->global->MAIN_PDF_MARGIN_LEFT)?10:$conf->global->MAIN_PDF_MARGIN_LEFT;
+    print '</td></tr>';
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_RIGHT").'</td><td>';
+    print empty($conf->global->MAIN_PDF_MARGIN_RIGHT)?10:$conf->global->MAIN_PDF_MARGIN_RIGHT;
+    print '</td></tr>';
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_TOP").'</td><td>';
+    print empty($conf->global->MAIN_PDF_MARGIN_TOP)?10:$conf->global->MAIN_PDF_MARGIN_TOP;
+    print '</td></tr>';
+    print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_MARGIN_BOTTOM").'</td><td>';
+    print empty($conf->global->MAIN_PDF_MARGIN_BOTTOM)?10:$conf->global->MAIN_PDF_MARGIN_BOTTOM;
+    print '</td></tr>';
+    
+    
 	print '</table>';
 	print '</table>';
 
 
 	print '<br>';
 	print '<br>';

+ 1 - 3
htdocs/admin/perms.php

@@ -140,7 +140,6 @@ if ($result)
 {
 {
     $num	= $db->num_rows($result);
     $num	= $db->num_rows($result);
     $i		= 0;
     $i		= 0;
-    $var	= True;
     $oldmod	= "";
     $oldmod	= "";
 
 
     while ($i < $num)
     while ($i < $num)
@@ -187,8 +186,7 @@ if ($result)
         }
         }
 
 
         
         
-        print '<tr '. $bc[$var].'>';
-
+        print '<tr class="oddeven">';
         print '<td>'.img_object('',$picto).' '.$objMod->getName();
         print '<td>'.img_object('',$picto).' '.$objMod->getName();
         print '<a name="'.$objMod->getName().'">&nbsp;</a>';
         print '<a name="'.$objMod->getName().'">&nbsp;</a>';
 
 

+ 8 - 7
htdocs/admin/propal.php

@@ -570,11 +570,17 @@ print "</td></tr>\n";
 print '</form>';
 print '</form>';
 */
 */
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_PROPOSAL_FREE_TEXT">';
 print '<input type="hidden" name="action" value="set_PROPOSAL_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnProposal").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnProposal"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='PROPOSAL_FREE_TEXT';
 $variablename='PROPOSAL_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -596,12 +602,7 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_PROPALE_DRAFT_WATERMARK\">";
 print "<input type=\"hidden\" name=\"action\" value=\"set_PROPALE_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
 print '<tr class="oddeven"><td>';
-$substitutionarray=pdf_getSubstitutionArray($langs);
-$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
-$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
-foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
-$htmltext.='</i>';
-print $form->textwithpicto($langs->trans("WatermarkOnDraftProposal"), $htmltext);
+print $form->textwithpicto($langs->trans("WatermarkOnDraftProposal"), $htmltext).'<br>';
 print '</td><td>';
 print '</td><td>';
 print '<input class="flat minwidth200" type="text" name="PROPALE_DRAFT_WATERMARK" value="'.$conf->global->PROPALE_DRAFT_WATERMARK.'">';
 print '<input class="flat minwidth200" type="text" name="PROPALE_DRAFT_WATERMARK" value="'.$conf->global->PROPALE_DRAFT_WATERMARK.'">';
 print '</td><td align="right">';
 print '</td><td align="right">';

+ 1 - 1
htdocs/admin/salaries.php

@@ -99,7 +99,7 @@ foreach ($list as $key)
 {
 {
 	
 	
 
 
-	print '<tr '.$bc[$var].' class="value">';
+	print '<tr class="oddeven value">';
 
 
 	// Param
 	// Param
 	$label = $langs->trans($key);
 	$label = $langs->trans($key);

+ 56 - 0
htdocs/admin/stock.php

@@ -432,6 +432,61 @@ if ($virtualdiffersfromphysical)
 }
 }
 
 
 
 
+print '<br />';
+if ($conf->global->MAIN_LEVEL_FEATURES >= 2)
+{
+	$var=false;
+	print '<table class="noborder" width="100%">';
+	print '<tr class="liste_titre">';
+	print '<td>'.$langs->trans("Inventory").'</td>'."\n";
+	print '<td align="center" width="20">&nbsp;</td>';
+	print '<td align="center" width="100">&nbsp;</td>'."\n";
+	
+	// Example with a yes / no select
+	$var=!$var;
+	print '<tr '.$bc[$var].'>';
+	print '<td>'.$langs->trans("INVENTORY_DISABLE_VIRTUAL").'</td>';
+	print '<td align="center" width="20">&nbsp;</td>';
+	print '<td align="right" width="300">';
+	print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
+	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	print '<input type="hidden" name="action" value="set_INVENTORY_DISABLE_VIRTUAL">';
+	print $form->selectyesno("INVENTORY_DISABLE_VIRTUAL",$conf->global->INVENTORY_DISABLE_VIRTUAL,1);
+	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
+	print '</form>';
+	print '</td></tr>';
+	
+	// Example with a yes / no select
+	$var=!$var;
+	print '<tr '.$bc[$var].'>';
+	print '<td>'.$langs->trans("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA").'</td>';
+	print '<td align="center" width="20">&nbsp;</td>';
+	print '<td align="right" width="300">';
+	print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
+	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	print '<input type="hidden" name="action" value="set_INVENTORY_USE_MIN_PA_IF_NO_LAST_PA">';
+	print $form->selectyesno("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA",$conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA,1);
+	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
+	print '</form>';
+	print '</td></tr>';
+	
+	// Example with a yes / no select
+	$var=!$var;
+	print '<tr '.$bc[$var].'>';
+	print '<td>'.$langs->trans("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT").'</td>';
+	print '<td align="center" width="20">&nbsp;</td>';
+	print '<td align="right" width="300">';
+	print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
+	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	print '<input type="hidden" name="action" value="set_INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT">';
+	print $form->selectyesno("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT",$conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT,1);
+	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
+	print '</form>';
+	print '</td></tr>';
+	
+	print '</table>';
+}
+
 $var=true;
 $var=true;
 print '<table class="noborder" width="100%">';
 print '<table class="noborder" width="100%">';
 
 
@@ -508,6 +563,7 @@ if ($conf->global->PRODUIT_SOUSPRODUITS)
 
 
 print '</table>';
 print '</table>';
 
 
+
 llxFooter();
 llxFooter();
 
 
 $db->close();
 $db->close();

+ 9 - 4
htdocs/admin/supplier_invoice.php

@@ -5,7 +5,7 @@
  * Copyright (C) 2004      Sebastien Di Cintio     <sdicintio@ressource-toi.org>
  * Copyright (C) 2004      Sebastien Di Cintio     <sdicintio@ressource-toi.org>
  * Copyright (C) 2004      Benoit Mortier          <benoit.mortier@opensides.be>
  * Copyright (C) 2004      Benoit Mortier          <benoit.mortier@opensides.be>
  * Copyright (C) 2010-2013 Juanjo Menent           <jmenent@2byte.es>
  * Copyright (C) 2010-2013 Juanjo Menent           <jmenent@2byte.es>
- * Copyright (C) 2011-2015 Philippe Grand          <philippe.grand@atoo-net.com>
+ * Copyright (C) 2011-2017 Philippe Grand          <philippe.grand@atoo-net.com>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -361,7 +361,6 @@ foreach ($dirmodels as $reldir)
 
 
     if (is_dir($dir))
     if (is_dir($dir))
     {
     {
-        $var=true;
 
 
         $handle=opendir($dir);
         $handle=opendir($dir);
 
 
@@ -379,7 +378,7 @@ foreach ($dirmodels as $reldir)
 	                $module = new $classname($db, new FactureFournisseur($db));
 	                $module = new $classname($db, new FactureFournisseur($db));
 
 
                     
                     
-                    print "<tr ".$bc[$var].">\n";
+                    print "<tr class=\"oddeven\">\n";
                     print "<td>";
                     print "<td>";
 	                print (empty($module->name)?$name:$module->name);
 	                print (empty($module->name)?$name:$module->name);
 	                print "</td>\n";
 	                print "</td>\n";
@@ -471,8 +470,14 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print '<td width="80">&nbsp;</td>';
 print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 print "</tr>\n";
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnInvoices").' '.img_info($langs->trans("AddCRIfTooLong")).'</br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnInvoices"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SUPPLIER_INVOICE_FREE_TEXT';
 $variablename='SUPPLIER_INVOICE_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {

+ 10 - 4
htdocs/admin/supplier_order.php

@@ -5,7 +5,7 @@
  * Copyright (C) 2004      Sebastien Di Cintio     <sdicintio@ressource-toi.org>
  * Copyright (C) 2004      Sebastien Di Cintio     <sdicintio@ressource-toi.org>
  * Copyright (C) 2004      Benoit Mortier          <benoit.mortier@opensides.be>
  * Copyright (C) 2004      Benoit Mortier          <benoit.mortier@opensides.be>
  * Copyright (C) 2010-2013 Juanjo Menent           <jmenent@2byte.es>
  * Copyright (C) 2010-2013 Juanjo Menent           <jmenent@2byte.es>
- * Copyright (C) 2011-2015 Philippe Grand          <philippe.grand@atoo-net.com>
+ * Copyright (C) 2011-2017 Philippe Grand          <philippe.grand@atoo-net.com>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -382,7 +382,6 @@ print '</tr>'."\n";
 
 
 clearstatcache();
 clearstatcache();
 
 
-$var=true;
 foreach ($dirmodels as $reldir)
 foreach ($dirmodels as $reldir)
 {
 {
 	$dir = dol_buildpath($reldir."core/modules/supplier_order/pdf/");
 	$dir = dol_buildpath($reldir."core/modules/supplier_order/pdf/");
@@ -403,7 +402,7 @@ foreach ($dirmodels as $reldir)
 	                $module = new $classname($db, new CommandeFournisseur($db));
 	                $module = new $classname($db, new CommandeFournisseur($db));
 
 
                     
                     
-                    print "<tr ".$bc[$var].">\n";
+                    print "<tr class=\"oddeven\">\n";
                     print "<td>";
                     print "<td>";
 	                print (empty($module->name)?$name:$module->name);
 	                print (empty($module->name)?$name:$module->name);
 	                print "</td>\n";
 	                print "</td>\n";
@@ -491,6 +490,7 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print '<td width="80">&nbsp;</td>';
 print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 print "</tr>\n";
 $var=false;
 $var=false;
+
 //if ($conf->global->MAIN_FEATURES_LEVEL > 0)
 //if ($conf->global->MAIN_FEATURES_LEVEL > 0)
 //{
 //{
 	print '<tr class="oddeven"><td>';
 	print '<tr class="oddeven"><td>';
@@ -536,8 +536,14 @@ else
 }
 }
 */
 */
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnOrders").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnOrders"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SUPPLIER_ORDER_FREE_TEXT';
 $variablename='SUPPLIER_ORDER_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {

+ 1 - 2
htdocs/admin/supplier_payment.php

@@ -367,7 +367,6 @@ foreach ($dirmodels as $reldir)
 
 
     if (is_dir($dir))
     if (is_dir($dir))
     {
     {
-        $var=true;
 
 
         $handle=opendir($dir);
         $handle=opendir($dir);
 
 
@@ -385,7 +384,7 @@ foreach ($dirmodels as $reldir)
 	                $module = new $classname($db, new PaiementFourn($db));
 	                $module = new $classname($db, new PaiementFourn($db));
 
 
                     
                     
-                    print "<tr ".$bc[$var].">\n";
+                    print "<tr class=\"oddeven\">\n";
                     print "<td>";
                     print "<td>";
 	                print (empty($module->name)?$name:$module->name);
 	                print (empty($module->name)?$name:$module->name);
 	                print "</td>\n";
 	                print "</td>\n";

+ 9 - 2
htdocs/admin/supplier_proposal.php

@@ -523,12 +523,18 @@ print '<td width="60" align="center">'.$langs->trans("Value")."</td>\n";
 print "<td>&nbsp;</td>\n";
 print "<td>&nbsp;</td>\n";
 print "</tr>";
 print "</tr>";
 
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_SUPPLIER_PROPOSAL_FREE_TEXT">';
 print '<input type="hidden" name="action" value="set_SUPPLIER_PROPOSAL_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnSupplierProposal").' '.img_info($langs->trans("AddCRIfTooLong")).'</br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnSupplierProposal"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SUPPLIER_PROPOSAL_FREE_TEXT';
 $variablename='SUPPLIER_PROPOSAL_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
 {
@@ -550,7 +556,8 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_SUPPLIER_PROPOSAL_DRAFT_WATERMARK\">";
 print "<input type=\"hidden\" name=\"action\" value=\"set_SUPPLIER_PROPOSAL_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
 print '<tr class="oddeven"><td>';
-print $langs->trans("WatermarkOnDraftSupplierProposal").'</td><td>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftProposal"), $htmltext).'<br>';
+print '</td><td>';
 print '<input size="50" class="flat" type="text" name="SUPPLIER_PROPOSAL_DRAFT_WATERMARK" value="'.$conf->global->SUPPLIER_PROPOSAL_DRAFT_WATERMARK.'">';
 print '<input size="50" class="flat" type="text" name="SUPPLIER_PROPOSAL_DRAFT_WATERMARK" value="'.$conf->global->SUPPLIER_PROPOSAL_DRAFT_WATERMARK.'">';
 print '</td><td align="right">';
 print '</td><td align="right">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';

+ 14 - 8
htdocs/admin/syslog.php

@@ -40,7 +40,7 @@ $action = GETPOST("action");
 $syslogModules = array();
 $syslogModules = array();
 $activeModules = array();
 $activeModules = array();
 
 
-if (defined('SYSLOG_HANDLERS')) $activeModules = json_decode(constant('SYSLOG_HANDLERS'));
+if (! empty($conf->global->SYSLOG_HANDLERS)) $activeModules = json_decode($conf->global->SYSLOG_HANDLERS);
 
 
 $dirsyslogs = array_merge(array('/core/modules/syslog/'), $conf->modules_parts['syslog']);
 $dirsyslogs = array_merge(array('/core/modules/syslog/'), $conf->modules_parts['syslog']);
 foreach ($dirsyslogs as $reldir) {
 foreach ($dirsyslogs as $reldir) {
@@ -88,7 +88,8 @@ if ($action == 'set')
 
 
 	$newActiveModules = array();
 	$newActiveModules = array();
 	$selectedModules = (isset($_POST['SYSLOG_HANDLERS']) ? $_POST['SYSLOG_HANDLERS'] : array());
 	$selectedModules = (isset($_POST['SYSLOG_HANDLERS']) ? $_POST['SYSLOG_HANDLERS'] : array());
-	//var_dump($selectedModules);
+	
+	// Save options of handler
 	foreach ($syslogModules as $syslogHandler)
 	foreach ($syslogModules as $syslogHandler)
 	{
 	{
 		if (in_array($syslogHandler, $syslogModules))
 		if (in_array($syslogHandler, $syslogModules))
@@ -101,7 +102,7 @@ if ($action == 'set')
 				if (isset($_POST[$option['constant']]))
 				if (isset($_POST[$option['constant']]))
 				{
 				{
 					$_POST[$option['constant']] = trim($_POST[$option['constant']]);
 					$_POST[$option['constant']] = trim($_POST[$option['constant']]);
-					dolibarr_del_const($db, $option['constant'], 0);
+					dolibarr_del_const($db, $option['constant'], -1);
 					dolibarr_set_const($db, $option['constant'], $_POST[$option['constant']], 'chaine',0, '', 0);
 					dolibarr_set_const($db, $option['constant'], $_POST[$option['constant']], 'chaine',0, '', 0);
 				}
 				}
 			}
 			}
@@ -109,7 +110,9 @@ if ($action == 'set')
 	}
 	}
 
 
 	$activeModules = $newActiveModules;
 	$activeModules = $newActiveModules;
-	dolibarr_set_const($db, 'SYSLOG_HANDLERS', json_encode($activeModules), 'chaine',0,'',0);
+
+    dolibarr_del_const($db, 'SYSLOG_HANDLERS', -1);  // To be sure ther is not a setup into another entity	
+    dolibarr_set_const($db, 'SYSLOG_HANDLERS', json_encode($activeModules), 'chaine',0,'',0);
 
 
 	// Check configuration
 	// Check configuration
 	foreach ($activeModules as $modulename) {
 	foreach ($activeModules as $modulename) {
@@ -194,7 +197,6 @@ print '<tr class="liste_titre">';
 print '<td>'.$langs->trans("Type").'</td><td>'.$langs->trans("Value").'</td>';
 print '<td>'.$langs->trans("Type").'</td><td>'.$langs->trans("Value").'</td>';
 print '<td align="right" colspan="2"><input type="submit" class="button" '.$option.' value="'.$langs->trans("Modify").'"></td>';
 print '<td align="right" colspan="2"><input type="submit" class="button" '.$option.' value="'.$langs->trans("Modify").'"></td>';
 print "</tr>\n";
 print "</tr>\n";
-$var=true;
 
 
 foreach ($syslogModules as $moduleName)
 foreach ($syslogModules as $moduleName)
 {
 {
@@ -207,7 +209,7 @@ foreach ($syslogModules as $moduleName)
 	
 	
 	print '<tr class="oddeven">';
 	print '<tr class="oddeven">';
 	print '<td width="140">';
 	print '<td width="140">';
-	print '<input '.$bc[$var].' type="checkbox" name="SYSLOG_HANDLERS[]" value="'.$moduleName.'" '.(in_array($moduleName, $activeModules) ? 'checked' : '').($moduleactive <= 0 ? 'disabled' : '').'> ';
+	print '<input class="oddeven" type="checkbox" name="SYSLOG_HANDLERS[]" value="'.$moduleName.'" '.(in_array($moduleName, $activeModules) ? 'checked' : '').($moduleactive <= 0 ? 'disabled' : '').'> ';
 	print $module->getName();
 	print $module->getName();
 	print '</td>';
 	print '</td>';
 
 
@@ -217,8 +219,12 @@ foreach ($syslogModules as $moduleName)
 	{
 	{
 		foreach ($setuparray as $option)
 		foreach ($setuparray as $option)
 		{
 		{
-			if (isset($_POST[$option['constant']])) $value=$_POST[$option['constant']];
-			else if (defined($option['constant'])) $value = constant($option['constant']);
+		    $tmpoption=$option['constant'];
+		    if (! empty($tmpoption))
+		    {
+    			if (isset($_POST[$tmpoption])) $value=$_POST[$tmpoption];
+    			else if (! empty($conf->global->$tmpoption)) $value = $conf->global->$tmpoption;
+		    }
 			else $value = (isset($option['default']) ? $option['default'] : '');
 			else $value = (isset($option['default']) ? $option['default'] : '');
 
 
 			print $option['name'].': <input type="text" class="flat" name="'.$option['constant'].'" value="'.$value.'"'.(isset($option['attr']) ? ' '.$option['attr'] : '').'>';
 			print $option['name'].': <input type="text" class="flat" name="'.$option['constant'].'" value="'.$value.'"'.(isset($option['attr']) ? ' '.$option['attr'] : '').'>';

+ 5 - 5
htdocs/admin/taxes.php

@@ -136,10 +136,10 @@ else
     print '<tr class="liste_titre">';
     print '<tr class="liste_titre">';
     print '<td colspan="2">'.$langs->trans('OptionVatMode').'</td><td>'.$langs->trans('Description').'</td>';
     print '<td colspan="2">'.$langs->trans('OptionVatMode').'</td><td>'.$langs->trans('Description').'</td>';
     print "</tr>\n";
     print "</tr>\n";
-    print '<tr '.$bc[false].'><td width="200"><input type="radio" name="tax_mode" value="0"'.($tax_mode != 1 ? ' checked' : '').'> '.$langs->trans('OptionVATDefault').'</td>';
+    print '<tr class="oddeven"><td width="200"><input type="radio" name="tax_mode" value="0"'.($tax_mode != 1 ? ' checked' : '').'> '.$langs->trans('OptionVATDefault').'</td>';
     print '<td colspan="2">'.nl2br($langs->trans('OptionVatDefaultDesc'));
     print '<td colspan="2">'.nl2br($langs->trans('OptionVatDefaultDesc'));
     print "</td></tr>\n";
     print "</td></tr>\n";
-    print '<tr '.$bc[true].'><td width="200"><input type="radio" name="tax_mode" value="1"'.($tax_mode == 1 ? ' checked' : '').'> '.$langs->trans('OptionVATDebitOption').'</td>';
+    print '<tr class="oddeven"><td width="200"><input type="radio" name="tax_mode" value="1"'.($tax_mode == 1 ? ' checked' : '').'> '.$langs->trans('OptionVATDebitOption').'</td>';
     print '<td colspan="2">'.nl2br($langs->trans('OptionVatDebitOptionDesc'))."</td></tr>\n";
     print '<td colspan="2">'.nl2br($langs->trans('OptionVatDebitOptionDesc'))."</td></tr>\n";
 
 
     print "</table>\n";
     print "</table>\n";
@@ -152,7 +152,7 @@ else
     print '<tr class="liste_titre"><td>&nbsp;</td><td>'.$langs->trans("Buy").'</td><td>'.$langs->trans("Sell").'</td></tr>';
     print '<tr class="liste_titre"><td>&nbsp;</td><td>'.$langs->trans("Buy").'</td><td>'.$langs->trans("Sell").'</td></tr>';
 
 
     // Products
     // Products
-    print '<tr '.$bc[false].'><td>'.$langs->trans("Product").'</td>';
+    print '<tr class="oddeven"><td>'.$langs->trans("Product").'</td>';
     print '<td>';
     print '<td>';
     print $langs->trans("OnDelivery");
     print $langs->trans("OnDelivery");
     print ' ('.$langs->trans("SupposedToBeInvoiceDate").')';
     print ' ('.$langs->trans("SupposedToBeInvoiceDate").')';
@@ -163,7 +163,7 @@ else
     print '</td></tr>';
     print '</td></tr>';
 
 
     // Services
     // Services
-    print '<tr '.$bc[true].'><td>'.$langs->trans("Services").'</td>';
+    print '<tr class="oddeven"><td>'.$langs->trans("Services").'</td>';
     print '<td>';
     print '<td>';
     if ($tax_mode == 0)
     if ($tax_mode == 0)
     {
     {
@@ -206,7 +206,7 @@ foreach ($list as $key)
 {
 {
 	
 	
 
 
-	print '<tr '.$bc[$var].' class="value">';
+	print '<tr class="oddeven value">';
 
 
 	// Param
 	// Param
 	$label = $langs->trans($key); 
 	$label = $langs->trans($key); 

+ 21 - 5
htdocs/admin/translation.php

@@ -71,7 +71,7 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e
 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
 
 
 // Purge search criteria
 // Purge search criteria
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 {
 {
     $transkey='';
     $transkey='';
     $transvalue='';
     $transvalue='';
@@ -114,8 +114,16 @@ if ($action == 'add' || (GETPOST('add') && $action != 'update'))
 		}
 		}
 		else
 		else
 		{
 		{
-	        $db->rollback();
-		    setEventMessages($db->lasterror(), null, 'errors');
+
+		    $db->rollback();
+		    if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
+		    {
+		        setEventMessages($langs->trans("WarningAnEntryAlreadyExistForTransKey"), null, 'warnings');
+		    }
+		    else 
+		    {
+		        setEventMessages($db->lasterror(), null, 'errors');
+		    }
 			$action='';
 			$action='';
 		}
 		}
 	}
 	}
@@ -407,9 +415,17 @@ if ($mode == 'searchkey')
         print '<tr class="oddeven"><td>'.$langcode.'</td><td>'.$key.'</td><td>';
         print '<tr class="oddeven"><td>'.$langcode.'</td><td>'.$key.'</td><td>';
         print dol_escape_htmltag($val);
         print dol_escape_htmltag($val);
         print '</td><td align="right">';
         print '</td><td align="right">';
-        if ($val != $newlangfileonly->tab_translate[$key]) 
+        if (! empty($newlangfileonly->tab_translate[$key]))
+        {
+            if ($val != $newlangfileonly->tab_translate[$key]) 
+            {
+                $htmltext = $langs->trans("OriginalValueWas", $newlangfileonly->tab_translate[$key]);
+                print $form->textwithpicto('', $htmltext, 1, 'info');
+            }
+        }
+        else
         {
         {
-            $htmltext = $langs->trans("OriginalValueWas", $newlangfileonly->tab_translate[$key]);
+            $htmltext = $langs->trans("TransKeyWithoutOriginalValue", $key);
             print $form->textwithpicto('', $htmltext, 1, 'warning');
             print $form->textwithpicto('', $htmltext, 1, 'warning');
         }
         }
         /*if (! empty($conf->multicompany->enabled) && !$user->entity)
         /*if (! empty($conf->multicompany->enabled) && !$user->entity)

+ 17 - 34
htdocs/admin/websites.php

@@ -375,11 +375,11 @@ if ($id)
             // dans les dictionnaires de donnees
             // dans les dictionnaires de donnees
             $valuetoshow=ucfirst($fieldlist[$field]);   // Par defaut
             $valuetoshow=ucfirst($fieldlist[$field]);   // Par defaut
             $valuetoshow=$langs->trans($valuetoshow);   // try to translate
             $valuetoshow=$langs->trans($valuetoshow);   // try to translate
-            $align="left";
+            $align='';
             if ($fieldlist[$field]=='lang')            { $valuetoshow=$langs->trans("Language"); }
             if ($fieldlist[$field]=='lang')            { $valuetoshow=$langs->trans("Language"); }
             if ($valuetoshow != '')
             if ($valuetoshow != '')
             {
             {
-                print '<td align="'.$align.'">';
+                print '<td class="'.$align.'">';
             	if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1,$valuetoshow).'</a>';
             	if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1,$valuetoshow).'</a>';
             	else if (! empty($tabhelp[$id][$value])) print $form->textwithpicto($valuetoshow,$tabhelp[$id][$value]);
             	else if (! empty($tabhelp[$id][$value])) print $form->textwithpicto($valuetoshow,$tabhelp[$id][$value]);
             	else print $valuetoshow;
             	else print $valuetoshow;
@@ -413,14 +413,11 @@ if ($id)
         $reshook=$hookmanager->executeHooks('createDictionaryFieldlist',$parameters, $obj, $tmpaction);    // Note that $action and $object may have been modified by some hooks
         $reshook=$hookmanager->executeHooks('createDictionaryFieldlist',$parameters, $obj, $tmpaction);    // Note that $action and $object may have been modified by some hooks
         $error=$hookmanager->error; $errors=$hookmanager->errors;
         $error=$hookmanager->error; $errors=$hookmanager->errors;
 
 
-        if ($id == 3) unset($fieldlist[2]);
-
         if (empty($reshook))
         if (empty($reshook))
         {
         {
        		fieldListWebsites($fieldlist,$obj,$tabname[$id],'add');
        		fieldListWebsites($fieldlist,$obj,$tabname[$id],'add');
         }
         }
 
 
-        if ($id == 4) print '<td></td>';
         print '<td colspan="3" align="right">';
         print '<td colspan="3" align="right">';
         if ($action != 'edit')
         if ($action != 'edit')
         {
         {
@@ -430,15 +427,9 @@ if ($id)
         print "</tr>";
         print "</tr>";
 
 
         $colspan=count($fieldlist)+2;
         $colspan=count($fieldlist)+2;
-        if ($id == 4) $colspan++;
-
-        if (! empty($alabelisused) && $id != 25)  // If there is one label among fields, we show legend of *
-        {
-        	print '<tr><td colspan="'.$colspan.'">* '.$langs->trans("LabelUsedByDefault").'.</td></tr>';
-        }
-        print '<tr><td colspan="'.$colspan.'">&nbsp;</td></tr>';	// Keep &nbsp; to have a line with enough height
     }
     }
 
 
+    print '</table>';
     print '</form>';
     print '</form>';
 
 
 
 
@@ -450,9 +441,17 @@ if ($id)
     {
     {
         $num = $db->num_rows($resql);
         $num = $db->num_rows($resql);
         $i = 0;
         $i = 0;
-        $var=true;
         if ($num)
         if ($num)
         {
         {
+            print '<br>';
+            
+            print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
+            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+            print '<input type="hidden" name="page" value="'.$page.'">';
+            print '<input type="hidden" name="rowid" value="'.$rowid.'">';
+            
+            print '<table class="noborder" width="100%">';
+        
             // There is several pages
             // There is several pages
             if ($num > $listlimit)
             if ($num > $listlimit)
             {
             {
@@ -499,18 +498,12 @@ if ($id)
             // Lines with values
             // Lines with values
             while ($i < $num)
             while ($i < $num)
             {
             {
-                $var = ! $var;
 
 
                 $obj = $db->fetch_object($resql);
                 $obj = $db->fetch_object($resql);
                 //print_r($obj);
                 //print_r($obj);
-                print '<tr '.$bc[$var].' id="rowid-'.$obj->rowid.'">';
+                print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
                 if ($action == 'edit' && ($rowid == (! empty($obj->rowid)?$obj->rowid:$obj->code)))
                 if ($action == 'edit' && ($rowid == (! empty($obj->rowid)?$obj->rowid:$obj->code)))
                 {
                 {
-                    print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
-                    print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-                    print '<input type="hidden" name="page" value="'.$page.'">';
-                    print '<input type="hidden" name="rowid" value="'.$rowid.'">';
-
                     $tmpaction='edit';
                     $tmpaction='edit';
                     $parameters=array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]);
                     $parameters=array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]);
                     $reshook=$hookmanager->executeHooks('editDictionaryFieldlist',$parameters,$obj, $tmpaction);    // Note that $action and $object may have been modified by some hooks
                     $reshook=$hookmanager->executeHooks('editDictionaryFieldlist',$parameters,$obj, $tmpaction);    // Note that $action and $object may have been modified by some hooks
@@ -548,16 +541,6 @@ if ($id)
 
 
                     $url = $_SERVER["PHP_SELF"].'?'.($page?'page='.$page.'&':'').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(! empty($obj->rowid)?$obj->rowid:(! empty($obj->code)?$obj->code:'')).'&amp;code='.(! empty($obj->code)?urlencode($obj->code):'').'&amp;id='.$id.'&amp;';
                     $url = $_SERVER["PHP_SELF"].'?'.($page?'page='.$page.'&':'').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(! empty($obj->rowid)?$obj->rowid:(! empty($obj->code)?$obj->code:'')).'&amp;code='.(! empty($obj->code)?urlencode($obj->code):'').'&amp;id='.$id.'&amp;';
 
 
-					// Favorite
-					// Only activated on country dictionary
-                    if ($id == 4)
-					{
-						print '<td align="center" class="nowrap">';
-						if ($iserasable) print '<a href="'.$url.'action='.$acts[$obj->favorite].'_favorite">'.$actl[$obj->favorite].'</a>';
-						else print $langs->trans("AlwaysActive");
-						print '</td>';
-					}
-
                     // Active
                     // Active
                     print '<td align="center" class="nowrap">';
                     print '<td align="center" class="nowrap">';
                     print '<a href="'.$url.'action='.$acts[$obj->status].'">'.$actl[$obj->status].'</a>';
                     print '<a href="'.$url.'action='.$acts[$obj->status].'">'.$actl[$obj->status].'</a>';
@@ -575,15 +558,15 @@ if ($id)
                 }
                 }
                 $i++;
                 $i++;
             }
             }
+            
+            print '</table>';
+            
+            print '</form>';
         }
         }
     }
     }
     else {
     else {
         dol_print_error($db);
         dol_print_error($db);
     }
     }
-
-    print '</table>';
-
-    print '</form>';
 }
 }
 
 
 print '<br>';
 print '<br>';

+ 1 - 2
htdocs/admin/workflow.php

@@ -120,8 +120,7 @@ foreach($workflowcodes as $key => $params)
 		$oldfamily = $family;
 		$oldfamily = $family;
    	}
    	}
 
 
-   	$var = !$var;
-   	print "<tr ".$bc[$var].">\n";
+   	print "<tr class=\"oddeven\">\n";
    	print "<td>".img_object('', $picto).$langs->trans('desc'.$key);
    	print "<td>".img_object('', $picto).$langs->trans('desc'.$key);
    	if (! empty($params['warning']))
    	if (! empty($params['warning']))
    	{
    	{

+ 2 - 0
htdocs/api/class/api.class.php

@@ -90,6 +90,8 @@ class DolibarrApi
         // Remove linkedObjects. We should already have linkedObjectIds that avoid huge responses
         // Remove linkedObjects. We should already have linkedObjectIds that avoid huge responses
         unset($object->linkedObjects);
         unset($object->linkedObjects);
         
         
+        unset($object->fields);
+        
         unset($object->oldline);
         unset($object->oldline);
         
         
         unset($object->error);
         unset($object->error);

+ 1 - 1
htdocs/api/class/api_login.class.php

@@ -102,7 +102,7 @@ class Login
 			'success' => array(
 			'success' => array(
 				'code' => 200,
 				'code' => 200,
 				'token' => $token,
 				'token' => $token,
-				'message' => 'Welcome ' . $login.($reset?' - Token is new':' - This is your token (generated by a previous call)')
+				'message' => 'Welcome ' . $login.($reset?' - Token is new':' - This is your token (generated by a previous call). You can use it to make any REST API call, or enter it into the DOLAPIKEY field to use the Dolibarr API explorer.')
 			)
 			)
 		);
 		);
 	}
 	}

+ 8 - 4
htdocs/comm/card.php

@@ -1090,11 +1090,15 @@ if ($id > 0)
     
     
     				if (! empty($conf->commande->enabled))
     				if (! empty($conf->commande->enabled))
     				{
     				{
-    					if (! empty($orders2invoice) && $orders2invoice > 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/orderstoinvoice.php?socid='.$object->id.'">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
-    					else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("NoOrdersToInvoice")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
+    				    if ($object->client != 0 && $object->client != 2)
+    				    {
+    					   if (! empty($orders2invoice) && $orders2invoice > 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/orderstoinvoice.php?socid='.$object->id.'">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
+    					   else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("NoOrdersToInvoice")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
+    				    }
+    				    else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     				}
     				}
-    
-    				if ($object->client != 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&socid='.$object->id.'">'.$langs->trans("AddBill").'</a></div>';
+
+    				if ($object->client != 0 && $object->client != 2) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&socid='.$object->id.'">'.$langs->trans("AddBill").'</a></div>';
     				else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     				else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     
     
     			}
     			}

+ 27 - 24
htdocs/comm/mailing/cibles.php

@@ -161,6 +161,7 @@ if ($_POST["button_removefilter"])
 	$search_lastname='';
 	$search_lastname='';
 	$search_firstname='';
 	$search_firstname='';
 	$search_email='';
 	$search_email='';
+	$search_dest_status='';
 }
 }
 
 
 
 
@@ -399,7 +400,7 @@ if ($object->fetch($id) >= 0)
 	if ($search_lastname)    $sql.= " AND mc.lastname    LIKE '%".$db->escape($search_lastname)."%'";
 	if ($search_lastname)    $sql.= " AND mc.lastname    LIKE '%".$db->escape($search_lastname)."%'";
 	if ($search_firstname) $sql.= " AND mc.firstname LIKE '%".$db->escape($search_firstname)."%'";
 	if ($search_firstname) $sql.= " AND mc.firstname LIKE '%".$db->escape($search_firstname)."%'";
 	if ($search_email)  $sql.= " AND mc.email  LIKE '%".$db->escape($search_email)."%'";
 	if ($search_email)  $sql.= " AND mc.email  LIKE '%".$db->escape($search_email)."%'";
-	if (!empty($search_dest_status)) $sql.= " AND mc.statut=".$db->escape($search_dest_status)." ";
+	if ($search_dest_status != '' && $search_dest_status >= -1) $sql.= " AND mc.statut=".$db->escape($search_dest_status)." ";
 	$sql .= $db->order($sortfield,$sortorder);
 	$sql .= $db->order($sortfield,$sortorder);
 
 
 	// Count total nb of records
 	// Count total nb of records
@@ -411,7 +412,7 @@ if ($object->fetch($id) >= 0)
 	}
 	}
 	//$nbtotalofrecords=$object->nbemail;     // nbemail is a denormalized field storing nb of targets
 	//$nbtotalofrecords=$object->nbemail;     // nbemail is a denormalized field storing nb of targets
 	$sql .= $db->plimit($limit+1, $offset);
 	$sql .= $db->plimit($limit+1, $offset);
-
+	
 	$resql=$db->query($sql);
 	$resql=$db->query($sql);
 	if ($resql)
 	if ($resql)
 	{
 	{
@@ -446,29 +447,12 @@ if ($object->fetch($id) >= 0)
 		print '<input type="hidden" name="limit" value="'.$limit.'">';
 		print '<input type="hidden" name="limit" value="'.$limit.'">';
 		
 		
 
 
-		if ($page)			$param.= "&amp;page=".$page;
+		if ($page)	$param.= "&amp;page=".$page;
+		
 		print '<table class="noborder" width="100%">';
 		print '<table class="noborder" width="100%">';
-		print '<tr class="liste_titre">';
-		print_liste_field_titre($langs->trans("EMail"),$_SERVER["PHP_SELF"],"mc.email",$param,"","",$sortfield,$sortorder);
-		print_liste_field_titre($langs->trans("Lastname"),$_SERVER["PHP_SELF"],"mc.lastname",$param,"","",$sortfield,$sortorder);
-		print_liste_field_titre($langs->trans("Firstname"),$_SERVER["PHP_SELF"],"mc.firstname",$param,"","",$sortfield,$sortorder);
-		print_liste_field_titre($langs->trans("OtherInformations"),$_SERVER["PHP_SELF"],"",$param,"","",$sortfield,$sortorder);
-		print_liste_field_titre($langs->trans("Source"),$_SERVER["PHP_SELF"],"",$param,"",'align="center"',$sortfield,$sortorder);
-		// Date sending
-		if ($object->statut < 2)
-		{
-			print_liste_field_titre('');
-		}
-		else
-		{
-			print_liste_field_titre($langs->trans("DateSending"),$_SERVER["PHP_SELF"],"mc.date_envoi",$param,'','align="center"',$sortfield,$sortorder);
-		}
-		print_liste_field_titre($langs->trans("Status"),$_SERVER["PHP_SELF"],"mc.statut",$param,'','align="right"',$sortfield,$sortorder);
-		print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'','','',$sortfield,$sortorder,'maxwidthsearch ');
-		print '</tr>';
-
+		
 		// Ligne des champs de filtres
 		// Ligne des champs de filtres
-		print '<tr class="liste_titre">';
+		print '<tr class="liste_titre_filter">';
 		// EMail
 		// EMail
 		print '<td class="liste_titre">';
 		print '<td class="liste_titre">';
 		print '<input class="flat maxwidth100" type="text" name="search_email" value="'.dol_escape_htmltag($search_email).'">';
 		print '<input class="flat maxwidth100" type="text" name="search_email" value="'.dol_escape_htmltag($search_email).'">';
@@ -489,7 +473,7 @@ if ($object->fetch($id) >= 0)
 		print '<td class="liste_titre">';
 		print '<td class="liste_titre">';
 		print '&nbsp';
 		print '&nbsp';
 		print '</td>';
 		print '</td>';
-
+		
 		// Date sending
 		// Date sending
 		print '<td class="liste_titre">';
 		print '<td class="liste_titre">';
 		print '&nbsp';
 		print '&nbsp';
@@ -504,6 +488,25 @@ if ($object->fetch($id) >= 0)
 		print $searchpitco;
 		print $searchpitco;
 		print '</td>';
 		print '</td>';
 		print '</tr>';
 		print '</tr>';
+		
+		print '<tr class="liste_titre">';
+		print_liste_field_titre($langs->trans("EMail"),$_SERVER["PHP_SELF"],"mc.email",$param,"","",$sortfield,$sortorder);
+		print_liste_field_titre($langs->trans("Lastname"),$_SERVER["PHP_SELF"],"mc.lastname",$param,"","",$sortfield,$sortorder);
+		print_liste_field_titre($langs->trans("Firstname"),$_SERVER["PHP_SELF"],"mc.firstname",$param,"","",$sortfield,$sortorder);
+		print_liste_field_titre($langs->trans("OtherInformations"),$_SERVER["PHP_SELF"],"",$param,"","",$sortfield,$sortorder);
+		print_liste_field_titre($langs->trans("Source"),$_SERVER["PHP_SELF"],"",$param,"",'align="center"',$sortfield,$sortorder);
+		// Date sending
+		if ($object->statut < 2)
+		{
+			print_liste_field_titre('');
+		}
+		else
+		{
+			print_liste_field_titre($langs->trans("DateSending"),$_SERVER["PHP_SELF"],"mc.date_envoi",$param,'','align="center"',$sortfield,$sortorder);
+		}
+		print_liste_field_titre($langs->trans("Status"),$_SERVER["PHP_SELF"],"mc.statut",$param,'','align="right"',$sortfield,$sortorder);
+		print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'','','',$sortfield,$sortorder,'maxwidthsearch ');
+		print '</tr>';
 
 
 		$i = 0;
 		$i = 0;
 
 

+ 1 - 1
htdocs/comm/mailing/class/mailing.class.php

@@ -80,8 +80,8 @@ class Mailing extends CommonObject
 		$this->statuts[2] = 'MailingStatusSentPartialy';
 		$this->statuts[2] = 'MailingStatusSentPartialy';
 		$this->statuts[3] = 'MailingStatusSentCompletely';
 		$this->statuts[3] = 'MailingStatusSentCompletely';
 
 
-		$this->statut_dest[0] = 'MailingStatusNotSent';
 		$this->statut_dest[-1] = 'MailingStatusError';
 		$this->statut_dest[-1] = 'MailingStatusError';
+		$this->statut_dest[0] = 'MailingStatusNotSent';
 		$this->statut_dest[1] = 'MailingStatusSent';
 		$this->statut_dest[1] = 'MailingStatusSent';
 		$this->statut_dest[2] = 'MailingStatusRead';
 		$this->statut_dest[2] = 'MailingStatusRead';
 		$this->statut_dest[3] = 'MailingStatusReadAndUnsubscribe';    // Read but ask to not be contacted anymore
 		$this->statut_dest[3] = 'MailingStatusReadAndUnsubscribe';    // Read but ask to not be contacted anymore

+ 5 - 4
htdocs/comm/propal/class/api_proposals.class.php

@@ -260,12 +260,9 @@ class Proposals extends DolibarrApi
                         $request_data->localtax2_tx,
                         $request_data->localtax2_tx,
                         $request_data->fk_product,
                         $request_data->fk_product,
                         $request_data->remise_percent,
                         $request_data->remise_percent,
-                        $request_data->info_bits,
-                        $request_data->fk_remise_except,
                         'HT',
                         'HT',
                         0,
                         0,
-                        $request_data->date_start,
-                        $request_data->date_end,
+                        $request_data->info_bits,
                         $request_data->product_type,
                         $request_data->product_type,
                         $request_data->rang,
                         $request_data->rang,
                         $request_data->special_code,
                         $request_data->special_code,
@@ -273,10 +270,14 @@ class Proposals extends DolibarrApi
                         $request_data->fk_fournprice,
                         $request_data->fk_fournprice,
                         $request_data->pa_ht,
                         $request_data->pa_ht,
                         $request_data->label,
                         $request_data->label,
+                        $request_data->date_start,
+                        $request_data->date_end,
                         $request_data->array_options,
                         $request_data->array_options,
                         $request_data->fk_unit,
                         $request_data->fk_unit,
                         $this->element,
                         $this->element,
                         $request_data->id
                         $request_data->id
+                        // not used anymore ?
+                        // $request_data->fk_remise_except
       );
       );
 
 
       if ($updateRes > 0) {
       if ($updateRes > 0) {

+ 2 - 2
htdocs/comm/propal/contact.php

@@ -130,12 +130,12 @@ else if ($action == 'deletecontact' && $user->rights->propale->creer)
 		dol_print_error($db);
 		dol_print_error($db);
 	}
 	}
 }
 }
-
+/*
 else if ($action == 'setaddress' && $user->rights->propale->creer)
 else if ($action == 'setaddress' && $user->rights->propale->creer)
 {
 {
 	$result=$object->setDeliveryAddress($_POST['fk_address']);
 	$result=$object->setDeliveryAddress($_POST['fk_address']);
 	if ($result < 0) dol_print_error($db,$object->error);
 	if ($result < 0) dol_print_error($db,$object->error);
-}
+}*/
 
 
 
 
 /*
 /*

+ 1 - 0
htdocs/commande/class/commande.class.php

@@ -464,6 +464,7 @@ class Commande extends CommonOrder
                     if ($this->lines[$i]->fk_product > 0)
                     if ($this->lines[$i]->fk_product > 0)
                     {
                     {
                         $mouvP = new MouvementStock($this->db);
                         $mouvP = new MouvementStock($this->db);
+                        $mouvP->origin = &$this;
                         // We increment stock of product (and sub-products)
                         // We increment stock of product (and sub-products)
                         $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans("OrderBackToDraftInDolibarr",$this->ref));
                         $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans("OrderBackToDraftInDolibarr",$this->ref));
                         if ($result < 0) { $error++; $this->error=$mouvP->error; break; }
                         if ($result < 0) { $error++; $this->error=$mouvP->error; break; }

+ 3 - 2
htdocs/commande/contact.php

@@ -107,13 +107,14 @@ else if ($action == 'deletecontact' && $user->rights->commande->creer)
 		dol_print_error($db);
 		dol_print_error($db);
 	}
 	}
 }
 }
-
+/*
 else if ($action == 'setaddress' && $user->rights->commande->creer)
 else if ($action == 'setaddress' && $user->rights->commande->creer)
 {
 {
 	$object->fetch($id);
 	$object->fetch($id);
 	$result=$object->setDeliveryAddress($_POST['fk_address']);
 	$result=$object->setDeliveryAddress($_POST['fk_address']);
 	if ($result < 0) dol_print_error($db,$object->error);
 	if ($result < 0) dol_print_error($db,$object->error);
-}
+}*/
+
 
 
 /*
 /*
  * View
  * View

+ 1 - 1
htdocs/compta/bank/card.php

@@ -117,7 +117,7 @@ if ($action == 'add')
     
     
     if ($conf->global->MAIN_BANK_ACCOUNTANCY_CODE_ALWAYS_REQUIRED && empty($object->account_number))
     if ($conf->global->MAIN_BANK_ACCOUNTANCY_CODE_ALWAYS_REQUIRED && empty($object->account_number))
     {
     {
-        setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), null, 'error');
+        setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), null, 'errors');
         $action='create';       // Force chargement page en mode creation
         $action='create';       // Force chargement page en mode creation
         $error++;
         $error++;
     }
     }

+ 1 - 1
htdocs/compta/facture/admin/facture_cust_extrafields.php

@@ -70,7 +70,7 @@ print load_fiche_titre($langs->trans("BillsSetup"),$linkback,'title_setup');
 
 
 $head = invoice_admin_prepare_head();
 $head = invoice_admin_prepare_head();
 
 
-dol_fiche_head($head, 'attributes', $langs->trans("Invoices"), 0, 'invoice');
+dol_fiche_head($head, 'attributes', $langs->trans("Invoices"), -1, 'invoice');
 
 
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 
 

+ 1 - 1
htdocs/compta/facture/admin/facturedet_cust_extrafields.php

@@ -71,7 +71,7 @@ print load_fiche_titre($langs->trans("BillsSetup"),$linkback,'title_setup');
 
 
 $head = invoice_admin_prepare_head();
 $head = invoice_admin_prepare_head();
 
 
-dol_fiche_head($head, 'attributeslines', $langs->trans("Invoices"), 0, 'invoice');
+dol_fiche_head($head, 'attributeslines', $langs->trans("Invoices"), -1, 'invoice');
 
 
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 
 

+ 11 - 22
htdocs/compta/facture/card.php

@@ -611,7 +611,9 @@ if (empty($reshook))
 		{
 		{
 			$db->begin();
 			$db->begin();
 
 
-			// Boucle sur chaque taux de tva
+			$amount_ht = $amount_tva = $amount_ttc = array();
+			
+			// Loop on each vat rate
 			$i = 0;
 			$i = 0;
 			foreach ($object->lines as $line)
 			foreach ($object->lines as $line)
 			{
 			{
@@ -630,20 +632,19 @@ if (empty($reshook))
 				$discount->description = '(CREDIT_NOTE)';
 				$discount->description = '(CREDIT_NOTE)';
 			elseif ($object->type == Facture::TYPE_DEPOSIT)
 			elseif ($object->type == Facture::TYPE_DEPOSIT)
 				$discount->description = '(DEPOSIT)';
 				$discount->description = '(DEPOSIT)';
-			elseif ($object->type == Facture::TYPE_STANDARD)
+			elseif ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_SITUATION)
 				$discount->description = '(EXCESS RECEIVED)';
 				$discount->description = '(EXCESS RECEIVED)';
 			else {
 			else {
 				setEventMessages($langs->trans('CantConvertToReducAnInvoiceOfThisType'), null, 'errors');
 				setEventMessages($langs->trans('CantConvertToReducAnInvoiceOfThisType'), null, 'errors');
 			}
 			}
-			$discount->tva_tx = abs($object->total_ttc);
 			$discount->fk_soc = $object->socid;
 			$discount->fk_soc = $object->socid;
 			$discount->fk_facture_source = $object->id;
 			$discount->fk_facture_source = $object->id;
 
 
 			$error = 0;
 			$error = 0;
 			
 			
-			if ($object->type == Facture::TYPE_STANDARD) {
-				
-				// If we're on a standard invoice, we have to get excess received to create it in TTC wuthout VAT
+			if ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_SITUATION) 
+			{
+				// If we're on a standard invoice, we have to get excess received to create a discount in TTC without VAT
 				
 				
 				$sql = 'SELECT SUM(pf.amount) as total_paiements
 				$sql = 'SELECT SUM(pf.amount) as total_paiements
 						FROM llx_c_paiement as c, llx_paiement_facture as pf, llx_paiement as p
 						FROM llx_c_paiement as c, llx_paiement_facture as pf, llx_paiement as p
@@ -663,8 +664,9 @@ if (empty($reshook))
 					$error++;
 					$error++;
 				}
 				}
 				
 				
-			} else {
-			
+			}
+			if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT)
+			{
 				foreach ($amount_ht as $tva_tx => $xxx)
 				foreach ($amount_ht as $tva_tx => $xxx)
 				{
 				{
 					$discount->amount_ht = abs($amount_ht[$tva_tx]);
 					$discount->amount_ht = abs($amount_ht[$tva_tx]);
@@ -871,19 +873,6 @@ if (empty($reshook))
 	                    $object->addline($langs->trans('invoiceAvoirLineWithPaymentRestAmount'),$remain_to_pay,1,0,0,0,0,0,'','','TTC');
 	                    $object->addline($langs->trans('invoiceAvoirLineWithPaymentRestAmount'),$remain_to_pay,1,0,0,0,0,0,'','','TTC');
 	                }
 	                }
 	            }
 	            }
-
-				// Add predefined lines
-				/*
-	             TODO delete
-	             for($i = 1; $i <= $NBLINES; $i ++) {
-					if ($_POST['idprod' . $i]) {
-						$product = new Product($db);
-						$product->fetch($_POST['idprod' . $i]);
-						$startday = dol_mktime(12, 0, 0, $_POST['date_start' . $i . 'month'], $_POST['date_start' . $i . 'day'], $_POST['date_start' . $i . 'year']);
-						$endday = dol_mktime(12, 0, 0, $_POST['date_end' . $i . 'month'], $_POST['date_end' . $i . 'day'], $_POST['date_end' . $i . 'year']);
-						$result = $object->addline($product->description, $product->price, $_POST['qty' . $i], $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, $_POST['idprod' . $i], $_POST['remise_percent' . $i], $startday, $endday, 0, 0, '', $product->price_base_type, $product->price_ttc, $product->type);
-					}
-				}*/
 			}
 			}
 		}
 		}
 
 
@@ -2191,7 +2180,7 @@ if ($action == 'create')
 	else
 	else
 	{
 	{
 		print '<td colspan="2">';
 		print '<td colspan="2">';
-		print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty');
+		print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
 		// Option to reload page to retrieve customer informations. Note, this clear other input
 		// Option to reload page to retrieve customer informations. Note, this clear other input
 		if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE))
 		if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE))
 		{
 		{

+ 2 - 1
htdocs/compta/facture/fiche-rec.php

@@ -35,8 +35,9 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
 if (! empty($conf->projet->enabled)) {
 if (! empty($conf->projet->enabled)) {
     require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
     require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
-    require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
+    //require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
 }
 }
+require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
 
 

+ 19 - 19
htdocs/compta/paiement.php

@@ -1,6 +1,6 @@
 <?php
 <?php
 /* Copyright (C) 2001-2006 Rodolphe Quiedeville  <rodolphe@quiedeville.org>
 /* Copyright (C) 2001-2006 Rodolphe Quiedeville  <rodolphe@quiedeville.org>
- * Copyright (C) 2004-2016 Laurent Destailleur   <eldy@users.sourceforge.net>
+ * Copyright (C) 2004-2017 Laurent Destailleur   <eldy@users.sourceforge.net>
  * Copyright (C) 2005      Marc Barilley / Ocebo <marc@ocebo.com>
  * Copyright (C) 2005      Marc Barilley / Ocebo <marc@ocebo.com>
  * Copyright (C) 2005-2012 Regis Houssin         <regis.houssin@capnetworks.com>
  * Copyright (C) 2005-2012 Regis Houssin         <regis.houssin@capnetworks.com>
  * Copyright (C) 2007      Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
  * Copyright (C) 2007      Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
@@ -221,7 +221,7 @@ if (empty($reshook))
 	    $db->begin();
 	    $db->begin();
 
 
 	    // Clean parameters amount if payment is for a credit note
 	    // Clean parameters amount if payment is for a credit note
-	    if (GETPOST('type') == 2)
+	    if (GETPOST('type') == Facture::TYPE_CREDIT_NOTE)
 	    {
 	    {
 		    foreach ($amounts as $key => $value)	// How payment is dispatch
 		    foreach ($amounts as $key => $value)	// How payment is dispatch
 		    {
 		    {
@@ -249,7 +249,7 @@ if (empty($reshook))
 	    // Creation of payment line
 	    // Creation of payment line
 	    $paiement = new Paiement($db);
 	    $paiement = new Paiement($db);
 	    $paiement->datepaye     = $datepaye;
 	    $paiement->datepaye     = $datepaye;
-	    $paiement->amounts      = $amounts;   // Array with all payments dispatching
+	    $paiement->amounts      = $amounts;   // Array with all payments dispatching with invoice id
 	    $paiement->multicurrency_amounts = $multicurrency_amounts;   // Array with all payments dispatching
 	    $paiement->multicurrency_amounts = $multicurrency_amounts;   // Array with all payments dispatching
 	    $paiement->paiementid   = dol_getIdFromCode($db,GETPOST('paiementcode'),'c_paiement');
 	    $paiement->paiementid   = dol_getIdFromCode($db,GETPOST('paiementcode'),'c_paiement');
 	    $paiement->num_paiement = GETPOST('num_paiement');
 	    $paiement->num_paiement = GETPOST('num_paiement');
@@ -257,7 +257,7 @@ if (empty($reshook))
 
 
 	    if (! $error)
 	    if (! $error)
 	    {
 	    {
-	    	$paiement_id = $paiement->create($user, (GETPOST('closepaidinvoices')=='on'?1:0));
+	    	$paiement_id = $paiement->create($user, (GETPOST('closepaidinvoices')=='on'?1:0));    // This include closing invoices
 	    	if ($paiement_id < 0)
 	    	if ($paiement_id < 0)
 	        {
 	        {
 	            setEventMessages($paiement->error, $paiement->errors, 'errors');
 	            setEventMessages($paiement->error, $paiement->errors, 'errors');
@@ -268,7 +268,7 @@ if (empty($reshook))
 	    if (! $error)
 	    if (! $error)
 	    {
 	    {
 	    	$label='(CustomerInvoicePayment)';
 	    	$label='(CustomerInvoicePayment)';
-	    	if (GETPOST('type') == 2) $label='(CustomerInvoicePaymentBack)';
+	    	if (GETPOST('type') == Facture::TYPE_CREDIT_NOTE) $label='(CustomerInvoicePaymentBack)';  // Refund of a credit note
 	        $result=$paiement->addPaymentToBank($user,'payment',$label,GETPOST('accountid'),GETPOST('chqemetteur'),GETPOST('chqbank'));
 	        $result=$paiement->addPaymentToBank($user,'payment',$label,GETPOST('accountid'),GETPOST('chqemetteur'),GETPOST('chqbank'));
 	        if ($result < 0)
 	        if ($result < 0)
 	        {
 	        {
@@ -281,7 +281,7 @@ if (empty($reshook))
 	    {
 	    {
 	        $db->commit();
 	        $db->commit();
 
 
-	        // If payment dispatching on more than one invoice, we keep on summary page, otherwise go on invoice card
+	        // If payment dispatching on more than one invoice, we keep on summary page, otherwise jump on invoice card
 	        $invoiceid=0;
 	        $invoiceid=0;
 	        foreach ($paiement->amounts as $key => $amount)
 	        foreach ($paiement->amounts as $key => $amount)
 	        {
 	        {
@@ -309,7 +309,7 @@ if (empty($reshook))
  * View
  * View
  */
  */
 
 
-llxHeader();
+llxHeader('', $langs->trans("Payment"));
 
 
 $form=new Form($db);
 $form=new Form($db);
 
 
@@ -324,8 +324,8 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
 		$facture->fetch_thirdparty();
 		$facture->fetch_thirdparty();
 
 
 		$title='';
 		$title='';
-		if ($facture->type != 2) $title.=$langs->trans("EnterPaymentReceivedFromCustomer");
-		if ($facture->type == 2) $title.=$langs->trans("EnterPaymentDueToCustomer");
+		if ($facture->type != Facture::TYPE_CREDIT_NOTE) $title.=$langs->trans("EnterPaymentReceivedFromCustomer");
+		if ($facture->type == Facture::TYPE_CREDIT_NOTE) $title.=$langs->trans("EnterPaymentDueToCustomer");
 		print load_fiche_titre($title);
 		print load_fiche_titre($title);
 
 
 		// Initialize data for confirmation (this is used because data can be change during confirmation)
 		// Initialize data for confirmation (this is used because data can be change during confirmation)
@@ -347,7 +347,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
 		}
 		}
 
 
 		// Add realtime total information
 		// Add realtime total information
-		if ($conf->use_javascript_ajax)
+		if (! empty($conf->use_javascript_ajax))
 		{
 		{
 			print "\n".'<script type="text/javascript" language="javascript">';
 			print "\n".'<script type="text/javascript" language="javascript">';
 			print '$(document).ready(function () {
 			print '$(document).ready(function () {
@@ -369,7 +369,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
 			                    }
 			                    }
             					if ($(\'#fieldchqemetteur\').val() == \'\')
             					if ($(\'#fieldchqemetteur\').val() == \'\')
             					{
             					{
-            						var emetteur = ('.$facture->type.' == 2) ? \''.dol_escape_js(dol_escape_htmltag($conf->global->MAIN_INFO_SOCIETE_NOM)).'\' : jQuery(\'#thirdpartylabel\').val();
+            						var emetteur = ('.$facture->type.' == '.Facture::TYPE_CREDIT_NOTE.') ? \''.dol_escape_js(dol_escape_htmltag($conf->global->MAIN_INFO_SOCIETE_NOM)).'\' : jQuery(\'#thirdpartylabel\').val();
             						$(\'#fieldchqemetteur\').val(emetteur);
             						$(\'#fieldchqemetteur\').val(emetteur);
             					}
             					}
             				}
             				}
@@ -437,14 +437,14 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
 			';
 			';
 
 
 			print '	});'."\n";
 			print '	});'."\n";
-			if (!empty($conf->use_javascript_ajax)){
-				//Add js for AutoFill
-				print ' $(document).ready(function () {';
-				print ' 	$(".AutoFillAmout").on(\'click touchstart\', function(){
-								$("input[name="+$(this).data(\'rowname\')+"]").val($(this).data("value")).trigger("change");
-							});';
-				print '	});'."\n";
-			}
+
+			//Add js for AutoFill
+			print ' $(document).ready(function () {';
+			print ' 	$(".AutoFillAmout").on(\'click touchstart\', function(){
+							$("input[name="+$(this).data(\'rowname\')+"]").val($(this).data("value")).trigger("change");
+						});';
+			print '	});'."\n";
+
 			print '	</script>'."\n";
 			print '	</script>'."\n";
 		}
 		}
 
 

+ 55 - 5
htdocs/compta/paiement/class/paiement.class.php

@@ -255,7 +255,7 @@ class Paiement extends CommonObject
                                 {
                                 {
                                     if (! empty($conf->prelevement->enabled))
                                     if (! empty($conf->prelevement->enabled))
                                     {
                                     {
-                                        // TODO Check if this payment has a withdraw request
+                                        // FIXME Check if this invoice has a withdraw request
                                         // if not, $mustwait++;      // This will disable automatic close on invoice to allow to process
                                         // if not, $mustwait++;      // This will disable automatic close on invoice to allow to process
                                     }
                                     }
                                 }
                                 }
@@ -275,11 +275,61 @@ class Paiement extends CommonObject
                             else if ($mustwait) dol_syslog("There is ".$mustwait." differed payment to process, we do nothing more.");
                             else if ($mustwait) dol_syslog("There is ".$mustwait." differed payment to process, we do nothing more.");
                             else
                             else
                             {
                             {
-                                $result=$invoice->set_paid($user,'','');
-                                if ($result<0)
+                                // If invoice is a down payment, we also convert down payment to discount
+                                if ($invoice->type == Facture::TYPE_DEPOSIT)
                                 {
                                 {
-                                    $this->error=$invoice->error;
-                                    $error++;
+			                        $amount_ht = $amount_tva = $amount_ttc = array();
+			                         
+                                    // Loop on each vat rate
+                                    $i = 0;
+                                    foreach ($invoice->lines as $line)
+                                    {
+                                        if ($line->total_ht!=0)
+                                        { 	// no need to create discount if amount is null
+                                            $amount_ht[$line->tva_tx] += $line->total_ht;
+                                            $amount_tva[$line->tva_tx] += $line->total_tva;
+                                            $amount_ttc[$line->tva_tx] += $line->total_ttc;
+                                            $i ++;
+                                        }
+                                    }
+                                    
+                                    // Insert one discount by VAT rate category
+                                    $discount = new DiscountAbsolute($this->db);
+                                    $discount->description = '(DEPOSIT)';
+                                    $discount->fk_soc = $invoice->socid;
+                                    $discount->fk_facture_source = $invoice->id;
+                                
+                                    foreach ($amount_ht as $tva_tx => $xxx)
+                                    {
+                                        $discount->amount_ht = abs($amount_ht[$tva_tx]);
+                                        $discount->amount_tva = abs($amount_tva[$tva_tx]);
+                                        $discount->amount_ttc = abs($amount_ttc[$tva_tx]);
+                                        $discount->tva_tx = abs($tva_tx);
+                            
+                                        $result = $discount->create($user);
+                                        if ($result < 0)
+                                        {
+                                            $error++;
+                                            break;
+                                        }
+                                    }
+                                    
+                                    if ($error)
+                                    {
+                                        setEventMessages($discount->error, $discount->errors, 'errors');
+                                        $error++;
+                                    }                                   
+                                }
+                                
+                                // Set invoice to paid
+                                if (! $error)
+                                {
+                                    $result=$invoice->set_paid($user,'','');
+                                    if ($result<0)
+                                    {
+                                        $this->error=$invoice->error;
+                                        $error++;
+                                    }
                                 }
                                 }
                             }
                             }
 					    }
 					    }

+ 6 - 1
htdocs/core/ajax/check_notifications.php

@@ -21,7 +21,6 @@ if (! defined('NOREQUIREMENU'))  define('NOREQUIREMENU','1');
 if (! defined('NOREQUIREHTML'))  define('NOREQUIREHTML','1');
 if (! defined('NOREQUIREHTML'))  define('NOREQUIREHTML','1');
 if (! defined('NOREQUIREAJAX'))  define('NOREQUIREAJAX','1');
 if (! defined('NOREQUIREAJAX'))  define('NOREQUIREAJAX','1');
 if (! defined('NOREQUIRESOC'))   define('NOREQUIRESOC','1');
 if (! defined('NOREQUIRESOC'))   define('NOREQUIRESOC','1');
-if (! defined('NOREQUIRETRAN'))  define('NOREQUIRETRAN','1');
 
 
 require '../../main.inc.php';
 require '../../main.inc.php';
 
 
@@ -88,9 +87,11 @@ if ($time >= $_SESSION['auto_check_events_not_before'])
         while ($obj = $db->fetch_object($resql)) 
         while ($obj = $db->fetch_object($resql)) 
         {
         {
             $langs->load("agenda");
             $langs->load("agenda");
+            $langs->load("commercial");
             
             
             $actionmod->fetch($obj->id);
             $actionmod->fetch($obj->id);
 
 
+            // Message must be formated and translated to be used with javascript directly
             $event = array();
             $event = array();
             $event['type'] = 'agenda';
             $event['type'] = 'agenda';
             $event['id'] = $actionmod->id;
             $event['id'] = $actionmod->id;
@@ -101,6 +102,10 @@ if ($time >= $_SESSION['auto_check_events_not_before'])
             $eventfound[] = $event;
             $eventfound[] = $event;
         }
         }
     }
     }
+    else
+    {
+        dol_syslog("Error sql = ".$db->lasterror(), LOG_ERR);
+    }
 
 
 }
 }
 
 

+ 5 - 2
htdocs/core/boxes/box_external_rss.php

@@ -80,8 +80,11 @@ class box_external_rss extends ModeleBoxes
 		// documents/externalrss is created by module activation
 		// documents/externalrss is created by module activation
 		// documents/externalrss/tmp is created by rssparser
 		// documents/externalrss/tmp is created by rssparser
 
 
+		$keyforparamurl="EXTERNAL_RSS_URLRSS_".$site;
+		$keyforparamtitle="EXTERNAL_RSS_TITLE_".$site;
+		
 		// Get RSS feed
 		// Get RSS feed
-        $url=@constant("EXTERNAL_RSS_URLRSS_".$site);
+		$url=$conf->global->$keyforparamurl;
 
 
         $rssparser=new RssParser($this->db);
         $rssparser=new RssParser($this->db);
 		$result = $rssparser->parser($url, $this->max, $cachedelay, $conf->externalrss->dir_temp);
 		$result = $rssparser->parser($url, $this->max, $cachedelay, $conf->externalrss->dir_temp);
@@ -90,7 +93,7 @@ class box_external_rss extends ModeleBoxes
 		$description=$rssparser->getDescription();
 		$description=$rssparser->getDescription();
 		$link=$rssparser->getLink();
 		$link=$rssparser->getLink();
 
 
-        $title=$langs->trans("BoxTitleLastRssInfos",$max, @constant("EXTERNAL_RSS_TITLE_". $site));
+        $title=$langs->trans("BoxTitleLastRssInfos", $max, $conf->global->$keyforparamtitle);
         if ($result < 0 || ! empty($rssparser->error))
         if ($result < 0 || ! empty($rssparser->error))
         {
         {
             // Show warning
             // Show warning

+ 2 - 1
htdocs/core/class/commoninvoice.class.php

@@ -51,7 +51,8 @@ abstract class CommonInvoice extends CommonObject
     const TYPE_DEPOSIT = 3;
     const TYPE_DEPOSIT = 3;
 
 
     /**
     /**
-     * Proforma invoice
+     * Proforma invoice. 
+     * @deprectad Remove this. A "proforma invoice" is an order with a look of invoice, not an invoice !
      */
      */
     const TYPE_PROFORMA = 4;
     const TYPE_PROFORMA = 4;
 
 

+ 367 - 56
htdocs/core/class/commonobject.class.php

@@ -11,6 +11,7 @@
  * Copyright (C) 2012      Cedric Salvador      <csalvador@gpcsolutions.fr>
  * Copyright (C) 2012      Cedric Salvador      <csalvador@gpcsolutions.fr>
  * Copyright (C) 2015      Alexandre Spangaro   <aspangaro.dolibarr@gmail.com>
  * Copyright (C) 2015      Alexandre Spangaro   <aspangaro.dolibarr@gmail.com>
  * Copyright (C) 2016      Bahfir abbes         <dolipar@dolipar.org>
  * Copyright (C) 2016      Bahfir abbes         <dolipar@dolipar.org>
+ * Copyright (C) 2017      ATM Consulting       <support@atm-consulting.fr>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -238,6 +239,7 @@ abstract class CommonObject
 
 
 	/**
 	/**
 	 * @var int Delivery address ID
 	 * @var int Delivery address ID
+	 * @deprecated
 	 * @see setDeliveryAddress()
 	 * @see setDeliveryAddress()
 	 */
 	 */
 	public $fk_delivery_address;
 	public $fk_delivery_address;
@@ -1623,7 +1625,8 @@ abstract class CommonObject
 
 
     /**
     /**
      *	Define delivery address
      *	Define delivery address
-     *
+     *  @deprecated
+     *  
      *	@param      int		$id		Address id
      *	@param      int		$id		Address id
      *	@return     int				<0 si ko, >0 si ok
      *	@return     int				<0 si ko, >0 si ok
      */
      */
@@ -3223,51 +3226,14 @@ abstract class CommonObject
 
 
     /**
     /**
      *  Return if a country is inside the EEC (European Economic Community)
      *  Return if a country is inside the EEC (European Economic Community)
-     *  TODO Add a field into dictionary
+     *  @deprecated
      *
      *
      *  @return     boolean		true = country inside EEC, false = country outside EEC
      *  @return     boolean		true = country inside EEC, false = country outside EEC
      */
      */
     function isInEEC()
     function isInEEC()
     {
     {
-        // List of all country codes that are in europe for european vat rules
-        // List found on http://ec.europa.eu/taxation_customs/common/faq/faq_1179_en.htm#9
-        $country_code_in_EEC=array(
-    			'AT',	// Austria
-    			'BE',	// Belgium
-    			'BG',	// Bulgaria
-    			'CY',	// Cyprus
-    			'CZ',	// Czech republic
-    			'DE',	// Germany
-    			'DK',	// Danemark
-    			'EE',	// Estonia
-    			'ES',	// Spain
-    			'FI',	// Finland
-    			'FR',	// France
-    			'GB',	// United Kingdom
-    			'GR',	// Greece
-    			'HR',   // Croatia
-                'NL',	// Holland
-    			'HU',	// Hungary
-    			'IE',	// Ireland
-    			'IM',	// Isle of Man - Included in UK
-    			'IT',	// Italy
-    			'LT',	// Lithuania
-    			'LU',	// Luxembourg
-    			'LV',	// Latvia
-    			'MC',	// Monaco - Included in France
-    			'MT',	// Malta
-                //'NO',	// Norway
-    			'PL',	// Poland
-    			'PT',	// Portugal
-    			'RO',	// Romania
-    			'SE',	// Sweden
-    			'SK',	// Slovakia
-    			'SI',	// Slovenia
-    			'UK',	// United Kingdom
-        //'CH',	// Switzerland - No. Swizerland in not in EEC
-        );
-        //print "dd".$this->country_code;
-        return in_array($this->country_code,$country_code_in_EEC);
+        require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
+        return isInEEC($this);
     }
     }
 
 
 
 
@@ -3754,21 +3720,6 @@ abstract class CommonObject
     }
     }
 
 
 
 
-	/**
-	 * Show the array with all margin infos
-	 *
-	 * @param 		bool	$force_price	Force price
-	 * @return		void
-	 * @deprecated	3.8 Load FormMargin class and make a direct call to displayMarginInfos
-	 */
-	function displayMarginInfos($force_price=false)
-	{
-		include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmargin.class.php';
-		$formmargin=new FormMargin($this->db);
-		$formmargin->displayMarginInfos($this, $force_price);
-	}
-
-
 	/**
 	/**
 	 *	Add resources to the current object : add entry into llx_element_resources
 	 *	Add resources to the current object : add entry into llx_element_resources
 	 *	Need $this->element & $this->id
 	 *	Need $this->element & $this->id
@@ -4711,4 +4662,364 @@ abstract class CommonObject
 		}
 		}
 		return $buyPrice;
 		return $buyPrice;
 	}
 	}
+	
+	/**
+	 * Function test if type is date
+	 *
+	 * @param   array   $info   content informations of field
+	 * @return                  bool
+	 */
+	protected function isDate($info)
+	{
+		if(isset($info['type']) && $info['type']=='date') return true;
+		else return false;
+	}
+	
+	/**
+	 * Function test if type is array
+	 *
+	 * @param   array   $info   content informations of field
+	 * @return                  bool
+	 */
+	protected function isArray($info)
+	{
+		if(is_array($info))
+		{
+			if(isset($info['type']) && $info['type']=='array') return true;
+			else return false;
+		}
+		else return false;
+	}
+	
+	/**
+	 * Function test if type is null
+	 *
+	 * @param   array   $info   content informations of field
+	 * @return                  bool
+	 */
+	protected function isNull($info)
+	{
+		if(is_array($info))
+		{
+			if(isset($info['type']) && $info['type']=='null') return true;
+			else return false;
+		}
+		else return false;
+	}
+	
+	/**
+	 * Function test if type is integer
+	 *
+	 * @param   array   $info   content informations of field
+	 * @return                  bool
+	 */
+	protected function isInt($info)
+	{
+		if(is_array($info))
+		{
+			if(isset($info['type']) && ($info['type']=='int' || $info['type']=='integer' )) return true;
+			else return false;
+		}
+		else return false;
+	}
+	
+	/**
+	 * Function test if type is float
+	 *
+	 * @param   array   $info   content informations of field
+	 * @return                  bool
+	 */
+	protected function isFloat($info)
+	{
+		if(is_array($info))
+		{
+			if(isset($info['type']) && $info['type']=='float') return true;
+			else return false;
+		}
+		else return false;
+	}
+	
+	/**
+	 * Function test if type is text
+	 *
+	 * @param   array   $info   content informations of field
+	 * @return                  bool
+	 */
+	protected function isText($info)
+	{
+		if(is_array($info))
+		{
+			if(isset($info['type']) && $info['type']=='text') return true;
+			else return false;
+		}
+		else return false;
+	}
+	
+	/**
+	 * Function test if is indexed
+	 *
+	 * @param   array   $info   content informations of field
+	 * @return                  bool
+	 */
+	protected function isIndex($info)
+	{
+		if(is_array($info))
+		{
+			if(isset($info['index']) && $info['index']==true) return true;
+			else return false;
+		}
+		else return false;
+	}
+	
+	/**
+	 * Function to prepare the values to insert
+	 *
+	 * @return array
+	 */
+	private function set_save_query()
+	{
+		$query=array();
+		foreach ($this->fields as $field=>$info)
+		{
+			if($this->isDate($info))
+			{
+				if(empty($this->{$field}))
+				{
+					$query[$field] = NULL;
+				}
+				else
+				{
+					$query[$field] = $this->db->idate($this->{$field});
+				}
+			}
+			else if($this->isArray($info))
+			{
+				$query[$field] = serialize($this->{$field});
+			}
+			else if($this->isInt($info))
+			{
+				$query[$field] = (int) price2num($this->{$field});
+			}
+			else if($this->isFloat($info))
+			{
+				$query[$field] = (double) price2num($this->{$field});
+			}
+			elseif($this->isNull($info))
+			{
+				$query[$field] = (is_null($this->{$field}) || (empty($this->{$field}) && $this->{$field}!==0 && $this->{$field}!=='0') ? null : $this->{$field});
+			}
+			else
+			{
+				$query[$field] = $this->{$field};
+			}
+		}
+		
+		return $query;
+	}
+
+	/**
+	 * Create object into database
+	 *
+	 * @param  User $user      User that creates
+	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
+	 *
+	 * @return int <0 if KO, Id of created object if OK
+	 */
+	public function createCommon(User $user, $notrigger = false)
+	{
+	    
+	    $fields = array_merge(array('datec'=>$this->db->idate(dol_now())), $this->set_save_query());
+	    
+	    foreach ($fields as $k => $v) {
+	    	
+	    	$keys[] = $k;
+	    	$values[] = $this->quote($v);
+	    	
+	    }
+	    $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'
+					( '.implode( ",", $keys ).' )
+					VALUES ( '.implode( ",", $values ).' ) ';
+	    $res = $this->db->query( $sql );
+	    if($res===false) {
+	    	
+	    	return false;
+	    }
+	    
+	    // TODO Add triggers
+	    
+	    return true;
+	    
+	}
+	
+	/**
+	 * Function to load data into current object this
+	 *
+	 * @param   stdClass    $obj    Contain data of object from database
+	 */
+	private function set_vars_by_db(&$obj)
+	{
+		foreach ($this->fields as $field => $info)
+		{
+			if($this->isDate($info))
+			{
+				if(empty($obj->{$field}) || $obj->{$field} === '0000-00-00 00:00:00' || $obj->{$field} === '1000-01-01 00:00:00') $this->{$field} = 0;
+				else $this->{$field} = strtotime($obj->{$field});
+			}
+			elseif($this->isArray($info))
+			{
+				$this->{$field} = @unserialize($obj->{$field});
+				// Hack for data not in UTF8
+				if($this->{$field } === FALSE) @unserialize(utf8_decode($obj->{$field}));
+			}
+			elseif($this->isInt($info))
+			{
+				$this->{$field} = (int) $obj->{$field};
+			}
+			elseif($this->isFloat($info))
+			{
+				$this->{$field} = (double) $obj->{$field};
+			}
+			elseif($this->isNull($info))
+			{
+				$val = $obj->{$field};
+				// zero is not null
+				$this->{$field} = (is_null($val) || (empty($val) && $val!==0 && $val!=='0') ? null : $val);
+			}
+			else
+			{
+				$this->{$field} = $obj->{$field};
+			}
+			
+		}
+	}
+	
+	/**
+	 * Function to concat keys of fields
+	 *
+	 * @return string
+	 */
+	private function get_field_list()
+	{
+		$keys = array_keys($this->fields);
+		return implode(',', $keys);
+	}
+	
+	/**
+	 * Load object in memory from the database
+	 *
+	 * @param int    $id  Id object
+	 * @param string $ref Ref
+	 *
+	 * @return int <0 if KO, 0 if not found, >0 if OK
+	 */
+	public function fetchCommon($id, $ref = null)
+	{
+	    
+		if (empty($id) && empty($ref)) return false;
+		
+		$sql = 'SELECT '.$this->get_field_list().', datec, tms';
+		$sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element;
+		
+		if(!empty($id)) $sql.= ' WHERE rowid = '.$id;
+		else  $sql.= ' WHERE ref = \''.$this->quote($ref).'\'';
+		
+		$res = $this->db->query($sql);
+		if($obj = $this->db->fetch_object($res))
+		{
+			$this->id = $id;
+			$this->set_vars_by_db($obj);
+			
+			$this->datec = $this->db->idate($obj->datec);
+			$this->tms = $this->db->idate($obj->tms);
+			
+			return $this->id;
+		}
+		else
+		{
+			$this->error = $this->db->lasterror();
+			$this->errors[] = $this->error;
+			return -1;
+		}
+		
+	}
+
+	/**
+	 * Update object into database
+	 *
+	 * @param  User $user      User that modifies
+	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
+	 *
+	 * @return int <0 if KO, >0 if OK
+	 */
+	public function updateCommon(User $user, $notrigger = false)
+	{
+		$fields = $this->set_save_query();
+		
+		foreach ($fields as $k => $v) {
+			
+			if (is_array($key)){
+				$i=array_search($k, $key);
+				if ( $i !== false) {
+					$where[] = $key[$i].'=' . $this->quote( $v ) ;
+					continue;
+				}
+			} else {
+				if ( $k == $key) {
+					$where[] = $k.'=' .$this->quote( $v ) ;
+					continue;
+				}
+			}
+			
+			$tmp[] = $k.'='.$this->quote($v);
+		}
+		$sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET '.implode( ',', $tmp ).' WHERE rowid='.$this->id ;
+		$res = $this->db->query( $sql );
+		
+		if($res===false) {
+			//error
+			return false;
+		}
+		
+		// TODO Add triggers
+		
+		return true;
+	}
+	
+	/**
+	 * Delete object in database
+	 *
+	 * @param User $user      User that deletes
+	 * @param bool $notrigger false=launch triggers after, true=disable triggers
+	 *
+	 * @return int <0 if KO, >0 if OK
+	 */
+	public function deleteCommon(User $user, $notrigger = false)
+	{
+		$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE rowid='.$this->id;
+		
+		$res = $this->db->query( $sql );
+		if($res===false) {
+			return false;
+		}
+		
+		// TODO Add triggers
+		
+		return true;
+	}
+
+	/**
+	 * Add quote to field value if necessary
+	 *
+	 * @param string|int	$value	value to protect
+	 * @return string|int
+	 */
+	protected function quote($value) {
+	
+	    if(is_null($value)) return 'NULL';
+	    else if(is_numeric($value)) return $value;
+	    else return "'".$this->db->escape( $value )."'";
+	
+	}
+	
 }
 }
+

+ 3 - 3
htdocs/core/class/conf.class.php

@@ -210,7 +210,7 @@ class Conf
                 $file=dol_sanitizeFileName($file);
                 $file=dol_sanitizeFileName($file);
                 include_once DOL_DOCUMENT_ROOT . "/".$file."/".$file."_consts.php";
                 include_once DOL_DOCUMENT_ROOT . "/".$file."/".$file."_consts.php";
                 foreach ($file2bddconsts as $key=>$value) {
                 foreach ($file2bddconsts as $key=>$value) {
-                    $this->global->$key=constant($value);
+                    $this->global->$key=$value;
                 }
                 }
             }
             }
         }
         }
@@ -358,8 +358,8 @@ class Conf
     			$this->supplier_order->dir_temp=$rootfordata."/fournisseur/commande/temp";
     			$this->supplier_order->dir_temp=$rootfordata."/fournisseur/commande/temp";
     			$this->supplier_invoice=new stdClass();
     			$this->supplier_invoice=new stdClass();
     			$this->supplier_invoice->enabled=1;
     			$this->supplier_invoice->enabled=1;
-    			$this->supplier_order->dir_output=$rootfordata."/fournisseur/facture";
-    			$this->supplier_order->dir_temp=$rootfordata."/fournisseur/facture/temp";
+    			$this->supplier_invoice->dir_output=$rootfordata."/fournisseur/facture";
+    			$this->supplier_invoice->dir_temp=$rootfordata."/fournisseur/facture/temp";
 			}
 			}
 		}
 		}
 
 

+ 440 - 0
htdocs/core/class/coreobject.class.php

@@ -0,0 +1,440 @@
+<?php
+/* EXPERIMENTAL
+ * 
+ * Copyright (C) 2016		ATM Consulting			<support@atm-consulting.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ *	\file       htdocs/core/class/coreobject.class.php
+ *	\ingroup    core
+ *	\brief      File of class to manage all object. Might be replace or merge into commonobject
+ */
+ 
+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
+	 */
+	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                  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
+     */
+    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
+     */
+	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                  < 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                  < 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                  < 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);
+			}
+			else if( $this->checkFieldType($key, 'array'))
+			{
+				$this->{$key} = $value;
+			}
+			else if( $this->checkFieldType($key, 'float') )
+			{
+				$this->{$key} = (double) price2num($value);
+			}
+			else if( $this->checkFieldType($key, 'int') ) {
+				$this->{$key} = (int) price2num($value);
+			}
+			else
+            {
+				$this->{$key} = $value;
+			}
+		}
+
+		return 1;
+	}
+
+}

+ 500 - 0
htdocs/core/class/ctyperesource.class.php

@@ -0,0 +1,500 @@
+<?php
+/* Copyright (C) 2007-2012  Laurent Destailleur <eldy@users.sourceforge.net>
+ * Copyright (C) 2014-2016  Juanjo Menent       <jmenent@2byte.es>
+ * Copyright (C) 2016       Florian Henry       <florian.henry@atm-consulting.fr>
+ * Copyright (C) 2015       Raphaël Doursenaud  <rdoursenaud@gpcsolutions.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file    resource/ctyperesource.class.php
+ * \ingroup resource
+ */
+
+/**
+ * Class Ctyperesource
+ *
+ * Put here description of your class
+ *
+ * @see CommonObject
+ */
+class Ctyperesource
+{
+	/**
+	 * @var string Id to identify managed objects
+	 */
+	public $element = 'ctyperesource';
+	/**
+	 * @var string Name of table without prefix where object is stored
+	 */
+	public $table_element = 'c_type_resource';
+
+	/**
+	 * @var CtyperesourceLine[] Lines
+	 */
+	public $lines = array();
+
+	/**
+	 */
+	
+	public $code;
+	public $label;
+	public $active;
+
+	/**
+	 */
+	
+
+	/**
+	 * Constructor
+	 *
+	 * @param DoliDb $db Database handler
+	 */
+	public function __construct(DoliDB $db)
+	{
+		$this->db = $db;
+	}
+
+	/**
+	 * Create object into database
+	 *
+	 * @param  User $user      User that creates
+	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
+	 *
+	 * @return int <0 if KO, Id of created object if OK
+	 */
+	public function create(User $user, $notrigger = false)
+	{
+		dol_syslog(__METHOD__, LOG_DEBUG);
+
+		$error = 0;
+
+		// Clean parameters
+		
+		if (isset($this->code)) {
+			 $this->code = trim($this->code);
+		}
+		if (isset($this->label)) {
+			 $this->label = trim($this->label);
+		}
+		if (isset($this->active)) {
+			 $this->active = trim($this->active);
+		}
+
+		
+
+		// Check parameters
+		// Put here code to add control on parameters values
+
+		// Insert request
+		$sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '(';
+		
+		$sql.= 'code,';
+		$sql.= 'label';
+		$sql.= 'active';
+
+		
+		$sql .= ') VALUES (';
+		
+		$sql .= ' '.(! isset($this->code)?'NULL':"'".$this->db->escape($this->code)."'").',';
+		$sql .= ' '.(! isset($this->label)?'NULL':"'".$this->db->escape($this->label)."'").',';
+		$sql .= ' '.(! isset($this->active)?'NULL':$this->active);
+
+		
+		$sql .= ')';
+
+		$this->db->begin();
+
+		$resql = $this->db->query($sql);
+		if (!$resql) {
+			$error ++;
+			$this->errors[] = 'Error ' . $this->db->lasterror();
+			dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
+		}
+
+		if (!$error) {
+			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
+
+			if (!$notrigger) {
+				// Uncomment this and change MYOBJECT to your own tag if you
+				// want this action to call a trigger.
+
+				//// Call triggers
+				//$result=$this->call_trigger('MYOBJECT_CREATE',$user);
+				//if ($result < 0) $error++;
+				//// End call triggers
+			}
+		}
+
+		// Commit or rollback
+		if ($error) {
+			$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 $code code
+	 * @param string $label Label
+	 *
+	 * @return int <0 if KO, 0 if not found, >0 if OK
+	 */
+	public function fetch($id,$code='',$label='')
+	{
+		dol_syslog(__METHOD__, LOG_DEBUG);
+
+		$sql = 'SELECT';
+		$sql .= ' t.rowid,';
+		
+		$sql .= " t.code,";
+		$sql .= " t.label,";
+		$sql .= " t.active";
+
+		
+		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
+		if ($id)   $sql.= " WHERE t.id = ".$id;
+		elseif ($code) $sql.= " WHERE t.code = '".$this->db->escape($code)."'";
+		elseif ($label) $sql.= " WHERE t.label = '".$this->db->escape($label)."'";
+		
+		
+		$resql = $this->db->query($sql);
+		if ($resql) {
+			$numrows = $this->db->num_rows($resql);
+			if ($numrows) {
+				$obj = $this->db->fetch_object($resql);
+
+				$this->id = $obj->rowid;
+				
+				$this->code = $obj->code;
+				$this->label = $obj->label;
+				$this->active = $obj->active;
+
+				
+			}
+			
+			// Retrieve all extrafields for invoice
+			// fetch optionals attributes and labels
+			/*
+			require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+			$extrafields=new ExtraFields($this->db);
+			$extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true);
+			$this->fetch_optionals($this->id,$extralabels);
+            */
+			
+			// $this->fetch_lines();
+			
+			$this->db->free($resql);
+
+			if ($numrows) {
+				return 1;
+			} else {
+				return 0;
+			}
+		} else {
+			$this->errors[] = 'Error ' . $this->db->lasterror();
+			dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
+
+			return - 1;
+		}
+	}
+
+	/**
+	 * Load object in memory from the database
+	 *
+	 * @param string $sortorder Sort Order
+	 * @param string $sortfield Sort field
+	 * @param int    $limit     offset limit
+	 * @param int    $offset    offset limit
+	 * @param array  $filter    filter array
+	 * @param string $filtermode filter mode (AND or OR)
+	 *
+	 * @return int <0 if KO, >0 if OK
+	 */
+	public function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND')
+	{
+		dol_syslog(__METHOD__, LOG_DEBUG);
+
+		$sql = 'SELECT';
+		$sql .= ' t.rowid,';
+		
+		$sql .= " t.code,";
+		$sql .= " t.label,";
+		$sql .= " t.active";
+
+		
+		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t';
+
+		// Manage filter
+		$sqlwhere = array();
+		if (count($filter) > 0) {
+			foreach ($filter as $key => $value) {
+				$sqlwhere [] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\'';
+			}
+		}
+		
+		if (count($sqlwhere) > 0) {
+			$sql .= ' WHERE ' . implode(' '.$filtermode.' ', $sqlwhere);
+		}
+		if (!empty($sortfield)) {
+			$sql .= $this->db->order($sortfield,$sortorder);
+		}
+		if (!empty($limit)) {
+		 $sql .=  ' ' . $this->db->plimit($limit, $offset);
+		}
+
+		$resql = $this->db->query($sql);
+		if ($resql) {
+			$num = $this->db->num_rows($resql);
+
+			while ($obj = $this->db->fetch_object($resql)) {
+				$line = new self($this->db);
+
+				$line->id = $obj->rowid;
+				
+				$line->code = $obj->code;
+				$line->label = $obj->label;
+				$line->active = $obj->active;
+
+				
+			}
+			$this->db->free($resql);
+
+			return $num;
+		} else {
+			$this->errors[] = 'Error ' . $this->db->lasterror();
+			dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
+
+			return - 1;
+		}
+	}
+
+	/**
+	 * Update object into database
+	 *
+	 * @param  User $user      User that modifies
+	 * @param  bool $notrigger false=launch triggers after, true=disable triggers
+	 *
+	 * @return int <0 if KO, >0 if OK
+	 */
+	public function update(User $user, $notrigger = false)
+	{
+		$error = 0;
+
+		dol_syslog(__METHOD__, LOG_DEBUG);
+
+		// Clean parameters
+		
+		if (isset($this->code)) {
+			 $this->code = trim($this->code);
+		}
+		if (isset($this->label)) {
+			 $this->label = trim($this->label);
+		}
+		if (isset($this->active)) {
+			 $this->active = trim($this->active);
+		}
+
+		// Check parameters
+		// Put here code to add a control on parameters values
+
+		// Update request
+		$sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET';
+		
+		$sql .= ' code = '.(isset($this->code)?"'".$this->db->escape($this->code)."'":"null").',';
+		$sql .= ' label = '.(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").',';
+		$sql .= ' active = '.(isset($this->active)?$this->active:"null");
+
+        
+		$sql .= ' WHERE rowid=' . $this->id;
+
+		$this->db->begin();
+
+		$resql = $this->db->query($sql);
+		if (!$resql) {
+			$error ++;
+			$this->errors[] = 'Error ' . $this->db->lasterror();
+			dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
+		}
+
+		if (!$error && !$notrigger) {
+			// Uncomment this and change MYOBJECT to your own tag if you
+			// want this action calls a trigger.
+
+			//// Call triggers
+			//$result=$this->call_trigger('MYOBJECT_MODIFY',$user);
+			//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
+			//// End call triggers
+		}
+
+		// Commit or rollback
+		if ($error) {
+			$this->db->rollback();
+
+			return - 1 * $error;
+		} else {
+			$this->db->commit();
+
+			return 1;
+		}
+	}
+
+	/**
+	 * Delete object in database
+	 *
+	 * @param User $user      User that deletes
+	 * @param bool $notrigger false=launch triggers after, true=disable triggers
+	 *
+	 * @return int <0 if KO, >0 if OK
+	 */
+	public function delete(User $user, $notrigger = false)
+	{
+		dol_syslog(__METHOD__, LOG_DEBUG);
+
+		$error = 0;
+
+		$this->db->begin();
+
+		if (!$error) {
+			if (!$notrigger) {
+				// Uncomment this and change MYOBJECT to your own tag if you
+				// want this action calls a trigger.
+
+				//// Call triggers
+				//$result=$this->call_trigger('MYOBJECT_DELETE',$user);
+				//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
+				//// End call triggers
+			}
+		}
+
+		// If you need to delete child tables to, you can insert them here
+		
+		if (!$error) {
+			$sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element;
+			$sql .= ' WHERE rowid=' . $this->id;
+
+			$resql = $this->db->query($sql);
+			if (!$resql) {
+				$error ++;
+				$this->errors[] = 'Error ' . $this->db->lasterror();
+				dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
+			}
+		}
+
+		// Commit or rollback
+		if ($error) {
+			$this->db->rollback();
+
+			return - 1 * $error;
+		} else {
+			$this->db->commit();
+
+			return 1;
+		}
+	}
+
+	/**
+	 * Load an object from its id and create a new one in database
+	 *
+	 * @param int $fromid Id of object to clone
+	 *
+	 * @return int New id of clone
+	 */
+	public function createFromClone($fromid)
+	{
+		dol_syslog(__METHOD__, LOG_DEBUG);
+
+		global $user;
+		$error = 0;
+		$object = new Ctyperesource($this->db);
+
+		$this->db->begin();
+
+		// Load source object
+		$object->fetch($fromid);
+		// Reset object
+		$object->id = 0;
+
+		// Clear fields
+		// ...
+
+		// Create clone
+		$result = $object->create($user);
+
+		// Other options
+		if ($result < 0) {
+			$error ++;
+			$this->errors = $object->errors;
+			dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
+		}
+
+		// End
+		if (!$error) {
+			$this->db->commit();
+
+			return $object->id;
+		} else {
+			$this->db->rollback();
+
+			return - 1;
+		}
+	}
+
+	/**
+	 * Initialise object with example values
+	 * Id must be 0 if object instance is a specimen
+	 *
+	 * @return void
+	 */
+	public function initAsSpecimen()
+	{
+		$this->id = 0;
+		
+		$this->code = '';
+		$this->label = '';
+		$this->active = '';
+	}
+
+}
+
+/**
+ * Class CtyperesourceLine
+ */
+class CtyperesourceLine
+{
+	/**
+	 * @var int ID
+	 */
+	public $id;
+	/**
+	 * @var mixed Sample line property 1
+	 */
+	
+	public $code;
+	public $label;
+	public $active;
+
+	/**
+	 * @var mixed Sample line property 2
+	 */
+	
+}

+ 4 - 0
htdocs/core/class/extrafields.class.php

@@ -727,6 +727,10 @@ class ExtraFields
     		{
     		{
     		    $showsize='minwidth400imp';
     		    $showsize='minwidth400imp';
     		}
     		}
+    		elseif ($type == 'boolean')
+    		{
+    		    $showsize='';
+    		}
     		else
     		else
     		{
     		{
     			if (round($size) < 12)
     			if (round($size) < 12)

+ 4 - 3
htdocs/core/class/html.form.class.php

@@ -492,10 +492,11 @@ class Form
      */
      */
     function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 2, $tooltiptrigger='')
     function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 2, $tooltiptrigger='')
     {
     {
-        global $conf;
+        global $conf, $langs;
 
 
         $alt = '';
         $alt = '';
-
+        if ($tooltiptrigger) $alt=$langs->trans("ClickToShowHelp");
+        
         //For backwards compatibility
         //For backwards compatibility
         if ($type == '0') $type = 'info';
         if ($type == '0') $type = 'info';
         elseif ($type == '1') $type = 'help';
         elseif ($type == '1') $type = 'help';
@@ -994,7 +995,7 @@ class Form
     				print img_picto($langs->trans("Search"), 'search');
     				print img_picto($langs->trans("Search"), 'search');
     			}
     			}
     		}
     		}
-            print '<input type="text" class="minwidth100" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->THIRDPARTY_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
+            print '<input type="text" class="'.$morecss.'" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->THIRDPARTY_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
     		if ($hidelabel == 3) {
     		if ($hidelabel == 3) {
     			print img_picto($langs->trans("Search"), 'search');
     			print img_picto($langs->trans("Search"), 'search');
     		}
     		}

+ 14 - 5
htdocs/core/class/html.formmail.class.php

@@ -1059,18 +1059,18 @@ class FormMail extends Form
 	}
 	}
 	
 	
 	/**
 	/**
-	 * Set substit array from object
+	 * Get list of substition keys available.
 	 * 
 	 * 
-	 * @param	string	$mode		'form', 'formwithlines', 'formforlines' or 'emailing'
+	 * @param	string	$mode		'formemail', 'formemailwithlines', 'formemailforlines', 'emailing', ...
 	 * @return	void
 	 * @return	void
 	 */
 	 */
-	function getAvailableSubstitKey($mode='form')
+	static function getAvailableSubstitKey($mode='formemail')
 	{
 	{
-		global $conf;
+		global $conf, $langs;
 		
 		
 		$vars=array();
 		$vars=array();
 		
 		
-		if ($mode == 'form' || $mode == 'formwithlines' || $mode == 'formforlines')
+		if ($mode == 'formemail' || $mode == 'formemailwithlines' || $mode == 'formemailforlines')
 		{
 		{
 			$vars=array(
 			$vars=array(
 				'__REF__', 
 				'__REF__', 
@@ -1133,6 +1133,15 @@ class FormMail extends Form
 				$vars['__SECUREKEYPAYPAL_MEMBER__']='';
 				$vars['__SECUREKEYPAYPAL_MEMBER__']='';
 			}
 			}
 		}
 		}
+		
+		$tmparray=array();
+		$parameters=array('mode'=>$mode);
+		complete_substitutions_array($tmparray, $langs, null, $parameters);
+		foreach($tmparray as $key => $val)
+		{
+		    $vars[$key]=$key;
+		}
+		
 		return $vars;
 		return $vars;
 	}
 	}
 
 

+ 7 - 7
htdocs/core/class/html.formmailing.class.php

@@ -32,9 +32,9 @@ class FormMailing  extends Form
 	/**
 	/**
 	 * Output a select with destinaries status
 	 * Output a select with destinaries status
 	 * 
 	 * 
-	 * @param string $selectedid the selected id
-	 * @param string $htmlname name of controm
-	 * @param integer $show_empty show empty option
+	 * @param string   $selectedid     The selected id
+	 * @param string   $htmlname       Name of controm
+	 * @param integer  $show_empty     Show empty option
 	 * @return string HTML select
 	 * @return string HTML select
 	 */
 	 */
 	public function selectDestinariesStatus($selectedid='',$htmlname='dest_status', $show_empty=0) {
 	public function selectDestinariesStatus($selectedid='',$htmlname='dest_status', $show_empty=0) {
@@ -46,13 +46,13 @@ class FormMailing  extends Form
 		$mailing = new Mailing($this->db);
 		$mailing = new Mailing($this->db);
 
 
 		$options = array();
 		$options = array();
-
+        
 		if ($show_empty) {
 		if ($show_empty) {
-			$options[''] = '';
+			$options[-2] = '';   // Note -1 is used for error
 		}
 		}
 
 
-		$options = array_merge($options, $mailing->statut_dest);
+        $options = $options + $mailing->statut_dest;
 
 
-		return Form::selectarray($htmlname, $options, $selectedid, 0, 0, 0, '', 1);
+        return Form::selectarray($htmlname, $options, $selectedid, 0, 0, 0, '', 1);
 	}
 	}
 }
 }

+ 12 - 5
htdocs/core/db/DoliDB.class.php

@@ -220,9 +220,9 @@ abstract class DoliDB implements Database
 	/**
 	/**
 	 * Define sort criteria of request
 	 * Define sort criteria of request
 	 *
 	 *
-	 * @param	string	$sortfield  List of sort fields, separated by comma. Example: 't1.fielda, t2.fieldb'
+	 * @param	string	        $sortfield  List of sort fields, separated by comma. Example: 't1.fielda, t2.fieldb'
 	 * @param	'ASC'|'DESC'	$sortorder  Sort order
 	 * @param	'ASC'|'DESC'	$sortorder  Sort order
-	 * @return	string      		String to provide syntax of a sort sql string
+	 * @return	string      		        String to provide syntax of a sort sql string
 	 */
 	 */
 	function order($sortfield=null,$sortorder=null)
 	function order($sortfield=null,$sortorder=null)
 	{
 	{
@@ -230,18 +230,25 @@ abstract class DoliDB implements Database
 		{
 		{
 			$return='';
 			$return='';
 			$fields=explode(',',$sortfield);
 			$fields=explode(',',$sortfield);
+			$orders=explode(',',$sortorder);
+			$i=0;
 			foreach($fields as $val)
 			foreach($fields as $val)
 			{
 			{
 				if (! $return) $return.=' ORDER BY ';
 				if (! $return) $return.=' ORDER BY ';
-				else $return.=',';
+				else $return.=', ';
 
 
 				$return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
 				$return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
+				
+				$tmpsortorder = trim($orders[$i]);
+				
 				// Only ASC and DESC values are valid SQL
 				// Only ASC and DESC values are valid SQL
-				if (strtoupper($sortorder) === 'ASC') {
+				if (strtoupper($tmpsortorder) === 'ASC') {
 					$return .= ' ASC';
 					$return .= ' ASC';
-				} elseif (strtoupper($sortorder) === 'DESC') {
+				} elseif (strtoupper($tmpsortorder) === 'DESC') {
 					$return .= ' DESC';
 					$return .= ' DESC';
 				}
 				}
+				
+				$i++;
 			}
 			}
 			return $return;
 			return $return;
 		}
 		}

+ 7 - 5
htdocs/core/js/lib_notification.js.php

@@ -65,7 +65,7 @@ if (! ($_SERVER['HTTP_REFERER'] === $dolibarr_main_url_root . '/' || $_SERVER['H
    	// We set a delay before launching first test so next check will arrive after the time_auto_update compared to previous one.
    	// We set a delay before launching first test so next check will arrive after the time_auto_update compared to previous one.
     var time_first_execution = (time_auto_update - (nowtime - time_js_next_test)) * 1000;	//need milliseconds
     var time_first_execution = (time_auto_update - (nowtime - time_js_next_test)) * 1000;	//need milliseconds
     if (login != '') { 
     if (login != '') { 
-    	console.log("Launch browser notif check: setTimeout to wait time_first_execution="+time_first_execution+" before first check - nowtime = "+nowtime+" auto_check_events_not_before = "+auto_check_events_not_before+" time_js_next_test = "+time_js_next_test+" time_auto_update="+time_auto_update);
+    	console.log("Launch browser notif check: setTimeout is set to launch 'first_execution' function after a wait of time_first_execution="+time_first_execution+". nowtime (time php page generation) = "+nowtime+" auto_check_events_not_before (val in session)= "+auto_check_events_not_before+" time_js_next_test (max now,auto_check_events_not_before) = "+time_js_next_test+" time_auto_update="+time_auto_update);
     	setTimeout(first_execution, time_first_execution); 
     	setTimeout(first_execution, time_first_execution); 
     } //first run auto check
     } //first run auto check
 
 
@@ -79,17 +79,18 @@ if (! ($_SERVER['HTTP_REFERER'] === $dolibarr_main_url_root . '/' || $_SERVER['H
     function check_events() {
     function check_events() {
     	if (Notification.permission === "granted")
     	if (Notification.permission === "granted")
     	{
     	{
-    		console.log("Call check_events time_js_next_test="+time_js_next_test);
-            $.ajax("<?php print dol_buildpath('/core/ajax/check_notifications.php', 1); ?>", {
-                type: "post",   // Usually post o get
+    		console.log("Call check_events time_js_next_test = date we are looking for event after ="+time_js_next_test);
+            $.ajax("<?php print DOL_URL_ROOT.'/core/ajax/check_notifications.php'; ?>", {
+                type: "post",   // Usually post or get
                 async: true,
                 async: true,
                 data: {time: time_js_next_test},
                 data: {time: time_js_next_test},
                 success: function (result) {
                 success: function (result) {
                     var arr = JSON.parse(result);
                     var arr = JSON.parse(result);
                     if (arr.length > 0) {
                     if (arr.length > 0) {
+                    	var audio = null; 
                         <?php
                         <?php
                         if (! empty($conf->global->AGENDA_NOTIFICATION_SOUND)) {
                         if (! empty($conf->global->AGENDA_NOTIFICATION_SOUND)) {
-                            print 'var audio = new Audio(\''.DOL_URL_ROOT.'/theme/common/sound/notification_agenda.wav'.'\');';
+                            print 'audio = new Audio(\''.DOL_URL_ROOT.'/theme/common/sound/notification_agenda.wav'.'\');';
                         }
                         }
                         ?>
                         ?>
     
     
@@ -136,6 +137,7 @@ if (! ($_SERVER['HTTP_REFERER'] === $dolibarr_main_url_root . '/' || $_SERVER['H
         }
         }
 
 
         time_js_next_test += time_auto_update;
         time_js_next_test += time_auto_update;
+		console.log('Updated time_js_next_test. New value is '+time_js_next_test);
     }
     }
 <?php 
 <?php 
 }
 }

+ 166 - 0
htdocs/core/js/listview.js

@@ -0,0 +1,166 @@
+// Copyright (C) 2017 Laurent Destailleur  <eldy@users.sourceforge.net>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// or see http://www.gnu.org/
+
+//
+// \file       htdocs/core/js/listview.js
+// \brief      File that include javascript functions for lists
+//
+var Listview_include = true;
+
+function Listview_OrderDown(idListe, column) {
+	var base_url = document.location.href;
+	
+	base_url = Listview_recup_form_param(idListe,base_url);
+	base_url = Listview_removeParam(base_url,'Listview['+encodeURIComponent(idListe)+'][orderBy]');
+	
+	base_url = Listview_removeParam(base_url,'get-all-for-export');
+	
+	document.location.href=Listview_modifyUrl(base_url,"Listview["+encodeURIComponent(idListe)+"][orderBy]["+encodeURIComponent(column)+"]","DESC");
+}
+function Listview_OrderUp(idListe, column) {
+	
+	var base_url = document.location.href;
+	
+	base_url = Listview_recup_form_param(idListe,base_url);
+	base_url = Listview_removeParam(base_url,'Listview['+encodeURIComponent(idListe)+'][orderBy]');
+	
+	base_url = Listview_removeParam(base_url,'get-all-for-export');
+	
+	document.location.href=Listview_modifyUrl(base_url,"Listview["+encodeURIComponent(idListe)+"][orderBy]["+encodeURIComponent(column)+"]","ASC");
+}
+function Listview_modifyUrl(strURL,paramName,paramNewValue){
+	    if (strURL.indexOf(paramName+'=')!=-1){
+        	
+                var strFirstPart=strURL.substring(0,strURL.indexOf(paramName+'=',0))+paramName+'=';
+                var strLastPart="";
+                if (strURL.indexOf('&',strFirstPart.length-1)>0)
+                      strLastPart=strURL.substring(strURL.indexOf('&',strFirstPart.length-1),strURL.length);
+              		  strURL=strFirstPart+paramNewValue+strLastPart;
+                }
+        else{
+                if (strURL.search('=')!=-1) // permet de verifier s'il y a dej� des param�tres dans l'URL
+                        strURL+='&'+paramName+'='+paramNewValue;
+                else
+                        strURL+='?'+paramName+'='+paramNewValue;
+        }
+        
+        return strURL;
+}
+function Listview_removeParam(strURL, paramMask) {
+	var cpt=0;
+	var url = '';
+	
+	 while(strURL.indexOf(paramMask)!=-1 && cpt++ <50){
+	 	var strFirstPart= strURL.substring(0,strURL.indexOf(paramMask)-1);
+	 	
+	 	var strLastPart='';
+	 	if (strURL.indexOf('&',strFirstPart.length+1)>0) {
+	 		strLastPart = strURL.substring(strURL.indexOf('&',strFirstPart.length+1),strURL.length);	
+	 	}
+	 		
+		url = strFirstPart+strLastPart;
+	 	
+	 }
+	 
+	 if(url=='')url = strURL;
+	 
+	 return url;
+}
+
+function Listview_recup_form_param(idListe,base_url) {
+	
+	$('#'+idListe+' tr.barre-recherche [listviewtbs],#'+idListe+' tr.barre-recherche-head input,#'+idListe+' tr.barre-recherche-head select,#'+idListe+' div.tabsAction input[listviewtbs]').each(function(i,item) {
+		if($(item).attr("name")) {
+			base_url = Listview_modifyUrl(base_url, $(item).attr("name") , $(item).val());
+		}
+		
+	});
+	
+	return base_url;
+}
+
+function Listview_GoToPage(idListe,pageNumber){
+	
+	var base_url = document.location.href;
+	
+	base_url = Listview_recup_form_param(idListe,base_url);
+	base_url =Listview_modifyUrl(base_url,"Listview["+encodeURIComponent(idListe)+"][page]",pageNumber);
+	
+	base_url = Listview_removeParam(base_url,'get-all-for-export');
+	
+	document.location.href=base_url;
+}
+function Listview_submitSearch(obj) {
+	
+	$form = $(obj).closest('form');
+	console.log($form);
+	if($form.length>0){
+		$form.submit();
+	}
+}
+function Listview_launch_downloadAs(mode,url,token,session_name) {
+	 $('#listviewdAS_export_form').remove();
+	
+	$form = $('<form action="'+url+'" method="post" name="listviewdAS_export_form" id="listTBSdAS_export_form"></form>');
+	$form.append('<input type="hidden" name="mode" value="'+mode+'" />');
+	$form.append('<input type="hidden" name="token" value="'+token+'" />');
+	$form.append('<input type="hidden" name="session_name" value="'+session_name+'" />');
+	
+	$('body').append($form);
+	
+    $('#listviewdAS_export_form').submit();
+	
+}
+
+function Listview_downloadAs(obj, mode,url,token,session_name) {
+	
+	$form = $(obj).closest('form');
+	$div = $form.find('div.tabsAction');
+	$div.append('<input type="hidden" listviewtbs="hidden" name="token" value="'+token+'" />');
+	$div.append('<input type="hidden" listviewtbs="hidden" name="mode" value="'+mode+'" />');
+	$div.append('<input type="hidden" listviewtbs="hidden" name="url" value="'+url+'" />');
+	$div.append('<input type="hidden" listviewtbs="hidden" name="session_name" value="'+session_name+'" />');
+	$div.append('<input type="hidden" listviewtbs="hidden" name="get-all-for-export" value="1" />');
+	
+	Listview_submitSearch(obj);
+}
+
+$(document).ready(function() {
+	$('tr.barre-recherche input').keypress(function(e) {
+	    if(e.which == 13) {
+	       
+	       var id_list = $(this).closest('table').attr('id');
+	       
+	       $('#'+id_list+' .list-search-link').click();
+	       
+	    }
+	});
+	
+	var $_GET = {};
+	
+	document.location.search.replace(/\??(?:([^=]+)=([^&]*)&?)/g, function () {
+	    function decode(s) {
+	        return decodeURIComponent(s.split("+").join(" "));
+	    }
+	
+	    $_GET[decode(arguments[1])] = decode(arguments[2]);
+	});
+	
+	if(typeof $_GET["get-all-for-export"] != "undefined") {
+		Listview_launch_downloadAs($_GET['mode'],$_GET['url'],$_GET['token'],$_GET['session_name']);
+	}
+	
+});

+ 92 - 0
htdocs/core/lib/accounting.lib.php

@@ -202,3 +202,95 @@ function length_accounta($accounta)
 		return $accounta;
 		return $accounta;
 	}
 	}
 }
 }
+
+
+
+/**
+ *	Show header of a VAT report
+ *
+ *	@param	string				$nom            Name of report
+ *	@param 	string				$variante       Link for alternate report
+ *	@param 	string				$period         Period of report
+ *	@param 	string				$periodlink     Link to switch period
+ *	@param 	string				$description    Description
+ *	@param 	timestamp|integer	$builddate      Date generation
+ *	@param 	string				$exportlink     Link for export or ''
+ *	@param	array				$moreparam		Array with list of params to add into form
+ *	@param	string				$calcmode		Calculation mode
+ *  @param  string              $varlink        Add a variable into the address of the page
+ *	@return	void
+ */
+function journalHead($nom,$variante,$period,$periodlink,$description,$builddate,$exportlink='',$moreparam=array(),$calcmode='', $varlink='')
+{
+    global $langs;
+
+    if (empty($hselected)) $hselected='report';
+
+    print "\n\n<!-- debut cartouche journal -->\n";
+
+    if(! empty($varlink)) $varlink = '?'.$varlink;
+
+    $h=0;
+    $head[$h][0] = $_SERVER["PHP_SELF"].$varlink;
+    $head[$h][1] = $langs->trans("Journalization");
+    $head[$h][2] = 'journal';
+
+    dol_fiche_head($head, 'journal');
+
+    print '<form method="POST" action="'.$_SERVER["PHP_SELF"].$varlink.'">';
+    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>';
+    if (! $variantexxx) print '<td colspan="3">';
+    else print '<td>';
+    print $nom;
+    if ($variantexxx) print '</td><td colspan="2">'.$variantexxx;
+    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>';
+
+    print '<br><div class="center"><input type="submit" class="button" name="submit" value="'.$langs->trans("Refresh").'"></div>';
+
+    print '</form>';
+
+    dol_fiche_end();
+
+    print "\n<!-- fin cartouche journal -->\n\n";
+}
+

+ 1 - 1
htdocs/core/lib/ajax.lib.php

@@ -349,7 +349,7 @@ function ajax_dialog($title,$message,$w=350,$h=150)
 
 
 
 
 /**
 /**
- * Make a input box content all selected
+ * Make content of an input box selected when we click into input field.
  * 
  * 
  * @param string	$htmlname	Id of html object 
  * @param string	$htmlname	Id of html object 
  * @param int		$addlink	Add a link to after
  * @param int		$addlink	Add a link to after

+ 49 - 0
htdocs/core/lib/company.lib.php

@@ -496,6 +496,55 @@ function getFormeJuridiqueLabel($code)
     }
     }
 }
 }
 
 
+/**
+ *  Return if a country is inside the EEC (European Economic Community)
+ *  TODO Add a field into country dictionary.
+ *  
+ *  @param      Object      $object    Object
+ *  @return     boolean		           true = country inside EEC, false = country outside EEC
+ */
+function isInEEC($object)
+{
+    // List of all country codes that are in europe for european vat rules
+    // List found on http://ec.europa.eu/taxation_customs/common/faq/faq_1179_en.htm#9
+    $country_code_in_EEC=array(
+        'AT',	// Austria
+        'BE',	// Belgium
+        'BG',	// Bulgaria
+        'CY',	// Cyprus
+        'CZ',	// Czech republic
+        'DE',	// Germany
+        'DK',	// Danemark
+        'EE',	// Estonia
+        'ES',	// Spain
+        'FI',	// Finland
+        'FR',	// France
+        'GB',	// United Kingdom
+        'GR',	// Greece
+        'HR',   // Croatia
+        'NL',	// Holland
+        'HU',	// Hungary
+        'IE',	// Ireland
+        'IM',	// Isle of Man - Included in UK
+        'IT',	// Italy
+        'LT',	// Lithuania
+        'LU',	// Luxembourg
+        'LV',	// Latvia
+        'MC',	// Monaco - Included in France
+        'MT',	// Malta
+        //'NO',	// Norway
+        'PL',	// Poland
+        'PT',	// Portugal
+        'RO',	// Romania
+        'SE',	// Sweden
+        'SK',	// Slovakia
+        'SI',	// Slovenia
+        'UK',	// United Kingdom
+        //'CH',	// Switzerland - No. Swizerland in not in EEC
+    );
+    //print "dd".$this->country_code;
+    return in_array($object->country_code, $country_code_in_EEC);
+}
 
 
 
 
 /**
 /**

+ 24 - 6
htdocs/core/lib/files.lib.php

@@ -1495,10 +1495,10 @@ function dol_uncompress($inputfile,$outputdir)
 {
 {
     global $conf, $langs;
     global $conf, $langs;
 
 
-    if (defined('ODTPHP_PATHTOPCLZIP'))
+    if (! empty($conf->global->ODTPHP_PATHTOPCLZIP))
     {
     {
-    	dol_syslog("Constant ODTPHP_PATHTOPCLZIP for pclzip library is set to ".constant('ODTPHP_PATHTOPCLZIP').", so we use Pclzip to unzip into ".$outputdir);
-        include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
+    	dol_syslog("Constant ODTPHP_PATHTOPCLZIP for pclzip library is set to ".$conf->global->ODTPHP_PATHTOPCLZIP.", so we use Pclzip to unzip into ".$outputdir);
+        include_once $conf->global->ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
         $archive = new PclZip($inputfile);
         $archive = new PclZip($inputfile);
         $result=$archive->extract(PCLZIP_OPT_PATH, $outputdir);
         $result=$archive->extract(PCLZIP_OPT_PATH, $outputdir);
         //var_dump($result);
         //var_dump($result);
@@ -1584,7 +1584,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu
 	$sqlprotectagainstexternals='';
 	$sqlprotectagainstexternals='';
 	$ret=array();
 	$ret=array();
 
 
-	// find the subdirectory name as the reference
+    // Find the subdirectory name as the reference. For exemple original_file='10/myfile.pdf' -> refname='10'
 	if (empty($refname)) $refname=basename(dirname($original_file)."/");
 	if (empty($refname)) $refname=basename(dirname($original_file)."/");
 
 
 	$relative_original_file = $original_file;
 	$relative_original_file = $original_file;
@@ -1628,8 +1628,14 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu
 	// Wrapping pour les apercu intervention
 	// Wrapping pour les apercu intervention
 	elseif (($modulepart == 'apercufichinter' || $modulepart == 'apercuficheinter') && !empty($conf->ficheinter->dir_output))
 	elseif (($modulepart == 'apercufichinter' || $modulepart == 'apercuficheinter') && !empty($conf->ficheinter->dir_output))
 	{
 	{
-		if ($fuser->rights->ficheinter->lire) $accessallowed=1;
-		$original_file=$conf->ficheinter->dir_output.'/'.$original_file;
+	    if ($fuser->rights->ficheinter->lire) $accessallowed=1;
+	    $original_file=$conf->ficheinter->dir_output.'/'.$original_file;
+	}
+	// Wrapping pour les apercu commande
+	elseif (($modulepart == 'apercusupplier_order' || $modulepart == 'apercusupplier_order') && !empty($conf->fournisseur->commande->dir_output))
+	{
+	    if ($fuser->rights->fournisseur->commande->lire) $accessallowed=1;
+	    $original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file;
 	}
 	}
 	// Wrapping pour les images des stats propales
 	// Wrapping pour les images des stats propales
 	elseif ($modulepart == 'propalstats' && !empty($conf->propal->dir_temp))
 	elseif ($modulepart == 'propalstats' && !empty($conf->propal->dir_temp))
@@ -1752,6 +1758,18 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu
 		$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
 		$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
 	}
 	}
 
 
+	// Wrapping for users
+	else if ($modulepart == 'user' && !empty($conf->user->dir_output))
+	{
+        $canreaduser=(! empty($fuser->admin) || $fuser->rights->user->user->lire);
+        if ($fuser->id == (int) $refname) { $canreaduser=1; } // A user can always read its own card
+        if ($canreaduser || preg_match('/^specimen/i',$original_file))
+	    {
+	        $accessallowed=1;
+	    }
+	    $original_file=$conf->user->dir_output.'/'.$original_file;
+	}
+	
 	// Wrapping for third parties
 	// Wrapping for third parties
 	else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output))
 	else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output))
 	{
 	{

+ 82 - 34
htdocs/core/lib/functions.lib.php

@@ -246,24 +246,64 @@ function dol_shutdown()
  *  @param  mixed   $options     Options to pass to filter_var when $check is set to custom
  *  @param  mixed   $options     Options to pass to filter_var when $check is set to custom
  *  @return string|string[]      Value found (string or array), or '' if check fails
  *  @return string|string[]      Value found (string or array), or '' if check fails
  */
  */
-function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL)
+function GETPOST($paramname, $check='', $method=0, $filter=NULL, $options=NULL)
 {
 {
 	if (empty($method))
 	if (empty($method))
 	{
 	{
 		$out = isset($_GET[$paramname])?$_GET[$paramname]:(isset($_POST[$paramname])?$_POST[$paramname]:'');
 		$out = isset($_GET[$paramname])?$_GET[$paramname]:(isset($_POST[$paramname])?$_POST[$paramname]:'');
-		
+
 		// Management of default values
 		// Management of default values
-		if (! empty($_GET['action']) && $_GET['action'] == 'create' && ! empty($paramname) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname]))
+		if (! isset($_GET['sortfield']))	// If we did a click on a field to sort, we do no apply default values
 		{
 		{
-			$relativepathstring = preg_replace('/\.[a-z]+$/', '', $_SERVER["PHP_SELF"]);
-			if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring);
-			$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
-			$relativepathstring = preg_replace('/^\//', '', $relativepathstring);
-			$relativepathstring=dol_string_nospecial($relativepathstring, '-');
-			// $relativepathstring is now string that identify the page: '_societe_card', '_agenda_card', ...
-			$keyfordefaultvalue = 'MAIN_DEFAULT_FOR_'.$relativepathstring.'_'.$paramname;
-			global $conf;
-			if (isset($conf->global->$keyfordefaultvalue)) $out = $conf->global->$keyfordefaultvalue;
+		    if (! empty($_GET['action']) && $_GET['action'] == 'create' && ! empty($paramname) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname]))
+			{
+				$relativepathstring = $_SERVER["PHP_SELF"];
+				if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^\//', '', $relativepathstring);
+				global $user;
+				if (! empty($user->default_values))		// $user->default_values defined from menu default values, and values loaded not at first 
+				{
+					//var_dump($user->default_values[$relativepathstring]['createform']);
+					if (isset($user->default_values[$relativepathstring]['createform'][$paramname])) $out = $user->default_values[$relativepathstring]['createform'][$paramname];
+				}
+			}
+			// Management of default search_filters and sort order
+			elseif (preg_match('/list.php$/', $_SERVER["PHP_SELF"]) && ! empty($paramname) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname]))
+			{
+			    $relativepathstring = $_SERVER["PHP_SELF"];
+				if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^\//', '', $relativepathstring);
+				global $user;
+				if (! empty($user->default_values))		// $user->default_values defined from menu default values, and values loaded not at first 
+				{
+				    //var_dump($user->default_values[$relativepathstring]);
+        			if ($paramname == 'sortfield')
+        			{
+        			    if (isset($user->default_values[$relativepathstring]['sortorder'])) 
+        			    {
+        			        foreach($user->default_values[$relativepathstring]['sortorder'] as $key => $val)
+        			        {
+        			            if ($out) $out.=', ';
+        			            $out.=$key;
+        			        }
+        			    }
+        			}
+        			elseif ($paramname == 'sortorder')
+        			{
+        			    if (isset($user->default_values[$relativepathstring]['sortorder'])) 
+        			    {
+        			        foreach($user->default_values[$relativepathstring]['sortorder'] as $key => $val)
+        			        {
+        			            if ($out) $out.=', ';
+        			            $out.=$val;
+        			        }
+        			    }
+        			}
+				    elseif (isset($user->default_values[$relativepathstring]['filters'][$paramname])) $out = $user->default_values[$relativepathstring]['filters'][$paramname];
+				}
+			}
 		}
 		}
 	}
 	}
 	elseif ($method==1) $out = isset($_GET[$paramname])?$_GET[$paramname]:'';
 	elseif ($method==1) $out = isset($_GET[$paramname])?$_GET[$paramname]:'';
@@ -303,6 +343,11 @@ function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL)
 	            global $user;
 	            global $user;
 	            $out = $user->id;
 	            $out = $user->id;
 	        }
 	        }
+	    	elseif ($reg[1] == 'SUPERVISORID')
+	        {
+	            global $user;
+	            $out = $user->fk_user;
+	        }
 	        elseif ($reg[1] == 'ENTITYID')
 	        elseif ($reg[1] == 'ENTITYID')
 	        {
 	        {
 	            global $conf;
 	            global $conf;
@@ -1020,11 +1065,11 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r
 	if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode=0;
 	if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode=0;
 	$modulepart='unknown';
 	$modulepart='unknown';
 
 
-	if ($object->element == 'societe')   $modulepart='societe';
-	if ($object->element == 'contact')   $modulepart='contact';
-	if ($object->element == 'member')    $modulepart='memberphoto';
-	if ($object->element == 'user')      $modulepart='userphoto';
-	if ($object->element == 'product')   $modulepart='product';
+	if ($object->element == 'societe')         $modulepart='societe';
+	if ($object->element == 'contact')         $modulepart='contact';
+	if ($object->element == 'member')          $modulepart='memberphoto';
+	if ($object->element == 'user')            $modulepart='userphoto';
+	if ($object->element == 'product')         $modulepart='product';
 	if (class_exists("Imagick"))
 	if (class_exists("Imagick"))
 	{
 	{
 		if ($object->element == 'propal')    $modulepart='propal';
 		if ($object->element == 'propal')    $modulepart='propal';
@@ -1032,6 +1077,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r
 		if ($object->element == 'facture')   $modulepart='facture';
 		if ($object->element == 'facture')   $modulepart='facture';
 		if ($object->element == 'fichinter') $modulepart='ficheinter';
 		if ($object->element == 'fichinter') $modulepart='ficheinter';
 		if ($object->element == 'contrat')   $modulepart='contract';
 		if ($object->element == 'contrat')   $modulepart='contract';
+	    if ($object->element == 'order_supplier')  $modulepart='supplier_order';
 	}
 	}
 
 
 	if ($object->element == 'product')
 	if ($object->element == 'product')
@@ -1057,12 +1103,11 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r
 	{
 	{
 		if ($showimage)
 		if ($showimage)
         {
         {
-        	if ($modulepart != 'unknown')
+            if ($modulepart != 'unknown')
             {
             {
                 $phototoshow='';
                 $phototoshow='';
-                
                 // Check if a preview file is available
                 // Check if a preview file is available
-                if (in_array($modulepart, array('propal', 'commande', 'facture', 'ficheinter', 'contract')) && class_exists("Imagick"))
+                if (in_array($modulepart, array('propal', 'commande', 'facture', 'ficheinter', 'contract', 'supplier_order')) && class_exists("Imagick"))
                 {
                 {
                     $objectref = dol_sanitizeFileName($object->ref);
                     $objectref = dol_sanitizeFileName($object->ref);
                     $dir_output = $conf->$modulepart->dir_output . "/";
                     $dir_output = $conf->$modulepart->dir_output . "/";
@@ -1092,7 +1137,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r
                         if (file_exists($fileimage))
                         if (file_exists($fileimage))
                         {
                         {
                             $phototoshow = '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
                             $phototoshow = '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
-                            $phototoshow.= '<img height="70" class="photo photowithmargin" src="'.DOL_URL_ROOT . '/viewimage.php?modulepart=apercu'.$modulepart.'&amp;file='.urlencode($relativepathimage).'">';
+                            $phototoshow.= '<img height="70" class="photo photowithmargin photowithborder" src="'.DOL_URL_ROOT . '/viewimage.php?modulepart=apercu'.$modulepart.'&amp;file='.urlencode($relativepathimage).'">';
                             $phototoshow.= '</div></div>';
                             $phototoshow.= '</div></div>';
                         }
                         }
                         // Si fichier png PDF de plus d'1 page trouve
                         // Si fichier png PDF de plus d'1 page trouve
@@ -1100,7 +1145,7 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r
                         {
                         {
                             $preview = preg_replace('/\.png/','',$relativepathimage) . "-0.png";
                             $preview = preg_replace('/\.png/','',$relativepathimage) . "-0.png";
                             $phototoshow = '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
                             $phototoshow = '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
-                            $phototoshow.= '<img height="70" class="photo photowithmargin" src="'.DOL_URL_ROOT . '/viewimage.php?modulepart=apercu'.$modulepart.'&amp;file='.urlencode($preview).'"><p>';
+                            $phototoshow.= '<img height="70" class="photo photowithmargin photowithborder" src="'.DOL_URL_ROOT . '/viewimage.php?modulepart=apercu'.$modulepart.'&amp;file='.urlencode($preview).'"><p>';
                             $phototoshow.= '</div></div>';
                             $phototoshow.= '</div></div>';
                         }
                         }
                     }
                     }
@@ -1126,7 +1171,6 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r
                     $width=80;
                     $width=80;
                     $cssclass='photorefcenter';
                     $cssclass='photorefcenter';
                     $nophoto=img_picto('', 'title_agenda', '', false, 1);
                     $nophoto=img_picto('', 'title_agenda', '', false, 1);
-                    $morehtmlleft.='<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$modulepart.($cssclass?' '.$cssclass:'').'" alt="No photo" border="0"'.($width?' width="'.$width.'"':'').' src="'.$nophoto.'"></div></div>';
                 }
                 }
                 else
                 else
                 {
                 {
@@ -1134,8 +1178,8 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r
                     $picto = $object->picto;
                     $picto = $object->picto;
                     if ($object->element == 'project' && ! $object->public) $picto = 'project'; // instead of projectpub
                     if ($object->element == 'project' && ! $object->public) $picto = 'project'; // instead of projectpub
     				$nophoto=img_picto('', 'object_'.$picto, '', false, 1);
     				$nophoto=img_picto('', 'object_'.$picto, '', false, 1);
-    				$morehtmlleft.='<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$modulepart.($cssclass?' '.$cssclass:'').'" alt="No photo" border="0"'.($width?' width="'.$width.'"':'').' src="'.$nophoto.'"></div></div>';
                 }
                 }
+                $morehtmlleft.='<!-- No photo to show --><div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$modulepart.($cssclass?' '.$cssclass:'').'" alt="No photo" border="0"'.($width?' width="'.$width.'"':'').' src="'.$nophoto.'"></div></div>';
                 $morehtmlleft.='</div>';
                 $morehtmlleft.='</div>';
             }
             }
         }
         }
@@ -3155,6 +3199,9 @@ function getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $m
 	$tag='th';
 	$tag='th';
 	if ($thead==2) $tag='div';
 	if ($thead==2) $tag='div';
 
 
+	$tmpsortfield=explode(',',$sortfield);
+	$sortfield=trim($tmpsortfield[0]);
+	
 	// If field is used as sort criteria we use a specific class
 	// If field is used as sort criteria we use a specific class
 	// Example if (sortfield,field)=("nom","xxx.nom") or (sortfield,field)=("nom","nom")
 	// Example if (sortfield,field)=("nom","xxx.nom") or (sortfield,field)=("nom","nom")
 	if ($field && ($sortfield == $field || $sortfield == preg_replace("/^[^\.]+\./","",$field))) $out.= '<'.$tag.' class="'.$prefix.'liste_titre_sel" '. $moreattrib.'>';
 	if ($field && ($sortfield == $field || $sortfield == preg_replace("/^[^\.]+\./","",$field))) $out.= '<'.$tag.' class="'.$prefix.'liste_titre_sel" '. $moreattrib.'>';
@@ -3169,13 +3216,13 @@ function getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $m
 
 
 		if ($field != $sortfield)
 		if ($field != $sortfield)
 		{
 		{
-            if ($sortorder == 'DESC') $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
-            if ($sortorder == 'ASC' || ! $sortorder) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
+            if (preg_match('/^DESC/', $sortorder)) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
+            else $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
 		}
 		}
 		else
 		else
 		{
 		{
-            if ($sortorder == 'DESC' || ! $sortorder) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
-            if ($sortorder == 'ASC') $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
+            if (preg_match('/^ASC/', $sortorder)) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
+		    else $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
 		}
 		}
 	}
 	}
 
 
@@ -3204,12 +3251,12 @@ function getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $m
 		}
 		}
 		else
 		else
 		{
 		{
-			if ($sortorder == 'DESC' ) {
+			if (preg_match('/^DESC/', $sortorder)) {
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
 				$sortimg.= '<span class="nowrap">'.img_up("Z-A",0).'</span>';
 				$sortimg.= '<span class="nowrap">'.img_up("Z-A",0).'</span>';
 			}
 			}
-			if ($sortorder == 'ASC' ) {
+			if (preg_match('/^ASC/', $sortorder)) {
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
 				$sortimg.= '<span class="nowrap">'.img_down("A-Z",0).'</span>';
 				$sortimg.= '<span class="nowrap">'.img_down("A-Z",0).'</span>';
@@ -3280,7 +3327,7 @@ function load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png',
 
 
 	$return.= "\n";
 	$return.= "\n";
 	$return.= '<table '.($id?'id="'.$id.'" ':'').'summary="" class="centpercent notopnoleftnoright'.($morecssontable?' '.$morecssontable:'').'" style="margin-bottom: 2px;"><tr>';
 	$return.= '<table '.($id?'id="'.$id.'" ':'').'summary="" class="centpercent notopnoleftnoright'.($morecssontable?' '.$morecssontable:'').'" style="margin-bottom: 2px;"><tr>';
-	if ($picto) $return.= '<td class="nobordernopadding widthpictotitle" valign="middle">'.img_picto('',$picto, 'id="pictotitle"', $pictoisfullpath).'</td>';
+	if ($picto) $return.= '<td class="nobordernopadding widthpictotitle" valign="middle">'.img_picto('',$picto, 'class="valignmiddle" id="pictotitle"', $pictoisfullpath).'</td>';
 	$return.= '<td class="nobordernopadding" valign="middle">';
 	$return.= '<td class="nobordernopadding" valign="middle">';
 	$return.= '<div class="titre">'.$titre.'</div>';
 	$return.= '<div class="titre">'.$titre.'</div>';
 	$return.= '</td>';
 	$return.= '</td>';
@@ -3522,14 +3569,14 @@ function vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0)
 	    $morelabel=' ('.$reg[1].')';
 	    $morelabel=' ('.$reg[1].')';
 	    $rate=preg_replace('/\s*'.preg_quote($morelabel,'/').'/','',$rate);
 	    $rate=preg_replace('/\s*'.preg_quote($morelabel,'/').'/','',$rate);
 	}
 	}
-	if (preg_match('/\*/',$rate) || preg_match('/'.constant('MAIN_LABEL_MENTION_NPR').'/i',$rate))
+	if (preg_match('/\*/',$rate))
 	{
 	{
 		$rate=str_replace('*','',$rate);
 		$rate=str_replace('*','',$rate);
 		$info_bits |= 1;
 		$info_bits |= 1;
 	}
 	}
 
 
 	$ret=price($rate,0,'',0,0).($addpercent?'%':'');
 	$ret=price($rate,0,'',0,0).($addpercent?'%':'');
-	if ($info_bits & 1) $ret.=' '.($usestarfornpr?'*':constant('MAIN_LABEL_MENTION_NPR'));
+	if ($info_bits & 1) $ret.=' *';
 	$ret.=$morelabel;
 	$ret.=$morelabel;
 	return $ret;
 	return $ret;
 }
 }
@@ -4905,7 +4952,8 @@ function make_substitutions($text, $substitutionarray, $outputlangs=null)
 }
 }
 
 
 /**
 /**
- *  Complete the $substitutionarray with more entries
+ *  Complete the $substitutionarray with more entries.
+ *  Can also add substitution keys coming from external module that had set the "substitutions=1" into module_part array. In this case, method completesubstitutionarray provided by module is called. 
  *
  *
  *  @param  array		$substitutionarray		Array substitution old value => new value value
  *  @param  array		$substitutionarray		Array substitution old value => new value value
  *  @param  Translate	$outputlangs            Output language
  *  @param  Translate	$outputlangs            Output language

+ 2 - 1
htdocs/core/lib/functions2.lib.php

@@ -5,6 +5,7 @@
  * Copyright (C) 2014-2016  Marcos García               <marcosgdf@gmail.com>
  * Copyright (C) 2014-2016  Marcos García               <marcosgdf@gmail.com>
  * Copyright (C) 2015       Ferran Marcet               <fmarcet@2byte.es>
  * Copyright (C) 2015       Ferran Marcet               <fmarcet@2byte.es>
  * Copyright (C) 2015-2016  Raphaël Doursenaud          <rdoursenaud@gpcsolutions.fr>
  * Copyright (C) 2015-2016  Raphaël Doursenaud          <rdoursenaud@gpcsolutions.fr>
+ * Copyright (C) 2017       Juanjo Menent               <jmenent@2byte.es>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -1439,7 +1440,7 @@ function dol_print_reduction($reduction,$langs)
     }
     }
     else
     else
     {
     {
-        $string = $reduction.'%';
+        $string = price($reduction).'%';
     }
     }
 
 
     return $string;
     return $string;

+ 28 - 5
htdocs/core/lib/pdf.lib.php

@@ -599,7 +599,14 @@ function pdf_getSubstitutionArray($outputlangs)
 	$substitutionarray=array(
 	$substitutionarray=array(
 		'__MYCOMPANY_NAME__' => $mysoc->name,
 		'__MYCOMPANY_NAME__' => $mysoc->name,
 		'__MYCOMPANY_EMAIL__' => $mysoc->email,
 		'__MYCOMPANY_EMAIL__' => $mysoc->email,
-		'__USER_ID__' => $user->id,
+		'__MYCOMPANY_PROFID1__' => $mysoc->idprof1,
+		'__MYCOMPANY_PROFID2__' => $mysoc->idprof2,
+		'__MYCOMPANY_PROFID3__' => $mysoc->idprof3,
+		'__MYCOMPANY_PROFID4__' => $mysoc->idprof4,
+		'__MYCOMPANY_PROFID5__' => $mysoc->idprof5,
+		'__MYCOMPANY_PROFID6__' => $mysoc->idprof6,
+		'__MYCOMPANY_CAPITAL__' => $mysoc->capital,
+	    '__USER_ID__' => $user->id,
 		'__USER_LOGIN__' => $user->login,
 		'__USER_LOGIN__' => $user->login,
 		'__USER_LASTNAME__' => $user->lastname,
 		'__USER_LASTNAME__' => $user->lastname,
 		'__USER_FIRSTNAME__' => $user->firstname,
 		'__USER_FIRSTNAME__' => $user->firstname,
@@ -1808,8 +1815,17 @@ function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookm
 	}
 	}
 	if (empty($reshook))
 	if (empty($reshook))
 	{
 	{
-        if ($object->lines[$i]->special_code == 3) return '';
-	    if (empty($hidedetails) || $hidedetails > 1) $result.=$object->lines[$i]->situation_percent . '%';
+        	if ($object->lines[$i]->special_code == 3) return '';
+		if (empty($hidedetails) || $hidedetails > 1)
+		{
+			if($conf->global->SITUATION_DISPLAY_DIFF_ON_PDF)
+			{
+			 	$prev_progress = $object->lines[$i]->get_prev_progress($object->id);
+			 	$result = ( $object->lines[$i]->situation_percent - $prev_progress) . '%';
+			}
+			else
+				$result = $object->lines[$i]->situation_percent . '%';
+	  	}
 	}
 	}
 	return $result;
 	return $result;
 }
 }
@@ -1844,7 +1860,7 @@ function pdf_getlinetotalexcltax($object,$i,$outputlangs,$hidedetails=0)
 		if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
 		if(!empty($hookmanager->resPrint)) $result.=$hookmanager->resPrint;
 	}
 	}
     if (empty($reshook))
     if (empty($reshook))
-	{
+    {
 	    if ($object->lines[$i]->special_code == 3)
 	    if ($object->lines[$i]->special_code == 3)
     	{
     	{
     		return $outputlangs->transnoentities("Option");
     		return $outputlangs->transnoentities("Option");
@@ -1852,9 +1868,16 @@ function pdf_getlinetotalexcltax($object,$i,$outputlangs,$hidedetails=0)
         if (empty($hidedetails) || $hidedetails > 1)
         if (empty($hidedetails) || $hidedetails > 1)
         {
         {
         	$total_ht = ($conf->multicurrency->enabled && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
         	$total_ht = ($conf->multicurrency->enabled && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
+        	if ($object->lines[$i]->situation_percent > 0 )
+        	{
+		 	$prev_progress = $object->lines[$i]->get_prev_progress($object->id);
+		 	$progress = ( $object->lines[$i]->situation_percent - $prev_progress) /100;
+		 	$result.=price($sign * ($total_ht/($object->lines[$i]->situation_percent/100)) * $progress, 0, $outputlangs);
+		}
+        	else
 			$result.=price($sign * $total_ht, 0, $outputlangs);
 			$result.=price($sign * $total_ht, 0, $outputlangs);
-        }
 	}
 	}
+    }
 	return $result;
 	return $result;
 }
 }
 
 

+ 14 - 14
htdocs/core/lib/report.lib.php

@@ -24,20 +24,20 @@
 
 
 
 
 /**
 /**
-*	Show header of a VAT report
-*
-*	@param	string				$nom            Name of report
-*	@param 	string				$variante       Link for alternate report
-*	@param 	string				$period         Period of report
-*	@param 	string				$periodlink     Link to switch period
-*	@param 	string				$description    Description
-*	@param 	timestamp|integer	$builddate      Date generation
-*	@param 	string				$exportlink     Link for export or ''
-*	@param	array				$moreparam		Array with list of params to add into form
-*	@param	string				$calcmode		Calculation mode
-*   @param  string              $varlink        Add a variable into the address of the page
-*	@return	void
-*/
+ *	Show header of a VAT report
+ *
+ *	@param	string				$nom            Name of report
+ *	@param 	string				$variante       Link for alternate report
+ *	@param 	string				$period         Period of report
+ *	@param 	string				$periodlink     Link to switch period
+ *	@param 	string				$description    Description
+ *	@param 	timestamp|integer	$builddate      Date generation
+ *	@param 	string				$exportlink     Link for export or ''
+ *	@param	array				$moreparam		Array with list of params to add into form
+ *	@param	string				$calcmode		Calculation mode
+ *   @param  string              $varlink        Add a variable into the address of the page
+ *	@return	void
+ */
 function report_header($nom,$variante,$period,$periodlink,$description,$builddate,$exportlink='',$moreparam=array(),$calcmode='', $varlink='')
 function report_header($nom,$variante,$period,$periodlink,$description,$builddate,$exportlink='',$moreparam=array(),$calcmode='', $varlink='')
 {
 {
 	global $langs;
 	global $langs;

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

@@ -150,9 +150,9 @@ function dol_loginfunction($langs,$conf,$mysoc)
 
 
 	// Title
 	// Title
 	$appli=constant('DOL_APPLICATION_TITLE');
 	$appli=constant('DOL_APPLICATION_TITLE');
-	$title=$appli.' '.DOL_VERSION;
+	$title=$appli.' '.constant('DOL_VERSION');
 	if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $title=$conf->global->MAIN_APPLICATION_TITLE;
 	if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $title=$conf->global->MAIN_APPLICATION_TITLE;
-	$titletruedolibarrversion=DOL_VERSION;	// $title used by login template after the @ to inform of true Dolibarr version
+	$titletruedolibarrversion=constant('DOL_VERSION');	// $title used by login template after the @ to inform of true Dolibarr version
 
 
 	// Note: $conf->css looks like '/theme/eldy/style.css.php'
 	// Note: $conf->css looks like '/theme/eldy/style.css.php'
 	$conf->css = "/theme/".(GETPOST('theme')?GETPOST('theme','alpha'):$conf->theme)."/style.css.php";
 	$conf->css = "/theme/".(GETPOST('theme')?GETPOST('theme','alpha'):$conf->theme)."/style.css.php";

+ 15 - 3
htdocs/core/menus/standard/eldy.lib.php

@@ -545,7 +545,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu
 				$newmenu->add("/admin/ihm.php?mainmenu=home", $langs->trans("GUISetup"),1);
 				$newmenu->add("/admin/ihm.php?mainmenu=home", $langs->trans("GUISetup"),1);
 
 
 				$newmenu->add("/admin/translation.php?mainmenu=home", $langs->trans("Translation"),1);
 				$newmenu->add("/admin/translation.php?mainmenu=home", $langs->trans("Translation"),1);
-				$newmenu->add("/admin/defaultvalues.php?mainmenu=home", $langs->trans("DefaultValues"),1, $conf->global->MAIN_FEATURES_LEVEL);
+				$newmenu->add("/admin/defaultvalues.php?mainmenu=home", $langs->trans("DefaultValues"),1);
 				$newmenu->add("/admin/boxes.php?mainmenu=home", $langs->trans("Boxes"),1);
 				$newmenu->add("/admin/boxes.php?mainmenu=home", $langs->trans("Boxes"),1);
 				$newmenu->add("/admin/delais.php?mainmenu=home",$langs->trans("MenuWarnings"),1);
 				$newmenu->add("/admin/delais.php?mainmenu=home",$langs->trans("MenuWarnings"),1);
 				$newmenu->add("/admin/security_other.php?mainmenu=home", $langs->trans("Security"),1);
 				$newmenu->add("/admin/security_other.php?mainmenu=home", $langs->trans("Security"),1);
@@ -800,9 +800,9 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu
 			if (! empty($conf->facture->enabled))
 			if (! empty($conf->facture->enabled))
 			{
 			{
 				$langs->load("bills");
 				$langs->load("bills");
-				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("BillsCustomers"),0,$user->rights->facture->lire);
+				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("BillsCustomers"),0,$user->rights->facture->lire, '', $mainmenu, 'customers_bills');
 				$newmenu->add("/compta/facture/card.php?action=create",$langs->trans("NewBill"),1,$user->rights->facture->creer);
 				$newmenu->add("/compta/facture/card.php?action=create",$langs->trans("NewBill"),1,$user->rights->facture->creer);
-				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("List"),1,$user->rights->facture->lire);
+				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("List"),1,$user->rights->facture->lire, '', $mainmenu, 'customers_bills');
 
 
 				if ($usemenuhider || empty($leftmenu) || preg_match('/customers_bills/', $leftmenu))
 				if ($usemenuhider || empty($leftmenu) || preg_match('/customers_bills/', $leftmenu))
 				{
 				{
@@ -1252,6 +1252,18 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu
                 if ($conf->supplier_order->enabled) $newmenu->add("/product/stock/replenish.php", $langs->trans("Replenishment"), 1, $user->rights->stock->mouvement->creer && $user->rights->fournisseur->lire);
                 if ($conf->supplier_order->enabled) $newmenu->add("/product/stock/replenish.php", $langs->trans("Replenishment"), 1, $user->rights->stock->mouvement->creer && $user->rights->fournisseur->lire);
 			}
 			}
 
 
+			// Inventory
+			if ($conf->global->MAIN_LEVEL_FEATURES >= 2)
+			{
+    			if (! empty($conf->stock->enabled))
+    			{
+    				$langs->load("stocks");
+    				$newmenu->add("/product/inventory/list.php?leftmenu=stock", $langs->trans("Inventory"), 0, $user->rights->stock->lire, '', $mainmenu, 'stock');
+    				$newmenu->add("/product/inventory/card.php?action=create", $langs->trans("NewInventory"), 1, $user->rights->stock->creer);
+    				$newmenu->add("/product/inventory/list.php", $langs->trans("List"), 1, $user->rights->stock->lire);
+    			}
+			}
+			
 			// Expeditions
 			// Expeditions
 			if (! empty($conf->expedition->enabled))
 			if (! empty($conf->expedition->enabled))
 			{
 			{

部分文件因为文件数量过多而无法显示