Browse Source

Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop

Conflicts:
htdocs/contrat/index.php

Laurent Destailleur 3 years ago
parent
commit
a483af70df
100 changed files with 2414 additions and 1277 deletions
  1. 1 1
      COPYRIGHT
  2. 4 2
      ChangeLog
  3. 12 13
      README.md
  4. 3 2
      SECURITY.md
  5. 4 59
      build/exe/doliwamp/doliwamp.iss
  6. 1 3
      build/makepack-dolibarr.pl
  7. 1 1
      dev/tools/test/namespacemig/main.inc.php
  8. 2 2
      htdocs/accountancy/admin/card.php
  9. 30 1
      htdocs/accountancy/admin/defaultaccounts.php
  10. 8 7
      htdocs/accountancy/admin/productaccount.php
  11. 2 2
      htdocs/accountancy/bookkeeping/card.php
  12. 1 1
      htdocs/accountancy/bookkeeping/list.php
  13. 1 1
      htdocs/accountancy/bookkeeping/listbyaccount.php
  14. 5 5
      htdocs/accountancy/class/accountingaccount.class.php
  15. 73 48
      htdocs/accountancy/class/bookkeeping.class.php
  16. 8 8
      htdocs/accountancy/class/lettering.class.php
  17. 23 2
      htdocs/accountancy/customer/list.php
  18. 11 11
      htdocs/accountancy/journal/bankjournal.php
  19. 12 7
      htdocs/accountancy/journal/sellsjournal.php
  20. 27 6
      htdocs/accountancy/supplier/list.php
  21. 1 1
      htdocs/adherents/admin/member.php
  22. 3 2
      htdocs/adherents/admin/website.php
  23. 1 1
      htdocs/adherents/agenda.php
  24. 1 1
      htdocs/adherents/card.php
  25. 5 5
      htdocs/adherents/class/subscription.class.php
  26. 10 10
      htdocs/adherents/index.php
  27. 1 1
      htdocs/adherents/list.php
  28. 12 5
      htdocs/adherents/partnership.php
  29. 1 1
      htdocs/adherents/subscription/list.php
  30. 3 0
      htdocs/admin/agenda.php
  31. 1 1
      htdocs/admin/defaultvalues.php
  32. 233 246
      htdocs/admin/dict.php
  33. 3 0
      htdocs/admin/dolistore/class/PSWebServiceLibrary.class.php
  34. 12 6
      htdocs/admin/emailcollector_card.php
  35. 232 141
      htdocs/admin/emailcollector_list.php
  36. 2 2
      htdocs/admin/eventorganization.php
  37. 2 2
      htdocs/admin/expensereport_rules.php
  38. 11 11
      htdocs/admin/holiday.php
  39. 2 2
      htdocs/admin/hrm.php
  40. 127 124
      htdocs/admin/ihm.php
  41. 2 2
      htdocs/admin/knowledgemanagement.php
  42. 1 1
      htdocs/admin/mails_senderprofile_list.php
  43. 258 193
      htdocs/admin/mails_templates.php
  44. 7 3
      htdocs/admin/modulehelp.php
  45. 4 4
      htdocs/admin/system/filecheck.php
  46. 16 0
      htdocs/admin/system/phpinfo.php
  47. 0 17
      htdocs/admin/system/xcache.php
  48. 70 106
      htdocs/admin/ticket.php
  49. 86 19
      htdocs/admin/ticket_public.php
  50. 9 2
      htdocs/admin/tools/update.php
  51. 4 4
      htdocs/admin/translation.php
  52. 2 2
      htdocs/admin/workstation.php
  53. 3 4
      htdocs/api/class/api_documents.class.php
  54. 2 2
      htdocs/asset/admin/setup.php
  55. 1 1
      htdocs/barcode/codeinit.php
  56. 1 1
      htdocs/blockedlog/admin/blockedlog_list.php
  57. 5 5
      htdocs/blockedlog/ajax/block-info.php
  58. 2 1
      htdocs/categories/index.php
  59. 2 2
      htdocs/categories/viewcat.php
  60. 1 1
      htdocs/comm/action/class/actioncomm.class.php
  61. 2 1
      htdocs/comm/action/index.php
  62. 1 1
      htdocs/comm/action/list.php
  63. 3 1
      htdocs/comm/action/pertype.php
  64. 3 1
      htdocs/comm/action/peruser.php
  65. 3 3
      htdocs/comm/card.php
  66. 1 1
      htdocs/comm/mailing/list.php
  67. 183 6
      htdocs/comm/propal/card.php
  68. 3 1
      htdocs/comm/propal/class/api_proposals.class.php
  69. 11 2
      htdocs/comm/propal/class/propal.class.php
  70. 16 5
      htdocs/comm/propal/list.php
  71. 182 19
      htdocs/commande/card.php
  72. 2 1
      htdocs/commande/class/api_orders.class.php
  73. 16 3
      htdocs/commande/class/commande.class.php
  74. 8 8
      htdocs/commande/list.php
  75. 1 1
      htdocs/compta/bank/bankentries_list.php
  76. 21 12
      htdocs/compta/bank/line.php
  77. 34 14
      htdocs/compta/bank/various_payment/list.php
  78. 1 1
      htdocs/compta/cashcontrol/cashcontrol_list.php
  79. 14 1
      htdocs/compta/facture/card-rec.php
  80. 14 3
      htdocs/compta/facture/card.php
  81. 2 1
      htdocs/compta/facture/class/api_invoices.class.php
  82. 100 8
      htdocs/compta/facture/class/facture-rec.class.php
  83. 298 4
      htdocs/compta/facture/class/facture.class.php
  84. 16 5
      htdocs/compta/facture/list.php
  85. 10 10
      htdocs/compta/facture/prelevement.php
  86. 1 1
      htdocs/compta/facture/stats/index.php
  87. 1 1
      htdocs/compta/paiement/list.php
  88. 1 1
      htdocs/compta/paiement_charge.php
  89. 1 1
      htdocs/compta/paiement_vat.php
  90. 2 2
      htdocs/compta/prelevement/class/bonprelevement.class.php
  91. 2 1
      htdocs/compta/prelevement/stats.php
  92. 23 4
      htdocs/compta/sociales/list.php
  93. 1 1
      htdocs/compta/sociales/payments.php
  94. 26 10
      htdocs/compta/tva/list.php
  95. 1 1
      htdocs/contact/card.php
  96. 1 1
      htdocs/contact/consumption.php
  97. 18 6
      htdocs/contact/list.php
  98. 1 11
      htdocs/contrat/class/contrat.class.php
  99. 15 8
      htdocs/contrat/index.php
  100. 7 1
      htdocs/contrat/list.php

+ 1 - 1
COPYRIGHT

@@ -24,7 +24,6 @@ Component              Version       License                     GPL Compatible
 -------------------------------------------------------------------------------------
 PHP libraries:
 ADOdb-Date             0.36          Modified BSD License        Yes             Date convertion (not into rpm package)
-CKEditor               4.12.1        LGPL-2.1+                   Yes             Editor WYSIWYG
 EvalMath               1.0           BSD                         Yes             Safe math expressions evaluation
 Escpos-php             2.2           MIT License                 Yes             Thermal receipt printer library, for use with ESC/POS compatible printers
 GeoIP2                 0.2.0         Apache License 2.0          Yes             Lib to make geoip convert
@@ -50,6 +49,7 @@ TCPDI                  1.0.0         LGPL-3+ / Apache 2.0        Yes
 JS libraries:
 Ace                    1.4.14        BSD                         Yes             JS library to get code syntaxique coloration in a textarea.
 ChartJS                3.7.1         MIT License                 Yes             JS library for graph
+CKEditor               4.18          LGPL-2.1+                   Yes             Editor WYSIWYG
 jQuery                 3.6.0         MIT License                 Yes             JS library
 jQuery UI              1.13.1        GPL and MIT License         Yes             JS library plugin UI
 jQuery select2         4.0.13        GPL and Apache License      Yes             JS library plugin for sexier multiselect. Warning: 4.0.6+ create troubles without patching css

+ 4 - 2
ChangeLog

@@ -9,7 +9,7 @@ English Dolibarr ChangeLog
 For users:
 ---------------
 
-NEW: PHP 8.0 compatibility
+NEW: PHP 8.1 compatibility
 
 
 
@@ -27,6 +27,8 @@ NEW: A lot of addition of hooks.
 
 
 Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
+* There is a new specific permission to be allowed to enter timesheets. If you use timesheet, don't forget to give the new permission (disable and 
+  enable the module project if it is not visible).
 * The default value for MAIN_SECURITY_CSRF_WITH_TOKEN has been set to 2. It means any POST and any GET request that contains the "action" or "massaction"
   with a value of a sensitive action must also a valid token parameter (With previous value 1, only POST was concerned). Note: With value 3, any URL
   with parameter "action" or "massaction" need the token, whatever is the value of the action.
@@ -37,7 +39,7 @@ Following changes may create regressions for some external modules, but were nec
 * Move massaction 'confirm_createbills' from actions_massactions.inc.php to commande/list.php
 * Method fetch_all_resources(), fetch_all_used(), fetch_all_available() of DolResource has been removed (they were not used by core code).
 * Method fetch_all of DolResource has been renamed into fetchAll() to match naming conventions.
-
+* The hook 'upgrade' and 'doUpgrade2" has been renamed 'doUpgradeBefore' and 'doUpgradeAfterDB'. A new trigger 'doUpgradeAfterFiles' has been introduced.
 
 ***** ChangeLog for 15.0.1 compared to 15.0.0 *****
 FIX: #19777 #20281

+ 12 - 13
README.md

@@ -111,7 +111,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
 
 - Customers/Prospects + Contacts management
 - Opportunities or Leads management
-- Commercial proposals management
+- Commercial proposals management (online signing)
 - Customer Orders management
 - Contracts/Subscription management
 - Interventions management
@@ -129,11 +129,11 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
 - Supplier Invoices/credit notes and payment management
 - INCOTERMS
 
- Finance / Accounting
+ Finance/Accounting
 
-- Invoices / Payments
+- Invoices/Payments
 - Bank accounts management
-- Direct debit orders management (European SEPA)
+- Direct debit and Credit transfer management (European SEPA)
 - Accounting management
 - Donations management
 - Loan management
@@ -142,14 +142,14 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
 
  Collaboration
 
-- Shared calendar/agenda (with ical and vcal export for third party tools integration)
+- Shared calendar/agenda (with ical and vcal import/export for third party tools integration)
 - Projects & Tasks management
 - Ticket System
 - Surveys
 
  HR
 
-- Employee's leave requests management
+- Employee's leaves management
 - Expense reports
 - Recruitment management
 - Timesheets
@@ -157,16 +157,14 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
 ### Other application/modules
 
 - Electronic Document Management (EDM)
-- Bookmarks management
+- Bookmarks
 - Reporting
 - Data export/import
 - Barcodes
-- Margin calculations
 - LDAP connectivity
 - ClickToDial integration
 - Mass emailing
 - RSS integration
-- Skype integration
 - Social platforms linking
 - Payment platforms integration (PayPal, Stripe, Paybox...)
 - Email-Collector
@@ -175,13 +173,12 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
 
 ### Other general features
 
-- Localization in most major languages
-- Multi-Language Support
+- Multi-Language Support (Localization in most major languages)
 - Multi-Users and groups with finely grained rights
 - Multi-Currency
 - Multi-Company (by adding of an external module)
 - Very user friendly and easy to use
-- customizable Dashboard
+- Customizable dashboards
 - Highly customizable: enable only the modules you need, add user personalized fields, choose your skin, several menu managers (can be used by internal users as a back-office with a particular menu, or by external users as a front-office with another one)
 - APIs (REST, SOAP)
 - Code that is easy to understand, maintain and develop (PHP with no heavy framework; trigger and hook architecture)
@@ -191,8 +188,9 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
   - Canadian double taxes (federal/province) and other countries using cumulative VAT
   - Tunisian tax stamp
   - Argentina invoice numbering using A,B,C...
+  - ZATCA e-invoicing QR-Code
   - Compatible with [European directives](https://europa.eu/legislation_summaries/taxation/l31057_en.htm) (2006/112/CE ... 2010/45/UE)
-  - Compatible with European GDPR rules
+  - Compatible with data privacy rules (europe GDPR, ...)
   - ...
 - Flexible PDF & ODT generation for invoices, proposals, orders...
 - ...
@@ -244,6 +242,7 @@ Follow Dolibarr project on:
 - [Facebook](https://www.facebook.com/dolibarr)
 - [Twitter](https://www.twitter.com/dolibarr)
 - [LinkedIn](https://www.linkedin.com/company/association-dolibarr)
+- [Reddit](https://www.reddit.com/r/Dolibarr_ERP_CRM/)
 - [YouTube](https://www.youtube.com/user/DolibarrERPCRM)
 - [GitHub](https://github.com/Dolibarr/dolibarr)
 

+ 3 - 2
SECURITY.md

@@ -6,8 +6,9 @@ This file contains some policies about the security reports on Dolibarr ERP CRM
 
 | Version    | Supported              |
 | ---------- | ---------------------- |
-| <= 14.0.4  | :x:                    |
-| >= 14.0.5+ | :white_check_mark: except CSRF attacks|
+| <= 15.0.0  | :x:                    |
+| >= 15.0.1+ | :white_check_mark: except CSRF attacks|
+| >= 16.0.0  | :white_check_mark:     |
 | >= develop | :white_check_mark:     |
 
 ## Reporting a Vulnerability

+ 4 - 59
build/exe/doliwamp/doliwamp.iss

@@ -27,12 +27,12 @@ OutputBaseFilename=__FILENAMEEXEDOLIWAMP__
 ;SourceDir=Z:\home\ldestailleur\git\dolibarrxxx
 SourceDir=..\..\..
 AppId=doliwamp
-AppPublisher=NLTechno
-AppPublisherURL=https://www.nltechno.com
+AppPublisher=DoliCloud
+AppPublisherURL=https://www.dolicloud.com
 AppSupportURL=https://www.dolibarr.org
 AppUpdatesURL=https://www.dolibarr.org
 AppComments=DoliWamp includes Dolibarr, Apache, PHP and Mysql software.
-AppCopyright=Copyright (C) 2008-2020 Laurent Destailleur (NLTechno), Fabian Rodriguez (Le Goût du Libre)
+AppCopyright=Copyright (C) 2008-2022 Laurent Destailleur (NLTechno), Fabian Rodriguez (Le Goût du Libre)
 DefaultDirName=c:\dolibarr
 DefaultGroupName=Dolibarr
 ;LicenseFile=COPYING
@@ -99,13 +99,12 @@ Source: "build\exe\doliwamp\startdoliwamp_manual_donotuse.bat.install"; DestDir:
 Source: "build\exe\doliwamp\builddemosslfiles.bat.install"; DestDir: "{app}\"; Flags: ignoreversion;
 Source: "build\exe\doliwamp\UsedPort.exe"; DestDir: "{app}\"; Flags: ignoreversion;
 
-; PhpMyAdmin, Apache, Php, Mysql
+; Apache, Php, Mysql
 ; Put here path of Wampserver applications
 ; Value OK: apache 2.2.6,  php 5.2.5 (5.2.11, 5.3.0 and 5.3.1 fails if php_exif, php_pgsql, php_zip is on), mysql 5.0.45
 ; Value OK: apache 2.2.11, php 5.3.0 (if no php_exif, php_pgsql, php_zip), mysql 5.0.45
 ; Value OK: apache 2.4.9,  php 5.5.12, mysql 5.0.45 instead of 5.6.17 (wampserver2.5-Apache-2.4.9-Mysql-5.6.17-php5.5.12-32b.exe)
 ; Value OK: apache 2.4.41, php 7.3.12, mariadb10.4.10 (wampserver3.2.0_x64.exe)
-Source: "C:\wamp64\apps\phpmyadmin4.9.2\*.*"; DestDir: "{app}\apps\phpmyadmin4.9.2"; Flags: ignoreversion recursesubdirs; Excludes: "config.inc.php,wampserver.conf,*.log,*_log,darkblue_orange"
 ;Source: "C:\Program Files\Wamp\bin\apache\apache2.4.9\*.*"; DestDir: "{app}\bin\apache\apache2.4.9"; Flags: ignoreversion recursesubdirs; Excludes: "php.ini,httpd.conf,wampserver.conf,*.log,*_log"
 Source: "C:\wamp64\bin\apache\apache2.4.41\*.*"; DestDir: "{app}\bin\apache\apache2.4.41"; Flags: ignoreversion recursesubdirs; Excludes: "php.ini,httpd.conf,wampserver.conf,*.log,*_log"
 ;Source: "C:\Program Files\Wamp\bin\php\php5.5.12\*.*"; DestDir: "{app}\bin\php\php5.5.12"; Flags: ignoreversion recursesubdirs; Excludes: "php.ini,phpForApache.ini,wampserver.conf,*.log,*_log"
@@ -125,9 +124,7 @@ Source: "scripts\*.*"; DestDir: "{app}\www\dolibarr\scripts"; Flags: ignoreversi
 Source: "*.*"; DestDir: "{app}\www\dolibarr"; Flags: ignoreversion; Excludes: ".gitignore,.project,CVS\*,Thumbs.db,default.properties,install.lock"
 
 ; Config files
-Source: "build\exe\doliwamp\phpmyadmin.conf.install"; DestDir: "{app}\alias"; Flags: ignoreversion;
 Source: "build\exe\doliwamp\dolibarr.conf.install"; DestDir: "{app}\alias"; Flags: ignoreversion;
-Source: "build\exe\doliwamp\config.inc.php.install"; DestDir: "{app}\apps\phpmyadmin4.1.14"; Flags: ignoreversion;
 ;Source: "build\exe\doliwamp\httpd.conf.install"; DestDir: "{app}\bin\apache\apache2.4.9\conf"; Flags: ignoreversion;
 Source: "build\exe\doliwamp\httpd.conf.install"; DestDir: "{app}\bin\apache\apache2.4.41\conf"; Flags: ignoreversion;
 Source: "build\exe\doliwamp\my.ini.install"; DestDir: "{app}\bin\mysql\mysql5.0.45"; Flags: ignoreversion;
@@ -196,7 +193,6 @@ var destFileA: String;
 var srcContents: String;
 var browser: String;
 var mysqlVersion: String;
-var phpmyadminVersion: String;
 var phpDllCopy: String;
 var batFile: String;
 
@@ -246,7 +242,6 @@ begin
   phpVersion := '7.3.12' ;
   //mysqlVersion := '5.0.45';
   mysqlVersion := '10.4.10';
-  phpmyadminVersion := '4.1.14';
 
   smtpServer := 'localhost';
   apachePort := '80';
@@ -635,27 +630,6 @@ begin
       begin
 
 		
-		    //----------------------------------------------
-		    // Create file alias phpmyadmin (always)
-		    //----------------------------------------------
-		
-		    destFile := pathWithSlashes+'/alias/phpmyadmin.conf';
-		    srcFile := pathWithSlashes+'/alias/phpmyadmin.conf.install';
-		
-		    if FileExists(srcFile) then
-		    begin
-		      LoadStringFromFile (srcFile, srcContents);
-		
-		      //installDir et version de phpmyadmin
-		      StringChangeEx (srcContents, 'WAMPROOT', pathWithSlashes, True);
-		      StringChangeEx (srcContents, 'WAMPPHPMYADMINVERSION', phpmyadminVersion, True);
-		
-		      SaveStringToFile(destFile,srcContents, False);
-		    end;
-		    DeleteFile(srcFile);
-		
-		
-		
 		    //----------------------------------------------
 		    // Create file alias dolibarr (if not exists)
 		    //----------------------------------------------
@@ -691,35 +665,6 @@ begin
 		
 		
 		
-		    //----------------------------------------------
-		    // Create file configuration for phpmyadmin (if not exists)
-		    //----------------------------------------------
-		
-		    destFile := pathWithSlashes+'/apps/phpmyadmin'+phpmyadminVersion+'/config.inc.php';
-		    srcFile := pathWithSlashes+'/apps/phpmyadmin'+phpmyadminVersion+'/config.inc.php.install';
-		
-		    if FileExists(srcFile) then
-		    begin
-	  	      if not FileExists (destFile) then
-		      begin
-	            LoadStringFromFile (srcFile, srcContents);
-	            StringChangeEx (srcContents, 'WAMPMYSQLNEWPASSWORD', mypass, True);
-	            StringChangeEx (srcContents, 'WAMPMYSQLPORT', myport, True);
-	            SaveStringToFile(destFile,srcContents, False);
-		      end
-		      else
-		      begin
-		        // We must replace to use format 2.4 of apache
-	            DeleteFile(destFile);
-	            LoadStringFromFile (srcFile, srcContents);
-	            StringChangeEx (srcContents, 'WAMPMYSQLNEWPASSWORD', mypass, True);
-	            StringChangeEx (srcContents, 'WAMPMYSQLPORT', myport, True);
-	            SaveStringToFile(destFile,srcContents, False);
-		      end;
-		    end;
-		
-		
-		
 		    //----------------------------------------------
 		    // Create file httpd.conf (if not exists)
 		    //----------------------------------------------

+ 1 - 3
build/makepack-dolibarr.pl

@@ -582,9 +582,7 @@ if ($nboftargetok) {
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/teclib*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/timesheet*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/webmail*`;
-		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/oblyon*`;
-		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/allscreen*`;
-		$ret=`rm -f  $BUILDROOT/$PROJECT/htdocs/theme/common/octicons/LICENSE`;
+		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/theme/common/fontawesome-5/svgs`;
 		
 		# Removed other test files
 	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/public/test`;

+ 1 - 1
dev/tools/test/namespacemig/main.inc.php

@@ -1,7 +1,7 @@
 <?php
 
 /*spl_autoload_register(function ($class_name) {
-	var_dump('class='.$class_name);
+	//var_dump('class='.$class_name);
 	require $class_name;
 });
 */

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

@@ -300,7 +300,7 @@ if ($action == 'create') {
 
 		// Edit mode
 		if ($action == 'update') {
-			print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'billr');
+			print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'accounting_account');
 
 			print '<form name="update" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
 			print '<input type="hidden" name="token" value="'.newToken().'">';
@@ -368,7 +368,7 @@ if ($action == 'create') {
 			// View mode
 			$linkback = '<a href="'.DOL_URL_ROOT.'/accountancy/admin/account.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
 
-			print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), -1, 'billr');
+			print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), -1, 'accounting_account');
 
 			dol_banner_tab($object, 'ref', $linkback, 1, 'account_number', 'ref');
 

+ 30 - 1
htdocs/accountancy/admin/defaultaccounts.php

@@ -95,10 +95,11 @@ if ($conf->loan->enabled) {
 	$list_account[] = 'LOAN_ACCOUNTING_ACCOUNT_INTEREST';
 	$list_account[] = 'LOAN_ACCOUNTING_ACCOUNT_INSURANCE';
 }
+$list_account[] = 'ACCOUNTING_ACCOUNT_SUSPENSE';
 if ($conf->societe->enabled) {
+	$list_account[] = '---Deposits---';
 	$list_account[] = 'ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT';
 }
-$list_account[] = 'ACCOUNTING_ACCOUNT_SUSPENSE';
 
 /*
  * Actions
@@ -134,6 +135,20 @@ if ($action == 'update') {
 	}
 }
 
+if ($action == 'setdisableauxiliaryaccountoncustomerdeposit') {
+	$setDisableAuxiliaryAccountOnCustomerDeposit = GETPOST('value', 'int');
+	$res = dolibarr_set_const($db, "ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT", $setDisableAuxiliaryAccountOnCustomerDeposit, 'yesno', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+	}
+
+	if (!$error) {
+		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+	} else {
+		setEventMessages($langs->trans("Error"), null, 'mesgs');
+	}
+}
+
 
 /*
  * View
@@ -231,6 +246,20 @@ foreach ($list_account as $key) {
 	}
 }
 
+if ($conf->societe->enabled) {
+	print '<tr class="oddeven">';
+	print '<td>' . img_picto('', 'bill', 'class="pictofixedwidth"') . $langs->trans("UseAuxiliaryAccountOnCustomerDeposit") . '</td>';
+	if (!empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT)) {
+		print '<td class="right"><a class="reposition" href="' . $_SERVER['PHP_SELF'] . '?token=' . newToken() . '&action=setdisableauxiliaryaccountoncustomerdeposit&value=0">';
+		print img_picto($langs->trans("Activated"), 'switch_on', '', false, 0, 0, '', 'warning');
+		print '</a></td>';
+	} else {
+		print '<td class="right"><a class="reposition" href="' . $_SERVER['PHP_SELF'] . '?token=' . newToken() . '&action=setdisableauxiliaryaccountoncustomerdeposit&value=1">';
+		print img_picto($langs->trans("Disabled"), 'switch_off');
+		print '</a></td>';
+	}
+	print '</tr>';
+}
 
 print "</table>\n";
 print "</div>\n";

+ 8 - 7
htdocs/accountancy/admin/productaccount.php

@@ -384,6 +384,7 @@ if ($search_onpurchase != '' && $search_onpurchase != '-1') {
 $sql .= " GROUP BY p.rowid, p.ref, p.label, p.description, p.tosell, p.tobuy, p.tva_tx,";
 $sql .= " p.fk_product_type,";
 $sql .= ' p.tms,';
+$sql .= ' aa.rowid,';
 if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
 	$sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export";
 } else {
@@ -394,8 +395,8 @@ $sql .= $db->order($sortfield, $sortorder);
 
 $nbtotalofrecords = '';
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
-	$result = $db->query($sql);
-	$nbtotalofrecords = $db->num_rows($result);
+	$resql = $db->query($sql);
+	$nbtotalofrecords = $db->num_rows($resql);
 	if (($page * $limit) > $nbtotalofrecords) {	// if total resultset is smaller then paging size (filtering), goto and load page 0
 		$page = 0;
 		$offset = 0;
@@ -405,9 +406,9 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
 $sql .= $db->plimit($limit + 1, $offset);
 
 dol_syslog("/accountancy/admin/productaccount.php", LOG_DEBUG);
-$result = $db->query($sql);
-if ($result) {
-	$num = $db->num_rows($result);
+$resql = $db->query($sql);
+if ($resql) {
+	$num = $db->num_rows($resql);
 	$i = 0;
 
 	$param = '';
@@ -607,7 +608,7 @@ if ($result) {
 
 	$i = 0;
 	while ($i < min($num, $limit)) {
-		$obj = $db->fetch_object($result);
+		$obj = $db->fetch_object($resql);
 
 		// Ref produit as link
 		$product_static->ref = $obj->ref;
@@ -890,7 +891,7 @@ if ($result) {
 
 	print '</form>';
 
-	$db->free($result);
+	$db->free($resql);
 } else {
 	dol_print_error($db);
 }

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

@@ -431,12 +431,12 @@ if ($action == 'create') {
 		// Account movement
 		print '<tr>';
 		print '<td class="titlefield">'.$langs->trans("NumMvts").'</td>';
-		print '<td>'.$object->piece_num.'</td>';
+		print '<td>'.($mode == '_tmp' ? '<span class="opacitymedium" title="Id tmp '.$object->piece_num.'">'.$langs->trans("Draft").'</span>' : $object->piece_num).'</td>';
 		print '</tr>';
 
 		// Date
 		print '<tr><td>';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
+		print '<table class="nobordernopadding centpercent"><tr><td>';
 		print $langs->trans('Docdate');
 		print '</td>';
 		if ($action != 'editdate') {

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

@@ -304,7 +304,7 @@ if (empty($reshook)) {
 		$search_lettering_code = '';
 		$search_not_reconciled = '';
 		$search_import_key = '';
-		$toselect = '';
+		$toselect = array();
 	}
 
 	// Must be after the remove filter action, before the export.

+ 1 - 1
htdocs/accountancy/bookkeeping/listbyaccount.php

@@ -259,7 +259,7 @@ if (empty($reshook)) {
 		$search_lettering_code = '';
 		$search_not_reconciled = '';
 		$search_import_key = '';
-		$toselect = '';
+		$toselect = array();
 	}
 
 	// Must be after the remove filter action, before the export.

+ 5 - 5
htdocs/accountancy/class/accountingaccount.class.php

@@ -586,11 +586,11 @@ class AccountingAccount extends CommonObject
 		$sql .= ' WHERE a.rowid = ' . ((int) $id);
 
 		dol_syslog(get_class($this) . '::info sql=' . $sql);
-		$result = $this->db->query($sql);
+		$resql = $this->db->query($sql);
 
-		if ($result) {
-			if ($this->db->num_rows($result)) {
-				$obj = $this->db->fetch_object($result);
+		if ($resql) {
+			if ($this->db->num_rows($resql)) {
+				$obj = $this->db->fetch_object($resql);
 				$this->id = $obj->rowid;
 				if ($obj->fk_user_author) {
 					$cuser = new User($this->db);
@@ -605,7 +605,7 @@ class AccountingAccount extends CommonObject
 				$this->date_creation = $this->db->jdate($obj->datec);
 				$this->date_modification = $this->db->jdate($obj->tms);
 			}
-			$this->db->free($result);
+			$this->db->free($resql);
 		} else {
 			dol_print_error($this->db);
 		}

+ 73 - 48
htdocs/accountancy/class/bookkeeping.class.php

@@ -1843,8 +1843,8 @@ class BookKeeping extends CommonObject
 	/**
 	 * Transform transaction
 	 *
-	 * @param  number   $direction      If 0 tmp => real, if 1 real => tmp
-	 * @param  string   $piece_num      Piece num
+	 * @param  number   $direction      If 0: tmp => real, if 1: real => tmp
+	 * @param  string   $piece_num      Piece num = Transaction ref
 	 * @return int                      int <0 if KO, >0 if OK
 	 */
 	public function transformTransaction($direction = 0, $piece_num = '')
@@ -1862,57 +1862,82 @@ class BookKeeping extends CommonObject
 			if ($next_piecenum < 0) {
 				$error++;
 			}
-			$sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,';
-			$sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
-			$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
-			$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)';
-			$sql .= ' SELECT doc_date, doc_type,';
-			$sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
-			$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
-			$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'";
-			$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
-			$resql = $this->db->query($sql);
-			if (!$resql) {
-				$error++;
-				$this->errors[] = 'Error '.$this->db->lasterror();
-				dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+
+			if (!$error) {
+				// Delete if there is an empty line
+				$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity)." AND numero_compte IS NULL AND debit = 0 AND credit = 0";
+				$resql = $this->db->query($sql);
+				if (!$resql) {
+					$error++;
+					$this->errors[] = 'Error '.$this->db->lasterror();
+					dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+				}
 			}
-			$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
-			$resql = $this->db->query($sql);
-			if (!$resql) {
-				$error++;
-				$this->errors[] = 'Error '.$this->db->lasterror();
-				dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+
+			if (!$error) {
+				$sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,';
+				$sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
+				$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
+				$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)';
+				$sql .= ' SELECT doc_date, doc_type,';
+				$sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
+				$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
+				$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'";
+				$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
+				$resql = $this->db->query($sql);
+				if (!$resql) {
+					$error++;
+					$this->errors[] = 'Error '.$this->db->lasterror();
+					dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+				}
+			}
+
+			if (!$error) {
+				$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
+				$resql = $this->db->query($sql);
+				if (!$resql) {
+					$error++;
+					$this->errors[] = 'Error '.$this->db->lasterror();
+					dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+				}
 			}
 		} elseif ($direction == 1) {
-			$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
-			$resql = $this->db->query($sql);
-			if (!$resql) {
-				$error++;
-				$this->errors[] = 'Error '.$this->db->lasterror();
-				dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+			if (!$error) {
+				$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
+				$resql = $this->db->query($sql);
+				if (!$resql) {
+					$error++;
+					$this->errors[] = 'Error '.$this->db->lasterror();
+					dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+				}
 			}
-			$sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'_tmp (doc_date, doc_type,';
-			$sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
-			$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
-			$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)';
-			$sql .= ' SELECT doc_date, doc_type,';
-			$sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
-			$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
-			$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num';
-			$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
-			$resql = $this->db->query($sql);
-			if (!$resql) {
-				$error++;
-				$this->errors[] = 'Error '.$this->db->lasterror();
-				dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+
+			if (!$error) {
+				$sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'_tmp (doc_date, doc_type,';
+				$sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
+				$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
+				$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)';
+				$sql .= ' SELECT doc_date, doc_type,';
+				$sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
+				$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
+				$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num';
+				$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
+				$resql = $this->db->query($sql);
+				if (!$resql) {
+					$error++;
+					$this->errors[] = 'Error '.$this->db->lasterror();
+					dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+				}
 			}
-			$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
-			$resql = $this->db->query($sql);
-			if (!$resql) {
-				$error++;
-				$this->errors[] = 'Error '.$this->db->lasterror();
-				dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+
+			if (!$error) {
+				$sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
+				$resql = $this->db->query($sql);
+				if (!$resql) {
+					$error++;
+					$this->errors[] = 'Error '.$this->db->lasterror();
+					dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
+				}
 			}
 		}
 		if (!$error) {

+ 8 - 8
htdocs/accountancy/class/lettering.class.php

@@ -266,14 +266,14 @@ class Lettering extends BookKeeping
 		$sql .= " ORDER BY ab2.lettering_code DESC";
 		$sql .= " LIMIT 1 ";
 
-		$result = $this->db->query($sql);
-		if ($result) {
-			$obj = $this->db->fetch_object($result);
+		$resqla = $this->db->query($sql);
+		if ($resqla) {
+			$obj = $this->db->fetch_object($resqla);
 			$lettre = (empty($obj->lettering_code) ? 'AAA' : $obj->lettering_code);
 			if (!empty($obj->lettering_code)) {
 				$lettre++;
 			}
-			$this->db->free($result);
+			$this->db->free($resqla);
 		} else {
 			$this->errors[] = 'Error'.$this->db->lasterror();
 			$error++;
@@ -281,14 +281,14 @@ class Lettering extends BookKeeping
 
 		$sql = "SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE ";
 		$sql .= " rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''";
-		$result = $this->db->query($sql);
-		if ($result) {
-			$obj = $this->db->fetch_object($result);
+		$resqlb = $this->db->query($sql);
+		if ($resqlb) {
+			$obj = $this->db->fetch_object($resqlb);
 			if (!(round(abs($obj->deb), 2) === round(abs($obj->cred), 2))) {
 				$this->errors[] = 'Total not exacts '.round(abs($obj->deb), 2).' vs '.round(abs($obj->cred), 2);
 				$error++;
 			}
-			$this->db->free($result);
+			$this->db->free($resqlb);
 		} else {
 			$this->errors[] = 'Erreur sql'.$this->db->lasterror();
 			$error++;

+ 23 - 2
htdocs/accountancy/customer/list.php

@@ -5,6 +5,7 @@
  * Copyright (C) 2013-2021	Florian Henry		<florian.henry@open-concept.pro>
  * Copyright (C) 2014	  	Juanjo Menent		<jmenent@2byte.es>
  * Copyright (C) 2016	  	Laurent Destailleur <eldy@users.sourceforge.net>
+ * Copyright (C) 2021      	Gauthier VERDOL     <gauthier.verdol@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
@@ -46,6 +47,7 @@ $show_files = GETPOST('show_files', 'int');
 $confirm = GETPOST('confirm', 'alpha');
 $toselect = GETPOST('toselect', 'array');
 $optioncss = GETPOST('optioncss', 'alpha');
+$default_account = GETPOST('default_account', 'int');
 
 // Select Box
 $mesCasesCochees = GETPOST('toselect', 'array');
@@ -434,12 +436,15 @@ if ($result) {
 
 	$arrayofmassactions = array(
 		'ventil'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Ventilate")
+		,'set_default_account'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("ConfirmPreselectAccount")
 		//'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
 		//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
 	);
 	//if ($user->rights->mymodule->supprimer) $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
 	//if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
-	$massactionbutton = $form->selectMassAction('ventil', $arrayofmassactions, 1);
+	if ($massaction !== 'set_default_account') {
+		$massactionbutton = $form->selectMassAction('ventil', $arrayofmassactions, 1);
+	}
 
 	print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">'."\n";
 	print '<input type="hidden" name="action" value="ventil">';
@@ -454,6 +459,14 @@ if ($result) {
 
 	print_barre_liste($langs->trans("InvoiceLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit);
 
+	if ($massaction == 'set_default_account') {
+		$formquestion[]=array('type' => 'other',
+			'name' => 'set_default_account',
+			'label' => $langs->trans("AccountancyCode"),
+			'value' => $formaccounting->select_account('', 'default_account', 1, array(), 0, 0, 'maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone'));
+		print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmPreselectAccount"), $langs->trans("ConfirmPreselectAccountQuestion", count($toselect)), "confirm_set_default_account", $formquestion, 1, 0, 200, 500, 1);
+	}
+
 	print '<span class="opacitymedium">'.$langs->trans("DescVentilTodoCustomer").'</span></br><br>';
 
 	if ($msg) {
@@ -712,7 +725,7 @@ if ($result) {
 
 		// Suggested accounting account
 		print '<td>';
-		print $formaccounting->select_account($suggestedid, 'codeventil'.$facture_static_det->id, 1, array(), 0, 0, 'codeventil maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone');
+		print $formaccounting->select_account(($default_account > 0 && $confirm === 'yes' && in_array($objp->rowid."_".$i, $toselect)) ? $default_account : $suggestedid, 'codeventil'.$facture_static_det->id, 1, array(), 0, 0, 'codeventil maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone');
 		print '</td>';
 
 		// Column with checkbox
@@ -721,6 +734,14 @@ if ($result) {
 		if (!empty($suggestedid) && $suggestedaccountingaccountfor != '' && $suggestedaccountingaccountfor != 'eecwithoutvatnumber') {
 			$ischecked = 1;
 		}
+
+		if (!empty($toselect)) {
+			$ischecked = 0;
+			if (in_array($objp->rowid."_".$i, $toselect)) {
+				$ischecked=1;
+			}
+		}
+
 		print '<input type="checkbox" class="flat checkforselect checkforselect'.$facture_static_det->id.'" name="toselect[]" value="'.$facture_static_det->id."_".$i.'"'.($ischecked ? " checked" : "").'/>';
 		print '</td>';
 

+ 11 - 11
htdocs/accountancy/journal/bankjournal.php

@@ -558,11 +558,11 @@ if ($result) {
 }
 
 
-/*var_dump($tabpay);
-var_dump($tabcompany);
-var_dump($tabbq);
-var_dump($tabtp);
-var_dump($tabtype);*/
+//var_dump($tabpay);
+//var_dump($tabcompany);
+//var_dump($tabbq);
+//var_dump($tabtp);
+//var_dump($tabtype);
 
 // Write bookkeeping
 if (!$error && $action == 'writebookkeeping') {
@@ -594,9 +594,9 @@ if (!$error && $action == 'writebookkeeping') {
 		$db->begin();
 
 		// Introduce a protection. Total of tabtp must be total of tabbq
-		/*var_dump($tabpay);
-		var_dump($tabtp);
-		var_dump($tabbq);exit;*/
+		//var_dump($tabpay);
+		//var_dump($tabtp);
+		//var_dump($tabbq);exit;
 
 		// Bank
 		if (!$errorforline && is_array($tabbq[$key])) {
@@ -1267,9 +1267,9 @@ if (empty($action) || $action == 'view') {
 						$accounttoshowsubledger = length_accounta($k);
 						if ($accounttoshow != $accounttoshowsubledger) {
 							if (empty($accounttoshowsubledger) || $accounttoshowsubledger == 'NotDefined') {
-								/*var_dump($tabpay[$key]);
-								var_dump($tabtype[$key]);
-								var_dump($tabbq[$key]);*/
+								//var_dump($tabpay[$key]);
+								//var_dump($tabtype[$key]);
+								//var_dump($tabbq[$key]);
 								//print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
 								if (!empty($tabcompany[$key]['code_compta'])) {
 									if (in_array($tabtype[$key], array('payment_various', 'payment_salary'))) {

+ 12 - 7
htdocs/accountancy/journal/sellsjournal.php

@@ -418,9 +418,14 @@ if ($action == 'writebookkeeping') {
 					$bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
 					$bookkeeping->thirdparty_code = $companystatic->code_client;
 
-					if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
-						$bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
-						$bookkeeping->subledger_label = $tabcompany[$key]['name'];
+					if (!empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT)) {
+						if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
+							$bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
+							$bookkeeping->subledger_label = $tabcompany[$key]['name'];
+						} else {
+							$bookkeeping->subledger_account = '';
+							$bookkeeping->subledger_label = '';
+						}
 					} else {
 						$bookkeeping->subledger_account = '';
 						$bookkeeping->subledger_label = '';
@@ -897,12 +902,12 @@ if (empty($action) || $action == 'view') {
 			print "</td>";
 			// Subledger account
 			print "<td>";
-			if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
-				if (($accountoshow == "") || $accountoshow == 'NotDefined') {
-					print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
-				} else {
+			if (!empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT)) {
+				if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
 					print length_accounta($tabcompany[$key]['code_compta']);
 				}
+			} elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
+				print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
 			}
 			print '</td>';
 			$companystatic->id = $tabcompany[$key]['id'];

+ 27 - 6
htdocs/accountancy/supplier/list.php

@@ -1,8 +1,9 @@
 <?php
-/* Copyright (C) 2013-2014  Olivier Geffroy         <jeff@jeffinfo.com>
- * Copyright (C) 2013-2022  Alexandre Spangaro      <aspangaro@open-dsi.fr>
- * Copyright (C) 2014-2015  Ari Elbaz (elarifr)     <github@accedinfo.com>
- * Copyright (C) 2013-2014  Florian Henry           <florian.henry@open-concept.pro>
+/* Copyright (C) 2013-2014	Olivier Geffroy			<jeff@jeffinfo.com>
+ * Copyright (C) 2013-2022	Alexandre Spangaro		<aspangaro@open-dsi.fr>
+ * Copyright (C) 2014-2015	Ari Elbaz (elarifr)		<github@accedinfo.com>
+ * Copyright (C) 2013-2021	Florian Henry			<florian.henry@open-concept.pro>
+ * Copyright (C) 2021      	Gauthier VERDOL     <gauthier.verdol@atm-consulting.fr>
  * Copyright (C) 2014       Juanjo Menent           <jmenent@2byte.es>s
  * Copyright (C) 2016       Laurent Destailleur     <eldy@users.sourceforge.net>
  *
@@ -47,6 +48,7 @@ $show_files = GETPOST('show_files', 'int');
 $confirm = GETPOST('confirm', 'alpha');
 $toselect = GETPOST('toselect', 'array');
 $optioncss = GETPOST('optioncss', 'alpha');
+$default_account = GETPOST('default_account', 'int');
 
 // Select Box
 $mesCasesCochees = GETPOST('toselect', 'array');
@@ -442,12 +444,15 @@ if ($result) {
 
 	$arrayofmassactions = array(
 		'ventil'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Ventilate")
+		,'set_default_account'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("ConfirmPreselectAccount")
 		//'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
 		//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
 	);
 	//if ($user->rights->mymodule->supprimer) $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
 	//if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
-	$massactionbutton = $form->selectMassAction('ventil', $arrayofmassactions, 1);
+	if ($massaction !== 'set_default_account') {
+		$massactionbutton = $form->selectMassAction('ventil', $arrayofmassactions, 1);
+	}
 
 	print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">'."\n";
 	print '<input type="hidden" name="action" value="ventil">';
@@ -462,6 +467,14 @@ if ($result) {
 
 	print_barre_liste($langs->trans("InvoiceLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit);
 
+	if ($massaction == 'set_default_account') {
+		$formquestion[]=array('type' => 'other',
+				'name' => 'set_default_account',
+				'label' => $langs->trans("AccountancyCode"),
+				'value' => $formaccounting->select_account('', 'default_account', 1, array(), 0, 0, 'maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone'));
+		print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmPreselectAccount"), $langs->trans("ConfirmPreselectAccountQuestion", count($toselect)), "confirm_set_default_account", $formquestion, 1, 0, 200, 500, 1);
+	}
+
 	print '<span class="opacitymedium">'.$langs->trans("DescVentilTodoCustomer").'</span></br><br>';
 
 	if ($msg) {
@@ -736,7 +749,7 @@ if ($result) {
 
 		// Suggested accounting account
 		print '<td>';
-		print $formaccounting->select_account($suggestedid, 'codeventil'.$facturefourn_static_det->id, 1, array(), 0, 0, 'codeventil maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone');
+		print $formaccounting->select_account(($default_account > 0 && $confirm === 'yes' && in_array($objp->rowid."_".$i, $toselect)) ? $default_account : $suggestedid, 'codeventil'.$facturefourn_static_det->id, 1, array(), 0, 0, 'codeventil maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone');
 		print '</td>';
 
 		// Column with checkbox
@@ -745,6 +758,14 @@ if ($result) {
 		if (!empty($suggestedid) && $suggestedaccountingaccountfor != '' && $suggestedaccountingaccountfor != 'eecwithoutvatnumber') {
 			$ischecked = 1;
 		}
+
+		if (!empty($toselect)) {
+			$ischecked = 0;
+			if (in_array($objp->rowid."_".$i, $toselect)) {
+				$ischecked=1;
+			}
+		}
+
 		print '<input type="checkbox" class="flat checkforselect checkforselect'.$facturefourn_static_det->id.'" name="toselect[]" value="'.$facturefourn_static_det->id."_".$i.'"'.($ischecked ? " checked" : "").'/>';
 		print '</td>';
 

+ 1 - 1
htdocs/adherents/admin/member.php

@@ -64,7 +64,7 @@ if ($action == 'set_default') {
 } elseif ($action == 'del_default') {
 	$ret = delDocumentModel($value, $type);
 	if ($ret > 0) {
-		if ($conf->global->MEMBER_ADDON_PDF_ODT == "$value") {
+		if (getDolGlobalString('MEMBER_ADDON_PDF_ODT') == "$value") {
 			dolibarr_del_const($db, 'MEMBER_ADDON_PDF_ODT', $conf->entity);
 		}
 	}

+ 3 - 2
htdocs/adherents/admin/website.php

@@ -95,12 +95,13 @@ if ($action == 'update') {
 
 $form = new Form($db);
 
+$title = $langs->trans("MembersSetup");
 $help_url = 'EN:Module_Foundations|FR:Module_Adh&eacute;rents|ES:M&oacute;dulo_Miembros';
-llxHeader('', $langs->trans("MembersSetup"), $help_url);
+llxHeader('', $title, $help_url);
 
 
 $linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
-print load_fiche_titre($langs->trans("MembersSetup"), $linkback, 'title_setup');
+print load_fiche_titre($title, $linkback, 'title_setup');
 
 $head = member_admin_prepare_head();
 

+ 1 - 1
htdocs/adherents/agenda.php

@@ -163,7 +163,7 @@ if ($object->id > 0) {
 
 	$newcardbutton = '';
 	if (!empty($conf->agenda->enabled)) {
-		$newcardbutton .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/comm/action/card.php?action=create&backtopage=1&origin=member&originid='.$id);
+		$newcardbutton .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/comm/action/card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']).($object->id > 0 ? '?id='.$object->id : '').'&origin=member&originid='.$id);
 	}
 
 	if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) {

+ 1 - 1
htdocs/adherents/card.php

@@ -1286,7 +1286,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 		print '</td></tr>';
 
 		// EMail
-		print '<tr><td>'.($conf->global->ADHERENT_MAIL_REQUIRED ? '<span class="fieldrequired">' : '').$langs->trans("EMail").($conf->global->ADHERENT_MAIL_REQUIRED ? '</span>' : '').'</td>';
+		print '<tr><td>'.(getDolGlobalString("ADHERENT_MAIL_REQUIRED") ? '<span class="fieldrequired">' : '').$langs->trans("EMail").(getDolGlobalString("ADHERENT_MAIL_REQUIRED") ? '</span>' : '').'</td>';
 		print '<td>'.img_picto('', 'object_email', 'class="pictofixedwidth"').'<input type="text" name="member_email" class="minwidth300" maxlength="255" value="'.(GETPOSTISSET("member_email") ? GETPOST("member_email", '', 2) : $object->email).'"></td></tr>';
 
 		// Website

+ 5 - 5
htdocs/adherents/class/subscription.class.php

@@ -490,17 +490,17 @@ class Subscription extends CommonObject
 		$sql .= ' FROM '.MAIN_DB_PREFIX.'subscription as c';
 		$sql .= ' WHERE c.rowid = '.((int) $id);
 
-		$result = $this->db->query($sql);
-		if ($result) {
-			if ($this->db->num_rows($result)) {
-				$obj = $this->db->fetch_object($result);
+		$resql = $this->db->query($sql);
+		if ($resql) {
+			if ($this->db->num_rows($resql)) {
+				$obj = $this->db->fetch_object($resql);
 				$this->id = $obj->rowid;
 
 				$this->date_creation = $this->db->jdate($obj->datec);
 				$this->date_modification = $this->db->jdate($obj->datem);
 			}
 
-			$this->db->free($result);
+			$this->db->free($resql);
 		} else {
 			dol_print_error($this->db);
 		}

+ 10 - 10
htdocs/adherents/index.php

@@ -99,12 +99,12 @@ $sql .= " WHERE t.entity IN (".getEntity('member_type').")";
 $sql .= " GROUP BY t.rowid, t.libelle, t.subscription, d.statut";
 
 dol_syslog("index.php::select nb of members per type", LOG_DEBUG);
-$result = $db->query($sql);
-if ($result) {
-	$num = $db->num_rows($result);
+$resql = $db->query($sql);
+if ($resql) {
+	$num = $db->num_rows($resql);
 	$i = 0;
 	while ($i < $num) {
-		$objp = $db->fetch_object($result);
+		$objp = $db->fetch_object($resql);
 
 		$adhtype = new AdherentType($db);
 		$adhtype->id = $objp->rowid;
@@ -127,7 +127,7 @@ if ($result) {
 
 		$i++;
 	}
-	$db->free($result);
+	$db->free($resql);
 }
 
 $now = dol_now();
@@ -143,16 +143,16 @@ $sql .= " AND t.rowid = d.fk_adherent_type";
 $sql .= " GROUP BY d.fk_adherent_type";
 
 dol_syslog("index.php::select nb of uptodate members by type", LOG_DEBUG);
-$result = $db->query($sql);
-if ($result) {
-	$num = $db->num_rows($result);
+$resql = $db->query($sql);
+if ($resql) {
+	$num = $db->num_rows($resql);
 	$i = 0;
 	while ($i < $num) {
-		$objp = $db->fetch_object($result);
+		$objp = $db->fetch_object($resql);
 		$MembersUpToDate[$objp->fk_adherent_type] = $objp->somme;
 		$i++;
 	}
-	$db->free();
+	$db->free($resql);
 }
 
 /*

+ 1 - 1
htdocs/adherents/list.php

@@ -215,7 +215,7 @@ if (empty($reshook)) {
 		$search_status = "";
 		$catid = "";
 		$sall = "";
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 

+ 12 - 5
htdocs/adherents/partnership.php

@@ -85,11 +85,18 @@ $usercanclose 			= $user->rights->partnership->write; // Used by the include of
 $upload_dir 			= $conf->partnership->multidir_output[isset($object->entity) ? $object->entity : 1];
 
 
-if ($conf->global->PARTNERSHIP_IS_MANAGED_FOR != 'member') accessforbidden();
-if (empty($conf->partnership->enabled)) accessforbidden();
-if (empty($permissiontoread)) accessforbidden();
-if ($action == 'edit' && empty($permissiontoadd)) accessforbidden();
-
+if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') != 'member') {
+	accessforbidden('Partnership module is not activated for members');
+}
+if (empty($conf->partnership->enabled)) {
+	accessforbidden();
+}
+if (empty($permissiontoread)) {
+	accessforbidden();
+}
+if ($action == 'edit' && empty($permissiontoadd)) {
+	accessforbidden();
+}
 if (($action == 'update' || $action == 'edit') && $object->status != $object::STATUS_DRAFT) {
 	accessforbidden();
 }

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

@@ -135,7 +135,7 @@ if (empty($reshook)) {
 		$search_note = "";
 		$search_amount = "";
 		$search_account = "";
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 }

+ 3 - 0
htdocs/admin/agenda.php

@@ -173,6 +173,9 @@ if (!empty($triggers)) {
 		if ($module == 'contact') {
 			$module = 'societe';
 		}
+		if ($module == 'facturerec') {
+			$module = 'facture';
+		}
 
 		// If 'element' value is myobject@mymodule instead of mymodule
 		$tmparray = explode('@', $module);

+ 1 - 1
htdocs/admin/defaultvalues.php

@@ -101,7 +101,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
 	$defaulturl = '';
 	$defaultkey = '';
 	$defaultvalue = '';
-	$toselect = '';
+	$toselect = array();
 	$search_array_options = array();
 }
 

+ 233 - 246
htdocs/admin/dict.php

@@ -104,50 +104,50 @@ $taborder = array(9, 15, 30, 0, 4, 3, 2, 0, 1, 8, 19, 16, 39, 27, 40, 38, 0, 5,
 
 // Name of SQL tables of dictionaries
 $tabname = array();
-$tabname[1] = MAIN_DB_PREFIX."c_forme_juridique";
-$tabname[2] = MAIN_DB_PREFIX."c_departements";
-$tabname[3] = MAIN_DB_PREFIX."c_regions";
-$tabname[4] = MAIN_DB_PREFIX."c_country";
-$tabname[5] = MAIN_DB_PREFIX."c_civility";
-$tabname[6] = MAIN_DB_PREFIX."c_actioncomm";
-$tabname[7] = MAIN_DB_PREFIX."c_chargesociales";
-$tabname[8] = MAIN_DB_PREFIX."c_typent";
-$tabname[9] = MAIN_DB_PREFIX."c_currencies";
-$tabname[10] = MAIN_DB_PREFIX."c_tva";
-$tabname[11] = MAIN_DB_PREFIX."c_type_contact";
-$tabname[12] = MAIN_DB_PREFIX."c_payment_term";
-$tabname[13] = MAIN_DB_PREFIX."c_paiement";
-$tabname[14] = MAIN_DB_PREFIX."c_ecotaxe";
-$tabname[15] = MAIN_DB_PREFIX."c_paper_format";
-$tabname[16] = MAIN_DB_PREFIX."c_prospectlevel";
-$tabname[17] = MAIN_DB_PREFIX."c_type_fees";
-$tabname[18] = MAIN_DB_PREFIX."c_shipment_mode";
-$tabname[19] = MAIN_DB_PREFIX."c_effectif";
-$tabname[20] = MAIN_DB_PREFIX."c_input_method";
-$tabname[21] = MAIN_DB_PREFIX."c_availability";
-$tabname[22] = MAIN_DB_PREFIX."c_input_reason";
-$tabname[23] = MAIN_DB_PREFIX."c_revenuestamp";
-$tabname[24] = MAIN_DB_PREFIX."c_type_resource";
-$tabname[25] = MAIN_DB_PREFIX."c_type_container";
-//$tabname[26]= MAIN_DB_PREFIX."c_units";
-$tabname[27] = MAIN_DB_PREFIX."c_stcomm";
-$tabname[28] = MAIN_DB_PREFIX."c_holiday_types";
-$tabname[29] = MAIN_DB_PREFIX."c_lead_status";
-$tabname[30] = MAIN_DB_PREFIX."c_format_cards";
-//$tabname[31]= MAIN_DB_PREFIX."accounting_system";
-$tabname[32] = MAIN_DB_PREFIX."c_hrm_public_holiday";
-$tabname[33] = MAIN_DB_PREFIX."c_hrm_department";
-$tabname[34] = MAIN_DB_PREFIX."c_hrm_function";
-$tabname[35] = MAIN_DB_PREFIX."c_exp_tax_cat";
-$tabname[36] = MAIN_DB_PREFIX."c_exp_tax_range";
-$tabname[37] = MAIN_DB_PREFIX."c_units";
-$tabname[38] = MAIN_DB_PREFIX."c_socialnetworks";
-$tabname[39] = MAIN_DB_PREFIX."c_prospectcontactlevel";
-$tabname[40] = MAIN_DB_PREFIX."c_stcommcontact";
-$tabname[41] = MAIN_DB_PREFIX."c_transport_mode";
-$tabname[42] = MAIN_DB_PREFIX."c_product_nature";
-$tabname[43] = MAIN_DB_PREFIX."c_productbatch_qcstatus";
-$tabname[44] = MAIN_DB_PREFIX."c_asset_disposal_type";
+$tabname[1] = "c_forme_juridique";
+$tabname[2] = "c_departements";
+$tabname[3] = "c_regions";
+$tabname[4] = "c_country";
+$tabname[5] = "c_civility";
+$tabname[6] = "c_actioncomm";
+$tabname[7] = "c_chargesociales";
+$tabname[8] = "c_typent";
+$tabname[9] = "c_currencies";
+$tabname[10] = "c_tva";
+$tabname[11] = "c_type_contact";
+$tabname[12] = "c_payment_term";
+$tabname[13] = "c_paiement";
+$tabname[14] = "c_ecotaxe";
+$tabname[15] = "c_paper_format";
+$tabname[16] = "c_prospectlevel";
+$tabname[17] = "c_type_fees";
+$tabname[18] = "c_shipment_mode";
+$tabname[19] = "c_effectif";
+$tabname[20] = "c_input_method";
+$tabname[21] = "c_availability";
+$tabname[22] = "c_input_reason";
+$tabname[23] = "c_revenuestamp";
+$tabname[24] = "c_type_resource";
+$tabname[25] = "c_type_container";
+//$tabname[26]= "c_units";
+$tabname[27] = "c_stcomm";
+$tabname[28] = "c_holiday_types";
+$tabname[29] = "c_lead_status";
+$tabname[30] = "c_format_cards";
+//$tabname[31]= "accounting_system";
+$tabname[32] = "c_hrm_public_holiday";
+$tabname[33] = "c_hrm_department";
+$tabname[34] = "c_hrm_function";
+$tabname[35] = "c_exp_tax_cat";
+$tabname[36] = "c_exp_tax_range";
+$tabname[37] = "c_units";
+$tabname[38] = "c_socialnetworks";
+$tabname[39] = "c_prospectcontactlevel";
+$tabname[40] = "c_stcommcontact";
+$tabname[41] = "c_transport_mode";
+$tabname[42] = "c_product_nature";
+$tabname[43] = "c_productbatch_qcstatus";
+$tabname[44] = "c_asset_disposal_type";
 
 // Dictionary labels
 $tablib = array();
@@ -209,7 +209,7 @@ $tabsql[8] = "SELECT t.id	 as rowid, t.code as code, t.libelle, t.fk_country as
 $tabsql[9] = "SELECT c.code_iso as code, c.label, c.unicode, c.active FROM ".MAIN_DB_PREFIX."c_currencies AS c";
 $tabsql[10] = "SELECT t.rowid, t.code, t.taux, t.localtax1_type, t.localtax1, t.localtax2_type, t.localtax2, c.label as country, c.code as country_code, t.fk_pays as country_id, t.recuperableonly, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid";
 $tabsql[11] = "SELECT t.rowid as rowid, t.element, t.source, t.code, t.libelle, t.position, t.active FROM ".MAIN_DB_PREFIX."c_type_contact AS t";
-$tabsql[12] = "SELECT c.rowid as rowid, c.code, c.libelle, c.libelle_facture, c.nbjour, c.type_cdr, c.decalage, c.active, c.sortorder, c.entity FROM ".MAIN_DB_PREFIX."c_payment_term AS c WHERE c.entity = ".getEntity($tabname[12]);
+$tabsql[12] = "SELECT c.rowid as rowid, c.code, c.libelle, c.libelle_facture, c.deposit_percent, c.nbjour, c.type_cdr, c.decalage, c.active, c.sortorder, c.entity FROM ".MAIN_DB_PREFIX."c_payment_term AS c WHERE c.entity = ".getEntity($tabname[12]);
 $tabsql[13] = "SELECT c.id    as rowid, c.code, c.libelle, c.type, c.active, c.entity FROM ".MAIN_DB_PREFIX."c_paiement AS c WHERE c.entity = ".getEntity($tabname[13]);
 $tabsql[14] = "SELECT e.rowid as rowid, e.code as code, e.label, e.price, e.organization, e.fk_pays as country_id, c.code as country_code, c.label as country, e.active FROM ".MAIN_DB_PREFIX."c_ecotaxe AS e, ".MAIN_DB_PREFIX."c_country as c WHERE e.fk_pays=c.rowid and c.active=1";
 $tabsql[15] = "SELECT rowid   as rowid, code, label as libelle, width, height, unit, active FROM ".MAIN_DB_PREFIX."c_paper_format";
@@ -265,7 +265,7 @@ $tabsqlsort[17] = "code ASC";
 $tabsqlsort[18] = "code ASC, libelle ASC";
 $tabsqlsort[19] = "id ASC";
 $tabsqlsort[20] = "code ASC, libelle ASC";
-$tabsqlsort[21] = "code ASC, label ASC, position ASC, type_duration ASC, qty ASC";
+$tabsqlsort[21] = "position ASC, type_duration ASC, qty ASC";
 $tabsqlsort[22] = "code ASC, label ASC";
 $tabsqlsort[23] = "country ASC, taux ASC";
 $tabsqlsort[24] = "code ASC, label ASC";
@@ -303,7 +303,7 @@ $tabfield[8] = "code,libelle,country_id,country".(!empty($conf->global->SOCIETE_
 $tabfield[9] = "code,label,unicode";
 $tabfield[10] = "country_id,country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
 $tabfield[11] = "element,source,code,libelle,position";
-$tabfield[12] = "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder,entity";
+$tabfield[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder,entity";
 $tabfield[13] = "code,libelle,type,entity";
 $tabfield[14] = "code,label,price,organization,country";
 $tabfield[15] = "code,libelle,width,height,unit";
@@ -350,7 +350,7 @@ $tabfieldvalue[8] = "code,libelle,country".(!empty($conf->global->SOCIETE_SORT_O
 $tabfieldvalue[9] = "code,label,unicode";
 $tabfieldvalue[10] = "country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
 $tabfieldvalue[11] = "element,source,code,libelle,position";
-$tabfieldvalue[12] = "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder";
+$tabfieldvalue[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder";
 $tabfieldvalue[13] = "code,libelle,type";
 $tabfieldvalue[14] = "code,label,price,organization,country";
 $tabfieldvalue[15] = "code,libelle,width,height,unit";
@@ -397,7 +397,7 @@ $tabfieldinsert[8] = "code,libelle,fk_country".(!empty($conf->global->SOCIETE_SO
 $tabfieldinsert[9] = "code_iso,label,unicode";
 $tabfieldinsert[10] = "fk_pays,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
 $tabfieldinsert[11] = "element,source,code,libelle,position";
-$tabfieldinsert[12] = "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder,entity";
+$tabfieldinsert[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder,entity";
 $tabfieldinsert[13] = "code,libelle,type,entity";
 $tabfieldinsert[14] = "code,label,price,organization,fk_pays";
 $tabfieldinsert[15] = "code,label,width,height,unit";
@@ -528,112 +528,90 @@ $tabcond[42] = !empty($conf->product->enabled);
 $tabcond[43] = !empty($conf->product->enabled) && !empty($conf->productbatch->enabled) && $conf->global->MAIN_FEATURES_LEVEL >= 2;
 $tabcond[44] = !empty($conf->asset->enabled);
 
-// List of help for fields
+// List of help for fields (no more used, help is defined into tabcomplete)
 $tabhelp = array();
-$tabhelp[1]  = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[2]  = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[3]  = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[4]  = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[5]  = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[6]  = array('code'=>$langs->trans("EnterAnyCode"), 'color'=>$langs->trans("ColorFormat"), 'position'=>$langs->trans("PositionIntoComboList"));
-$tabhelp[7]  = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[8]  = array('code'=>$langs->trans("EnterAnyCode"), 'position'=>$langs->trans("PositionIntoComboList"));
-$tabhelp[9]  = array('code'=>$langs->trans("EnterAnyCode"), 'unicode'=>$langs->trans("UnicodeCurrency"));
-$tabhelp[10] = array('code'=>$langs->trans("EnterAnyCode"), 'taux'=>$langs->trans("SellTaxRate"), 'recuperableonly'=>$langs->trans("RecuperableOnly"), 'localtax1_type'=>$langs->trans("LocalTaxDesc"), 'localtax2_type'=>$langs->trans("LocalTaxDesc"));
-$tabhelp[11] = array('code'=>$langs->trans("EnterAnyCode"), 'position'=>$langs->trans("PositionIntoComboList"));
-$tabhelp[12] = array('code'=>$langs->trans("EnterAnyCode"), 'type_cdr'=>$langs->trans("TypeCdr", $langs->transnoentitiesnoconv("NbOfDays"), $langs->transnoentitiesnoconv("Offset"), $langs->transnoentitiesnoconv("NbOfDays"), $langs->transnoentitiesnoconv("Offset")));
-$tabhelp[13] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[14] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[15] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[16] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[17] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[18] = array('code'=>$langs->trans("EnterAnyCode"), 'tracking'=>$langs->trans("UrlTrackingDesc"));
-$tabhelp[19] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[20] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[21] = array('code'=>$langs->trans("EnterAnyCode"), 'position'=>$langs->trans("PositionIntoComboList"));
-$tabhelp[22] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[23] = array('revenuestamp_type'=>'FixedOrPercent');
-$tabhelp[24] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[25] = array('code'=>$langs->trans('EnterAnyCode'));
-//$tabhelp[26] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[27] = array('code'=>$langs->trans("EnterAnyCode"), 'picto'=>$langs->trans("PictoHelp"));
-$tabhelp[28] = array('affect'=>$langs->trans("FollowedByACounter"), 'delay'=>$langs->trans("MinimumNoticePeriod"), 'newbymonth'=>$langs->trans("NbAddedAutomatically"));
-$tabhelp[29] = array('code'=>$langs->trans("EnterAnyCode"), 'percent'=>$langs->trans("OpportunityPercent"), 'position'=>$langs->trans("PositionIntoComboList"));
-$tabhelp[30] = array('code'=>$langs->trans("EnterAnyCode"), 'name'=>$langs->trans("LabelName"), 'paper_size'=>$langs->trans("LabelPaperSize"));
-//$tabhelp[31] = array('pcg_version'=>$langs->trans("EnterAnyCode"));
-$tabhelp[32] = array('code'=>$langs->trans("EnterAnyCode"), 'dayrule'=>"Keep empty for a date defined with month and day (most common case).<br>Use a keyword like 'easter', 'eastermonday', ... for a date predefined by complex rules.", 'country'=>$langs->trans("CountryIfSpecificToOneCountry"), 'year'=>$langs->trans("ZeroMeansEveryYear"));
-$tabhelp[33] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[34] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[35] = array();
-$tabhelp[36] = array('range_ik'=>$langs->trans('PrevRangeToThisRange'));
-$tabhelp[37] = array('code'=>$langs->trans("EnterAnyCode"), 'unit_type' => $langs->trans('Measuringtype_durationDesc'), 'scale' => $langs->trans('MeasuringScaleDesc'));
-$tabhelp[38] = array('code'=>$langs->trans("EnterAnyCode"), 'url' => $langs->trans('UrlSocialNetworksDesc'), 'icon' => $langs->trans('FafaIconSocialNetworksDesc'));
-$tabhelp[39] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[40] = array('code'=>$langs->trans("EnterAnyCode"), 'picto'=>$langs->trans("PictoHelp"));
-$tabhelp[41] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[42] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[43] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[44] = array('code'=>$langs->trans("EnterAnyCode"));
 
 // Table to store complete informations (will replace all other table). Key is table name.
 $tabcomplete = array(
-	'c_forme_juridique'=>array('picto'=>'company'),
-	'c_departements'=>array('picto'=>'state'),
-	'c_regions'=>array('picto'=>'region'),
-	'c_country'=>array('picto'=>'country'),
-	'c_civility'=>array('picto'=>'contact'),
-	'c_actioncomm'=>array('picto'=>'action'),
-	'c_chargesociales'=>array('picto'=>'bill'),
-	'c_typent'=>array('picto'=>'company'),
-	'c_currencies'=>array('picto'=>'multicurrency'),
-	'c_tva'=>array('picto'=>'bill'),
-	'c_type_contact'=>array('picto'=>'contact'),
-	'c_payment_term'=>array('picto'=>'bill'),
-	'c_paiement'=>array('picto'=>'bill'),
-	'c_ecotaxe'=>array('picto'=>'bill'),
-	'c_paper_format'=>array('picto'=>'generic'),
-	'c_prospectlevel'=>array('picto'=>'company'),
-	'c_type_fees'=>array('picto'=>'trip'),
-	'c_effectif'=>array('picto'=>'company'),
-	'c_input_method'=>array('picto'=>'order'),
-	'c_input_reason'=>array('picto'=>'order'),
-	'c_availability'=>array('picto'=>'shipment'),
-	'c_shipment_mode'=>array('picto'=>'shipment'),
-	'c_revenuestamp'=>array('picto'=>'bill'),
-	'c_type_resource'=>array('picto'=>'resource'),
-	'c_type_container'=>array('picto'=>'website'),
-	'c_stcomm'=>array('picto'=>'company'),
-	'c_holiday_types'=>array('picto'=>'holiday'),
-	'c_lead_status'=>array('picto'=>'project'),
-	'c_format_cards'=>array('picto'=>'generic'),
-	'c_hrm_public_holiday'=>array('picto'=>'holiday'),
-	'c_hrm_department'=>array('picto'=>'hrm'),
-	'c_hrm_function'=>array('picto'=>'hrm'),
-	'c_exp_tax_cat'=>array('picto'=>'expensereport'),
-	'c_exp_tax_range'=>array('picto'=>'expensereport'),
-	'c_units'=>array('picto'=>'product'),
-	'c_socialnetworks'=>array('picto'=>'share-alt'),
-	'c_product_nature'=>array('picto'=>'product'),
-	'c_transport_mode'=>array('picto'=>'incoterm'),
-	'c_prospectcontactlevel'=>array('picto'=>'company'),
-	'c_stcommcontact'=>array('picto'=>'company'),
-	'c_product_nature'=>array('picto'=>'product'),
-	'c_productbatch_qcstatus'=>array('picto'=>'lot'),
-	'c_asset_disposal_type'=>array('picto'=>'asset'),
-
+	'c_forme_juridique'=>array('picto'=>'company', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_departements'=>array('picto'=>'state', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_regions'=>array('picto'=>'region', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_country'=>array('picto'=>'country', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_civility'=>array('picto'=>'contact', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_actioncomm'=>array('picto'=>'action', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'color'=>$langs->trans("ColorFormat"), 'position'=>$langs->trans("PositionIntoComboList"))),
+	'c_chargesociales'=>array('picto'=>'bill', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_typent'=>array('picto'=>'company', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'position'=>$langs->trans("PositionIntoComboList"))),
+	'c_currencies'=>array('picto'=>'multicurrency', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'unicode'=>$langs->trans("UnicodeCurrency"))),
+	'c_tva'=>array('picto'=>'bill', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'taux'=>$langs->trans("SellTaxRate"), 'recuperableonly'=>$langs->trans("RecuperableOnly"), 'localtax1_type'=>$langs->trans("LocalTaxDesc"), 'localtax2_type'=>$langs->trans("LocalTaxDesc"))),
+	'c_type_contact'=>array('picto'=>'contact', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'position'=>$langs->trans("PositionIntoComboList"))),
+	'c_payment_term'=>array('picto'=>'bill', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'type_cdr'=>$langs->trans("TypeCdr", $langs->transnoentitiesnoconv("NbOfDays"), $langs->transnoentitiesnoconv("Offset"), $langs->transnoentitiesnoconv("NbOfDays"), $langs->transnoentitiesnoconv("Offset")))),
+	'c_paiement'=>array('picto'=>'bill', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_ecotaxe'=>array('picto'=>'bill', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_paper_format'=>array('picto'=>'generic', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_prospectlevel'=>array('picto'=>'company', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_type_fees'=>array('picto'=>'trip', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_shipment_mode'=>array('picto'=>'shipment', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'tracking'=>$langs->trans("UrlTrackingDesc"))),
+	'c_effectif'=>array('picto'=>'company', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_input_method'=>array('picto'=>'order', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_input_reason'=>array('picto'=>'order', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'position'=>$langs->trans("PositionIntoComboList"))),
+	'c_availability'=>array('picto'=>'shipment', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_revenuestamp'=>array('picto'=>'bill', 'help'=>array('revenuestamp_type'=>$langs->trans('FixedOrPercent'))),
+	'c_type_resource'=>array('picto'=>'resource', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_type_container'=>array('picto'=>'website', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_stcomm'=>array('picto'=>'company', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'picto'=>$langs->trans("PictoHelp"))),
+	'c_holiday_types'=>array('picto'=>'holiday', 'help'=>array('affect'=>$langs->trans("FollowedByACounter"), 'delay'=>$langs->trans("MinimumNoticePeriod"), 'newbymonth'=>$langs->trans("NbAddedAutomatically"))),
+	'c_lead_status'=>array('picto'=>'project', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'percent'=>$langs->trans("OpportunityPercent"), 'position'=>$langs->trans("PositionIntoComboList"))),
+	'c_format_cards'=>array('picto'=>'generic', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'name'=>$langs->trans("LabelName"), 'paper_size'=>$langs->trans("LabelPaperSize"))),
+	'c_hrm_public_holiday'=>array('picto'=>'holiday', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'dayrule'=>"Keep empty for a date defined with month and day (most common case).<br>Use a keyword like 'easter', 'eastermonday', ... for a date predefined by complex rules.", 'country'=>$langs->trans("CountryIfSpecificToOneCountry"), 'year'=>$langs->trans("ZeroMeansEveryYear"))),
+	'c_hrm_department'=>array('picto'=>'hrm', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_hrm_function'=>array('picto'=>'hrm', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_exp_tax_cat'=>array('picto'=>'expensereport', 'help'=>array()),
+	'c_exp_tax_range'=>array('picto'=>'expensereport', 'help'=>array('range_ik'=>$langs->trans('PrevRangeToThisRange'))),
+	'c_units'=>array('picto'=>'product', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'unit_type' => $langs->trans('Measuringtype_durationDesc'), 'scale' => $langs->trans('MeasuringScaleDesc'))),
+	'c_socialnetworks'=>array('picto'=>'share-alt', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'url' => $langs->trans('UrlSocialNetworksDesc'), 'icon' => $langs->trans('FafaIconSocialNetworksDesc'))),
+	'c_prospectcontactlevel'=>array('picto'=>'company', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_stcommcontact'=>array('picto'=>'company', 'help'=>array('code'=>$langs->trans("EnterAnyCode"), 'picto'=>$langs->trans("PictoHelp"))),
+	'c_transport_mode'=>array('picto'=>'incoterm', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_product_nature'=>array('picto'=>'product', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_productbatch_qcstatus'=>array('picto'=>'lot', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
+	'c_asset_disposal_type'=>array('picto'=>'asset', 'help'=>array('code'=>$langs->trans("EnterAnyCode"))),
 );
 
 
 // Complete all arrays with entries found into modules
 complete_dictionary_with_modules($taborder, $tabname, $tablib, $tabsql, $tabsqlsort, $tabfield, $tabfieldvalue, $tabfieldinsert, $tabrowid, $tabcond, $tabhelp, $tabcomplete);
 
+// Complete the table $tabcomplete
+$i = 0;
+foreach ($tabcomplete as $key => $value) {
+	$i++;
+	$tabcomplete[$key]['id'] = $i;
+	$tabcomplete[$key]['cond'] = $tabcond[$i];
+	$tabcomplete[$key]['rowid'] = $tabrowid[$i];
+	$tabcomplete[$key]['fieldinsert'] = $tabfieldinsert[$i];
+	$tabcomplete[$key]['fieldvalue'] = $tabfieldvalue[$i];
+	$tabcomplete[$key]['lib'] = $tablib[$i];
+	$tabcomplete[$key]['sql'] = $tabsql[$i];
+	$tabcomplete[$key]['sqlsort'] = $tabsqlsort[$i];
+	$tabcomplete[$key]['field'] = $tabfield[$i];
+}
+
+$keytable = '';
+if ($id > 0) {
+	$arrayofkeys = array_keys($tabcomplete);
+	$keytable = $arrayofkeys[$id - 1];
+}
+
 // Defaut sortorder
 if (empty($sortfield)) {
-	$tmp1 = explode(',', empty($tabsqlsort[$id]) ? '' : $tabsqlsort[$id]);
+	$tmp1 = explode(',', empty($tabcomplete[$keytable]['sqlsort']) ? '' : $tabcomplete[$keytable]['sqlsort']);
 	$tmp2 = explode(' ', $tmp1[0]);
 	$sortfield = preg_replace('/^.*\./', '', $tmp2[0]);
+	$sortorder = $tmp2[1];
+	//var_dump($sortfield);var_dump($sortorder);
 }
 
+
 // Define elementList and sourceList (used for dictionary type of contacts "llx_c_type_contact")
 $elementList = array();
 $sourceList = array();
@@ -675,25 +653,22 @@ if ($id == 11) {
 }
 
 // Define localtax_typeList (used for dictionary "llx_c_tva")
-$localtax_typeList = array();
-if ($id == 10) {
-	$localtax_typeList = array(
-		"0" => $langs->trans("No"),
-		"1" => $langs->trans("Yes").' ('.$langs->trans("Type")." 1)", //$langs->trans("%ageOnAllWithoutVAT"),
-		"2" => $langs->trans("Yes").' ('.$langs->trans("Type")." 2)", //$langs->trans("%ageOnAllBeforeVAT"),
-		"3" => $langs->trans("Yes").' ('.$langs->trans("Type")." 3)", //$langs->trans("%ageOnProductsWithoutVAT"),
-		"4" => $langs->trans("Yes").' ('.$langs->trans("Type")." 4)", //$langs->trans("%ageOnProductsBeforeVAT"),
-		"5" => $langs->trans("Yes").' ('.$langs->trans("Type")." 5)", //$langs->trans("%ageOnServiceWithoutVAT"),
-		"6" => $langs->trans("Yes").' ('.$langs->trans("Type")." 6)"	//$langs->trans("%ageOnServiceBeforeVAT"),
-	);
-}
-
+$localtax_typeList = array(
+	"0" => $langs->trans("No"),
+	"1" => $langs->trans("Yes").' ('.$langs->trans("Type")." 1)", //$langs->trans("%ageOnAllWithoutVAT"),
+	"2" => $langs->trans("Yes").' ('.$langs->trans("Type")." 2)", //$langs->trans("%ageOnAllBeforeVAT"),
+	"3" => $langs->trans("Yes").' ('.$langs->trans("Type")." 3)", //$langs->trans("%ageOnProductsWithoutVAT"),
+	"4" => $langs->trans("Yes").' ('.$langs->trans("Type")." 4)", //$langs->trans("%ageOnProductsBeforeVAT"),
+	"5" => $langs->trans("Yes").' ('.$langs->trans("Type")." 5)", //$langs->trans("%ageOnServiceWithoutVAT"),
+	"6" => $langs->trans("Yes").' ('.$langs->trans("Type")." 6)"	//$langs->trans("%ageOnServiceBeforeVAT"),
+);
 
 
 /*
  * Actions
  */
 
+$object = new stdClass();
 $parameters = array(
 	'id'			=>$id,
 	'rowid'			=>$rowid,
@@ -761,7 +736,7 @@ if (empty($reshook)) {
 				continue; // For a column name 'sortorder', we use the field name 'position'
 			}
 			if ((!GETPOSTISSET($value) || GETPOST($value) == '')
-				&& (!in_array($value, array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking', 'picto'))  // Fields that are not mandatory
+					&& (!in_array($value, array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking', 'picto', 'deposit_percent'))  // Fields that are not mandatory
 					&& ($id != 10 || ($value != 'code' && $value != 'note')) // Field code and note is not mandatory for dictionary table 10
 					)
 				) {
@@ -774,6 +749,9 @@ if (empty($reshook)) {
 				if ($fieldnamekey == 'libelle_facture') {
 					$fieldnamekey = 'LabelOnDocuments';
 				}
+				if ($fieldnamekey == 'deposit_percent') {
+					$fieldnamekey = 'DepositPercent';
+				}
 				if ($fieldnamekey == 'nbjour') {
 					$fieldnamekey = 'NbOfDays';
 				}
@@ -817,11 +795,11 @@ if (empty($reshook)) {
 					$fieldnamekey = 'UseByDefault';
 				}
 
-					setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors');
+				setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors');
 			}
 		}
 		// Other checks
-		if (GETPOST('actionadd') && $tabname[$id] == MAIN_DB_PREFIX."c_actioncomm" && GETPOSTISSET("type") && in_array(GETPOST("type"), array('system', 'systemauto'))) {
+		if (GETPOST('actionadd') && $tabname[$id] == "c_actioncomm" && GETPOSTISSET("type") && in_array(GETPOST("type"), array('system', 'systemauto'))) {
 			$ok = 0;
 			setEventMessages($langs->transnoentities('ErrorReservedTypeSystemSystemAuto'), null, 'errors');
 		}
@@ -869,7 +847,7 @@ if (empty($reshook)) {
 			if ($tabrowid[$id]) {
 				// Get free id for insert
 				$newid = 0;
-				$sql = "SELECT max(".$tabrowid[$id].") newid from ".$tabname[$id];
+				$sql = "SELECT MAX(".$tabrowid[$id].") as newid FROM ".MAIN_DB_PREFIX.$tabname[$id];
 				$result = $db->query($sql);
 				if ($result) {
 					$obj = $db->fetch_object($result);
@@ -880,7 +858,7 @@ if (empty($reshook)) {
 			}
 
 			// Add new entry
-			$sql = "INSERT INTO ".$tabname[$id]." (";
+			$sql = "INSERT INTO ".MAIN_DB_PREFIX.$tabname[$id]." (";
 			// List of fields
 			if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
 				$sql .= $tabrowid[$id].",";
@@ -956,7 +934,7 @@ if (empty($reshook)) {
 			}
 
 			// Modify entry
-			$sql = "UPDATE ".$tabname[$id]." SET ";
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET ";
 			// Modifie valeur des champs
 			if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
 				$sql .= $tabrowid[$id]."=";
@@ -1011,11 +989,6 @@ if (empty($reshook)) {
 				setEventMessages($db->error(), null, 'errors');
 			}
 		}
-		//$_GET["id"]=GETPOST('id', 'int');       // Force affichage dictionnaire en cours d'edition
-	}
-
-	if (GETPOST('actioncancel')) {
-		//$_GET["id"]=GETPOST('id', 'int');       // Force affichage dictionnaire en cours d'edition
 	}
 
 	if ($action == 'confirm_delete' && $confirm == 'yes') {       // delete
@@ -1025,7 +998,7 @@ if (empty($reshook)) {
 			$rowidcol = "rowid";
 		}
 
-		$sql = "DELETE FROM ".$tabname[$id]." WHERE ".$rowidcol."='".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+		$sql = "DELETE FROM ".MAIN_DB_PREFIX.$tabname[$id]." WHERE ".$rowidcol." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 
 		dol_syslog("delete", LOG_DEBUG);
 		$result = $db->query($sql);
@@ -1047,9 +1020,9 @@ if (empty($reshook)) {
 		}
 
 		if ($rowid) {
-			$sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE ".$rowidcol."='".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET active = 1 WHERE ".$rowidcol." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		} elseif ($code) {
-			$sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE code='".dol_escape_htmltag($code)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET active = 1 WHERE code = '".$db->escape(dol_escape_htmltag($code))."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		}
 
 		$result = $db->query($sql);
@@ -1067,9 +1040,9 @@ if (empty($reshook)) {
 		}
 
 		if ($rowid) {
-			$sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE ".$rowidcol."='".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET active = 0 WHERE ".$rowidcol." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		} elseif ($code) {
-			$sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE code='".dol_escape_htmltag($code)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET active = 0 WHERE code = '".$db->escape(dol_escape_htmltag($code))."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		}
 
 		$result = $db->query($sql);
@@ -1087,9 +1060,9 @@ if (empty($reshook)) {
 		}
 
 		if ($rowid) {
-			$sql = "UPDATE ".$tabname[$id]." SET favorite = 1 WHERE ".$rowidcol."='".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET favorite = 1 WHERE ".$rowidcol." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		} elseif ($code) {
-			$sql = "UPDATE ".$tabname[$id]." SET favorite = 1 WHERE code='".dol_escape_htmltag($code)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET favorite = 1 WHERE code = '".$db->escape(dol_escape_htmltag($code))."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		}
 
 		$result = $db->query($sql);
@@ -1107,9 +1080,9 @@ if (empty($reshook)) {
 		}
 
 		if ($rowid) {
-			$sql = "UPDATE ".$tabname[$id]." SET favorite = 0 WHERE ".$rowidcol."='".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET favorite = 0 WHERE ".$rowidcol." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		} elseif ($code) {
-			$sql = "UPDATE ".$tabname[$id]." SET favorite = 0 WHERE code='".dol_escape_htmltag($code)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET favorite = 0 WHERE code = '".$db->escape(dol_escape_htmltag($code))."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		}
 
 		$result = $db->query($sql);
@@ -1127,9 +1100,9 @@ if (empty($reshook)) {
 		}
 
 		if ($rowid) {
-			$sql = "UPDATE ".$tabname[$id]." SET eec = 1 WHERE ".$rowidcol."='".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET eec = 1 WHERE ".$rowidcol." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		} elseif ($code) {
-			$sql = "UPDATE ".$tabname[$id]." SET eec = 1 WHERE code='".dol_escape_htmltag($code)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET eec = 1 WHERE code = '".$db->escape(dol_escape_htmltag($code))."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		}
 
 		$result = $db->query($sql);
@@ -1147,9 +1120,9 @@ if (empty($reshook)) {
 		}
 
 		if ($rowid) {
-			$sql = "UPDATE ".$tabname[$id]." SET eec = 0 WHERE ".$rowidcol."='".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET eec = 0 WHERE ".$rowidcol." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		} elseif ($code) {
-			$sql = "UPDATE ".$tabname[$id]." SET eec = 0 WHERE code='".dol_escape_htmltag($code)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
+			$sql = "UPDATE ".MAIN_DB_PREFIX.$tabname[$id]." SET eec = 0 WHERE code = '".$db->escape(dol_escape_htmltag($code))."'".($entity != '' ? " AND entity = ".(int) $entity : '');
 		}
 
 		$result = $db->query($sql);
@@ -1225,7 +1198,7 @@ if ($action == 'delete') {
 /*
  * Show a dictionary
  */
-if ($id) {
+if ($id > 0) {
 	// Complete search values request with sort criteria
 	$sql = $tabsql[$id];
 
@@ -1293,6 +1266,7 @@ if ($id) {
 		print '<table class="noborder centpercent">';
 
 		// Line for title
+		print '<!-- line title to add new entry -->';
 		$tdsoffields = '<tr class="liste_titre">';
 		foreach ($fieldlist as $field => $value) {
 			if ($value == 'entity') {
@@ -1315,7 +1289,7 @@ if ($id) {
 				$valuetoshow = $langs->trans("PriceUHT");
 			}
 			if ($value == 'taux') {
-				if ($tabname[$id] != MAIN_DB_PREFIX."c_revenuestamp") {
+				if ($tabname[$id] != "c_revenuestamp") {
 					$valuetoshow = $langs->trans("Rate");
 				} else {
 					$valuetoshow = $langs->trans("Amount");
@@ -1341,7 +1315,7 @@ if ($id) {
 				$valuetoshow = $langs->trans("Language");
 			}
 			if ($value == 'type') {
-				if ($tabname[$id] == MAIN_DB_PREFIX."c_paiement") {
+				if ($tabname[$id] == "c_paiement") {
 					$valuetoshow = $form->textwithtooltip($langs->trans("Type"), $langs->trans("TypePaymentDesc"), 2, 1, img_help(1, ''));
 				} else {
 					$valuetoshow = $langs->trans("Type");
@@ -1356,6 +1330,10 @@ if ($id) {
 			if ($value == 'libelle_facture') {
 				$valuetoshow = $form->textwithtooltip($langs->trans("LabelOnDocuments"), $langs->trans("LabelUsedByDefault"), 2, 1, img_help(1, ''));
 			}
+			if ($value == 'deposit_percent') {
+				$valuetoshow = $langs->trans('DepositPercent');
+				$class = 'right';
+			}
 			if ($value == 'country') {
 				if (in_array('region_id', $fieldlist)) {
 					print '<td>&nbsp;</td>'; continue;
@@ -1367,12 +1345,14 @@ if ($id) {
 			}
 			if ($value == 'nbjour') {
 				$valuetoshow = $langs->trans("NbOfDays");
+				$class = 'right';
 			}
 			if ($value == 'type_cdr') {
 				$valuetoshow = $langs->trans("AtEndOfMonth"); $class = "center";
 			}
 			if ($value == 'decalage') {
 				$valuetoshow = $langs->trans("Offset");
+				$class = 'right';
 			}
 			if ($value == 'width' || $value == 'nx') {
 				$valuetoshow = $langs->trans("Width");
@@ -1409,6 +1389,7 @@ if ($id) {
 			}
 			if ($value == 'sortorder') {
 				$valuetoshow = $langs->trans("SortOrder");
+				$class = 'center';
 			}
 			if ($value == 'short_label') {
 				$valuetoshow = $langs->trans("ShortLabel");
@@ -1505,7 +1486,7 @@ if ($id) {
 			}
 
 			if ($valuetoshow != '') {
-				$tdsoffields .= '<td'.($class ? ' class="'.$class.'"' : '').'>';
+				$tdsoffields .= '<th'.($class ? ' class="'.$class.'"' : '').'>';
 				if (!empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i', $tabhelp[$id][$value])) {
 					$tdsoffields .= '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
 				} elseif (!empty($tabhelp[$id][$value])) {
@@ -1513,29 +1494,29 @@ if ($id) {
 				} else {
 					$tdsoffields .= $valuetoshow;
 				}
-				$tdsoffields .= '</td>';
+				$tdsoffields .= '</th>';
 			}
 		}
 
 		if ($id == 4) {
-			$tdsoffields .= '<td></td>';
-			$tdsoffields .= '<td></td>';
+			$tdsoffields .= '<th></th>';
+			$tdsoffields .= '<th></th>';
 		}
-		$tdsoffields .= '<td>';
+		$tdsoffields .= '<th>';
 		$tdsoffields .= '<input type="hidden" name="id" value="'.$id.'">';
 		if (!is_null($withentity)) {
 			$tdsoffields .= '<input type="hidden" name="entity" value="'.$withentity.'">';
 		}
-		$tdsoffields .= '</td>';
-		$tdsoffields .= '<td style="min-width: 26px;"></td>';
-		$tdsoffields .= '<td style="min-width: 26px;"></td>';
+		$tdsoffields .= '</th>';
+		$tdsoffields .= '<th style="min-width: 26px;"></th>';
+		$tdsoffields .= '<th style="min-width: 26px;"></th>';
 		$tdsoffields .= '</tr>';
 
 		print $tdsoffields;
 
 
 		// Line to enter new values
-		print '<!-- line to add new entry -->';
+		print '<!-- line input to add new entry -->';
 		print '<tr class="oddeven nodrag nodrop nohover">';
 
 		$obj = new stdClass();
@@ -1606,6 +1587,7 @@ if ($id) {
 		print '<table class="noborder centpercent">';
 
 		// Title line with search input fields
+		print '<!-- line title to search record -->'."\n";
 		print '<tr class="liste_titre_filter">';
 		$filterfound = 0;
 		foreach ($fieldlist as $field => $value) {
@@ -1650,6 +1632,7 @@ if ($id) {
 		print '</tr>';
 
 		// Title of lines
+		print '<!-- line title of record -->'."\n";
 		print '<tr class="liste_titre">';
 		foreach ($fieldlist as $field => $value) {
 			if ($value == 'entity') {
@@ -1676,7 +1659,7 @@ if ($id) {
 				$valuetoshow = $langs->trans("PriceUHT");
 			}
 			if ($value == 'taux') {
-				if ($tabname[$id] != MAIN_DB_PREFIX."c_revenuestamp") {
+				if ($tabname[$id] != "c_revenuestamp") {
 					$valuetoshow = $langs->trans("Rate");
 				} else {
 					$valuetoshow = $langs->trans("Amount");
@@ -1717,6 +1700,10 @@ if ($id) {
 			if ($value == 'libelle_facture') {
 				$valuetoshow = $langs->trans("LabelOnDocuments");
 			}
+			if ($value == 'deposit_percent') {
+				$valuetoshow = $langs->trans('DepositPercent');
+				$cssprefix = 'right ';
+			}
 			if ($value == 'country') {
 				$valuetoshow = $langs->trans("Country");
 			}
@@ -1725,12 +1712,14 @@ if ($id) {
 			}
 			if ($value == 'nbjour') {
 				$valuetoshow = $langs->trans("NbOfDays");
+				$cssprefix = 'right ';
 			}
 			if ($value == 'type_cdr') {
 				$valuetoshow = $langs->trans("AtEndOfMonth"); $cssprefix = "center ";
 			}
 			if ($value == 'decalage') {
 				$valuetoshow = $langs->trans("Offset");
+				$cssprefix = 'right ';
 			}
 			if ($value == 'width' || $value == 'nx') {
 				$valuetoshow = $langs->trans("Width");
@@ -1764,6 +1753,7 @@ if ($id) {
 			}
 			if ($value == 'sortorder') {
 				$valuetoshow = $langs->trans("SortOrder");
+				$cssprefix = 'center ';
 			}
 			if ($value == 'short_label') {
 				$valuetoshow = $langs->trans("ShortLabel");
@@ -1962,58 +1952,58 @@ if ($id) {
 								$key = $langs->trans("PaymentCondition".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "PaymentCondition".strtoupper($obj->code) ? $key : $obj->{$value});
 								$valuetoshow = nl2br($valuetoshow);
-							} elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_country') {
+							} elseif ($value == 'label' && $tabname[$id] == 'c_country') {
 								$key = $langs->trans("Country".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "Country".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_availability') {
+							} elseif ($value == 'label' && $tabname[$id] == 'c_availability') {
 								$langs->load("propal");
 								$key = $langs->trans("AvailabilityType".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "AvailabilityType".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_actioncomm') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_actioncomm') {
 								$key = $langs->trans("Action".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "Action".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif (!empty($obj->code_iso) && $value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_currencies') {
+							} elseif (!empty($obj->code_iso) && $value == 'label' && $tabname[$id] == 'c_currencies') {
 								$key = $langs->trans("Currency".strtoupper($obj->code_iso));
 								$valuetoshow = ($obj->code_iso && $key != "Currency".strtoupper($obj->code_iso) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_typent') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_typent') {
 								$key = $langs->trans(strtoupper($obj->code));
 								$valuetoshow = ($key != strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_prospectlevel') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_prospectlevel') {
 								$key = $langs->trans(strtoupper($obj->code));
 								$valuetoshow = ($key != strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_civility') {
+							} elseif ($value == 'label' && $tabname[$id] == 'c_civility') {
 								$key = $langs->trans("Civility".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "Civility".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_type_contact') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_type_contact') {
 								$langs->load('agenda');
 								$key = $langs->trans("TypeContact_".$obj->element."_".$obj->source."_".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "TypeContact_".$obj->element."_".$obj->source."_".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_payment_term') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_payment_term') {
 								$langs->load("bills");
 								$key = $langs->trans("PaymentConditionShort".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "PaymentConditionShort".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_paiement') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_paiement') {
 								$langs->load("bills");
 								$key = $langs->trans("PaymentType".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "PaymentType".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'type' && $tabname[$id] == MAIN_DB_PREFIX.'c_paiement') {
+							} elseif ($value == 'type' && $tabname[$id] == 'c_paiement') {
 								$payment_type_list = array(0=>$langs->trans('PaymentTypeCustomer'), 1=>$langs->trans('PaymentTypeSupplier'), 2=>$langs->trans('PaymentTypeBoth'));
 								$valuetoshow = $payment_type_list[$valuetoshow];
-							} elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_input_reason') {
+							} elseif ($value == 'label' && $tabname[$id] == 'c_input_reason') {
 								$key = $langs->trans("DemandReasonType".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "DemandReasonType".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_input_method') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_input_method') {
 								$langs->load("orders");
 								$key = $langs->trans($obj->code);
 								$valuetoshow = ($obj->code && $key != $obj->code) ? $key : $obj->{$value};
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_shipment_mode') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_shipment_mode') {
 								$langs->load("sendings");
 								$key = $langs->trans("SendingMethod".strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != "SendingMethod".strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'libelle' && $tabname[$id] == MAIN_DB_PREFIX.'c_paper_format') {
+							} elseif ($value == 'libelle' && $tabname[$id] == 'c_paper_format') {
 								$key = $langs->trans('PaperFormat'.strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != 'PaperFormat'.strtoupper($obj->code) ? $key : $obj->{$value});
-							} elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_type_fees') {
+							} elseif ($value == 'label' && $tabname[$id] == 'c_type_fees') {
 								$langs->load('trips');
 								$key = $langs->trans(strtoupper($obj->code));
 								$valuetoshow = ($obj->code && $key != strtoupper($obj->code) ? $key : $obj->{$value});
@@ -2021,13 +2011,13 @@ if ($id) {
 								$showfield = 0;
 							} elseif ($value == 'unicode') {
 								$valuetoshow = $langs->getCurrencySymbol($obj->code, 1);
-							} elseif ($value == 'label' && $tabname[GETPOST("id", 'int')] == MAIN_DB_PREFIX.'c_units') {
+							} elseif ($value == 'label' && $tabname[GETPOST("id", 'int')] == 'c_units') {
 								$langs->load("products");
 								$valuetoshow = $langs->trans($obj->{$value});
-							} elseif ($value == 'short_label' && $tabname[GETPOST("id", 'int')] == MAIN_DB_PREFIX.'c_units') {
+							} elseif ($value == 'short_label' && $tabname[GETPOST("id", 'int')] == 'c_units') {
 								$langs->load("products");
 								$valuetoshow = $langs->trans($obj->{$value});
-							} elseif (($value == 'unit') && ($tabname[$id] == MAIN_DB_PREFIX.'c_paper_format')) {
+							} elseif (($value == 'unit') && ($tabname[$id] == 'c_paper_format')) {
 								$key = $langs->trans('SizeUnit'.strtolower($obj->unit));
 								$valuetoshow = ($obj->code && $key != 'SizeUnit'.strtolower($obj->unit) ? $key : $obj->{$value});
 							} elseif ($value == 'localtax1' || $value == 'localtax2') {
@@ -2068,20 +2058,20 @@ if ($id) {
 								}
 							} elseif ($value == 'fk_c_exp_tax_cat') {
 								$tmpid = $valuetoshow;
-								$valuetoshow = getDictionaryValue(MAIN_DB_PREFIX.'c_exp_tax_cat', 'label', $tmpid);
+								$valuetoshow = getDictionaryValue('c_exp_tax_cat', 'label', $tmpid);
 								$valuetoshow = $langs->trans($valuetoshow ? $valuetoshow : $tmpid);
-							} elseif ($tabname[$id] == MAIN_DB_PREFIX.'c_exp_tax_cat') {
+							} elseif ($tabname[$id] == 'c_exp_tax_cat') {
 								$valuetoshow = $langs->trans($valuetoshow);
-							} elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_units') {
+							} elseif ($value == 'label' && $tabname[$id] == 'c_units') {
 								$langs->load('other');
 								$key = $langs->trans($obj->label);
 								$valuetoshow = ($obj->label && $key != strtoupper($obj->label) ? $key : $obj->{$value});
 							} elseif ($value == 'code' && $id == 3) {
 								$valuetoshow = $obj->state_code;
-							} elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_product_nature') {
+							} elseif ($value == 'label' && $tabname[$id] == 'c_product_nature') {
 								$langs->load("products");
 								$valuetoshow = $langs->trans($obj->{$value});
-							} elseif ($fieldlist[$field] == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_productbatch_qcstatus') {
+							} elseif ($fieldlist[$field] == 'label' && $tabname[$id] == 'c_productbatch_qcstatus') {
 								$langs->load("productbatch");
 								$valuetoshow = $langs->trans($obj->{$value});
 							} elseif ($value == 'block_if_negative') {
@@ -2097,13 +2087,13 @@ if ($id) {
 							if ($value == 'tracking') {
 								$class .= ' tdoverflowauto';
 							}
-							if (in_array($value, array('pos', 'position'))) {
+							if (in_array($value, array('nbjour', 'decalage', 'pos', 'position', 'deposit_percent'))) {
 								$class .= ' right';
 							}
 							if (in_array($value, array('localtax1_type', 'localtax2_type'))) {
 								$class .= ' nowrap';
 							}
-							if (in_array($value, array('use_default', 'fk_parent'))) {
+							if (in_array($value, array('use_default', 'fk_parent', 'sortorder'))) {
 								$class .= ' center';
 							}
 							if ($value == 'public') {
@@ -2147,7 +2137,7 @@ if ($id) {
 					if (!empty($obj->code) && $obj->code == 'RECEP') {
 						$canbemodified = 1;
 					}
-					if ($tabname[$id] == MAIN_DB_PREFIX."c_actioncomm") {
+					if ($tabname[$id] == "c_actioncomm") {
 						$canbemodified = 1;
 					}
 
@@ -2174,7 +2164,7 @@ if ($id) {
 						if ($iserasable) {
 							print '<a class="reposition" href="'.$url.'action='.$acts[$obj->eec].'_eec&token='.newToken().'">'.$actl[$obj->eec].'</a>';
 						} else {
-							print $langs->trans("AlwaysActive");
+							print '<span class="opacitymedium">'.$langs->trans("AlwaysActive").'</span>';
 						}
 						print '</td>';
 						print '<td class="nowrap center">';
@@ -2182,7 +2172,7 @@ if ($id) {
 						if ($iserasable) {
 							print '<a class="reposition" href="'.$url.'action='.$acts[$obj->favorite].'_favorite&token='.newToken().'">'.$actl[$obj->favorite].'</a>';
 						} else {
-							print $langs->trans("AlwaysActive");
+							print '<span class="opacitymedium">'.$langs->trans("AlwaysActive").'</span>';
 						}
 						print '</td>';
 					}
@@ -2199,7 +2189,7 @@ if ($id) {
 						} elseif (isset($obj->type) && in_array($obj->type, array('system')) && !empty($obj->active) && $obj->code != 'AC_OTH') {
 							print $langs->trans("UsedOnlyWithTypeOption");
 						} else {
-							print $langs->trans("AlwaysActive");
+							print '<span class="opacitymedium">'.$langs->trans("AlwaysActive").'</span>';
 						}
 					}
 					print "</td>";
@@ -2283,7 +2273,7 @@ if ($id) {
 			print '</a>';
 			print '</td>';
 			print '<td class="right">';
-			print $form->textwithpicto('', $langs->trans("Table").': '.$tabname[$i]);
+			print $form->textwithpicto('', $langs->trans("Table").': '.MAIN_DB_PREFIX.$tabname[$i]);
 			print '</td>';
 			print '</tr>';
 			$lastlineisempty = false;
@@ -2333,7 +2323,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			continue;
 		}
 
-		if (in_array($value, array('code', 'libelle', 'type')) && $tabname == MAIN_DB_PREFIX."c_actioncomm" && in_array($obj->type, array('system', 'systemauto'))) {
+		if (in_array($value, array('code', 'libelle', 'type')) && $tabname == "c_actioncomm" && in_array($obj->type, array('system', 'systemauto'))) {
 			$hidden = (!empty($obj->{$value}) ? $obj->{$value}:'');
 			print '<td>';
 			print '<input type="hidden" name="'. $value .'" value="'.$hidden.'">';
@@ -2369,15 +2359,9 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			print '<td>';
 			print $formadmin->select_language($conf->global->MAIN_LANG_DEFAULT, 'lang');
 			print '</td>';
-		} elseif ($value == 'element') {
-			// The type of the element (for contact types)
+		} elseif (in_array($value, array('element', 'source'))) {	//Example: the type and source of the element (for contact types)
 			print '<td>';
-			print $form->selectarray('element', $elementList, (!empty($obj->{$value}) ? $obj->{$value}:''));
-			print '</td>';
-		} elseif ($value == 'source') {
-			// The source of the element (for contact types)
-			print '<td>';
-			print $form->selectarray('source', $sourceList, (!empty($obj->{$value}) ? $obj->{$value}:''));
+			print $form->selectarray($value, $elementList, (!empty($obj->{$value}) ? $obj->{$value}:''));
 			print '</td>';
 		} elseif (in_array($value, array('public', 'use_default'))) {
 			// Fields 0/1 with a combo select Yes/No
@@ -2389,12 +2373,12 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			print '<td>';
 			print $form->selectyesno("private", (!empty($obj->{$value}) ? $obj->{$value}:''));
 			print '</td>';
-		} elseif ($value == 'type' && $tabname == MAIN_DB_PREFIX."c_actioncomm") {
+		} elseif ($value == 'type' && $tabname == "c_actioncomm") {
 			$type = (!empty($obj->type) ? $obj->type : 'user'); // Check if type is different of 'user' (external module)
 			print '<td>';
 			print $type.'<input type="hidden" name="type" value="'.$type.'">';
 			print '</td>';
-		} elseif ($value == 'type' && $tabname == MAIN_DB_PREFIX.'c_paiement') {
+		} elseif ($value == 'type' && $tabname == 'c_paiement') {
 			print '<td>';
 			$select_list = array(0=>$langs->trans('PaymentTypeCustomer'), 1=>$langs->trans('PaymentTypeSupplier'), 2=>$langs->trans('PaymentTypeBoth'));
 			print $form->selectarray($value, $select_list, (!empty($obj->{$value}) ? $obj->{$value}:'2'));
@@ -2412,7 +2396,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			}
 			print '</td>';
 		} elseif (in_array($value, array('nbjour', 'decalage', 'taux', 'localtax1', 'localtax2'))) {
-			$class = "left";
+			$class = "right";
 			if (in_array($value, array('taux', 'localtax1', 'localtax2'))) {
 				$class = "center"; // Fields aligned on right
 			}
@@ -2424,7 +2408,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			$transfound = 0;
 			$transkey = '';
 			// Special case for labels
-			if ($tabname == MAIN_DB_PREFIX.'c_payment_term') {
+			if ($tabname == 'c_payment_term') {
 				$langs->load("bills");
 				$transkey = "PaymentCondition".strtoupper($obj->code);
 				if ($langs->trans($transkey) != $transkey) {
@@ -2490,18 +2474,21 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			print '</td>';
 		} else {
 			$fieldValue = isset($obj->{$value}) ? $obj->{$value}: '';
+			$classtd = ''; $class = '';
 
 			if ($value == 'sortorder') {
 				$fieldlist[$field] = 'position';
 			}
 
-			$classtd = ''; $class = '';
 			if ($fieldlist[$field] == 'code') {
 				$class = 'maxwidth100';
 			}
-			if (in_array($fieldlist[$field], array('pos', 'position'))) {
+			if (in_array($fieldlist[$field], array('deposit_percent'))) {
 				$classtd = 'right'; $class = 'maxwidth50 right';
 			}
+			if (in_array($fieldlist[$field], array('pos', 'position'))) {
+				$classtd = 'center'; $class = 'maxwidth50 center';
+			}
 			if (in_array($fieldlist[$field], array('dayrule', 'day', 'month', 'year', 'use_default', 'affect', 'delay', 'public', 'sortorder', 'sens', 'category_type', 'fk_parent'))) {
 				$class = 'maxwidth50 center';
 			}
@@ -2522,19 +2509,19 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			$maxlength = '';
 			if (in_array($fieldlist[$field], array('libelle', 'label'))) {
 				switch ($tabname) {
-					case MAIN_DB_PREFIX . 'c_accounting_category':
-					case MAIN_DB_PREFIX . 'c_ecotaxe':
-					case MAIN_DB_PREFIX . 'c_email_senderprofile':
-					case MAIN_DB_PREFIX . 'c_forme_juridique':
-					case MAIN_DB_PREFIX . 'c_holiday_types':
-					case MAIN_DB_PREFIX . 'c_payment_term':
-					case MAIN_DB_PREFIX . 'c_transport_mode':
+					case 'c_accounting_category':
+					case 'c_ecotaxe':
+					case 'c_email_senderprofile':
+					case 'c_forme_juridique':
+					case 'c_holiday_types':
+					case 'c_payment_term':
+					case 'c_transport_mode':
 						$maxlength = ' maxlength="255"';
 						break;
-					case MAIN_DB_PREFIX . 'c_email_templates':
+					case 'c_email_templates':
 						$maxlength = ' maxlength="180"';
 						break;
-					case MAIN_DB_PREFIX . 'c_socialnetworks':
+					case 'c_socialnetworks':
 						$maxlength = ' maxlength="150"';
 						break;
 					default:
@@ -2547,10 +2534,10 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			$transkey = '';
 			if (in_array($fieldlist[$field], array('label', 'libelle'))) {		// For label
 				// Special case for labels
-				if ($tabname == MAIN_DB_PREFIX.'c_civility' && !empty($obj->code)) {
+				if ($tabname == 'c_civility' && !empty($obj->code)) {
 					$transkey = "Civility".strtoupper($obj->code);
 				}
-				if ($tabname == MAIN_DB_PREFIX.'c_payment_term' && !empty($obj->code)) {
+				if ($tabname == 'c_payment_term' && !empty($obj->code)) {
 					$langs->load("bills");
 					$transkey = "PaymentConditionShort".strtoupper($obj->code);
 				}

+ 3 - 0
htdocs/admin/dolistore/class/PSWebServiceLibrary.class.php

@@ -232,6 +232,9 @@ class PrestaShopWebservice
 		if ($response != '') {
 			libxml_clear_errors();
 			libxml_use_internal_errors(true);
+			if (!function_exists('simplexml_load_string')) {
+				throw new PrestaShopWebserviceException('Method simplexml_load_string not available. Your PHP does not support xml.');
+			}
 			$xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA|LIBXML_NONET);
 			if (libxml_get_errors()) {
 				$msg = var_export(libxml_get_errors(), true);

+ 12 - 6
htdocs/admin/emailcollector_card.php

@@ -428,15 +428,21 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 				$connectstringtarget = $connectstringserver.$object->getEncodedUtf7($targetdir);
 			}
 
-			$timeoutconnect = empty($conf->global->MAIN_USE_CONNECT_TIMEOUT) ? 10 : $conf->global->MAIN_USE_CONNECT_TIMEOUT;
-			$timeoutread = empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT) ? 30 : $conf->global->MAIN_USE_RESPONSE_TIMEOUT;
+			$timeoutconnect = empty($conf->global->MAIN_USE_CONNECT_TIMEOUT) ? 5 : $conf->global->MAIN_USE_CONNECT_TIMEOUT;
+			$timeoutread = empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT) ? 20 : $conf->global->MAIN_USE_RESPONSE_TIMEOUT;
 
 			dol_syslog("imap_open connectstring=".$connectstringsource." login=".$object->login." password=".$object->password." timeoutconnect=".$timeoutconnect." timeoutread=".$timeoutread);
 
-			imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect);
-			imap_timeout(IMAP_READTIMEOUT, $timeoutread);
+			$result1 = imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect);	// timeout seems ignored with ssl connect
+			$result2 = imap_timeout(IMAP_READTIMEOUT, $timeoutread);
+			$result3 = imap_timeout(IMAP_WRITETIMEOUT, 5);
+			$result4 = imap_timeout(IMAP_CLOSETIMEOUT, 5);
+
+			dol_syslog("result1=".$result1." result2=".$result2." result3=".$result3." result4=".$result4);
 
 			$connection = imap_open($connectstringsource, $object->login, $object->password);
+
+			//dol_syslog("end imap_open connection=".var_export($connection, true));
 		} catch (Exception $e) {
 			print $e->getMessage();
 		}
@@ -490,7 +496,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 	print '<div class="div-table-responsive-no-min">';
 	print '<table id="tablelineoffilters" class="noborder margintable noshadow">';
 	print '<tr class="liste_titre nodrag nodrop">';
-	print '<td>'.img_picto('', 'filter', 'class="pictofixedwidth"').$form->textwithpicto($langs->trans("Filters"), $langs->trans("EmailCollectorFilterDesc")).'</td><td></td><td></td>';
+	print '<td>'.img_picto('', 'filter', 'class="pictofixedwidth opacitymedium"').$form->textwithpicto($langs->trans("Filters"), $langs->trans("EmailCollectorFilterDesc")).'</td><td></td><td></td>';
 	print '</tr>';
 	// Add filter
 	print '<tr class="oddeven nodrag nodrop">';
@@ -647,7 +653,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 			print $form->textwithpicto('', $langs->transnoentitiesnoconv('EmailCollectorLoadThirdPartyHelp'));
 		}
 		print '</td>';
-		print '<td class="wordbreak minwidth300">';
+		print '<td class="wordbreak minwidth300 small">';
 		if ($action == 'editoperation' && $ruleaction['id'] == $operationid) {
 			print '<input type="text" class="quatrevingtquinzepercent" name="operationparam2" value="'.$ruleaction['actionparam'].'"><br>';
 			print '<input type="hidden" name="rowidoperation2" value="'.$ruleaction['id'].'">';

+ 232 - 141
htdocs/admin/emailcollector_list.php

@@ -44,6 +44,7 @@ $toselect   = GETPOST('toselect', 'array'); // Array of ids of elements selected
 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'emailcollectorlist'; // To manage different context of search
 $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
 $optioncss  = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
+$mode       = GETPOST('mode', 'aZ');
 
 $id = GETPOST('id', 'int');
 
@@ -53,8 +54,9 @@ $sortfield = GETPOST('sortfield', 'aZ09comma');
 $sortorder = GETPOST('sortorder', 'aZ09comma');
 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
 if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) {
+	// If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
 	$page = 0;
-}     // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
+}
 $offset = $limit * $page;
 $pageprev = $page - 1;
 $pagenext = $page + 1;
@@ -74,7 +76,7 @@ $search_array_options = $extrafields->getOptionalsFromPost($object->table_elemen
 
 // Default sort order (if not yet defined by previous GETPOST)
 if (!$sortfield) {
-	$sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition.
+	$sortfield = "t.ref"; // Set here default search field. By default 1st field in definition.
 }
 if (!$sortorder) {
 	$sortorder = "ASC";
@@ -89,12 +91,16 @@ if ($user->socid > 0) {	// Protection if external user
 //$result = restrictedArea($user, 'emailcollector', $id, '');
 
 // Initialize array of search criterias
-$search_all = GETPOST("search_all", 'alphanohtml');
+$search_all = GETPOST('search_all', 'alphanohtml');
 $search = array();
 foreach ($object->fields as $key => $val) {
 	if (GETPOST('search_'.$key, 'alpha') !== '') {
 		$search[$key] = GETPOST('search_'.$key, 'alpha');
 	}
+	if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
+		$search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
+		$search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
+	}
 }
 
 // List of fields to search into when doing a "search in all"
@@ -110,29 +116,19 @@ $arrayfields = array();
 foreach ($object->fields as $key => $val) {
 	// If $val['visible']==0, then we never show the field
 	if (!empty($val['visible'])) {
-		$visible = dol_eval($val['visible'], 1, 1, '1');
+		$visible = (int) dol_eval($val['visible'], 1);
 		$arrayfields['t.'.$key] = array(
 			'label'=>$val['label'],
 			'checked'=>(($visible < 0) ? 0 : 1),
-			'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1, 1, '1')),
-			'position'=>$val['position']
+			'enabled'=>(abs($visible) != 3 && dol_eval($val['enabled'], 1)),
+			'position'=>$val['position'],
+			'help'=> isset($val['help']) ? $val['help'] : ''
 		);
 	}
 }
 // Extra fields
-if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) {
-	foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
-		if (!empty($extrafields->attributes[$object->table_element]['list'][$key])) {
-			$arrayfields["ef.".$key] = array(
-				'label'=>$extrafields->attributes[$object->table_element]['label'][$key],
-				'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1),
-				'position'=>$extrafields->attributes[$object->table_element]['pos'][$key],
-				'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key]),
-				'langfile'=>$extrafields->attributes[$object->table_element]['langfile'][$key]
-			);
-		}
-	}
-}
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
+
 $object->fields = dol_sort_array($object->fields, 'position');
 $arrayfields = dol_sort_array($arrayfields, 'position');
 
@@ -157,7 +153,8 @@ if (empty($conf->emailcollector->enabled)) {
  */
 
 if (GETPOST('cancel', 'alpha')) {
-	$action = 'list'; $massaction = '';
+	$action = 'list';
+	$massaction = '';
 }
 if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
 	$massaction = '';
@@ -177,8 +174,12 @@ if (empty($reshook)) {
 	if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
 		foreach ($object->fields as $key => $val) {
 			$search[$key] = '';
+			if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
+				$search[$key.'_dtstart'] = '';
+				$search[$key.'_dtend'] = '';
+			}
 		}
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 	if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
@@ -201,20 +202,22 @@ if (empty($reshook)) {
 
 $form = new Form($db);
 
+$now = dol_now();
+
 $help_url = "EN:Module_EMail_Collector|FR:Module_Collecteur_de_courrier_électronique|ES:Module_EMail_Collector";
 $title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("EmailCollector"));
+$morejs = array();
+$morecss = array();
 
 
 // Build and execute select
 // --------------------------------------------------------------------
 $sql = 'SELECT ';
-foreach ($object->fields as $key => $val) {
-	$sql .= "t.".$key.", ";
-}
+$sql .= $object->getFieldList('t');
 // Add fields from extrafields
 if (!empty($extrafields->attributes[$object->table_element]['label'])) {
 	foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
-		$sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key." as options_".$key.', ' : '');
+		$sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
 	}
 }
 // Add fields from hooks
@@ -232,18 +235,32 @@ if ($object->ismultientitymanaged == 1) {
 	$sql .= " WHERE 1 = 1";
 }
 foreach ($search as $key => $val) {
-	if ($key == 'status' && $search[$key] == -1) {
-		continue;
-	}
-	$mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
-	if (strpos($object->fields[$key]['type'], 'integer:') === 0) {
-		if ($search[$key] == '-1') {
-			$search[$key] = '';
+	if (array_key_exists($key, $object->fields)) {
+		if ($key == 'status' && $search[$key] == -1) {
+			continue;
+		}
+		$mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
+		if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
+			if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
+				$search[$key] = '';
+			}
+			$mode_search = 2;
+		}
+		if ($search[$key] != '') {
+			$sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
+		}
+	} else {
+		if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
+			$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
+			if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
+				if (preg_match('/_dtstart$/', $key)) {
+					$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
+				}
+				if (preg_match('/_dtend$/', $key)) {
+					$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
+				}
+			}
 		}
-		$mode_search = 2;
-	}
-	if ($search[$key] != '') {
-		$sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search));
 	}
 }
 if ($search_all) {
@@ -258,50 +275,49 @@ $sql .= $hookmanager->resPrint;
 
 /* If a group by is required
 $sql.= " GROUP BY ";
-foreach ($object->fields as $key => $val)
-{
-	$sql .= "t.".$key.", ";
+foreach ($object->fields as $key => $val) {
+	$sql .= "t.".$db->escape($key).", ";
 }
 // Add fields from extrafields
 if (! empty($extrafields->attributes[$object->table_element]['label'])) {
-	foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
+	foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
+		$sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
+	}
 }
 // Add where from hooks
 $parameters=array();
-$reshook=$hookmanager->executeHooks('printFieldListGroupBy',$parameters);    // Note that $action and $object may have been modified by hook
-$sql.=$hookmanager->resPrint;
-$sql=preg_replace('/, $/','', $sql);
+$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object);    // Note that $action and $object may have been modified by hook
+$sql .= $hookmanager->resPrint;
+$sql = preg_replace('/,\s*$/', '', $sql);
 */
 
-$sql .= $db->order($sortfield, $sortorder);
-
 // Count total nb of records
 $nbtotalofrecords = '';
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
 	$resql = $db->query($sql);
 	$nbtotalofrecords = $db->num_rows($resql);
+
 	if (($page * $limit) > $nbtotalofrecords) {	// if total of record found is smaller than page * limit, goto and load page 0
 		$page = 0;
 		$offset = 0;
 	}
-}
-// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set.
-if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) {
-	$num = $nbtotalofrecords;
-} else {
-	if ($limit) {
-		$sql .= $db->plimit($limit + 1, $offset);
-	}
 
-	$resql = $db->query($sql);
-	if (!$resql) {
-		dol_print_error($db);
-		exit;
-	}
+	$db->free($resql);
+}
+// Complete request and execute it with limit
+$sql .= $db->order($sortfield, $sortorder);
+if ($limit) {
+	$sql .= $db->plimit($limit + 1, $offset);
+}
 
-	$num = $db->num_rows($resql);
+$resql = $db->query($sql);
+if (!$resql) {
+	dol_print_error($db);
+	exit;
 }
 
+$num = $db->num_rows($resql);
+
 // Direct jump if only one record found
 if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) {
 	$obj = $db->fetch_object($resql);
@@ -314,7 +330,7 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $
 // Output page
 // --------------------------------------------------------------------
 
-llxHeader('', $title, $help_url);
+llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', '');
 
 $arrayofselected = is_array($toselect) ? $toselect : array();
 
@@ -328,9 +344,11 @@ if ($limit > 0 && $limit != $conf->liste_limit) {
 foreach ($search as $key => $val) {
 	if (is_array($search[$key]) && count($search[$key])) {
 		foreach ($search[$key] as $skey) {
-			$param .= '&search_'.$key.'[]='.urlencode($skey);
+			if ($skey != '') {
+				$param .= '&search_'.$key.'[]='.urlencode($skey);
+			}
 		}
-	} else {
+	} elseif ($search[$key] != '') {
 		$param .= '&search_'.$key.'='.urlencode($search[$key]);
 	}
 }
@@ -339,6 +357,10 @@ if ($optioncss != '') {
 }
 // Add $param from extra fields
 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
+// Add $param from hooks
+$parameters = array();
+$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook
+$param .= $hookmanager->resPrint;
 
 // List of mass actions available
 $arrayofmassactions = array(
@@ -353,7 +375,7 @@ if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'pr
 }
 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
 
-print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
+print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
 if ($optioncss != '') {
 	print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
 }
@@ -408,25 +430,43 @@ print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwit
 // Fields title search
 // --------------------------------------------------------------------
 print '<tr class="liste_titre">';
+// Action column
+if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
+	print '<td class="liste_titre maxwidthsearch">';
+	$searchpicto = $form->showFilterButtons('left');
+	print $searchpicto;
+	print '</td>';
+}
 foreach ($object->fields as $key => $val) {
-	$cssforfield = (empty($val['css']) ? '' : $val['css']);
+	$cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
 	if ($key == 'status') {
 		$cssforfield .= ($cssforfield ? ' ' : '').'center';
 	} elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
 		$cssforfield .= ($cssforfield ? ' ' : '').'center';
 	} elseif (in_array($val['type'], array('timestamp'))) {
 		$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
-	} elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') {
+	} elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
 		$cssforfield .= ($cssforfield ? ' ' : '').'right';
 	}
 	if (!empty($arrayfields['t.'.$key]['checked'])) {
 		print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
 		if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
-			print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1);
-		} elseif (strpos($val['type'], 'integer:') === 0) {
-			print $object->showInputField($val, $key, $search[$key], '', '', 'search_', 'maxwidth150', 1);
-		} elseif (!preg_match('/^(date|timestamp)/', $val['type'])) {
-			print '<input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag($search[$key]).'">';
+			print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1);
+		} elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) {
+			print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1);
+		} elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
+			print '<div class="nowrap">';
+			print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
+			print '</div>';
+			print '<div class="nowrap">';
+			print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
+			print '</div>';
+		} elseif ($key == 'lang') {
+			require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
+			$formadmin = new FormAdmin($db);
+			print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2);
+		} else {
+			print '<input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
 		}
 		print '</td>';
 	}
@@ -439,39 +479,51 @@ $parameters = array('arrayfields'=>$arrayfields);
 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook
 print $hookmanager->resPrint;
 // Action column
-print '<td class="liste_titre maxwidthsearch">';
-$searchpicto = $form->showFilterButtons();
-print $searchpicto;
-print '</td>';
+if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
+	print '<td class="liste_titre maxwidthsearch">';
+	$searchpicto = $form->showFilterButtons();
+	print $searchpicto;
+	print '</td>';
+}
 print '</tr>'."\n";
 
+$totalarray = array();
+$totalarray['nbfield'] = 0;
 
 // Fields title label
 // --------------------------------------------------------------------
 print '<tr class="liste_titre">';
+if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
+	print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
+}
 foreach ($object->fields as $key => $val) {
-	$cssforfield = (empty($val['css']) ? '' : $val['css']);
+	$cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
 	if ($key == 'status') {
 		$cssforfield .= ($cssforfield ? ' ' : '').'center';
 	} elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
 		$cssforfield .= ($cssforfield ? ' ' : '').'center';
 	} elseif (in_array($val['type'], array('timestamp'))) {
 		$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
-	} elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') {
+	} elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
 		$cssforfield .= ($cssforfield ? ' ' : '').'right';
 	}
+	$cssforfield = preg_replace('/small\s*/', '', $cssforfield);	// the 'small' css must not be used for the title label
 	if (!empty($arrayfields['t.'.$key]['checked'])) {
 		print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n";
+		$totalarray['nbfield']++;
 	}
 }
 // Extra fields
 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
 // Hook fields
-$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
+$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray);
 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
 print $hookmanager->resPrint;
 // Action column
-print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
+if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
+	print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
+}
+$totalarray['nbfield']++;
 print '</tr>'."\n";
 
 
@@ -489,8 +541,10 @@ if (isset($extrafields->attributes[$object->table_element]['computed']) && is_ar
 // Loop on record
 // --------------------------------------------------------------------
 $i = 0;
-$totalarray = array();
-while ($i < ($limit ? min($num, $limit) : $num)) {
+$savnbfield = $totalarray['nbfield'];
+$totalarray['nbfield'] = 0;
+$imaxinloop = ($limit ? min($num, $limit) : $num);
+while ($i < $imaxinloop) {
 	$obj = $db->fetch_object($resql);
 	if (empty($obj)) {
 		break; // Should not happen
@@ -499,73 +553,107 @@ while ($i < ($limit ? min($num, $limit) : $num)) {
 	// Store properties in $object
 	$object->setVarsFromFetchObj($obj);
 
-	// Show here line of result
-	print '<tr class="oddeven">';
-	foreach ($object->fields as $key => $val) {
-		$cssforfield = (empty($val['css']) ? '' : $val['css']);
-		if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
-			$cssforfield .= ($cssforfield ? ' ' : '').'center';
-		} elseif ($key == 'status') {
-			$cssforfield .= ($cssforfield ? ' ' : '').'center';
+	if ($mode == 'kanban') {
+		if ($i == 0) {
+			print '<tr><td colspan="'.$savnbfield.'">';
+			print '<div class="box-flex-container">';
 		}
-
-		if (in_array($val['type'], array('timestamp'))) {
-			$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
-		} elseif ($key == 'ref') {
-			$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
-		}
-
-		if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status'))) {
-			$cssforfield .= ($cssforfield ? ' ' : '').'right';
+		// Output Kanban
+		print $object->getKanbanView('');
+		if ($i == ($imaxinloop - 1)) {
+			print '</div>';
+			print '</td></tr>';
 		}
-		//if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100';
-
-		if (!empty($arrayfields['t.'.$key]['checked'])) {
-			print '<td'.($cssforfield ? ' class="'.$cssforfield.'"' : '').'>';
-			if ($key == 'status') {
-				print $object->getLibStatut(5);
-			} else {
-				print $object->showOutputField($val, $key, $object->$key, '');
+	} else {
+		// Show here line of result
+		$j = 0;
+		print '<tr data-rowid="'.$object->id.'" class="oddeven">';
+		// Action column
+		if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
+			print '<td class="nowrap center">';
+			if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
+				$selected = 0;
+				if (in_array($object->id, $arrayofselected)) {
+					$selected = 1;
+				}
+				print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
 			}
 			print '</td>';
-			if (!$i) {
-				$totalarray['nbfield']++;
+		}
+		foreach ($object->fields as $key => $val) {
+			$cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
+			if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
+				$cssforfield .= ($cssforfield ? ' ' : '').'center';
+			} elseif ($key == 'status') {
+				$cssforfield .= ($cssforfield ? ' ' : '').'center';
+			}
+
+			if (in_array($val['type'], array('timestamp'))) {
+				$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
+			} elseif ($key == 'ref') {
+				$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
+			}
+
+			if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) {
+				$cssforfield .= ($cssforfield ? ' ' : '').'right';
 			}
-			if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
+			//if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100';
+
+			if (!empty($arrayfields['t.'.$key]['checked'])) {
+				print '<td'.($cssforfield ? ' class="'.$cssforfield.'"' : '');
+				if (preg_match('/tdoverflow/', $cssforfield)) {
+					print ' title="'.dol_escape_htmltag($object->$key).'"';
+				}
+				print '>';
+				if ($key == 'status') {
+					print $object->getLibStatut(5);
+				} elseif ($key == 'rowid') {
+					print $object->showOutputField($val, $key, $object->id, '');
+				} else {
+					print $object->showOutputField($val, $key, $object->$key, '');
+				}
+				print '</td>';
 				if (!$i) {
-					$totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
+					$totalarray['nbfield']++;
 				}
-				if (!isset($totalarray['val'])) {
-					$totalarray['val'] = array();
+				if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
+					if (!$i) {
+						$totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
+					}
+					if (!isset($totalarray['val'])) {
+						$totalarray['val'] = array();
+					}
+					if (!isset($totalarray['val']['t.'.$key])) {
+						$totalarray['val']['t.'.$key] = 0;
+					}
+					$totalarray['val']['t.'.$key] += $object->$key;
 				}
-				if (!isset($totalarray['val']['t.'.$key])) {
-					$totalarray['val']['t.'.$key] = 0;
+			}
+		}
+		// Extra fields
+		include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
+		// Fields from hook
+		$parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
+		$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
+		print $hookmanager->resPrint;
+		// Action column
+		if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
+			print '<td class="nowrap center">';
+			if ($massactionbutton || $massaction) {   // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
+				$selected = 0;
+				if (in_array($object->id, $arrayofselected)) {
+					$selected = 1;
 				}
-				$totalarray['val']['t.'.$key] += $object->$key;
+				print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
 			}
+			print '</td>';
 		}
-	}
-	// Extra fields
-	include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
-	// Fields from hook
-	$parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
-	$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
-	print $hookmanager->resPrint;
-	// Action column
-	print '<td class="nowrap center">';
-	if ($massactionbutton || $massaction) {   // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
-		$selected = 0;
-		if (in_array($object->id, $arrayofselected)) {
-			$selected = 1;
+		if (!$i) {
+			$totalarray['nbfield']++;
 		}
-		print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
-	}
-	print '</td>';
-	if (!$i) {
-		$totalarray['nbfield']++;
-	}
 
-	print '</tr>'."\n";
+		print '</tr>'."\n";
+	}
 
 	$i++;
 }
@@ -582,7 +670,7 @@ if ($num == 0) {
 			$colspan++;
 		}
 	}
-	print '<tr><td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
+	print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
 }
 
 
@@ -596,16 +684,18 @@ print '</table>'."\n";
 print '</div>'."\n";
 
 print load_fiche_titre($langs->trans("Other"), '', '');
+
+
+print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
 print '<table class="noborder centpercent">';
 
 print '<tr class="liste_titre">';
 print '<td>'.$langs->trans("Parameter").'</td>';
 print '<td></td>';
-print '<td></td>';
 print "</tr>\n";
 
 // Hide e-mail headers from collected messages
-print '<tr class="oddeven"><td>'.$langs->trans("EmailCollectorHideMailHeaders").'</td>';
+print '<tr class="oddeven"><td>'.$form->textwithpicto($langs->trans("EmailCollectorHideMailHeaders"), $langs->transnoentitiesnoconv("EmailCollectorHideMailHeadersHelp")).'</td>';
 print '<td class="left">';
 if ($conf->use_javascript_ajax) {
 	print ajax_constantonoff('MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER');
@@ -614,12 +704,13 @@ if ($conf->use_javascript_ajax) {
 	print $form->selectarray("MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER", $arrval, $conf->global->TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND);
 }
 print '</td>';
-print '<td class="center">';
-print $form->textwithpicto('', $langs->trans("EmailCollectorHideMailHeadersHelp"), 1, 'help');
-print '</td>';
 print '</tr>';
 
-print '</table><br>';
+print '</table>';
+print '</div>';
+
+print '<br>';
+
 print '</form>'."\n";
 
 if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {

+ 2 - 2
htdocs/admin/eventorganization.php

@@ -457,7 +457,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 
 								print '<td class="center">';
 								$constforvar = 'EVENTORGANIZATION_'.strtoupper($myTmpObjectKey).'_ADDON';
-								if ($conf->global->$constforvar == $file) {
+								if (getDolGlobalString($constforvar) == $file) {
 									print img_picto($langs->trans("Activated"), 'switch_on');
 								} else {
 									print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmod&token='.newToken().'&object='.strtolower($myTmpObjectKey).'&value='.urlencode($file).'">';
@@ -597,7 +597,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 										// Default
 										print '<td class="center">';
 										$constforvar = 'EVENTORGANIZATION_'.strtoupper($myTmpObjectKey).'_ADDON';
-										if ($conf->global->$constforvar == $name) {
+										if (getDolGlobalString($constforvar) == $name) {
 											//print img_picto($langs->trans("Default"), 'on');
 											// Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset
 											print '<a href="'.$_SERVER["PHP_SELF"].'?action=unsetdoc&amp;token='.newToken().'&amp;object='.urlencode(strtolower($myTmpObjectKey)).'&amp;value='.$name.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').'</a>';

+ 2 - 2
htdocs/admin/expensereport_rules.php

@@ -266,11 +266,11 @@ foreach ($rules as $rule) {
 		if ($rule->fk_c_type_fees == -1) {
 			echo $langs->trans('AllExpenseReport');
 		} else {
-			$key = getDictionaryValue(MAIN_DB_PREFIX . 'c_type_fees', 'code', $rule->fk_c_type_fees, false, 'id');
+			$key = getDictionaryValue('c_type_fees', 'code', $rule->fk_c_type_fees, false, 'id');
 			if ($key && $key != $langs->trans($key)) {
 				echo $langs->trans($key);
 			} else {
-				$value = getDictionaryValue(MAIN_DB_PREFIX . 'c_type_fees', 'label', $rule->fk_c_type_fees, false, 'id');
+				$value = getDictionaryValue('c_type_fees', 'label', $rule->fk_c_type_fees, false, 'id');
 				echo $langs->trans($value ? $value : 'Undefined'); // TODO check to return trans of 'code'
 			}
 		}

+ 11 - 11
htdocs/admin/holiday.php

@@ -442,23 +442,23 @@ print '<td>'.$langs->trans("Parameter").'</td>';
 print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print "</tr>\n";
 
-/*var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_MONDAY);
-var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_FRIDAY);
-var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY);
-var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY);
-*/
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_MONDAY);
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_FRIDAY);
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY);
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY);
+
 if (!isset($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY)) {
 	$conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY = 1;
 }
 if (!isset($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY)) {
 	$conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY = 1;
 }
-/*
-var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_MONDAY);
-var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_FRIDAY);
-var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY);
-var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY);
-*/
+
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_MONDAY);
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_FRIDAY);
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SATURDAY);
+//var_dump($conf->global->MAIN_NON_WORKING_DAYS_INCLUDE_SUNDAY);
+
 
 // Set working days
 print '<tr class="oddeven">';

+ 2 - 2
htdocs/admin/hrm.php

@@ -279,7 +279,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 
 								print '<td class="center">';
 								$constforvar = 'HRMTEST_'.strtoupper($myTmpObjectKey).'_ADDON';
-								if ($conf->global->$constforvar == $file) {
+								if (getDolGlobalString($constforvar) == $file) {
 									print img_picto($langs->trans("Activated"), 'switch_on');
 								} else {
 									print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmod&token='.newToken().'&object='.strtolower($myTmpObjectKey).'&value='.urlencode($file).'">';
@@ -421,7 +421,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 										// Default
 										print '<td class="center">';
 										$constforvar = 'HRMTEST_'.strtoupper($myTmpObjectKey).'_ADDON';
-										if ($conf->global->$constforvar == $name) {
+										if (getDolGlobalString($constforvar) == $name) {
 											//print img_picto($langs->trans("Default"), 'on');
 											// Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset
 											print '<a href="'.$_SERVER["PHP_SELF"].'?action=unsetdoc&amp;token='.newToken().'&amp;object='.urlencode(strtolower($myTmpObjectKey)).'&amp;value='.$name.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').'</a>';

+ 127 - 124
htdocs/admin/ihm.php

@@ -323,130 +323,6 @@ print '<br>';
 
 clearstatcache();
 
-if ($mode == 'template') {
-	// Themes and themes options
-	showSkins(null, 1);
-}
-
-if ($mode == 'dashboard') {
-	print '<div class="div-table-responsive-no-min">';
-	print '<table summary="blockdashboard" class="noborder centpercent editmode tableforfield">';
-
-	// Message of the day on home page
-	$substitutionarray = getCommonSubstitutionArray($langs, 0, array('object', 'objectamount'));
-	complete_substitutions_array($substitutionarray, $langs);
-
-	print '<tr class="oddeven width25p"><td>';
-	$texthelp = $langs->trans("FollowingConstantsWillBeSubstituted") . '<br>';
-	foreach ($substitutionarray as $key => $val) {
-		$texthelp .= $key . '<br>';
-	}
-	print $form->textwithpicto($langs->trans("MessageOfDay"), $texthelp, 1, 'help', '', 0, 2, 'tooltipmessageofday');
-
-	print '</td><td>';
-
-	$doleditor = new DolEditor('main_motd', (isset($conf->global->MAIN_MOTD) ? $conf->global->MAIN_MOTD : ''), '', 142, 'dolibarr_notes', 'In', false, true, true, ROWS_4, '90%');
-	$doleditor->Create();
-
-	print '</td></tr>' . "\n";
-
-	/* no more need for this option. It is now a widget already controlled by end user
-	print '<tr class="oddeven"><td>' . $langs->trans('BoxstatsDisableGlobal') . '</td><td>';
-	print ajax_constantonoff("MAIN_DISABLE_GLOBAL_BOXSTATS", array(), $conf->entity, 0, 0, 1, 0);
-	print '</td>';
-	print '</tr>';
-	*/
-
-	print '</table>';
-	print '</div>';
-
-	print '<br>';
-
-	print '<div class="div-table-responsive-no-min">';
-	print '<table summary="blockdashboard" class="noborder centpercent editmode tableforfield">';
-
-	print '<tr class="liste_titre"><td class="titlefieldmiddle">';
-	print $langs->trans("DashboardDisableBlocks");
-	print '</td><td class="titlefieldmiddle">';
-	print '</td></tr>';
-
-	print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableGlobal') . '</td><td>';
-	print ajax_constantonoff("MAIN_DISABLE_GLOBAL_WORKBOARD", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-	print '</td>';
-	print '</tr>';
-
-	if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) {
-		// Block meteo
-		print '<tr class="oddeven"><td>' . $langs->trans('MAIN_DISABLE_METEO') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_METEO", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block agenda
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockAgenda') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_AGENDA", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block agenda
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockProject') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_PROJECT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block customer
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockCustomer') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_CUSTOMER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block supplier
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockSupplier') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_SUPPLIER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block contract
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockContract') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_CONTRACT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block ticket
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockTicket') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_TICKET", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block bank
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockBank') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_BANK", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block adherent
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockAdherent') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_ADHERENT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block expense report
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockExpenseReport') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_EXPENSEREPORT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-
-		// Block holiday
-		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockHoliday') . '</td><td>';
-		print ajax_constantonoff("MAIN_DISABLE_BLOCK_HOLIDAY", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
-		print '</td>';
-		print '</tr>';
-	}
-
-	print '</table>' . "\n";
-	print '</div>';
-}
-
 if ($mode == 'other') {
 	print '<div class="div-table-responsive-no-min">';
 	print '<table summary="edit" class="noborder centpercent editmode tableforfield">';
@@ -587,6 +463,133 @@ if ($mode == 'other') {
 	print '</div>';
 }
 
+
+if ($mode == 'template') {
+	// Themes and themes options
+	showSkins(null, 1);
+}
+
+
+if ($mode == 'dashboard') {
+	print '<div class="div-table-responsive-no-min">';
+	print '<table summary="blockdashboard" class="noborder centpercent editmode tableforfield">';
+
+	// Message of the day on home page
+	$substitutionarray = getCommonSubstitutionArray($langs, 0, array('object', 'objectamount'));
+	complete_substitutions_array($substitutionarray, $langs);
+
+	print '<tr class="oddeven width25p"><td>';
+	$texthelp = $langs->trans("FollowingConstantsWillBeSubstituted") . '<br>';
+	foreach ($substitutionarray as $key => $val) {
+		$texthelp .= $key . '<br>';
+	}
+	print $form->textwithpicto($langs->trans("MessageOfDay"), $texthelp, 1, 'help', '', 0, 2, 'tooltipmessageofday');
+
+	print '</td><td>';
+
+	$doleditor = new DolEditor('main_motd', (isset($conf->global->MAIN_MOTD) ? $conf->global->MAIN_MOTD : ''), '', 142, 'dolibarr_notes', 'In', false, true, true, ROWS_4, '90%');
+	$doleditor->Create();
+
+	print '</td></tr>' . "\n";
+
+	/* no more need for this option. It is now a widget already controlled by end user
+	 print '<tr class="oddeven"><td>' . $langs->trans('BoxstatsDisableGlobal') . '</td><td>';
+	 print ajax_constantonoff("MAIN_DISABLE_GLOBAL_BOXSTATS", array(), $conf->entity, 0, 0, 1, 0);
+	 print '</td>';
+	 print '</tr>';
+	 */
+
+	print '</table>';
+	print '</div>';
+
+	print '<br>';
+
+	print '<div class="div-table-responsive-no-min">';
+	print '<table summary="blockdashboard" class="noborder centpercent editmode tableforfield">';
+
+	print '<tr class="liste_titre"><td class="titlefieldmiddle">';
+	print $langs->trans("DashboardDisableBlocks");
+	print '</td><td class="titlefieldmiddle">';
+	print '</td></tr>';
+
+	print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableGlobal') . '</td><td>';
+	print ajax_constantonoff("MAIN_DISABLE_GLOBAL_WORKBOARD", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+	print '</td>';
+	print '</tr>';
+
+	if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) {
+		// Block meteo
+		print '<tr class="oddeven"><td>' . $langs->trans('MAIN_DISABLE_METEO') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_METEO", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block agenda
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockAgenda') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_AGENDA", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block agenda
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockProject') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_PROJECT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block customer
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockCustomer') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_CUSTOMER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block supplier
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockSupplier') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_SUPPLIER", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block contract
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockContract') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_CONTRACT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block ticket
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockTicket') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_TICKET", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block bank
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockBank') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_BANK", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block adherent
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockAdherent') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_ADHERENT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block expense report
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockExpenseReport') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_EXPENSEREPORT", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+
+		// Block holiday
+		print '<tr class="oddeven"><td>' . $langs->trans('DashboardDisableBlockHoliday') . '</td><td>';
+		print ajax_constantonoff("MAIN_DISABLE_BLOCK_HOLIDAY", array(), $conf->entity, 0, 0, 1, 0, 0, 0, '_red', 'dashboard');
+		print '</td>';
+		print '</tr>';
+	}
+
+	print '</table>' . "\n";
+	print '</div>';
+}
+
+
 if ($mode == 'login') {
 	// Other
 	print '<div class="div-table-responsive-no-min">';

+ 2 - 2
htdocs/admin/knowledgemanagement.php

@@ -403,7 +403,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 
 								print '<td class="center">';
 								$constforvar = 'KNOWLEDGEMANAGEMENT_'.strtoupper($myTmpObjectKey).'_ADDON';
-								if ($conf->global->$constforvar == $file) {
+								if (getDolGlobalString($constforvar) == $file) {
 									print img_picto($langs->trans("Activated"), 'switch_on');
 								} else {
 									print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmod&token='.newToken().'&object='.strtolower($myTmpObjectKey).'&value='.urlencode($file).'">';
@@ -545,7 +545,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 										// Default
 										print '<td class="center">';
 										$constforvar = 'KNOWLEDGEMANAGEMENT_'.strtoupper($myTmpObjectKey).'_ADDON';
-										if ($conf->global->$constforvar == $name) {
+										if (getDolGlobalString($constforvar) == $name) {
 											//print img_picto($langs->trans("Default"), 'on');
 											// Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset
 											print '<a href="'.$_SERVER["PHP_SELF"].'?action=unsetdoc&amp;token='.newToken().'&amp;object='.urlencode(strtolower($myTmpObjectKey)).'&amp;value='.$name.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').'</a>';

+ 1 - 1
htdocs/admin/mails_senderprofile_list.php

@@ -169,7 +169,7 @@ if (empty($reshook)) {
 		foreach ($object->fields as $key => $val) {
 			$search[$key] = '';
 		}
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 	if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')

+ 258 - 193
htdocs/admin/mails_templates.php

@@ -66,10 +66,6 @@ $search_lang = GETPOST('search_lang', 'alpha');
 $search_fk_user = GETPOST('search_fk_user', 'intcomma');
 $search_topic = GETPOST('search_topic', 'alpha');
 
-if (!empty($user->socid)) {
-	accessforbidden();
-}
-
 $acts = array();
 $actl = array();
 $acts[0] = "activate";
@@ -100,6 +96,7 @@ if (empty($sortorder)) {
 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
 $hookmanager->initHooks(array('emailtemplates'));
 
+
 // Name of SQL tables of dictionaries
 $tabname = array();
 $tabname[25] = MAIN_DB_PREFIX."c_email_templates";
@@ -246,6 +243,12 @@ if ($reshook == 0) {
 	}
 }
 
+
+
+if (!empty($user->socid)) {
+	accessforbidden();
+}
+
 $permissiontoadd = 1;
 
 //asort($elementList);
@@ -273,6 +276,9 @@ if ($reshook < 0) {
 }
 
 if (empty($reshook)) {
+	// Selection of new fields
+	include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
+
 	// Purge search criteria
 	if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
 		// All tests are required to be compatible with all browsers
@@ -281,7 +287,7 @@ if (empty($reshook)) {
 		$search_lang = '';
 		$search_fk_user = '';
 		$search_topic = '';
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 
@@ -395,7 +401,7 @@ if (empty($reshook)) {
 					}
 				} elseif ($keycode == 'content') {
 					$sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'";
-				} elseif (in_array($keycode, array('joinfiles', 'private', 'position'))) {
+				} elseif (in_array($keycode, array('joinfiles', 'private', 'position', 'entity'))) {
 					$sql .= (int) GETPOST($keycode, 'int');
 				} else {
 					$sql .= "'".$db->escape(GETPOST($keycode, 'nohtml'))."'";
@@ -502,9 +508,9 @@ if (empty($reshook)) {
 	if ($action == 'confirm_delete' && $confirm == 'yes') {       // delete
 		$rowidcol = "rowid";
 
-		$sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol."=".((int) $rowid);
+		$sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol." = ".((int) $rowid);
 		if (!$user->admin) {	// A non admin user can only edit its own template
-			$sql .= " AND fk_user  = ".((int) $user->id);
+			$sql .= " AND fk_user = ".((int) $user->id);
 		}
 		dol_syslog("delete", LOG_DEBUG);
 		$result = $db->query($sql);
@@ -548,47 +554,20 @@ if (empty($reshook)) {
  */
 
 $form = new Form($db);
+
+$now = dol_now();
+
 $formadmin = new FormAdmin($db);
 
+//$help_url = "EN:Module_MyObject|FR:Module_MyObject_FR|ES:Módulo_MyObject";
 $help_url = '';
 if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
 	$title = $langs->trans("EMailsSetup");
 } else {
-	$title = $langs->trans("EMailsTemplates");
+	$title = $langs->trans("EMailTemplates");
 }
-
-llxHeader('', $title, $help_url);
-
-$linkback = '';
-$titlepicto = 'title_setup';
-
-
-$url = DOL_URL_ROOT.'/admin/mails_templates.php?action=add';
-$newcardbutton = dolGetButtonTitle($langs->trans('NewEMailTemplate'), '', 'fa fa-plus-circle', $url, '', $permissiontoadd);
-
-
-if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
-	print load_fiche_titre($title, '', $titlepicto);
-} else {
-	print load_fiche_titre($title, $newcardbutton, $titlepicto);
-}
-
-if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
-	$head = email_admin_prepare_head();
-
-	print dol_get_fiche_head($head, 'templates', '', -1);
-
-	if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
-		print load_fiche_titre('', $newcardbutton, '');
-	}
-}
-
-
-// Confirmation de la suppression de la ligne
-if ($action == 'delete') {
-	print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.$rowid.'&code='.$code.'&id='.$id, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
-}
-
+$morejs = array();
+$morecss = array();
 
 $sql = "SELECT rowid as rowid, module, label, type_template, lang, fk_user, private, position, topic, joinfiles, content_lines, content, enabled, active";
 $sql .= " FROM ".MAIN_DB_PREFIX."c_email_templates";
@@ -623,6 +602,78 @@ $sql .= $db->order($sortfield, $sortorder);
 $sql .= $db->plimit($listlimit + 1, $offset);
 //print $sql;
 
+// Output page
+// --------------------------------------------------------------------
+
+llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', '');
+
+$arrayofselected = is_array($toselect) ? $toselect : array();
+
+$param = '';
+if (!empty($mode)) {
+	$param .= '&mode='.urlencode($mode);
+}
+if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
+	$param .= '&contextpage='.urlencode($contextpage);
+}
+if ($limit > 0 && $limit != $conf->liste_limit) {
+	$param .= '&limit='.urlencode($limit);
+}
+foreach ($search as $key => $val) {
+	if (is_array($search[$key]) && count($search[$key])) {
+		foreach ($search[$key] as $skey) {
+			if ($skey != '') {
+				$param .= '&search_'.$key.'[]='.urlencode($skey);
+			}
+		}
+	} elseif ($search[$key] != '') {
+		$param .= '&search_'.$key.'='.urlencode($search[$key]);
+	}
+}
+if ($optioncss != '') {
+	$param .= '&optioncss='.urlencode($optioncss);
+}
+// Add $param from extra fields
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
+// Add $param from hooks
+$parameters = array();
+$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook
+$param .= $hookmanager->resPrint;
+
+
+$linkback = '';
+$titlepicto = 'title_setup';
+
+
+$url = DOL_URL_ROOT.'/admin/mails_templates.php?action=add&token='.newToken();
+$newcardbutton = dolGetButtonTitle($langs->trans('NewEMailTemplate'), '', 'fa fa-plus-circle', $url, '', $permissiontoadd);
+
+
+if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
+	print load_fiche_titre($title, '', $titlepicto);
+} else {
+	print load_fiche_titre($title, $newcardbutton, $titlepicto);
+}
+
+if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
+	$head = email_admin_prepare_head();
+
+	print dol_get_fiche_head($head, 'templates', '', -1);
+
+	if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
+		print load_fiche_titre('', $newcardbutton, '');
+	}
+}
+
+
+// Confirmation de la suppression de la ligne
+if ($action == 'delete') {
+	print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.$rowid.'&code='.$code.'&id='.$id, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
+}
+
+
+
+
 $fieldlist = explode(',', $tabfield[$id]);
 
 if ($action == 'add') {
@@ -681,7 +732,7 @@ if ($action == 'add') {
 		}
 
 		if ($valuetoshow != '') {
-			print '<td class="'.$align.'">';
+			print '<th class="'.$align.'">';
 			if (!empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i', $tabhelp[$id][$value])) {
 				print '<a href="'.$tabhelp[$id][$value].'" target="_blank" rel="noopener noreferrer">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
 			} elseif (!empty($tabhelp[$id][$value])) {
@@ -693,12 +744,12 @@ if ($action == 'add') {
 			} else {
 				print $valuetoshow;
 			}
-			print '</td>';
+			print '</th>';
 		}
 	}
-	print '<td>';
+	print '<th>';
 	print '<input type="hidden" name="id" value="'.$id.'">';
-	print '</td>';
+	print '</th>';
 	print '</tr>';
 
 	$obj = new stdClass();
@@ -742,7 +793,7 @@ if ($action == 'add') {
 		$fieldsforcontent = array('topic', 'joinfiles', 'content', 'content_lines');
 	}
 	foreach ($fieldsforcontent as $tmpfieldlist) {
-		print '<tr class="impair nodrag nodrop nohover"><td colspan="6" class="nobottom">';
+		print '<tr class="impair nodrag nodrop nohover"><td colspan="7" class="nobottom">';
 
 		// Label
 		if ($tmpfieldlist == 'topic') {
@@ -773,24 +824,33 @@ if ($action == 'add') {
 			print $doleditor->Create(1);
 		}
 		print '</td>';
-		if ($tmpfieldlist == 'topic') {
-			print '<td class="center" rowspan="'.(count($fieldsforcontent)).'">';
-			if ($action != 'edit') {
-				print '<input type="submit" class="button button-add" name="actionadd" value="'.$langs->trans("Add").'"><br>';
-				print '<input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
-			}
-			print '</td>';
-		}
-		// else print '<td></td>';
 		print '</tr>';
 	}
 
 	print '</table>';
+
+	if ($action != 'edit') {
+		print '<center>';
+		print '<input type="submit" class="button button-add" name="actionadd" value="'.$langs->trans("Add").'"> ';
+		print '<input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
+		print '</center>';
+	}
+
 	print '</div>';
 	print '</form>';
-	print '<br>';
+	print '<br><br>';
 } // END IF not edit
 
+// List of available record in database
+dol_syslog("htdocs/admin/dict", LOG_DEBUG);
+$resql = $db->query($sql);
+if (!$resql) {
+	dol_print_error($db);
+	exit;
+}
+
+$num = $db->num_rows($resql);
+
 print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
 print '<input type="hidden" name="token" value="'.newToken().'">';
 print '<input type="hidden" name="from" value="'.dol_escape_htmltag(GETPOST('from', 'alpha')).'">';
@@ -798,157 +858,155 @@ print '<input type="hidden" name="from" value="'.dol_escape_htmltag(GETPOST('fro
 print '<div class="div-table-responsive-no-min">';
 print '<table class="noborder centpercent">';
 
-// List of available record in database
-dol_syslog("htdocs/admin/dict", LOG_DEBUG);
-$resql = $db->query($sql);
-if ($resql) {
-	$num = $db->num_rows($resql);
-	$i = 0;
+$i = 0;
+
+$param = '&id='.$id;
+if ($search_label) {
+	$param .= '&search_label='.urlencode($search_label);
+}
+if ($search_lang > 0) {
+	$param .= '&search_lang='.urlencode($search_lang);
+}
+if ($search_type_template != '-1') {
+	$param .= '&search_type_template='.urlencode($search_type_template);
+}
+if ($search_fk_user > 0) {
+	$param .= '&search_fk_user='.urlencode($search_fk_user);
+}
+if ($search_topic) {
+	$param .= '&search_topic='.urlencode($search_topic);
+}
+
+$paramwithsearch = $param;
+if ($sortorder) {
+	$paramwithsearch .= '&sortorder='.urlencode($sortorder);
+}
+if ($sortfield) {
+	$paramwithsearch .= '&sortfield='.urlencode($sortfield);
+}
+if (GETPOST('from', 'alpha')) {
+	$paramwithsearch .= '&from='.urlencode(GETPOST('from', 'alpha'));
+}
+
+// There is several pages
+if ($num > $listlimit) {
+	print '<tr class="none"><td class="right" colspan="'.(3 + count($fieldlist)).'">';
+	print_fleche_navigation($page, $_SERVER["PHP_SELF"], $paramwithsearch, ($num > $listlimit), '<li class="pagination"><span>'.$langs->trans("Page").' '.($page + 1).'</span></li>');
+	print '</td></tr>';
+}
+
 
-	$param = '&id='.$id;
-	if ($search_label) {
-		$param .= '&search_label='.urlencode($search_label);
+// Title line with search boxes
+print '<tr class="liste_titre">';
+
+foreach ($fieldlist as $field => $value) {
+	if ($value == 'label') {
+		print '<td class="liste_titre"><input type="text" name="search_label" class="maxwidth200" value="'.dol_escape_htmltag($search_label).'"></td>';
+	} elseif ($value == 'lang') {
+		print '<td class="liste_titre">';
+		print $formadmin->select_language($search_lang, 'search_lang', 0, null, 1, 0, 0, 'maxwidth150');
+		print '</td>';
+	} elseif ($value == 'fk_user') {
+		print '<td class="liste_titre">';
+		print $form->select_dolusers($search_fk_user, 'search_fk_user', 1, null, 0, ($user->admin ? '' : 'hierarchyme'), null, 0, 0, 0, '', 0, '', 'maxwidth150');
+		print '</td>';
+	} elseif ($value == 'topic') {
+		print '<td class="liste_titre"><input type="text" name="search_topic" value="'.dol_escape_htmltag($search_topic).'"></td>';
+	} elseif ($value == 'type_template') {
+		print '<td class="liste_titre center">';
+		print $form->selectarray('search_type_template', $elementList, $search_type_template, 1, 0, 0, '', 0, 0, 0, '', 'minwidth150', 1, '', 0, 1);
+		print '</td>';
+	} elseif (!in_array($value, array('content', 'content_lines'))) {
+		print '<td class="liste_titre"></td>';
 	}
-	if ($search_lang > 0) {
-		$param .= '&search_lang='.urlencode($search_lang);
+}
+
+if (empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES)) {
+	print '<td class="liste_titre"></td>';
+}
+
+// Action column
+print '<td class="liste_titre right" width="64">';
+$searchpicto = $form->showFilterButtons();
+print $searchpicto;
+print '</td>';
+print '</tr>';
+
+// Title of lines
+print '<tr class="liste_titre">';
+foreach ($fieldlist as $field => $value) {
+	$showfield = 1; // By defaut
+	$align = "left";
+	$sortable = 1;
+	$valuetoshow = '';
+	$forcenowrap = 1;
+	/*
+	$tmparray=getLabelOfField($fieldlist[$field]);
+	$showfield=$tmp['showfield'];
+	$valuetoshow=$tmp['valuetoshow'];
+	$align=$tmp['align'];
+	$sortable=$tmp['sortable'];
+	*/
+	$valuetoshow = ucfirst($fieldlist[$field]); // By defaut
+	$valuetoshow = $langs->trans($valuetoshow); // try to translate
+	if ($fieldlist[$field] == 'fk_user') {
+		$valuetoshow = $langs->trans("Owner");
 	}
-	if ($search_type_template != '-1') {
-		$param .= '&search_type_template='.urlencode($search_type_template);
+	if ($fieldlist[$field] == 'lang') {
+		$valuetoshow = $langs->trans("Language");
 	}
-	if ($search_fk_user > 0) {
-		$param .= '&search_fk_user='.urlencode($search_fk_user);
+	if ($fieldlist[$field] == 'type') {
+		$valuetoshow = $langs->trans("Type");
 	}
-	if ($search_topic) {
-		$param .= '&search_topic='.urlencode($search_topic);
+	if ($fieldlist[$field] == 'libelle' || $fieldlist[$field] == 'label') {
+		$valuetoshow = $langs->trans("Code");
 	}
-
-	$paramwithsearch = $param;
-	if ($sortorder) {
-		$paramwithsearch .= '&sortorder='.urlencode($sortorder);
+	if ($fieldlist[$field] == 'type_template') {
+		$align = 'center';
+		$valuetoshow = $langs->trans("TypeOfTemplate");
 	}
-	if ($sortfield) {
-		$paramwithsearch .= '&sortfield='.urlencode($sortfield);
+	if ($fieldlist[$field] == 'private') {
+		$align = 'center';
 	}
-	if (GETPOST('from', 'alpha')) {
-		$paramwithsearch .= '&from='.urlencode(GETPOST('from', 'alpha'));
+	if ($fieldlist[$field] == 'position') {
+		$align = 'center';
 	}
 
-	// There is several pages
-	if ($num > $listlimit) {
-		print '<tr class="none"><td class="right" colspan="'.(3 + count($fieldlist)).'">';
-		print_fleche_navigation($page, $_SERVER["PHP_SELF"], $paramwithsearch, ($num > $listlimit), '<li class="pagination"><span>'.$langs->trans("Page").' '.($page + 1).'</span></li>');
-		print '</td></tr>';
+	if ($fieldlist[$field] == 'joinfiles') {
+		$valuetoshow = $langs->trans("FilesAttachedToEmail"); $align = 'center'; $forcenowrap = 0;
 	}
-
-
-	// Title line with search boxes
-	print '<tr class="liste_titre">';
-
-	foreach ($fieldlist as $field => $value) {
-		if ($value == 'label') {
-			print '<td class="liste_titre"><input type="text" name="search_label" class="maxwidth200" value="'.dol_escape_htmltag($search_label).'"></td>';
-		} elseif ($value == 'lang') {
-			print '<td class="liste_titre">';
-			print $formadmin->select_language($search_lang, 'search_lang', 0, null, 1, 0, 0, 'maxwidth150');
-			print '</td>';
-		} elseif ($value == 'fk_user') {
-			print '<td class="liste_titre">';
-			print $form->select_dolusers($search_fk_user, 'search_fk_user', 1, null, 0, ($user->admin ? '' : 'hierarchyme'), null, 0, 0, 0, '', 0, '', 'maxwidth150');
-			print '</td>';
-		} elseif ($value == 'topic') {
-			print '<td class="liste_titre"><input type="text" name="search_topic" value="'.dol_escape_htmltag($search_topic).'"></td>';
-		} elseif ($value == 'type_template') {
-			print '<td class="liste_titre center">';
-			print $form->selectarray('search_type_template', $elementList, $search_type_template, 1, 0, 0, '', 0, 0, 0, '', 'minwidth150', 1, '', 0, 1);
-			print '</td>';
-		} elseif (!in_array($value, array('content', 'content_lines'))) {
-			print '<td class="liste_titre"></td>';
-		}
+	if ($fieldlist[$field] == 'content') {
+		$valuetoshow = $langs->trans("Content"); $showfield = 0;
 	}
-
-	if (empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES)) {
-		print '<td class="liste_titre"></td>';
+	if ($fieldlist[$field] == 'content_lines') {
+		$valuetoshow = $langs->trans("ContentForLines"); $showfield = 0;
 	}
 
-	// Action column
-	print '<td class="liste_titre right" width="64">';
-	$searchpicto = $form->showFilterButtons();
-	print $searchpicto;
-	print '</td>';
-	print '</tr>';
-
-	// Title of lines
-	print '<tr class="liste_titre">';
-	foreach ($fieldlist as $field => $value) {
-		$showfield = 1; // By defaut
-		$align = "left";
-		$sortable = 1;
-		$valuetoshow = '';
-		$forcenowrap = 1;
-		/*
-		$tmparray=getLabelOfField($fieldlist[$field]);
-		$showfield=$tmp['showfield'];
-		$valuetoshow=$tmp['valuetoshow'];
-		$align=$tmp['align'];
-		$sortable=$tmp['sortable'];
-		*/
-		$valuetoshow = ucfirst($fieldlist[$field]); // By defaut
-		$valuetoshow = $langs->trans($valuetoshow); // try to translate
-		if ($fieldlist[$field] == 'fk_user') {
-			$valuetoshow = $langs->trans("Owner");
-		}
-		if ($fieldlist[$field] == 'lang') {
-			$valuetoshow = $langs->trans("Language");
-		}
-		if ($fieldlist[$field] == 'type') {
-			$valuetoshow = $langs->trans("Type");
-		}
-		if ($fieldlist[$field] == 'libelle' || $fieldlist[$field] == 'label') {
-			$valuetoshow = $langs->trans("Code");
-		}
-		if ($fieldlist[$field] == 'type_template') {
-			$align = 'center';
-			$valuetoshow = $langs->trans("TypeOfTemplate");
-		}
-		if ($fieldlist[$field] == 'private') {
-			$align = 'center';
-		}
-		if ($fieldlist[$field] == 'position') {
-			$align = 'center';
-		}
-
-		if ($fieldlist[$field] == 'joinfiles') {
-			$valuetoshow = $langs->trans("FilesAttachedToEmail"); $align = 'center'; $forcenowrap = 0;
-		}
-		if ($fieldlist[$field] == 'content') {
-			$valuetoshow = $langs->trans("Content"); $showfield = 0;
-		}
-		if ($fieldlist[$field] == 'content_lines') {
-			$valuetoshow = $langs->trans("ContentForLines"); $showfield = 0;
-		}
-
-		// Show fields
-		if ($showfield) {
-			if (!empty($tabhelp[$id][$value])) {
-				if (in_array($value, array('topic'))) {
-					$valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, 'tooltip'.$value, $forcenowrap); // Tooltip on click
-				} else {
-					$valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, '', $forcenowrap); // Tooltip on hover
-				}
+	// Show fields
+	if ($showfield) {
+		if (!empty($tabhelp[$id][$value])) {
+			if (in_array($value, array('topic'))) {
+				$valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, 'tooltip'.$value, $forcenowrap); // Tooltip on click
+			} else {
+				$valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, '', $forcenowrap); // 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);
 	}
+}
 
-	print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "active", ($page ? 'page='.$page.'&' : ''), $param, 'align="center"', $sortfield, $sortorder);
-	print getTitleFieldOfList('');
-	print '</tr>';
+print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "active", ($page ? 'page='.$page.'&' : ''), $param, 'align="center"', $sortfield, $sortorder);
+print getTitleFieldOfList('');
+print '</tr>';
+
+if ($num) {
+	$nbqualified = 0;
 
-	if ($num) {
-		// Lines with values
-		while ($i < $num) {
-			$obj = $db->fetch_object($resql);
+	// Lines with values
+	while ($i < $num) {
+		$obj = $db->fetch_object($resql);
 
+		if ($obj) {
 			if ($action == 'edit' && ($rowid == (!empty($obj->rowid) ? $obj->rowid : $obj->code))) {
 				print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
 
@@ -1018,6 +1076,8 @@ if ($resql) {
 				}
 
 				print "</tr>\n";
+
+				$nbqualified++;
 			} else {
 				// If template is for a module, check module is enabled.
 				if ($obj->module) {
@@ -1039,6 +1099,8 @@ if ($resql) {
 					continue; // Email template not qualified
 				}
 
+				$nbqualified++;
+
 				print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
 
 				$tmpaction = 'view';
@@ -1155,13 +1217,16 @@ if ($resql) {
 
 				print "</tr>\n";
 			}
-
-
-			$i++;
 		}
+
+		$i++;
 	}
-} else {
-	dol_print_error($db);
+}
+
+// If no record found
+if ($nbqualified == 0) {
+	$colspan = 10;
+	print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
 }
 
 print '</table>';

+ 7 - 3
htdocs/admin/modulehelp.php

@@ -172,6 +172,10 @@ foreach ($modulesdir as $dir) {
 										$moduleposition = '80'; // External modules at end by default
 									}
 
+									if (empty($familyinfo[$familykey]['position'])) {
+										$familyinfo[$familykey]['position'] = '0';
+									}
+
 									$orders[$i] = $familyinfo[$familykey]['position']."_".$familykey."_".$moduleposition."_".$j; // Sort by family, then by module position then number
 									$dirmod[$i] = $dir;
 									//print $i.'-'.$dirmod[$i].'<br>';
@@ -250,19 +254,19 @@ if (!empty($conf->global->$const_name)) {
 	$text .= $langs->trans("Disabled");
 }
 $tmp = $objMod->getLastActivationInfo();
-$authorid = $tmp['authorid'];
+$authorid = (empty($tmp['authorid']) ? '' : $tmp['authorid']);
 if ($authorid > 0) {
 	$tmpuser = new User($db);
 	$tmpuser->fetch($authorid);
 	$text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationAuthor").':</span> ';
 	$text .= $tmpuser->getNomUrl(1);
 }
-$ip = $tmp['ip'];
+$ip = (empty($tmp['ip']) ? '' : $tmp['ip']);
 if ($ip) {
 	$text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationIP").':</span> ';
 	$text .= $ip;
 }
-$lastactivationversion = $tmp['lastactivationversion'];
+$lastactivationversion = (empty($tmp['lastactivationversion']) ? '' : $tmp['lastactivationversion']);
 if ($lastactivationversion) {
 	$text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationVersion").':</span> ';
 	$text .= $lastactivationversion;

+ 4 - 4
htdocs/admin/system/filecheck.php

@@ -407,10 +407,10 @@ if (empty($error) && !empty($xml)) {
 	$checksumget = md5(join(',', $checksumconcat));
 	$checksumtoget = trim((string) $xml->dolibarr_htdocs_dir_checksum);
 
-	/*var_dump(count($file_list['added']));
-	var_dump($checksumget);
-	var_dump($checksumtoget);
-	var_dump($checksumget == $checksumtoget);*/
+	//var_dump(count($file_list['added']));
+	//var_dump($checksumget);
+	//var_dump($checksumtoget);
+	//var_dump($checksumget == $checksumtoget);
 
 	$resultcomment = '';
 

+ 16 - 0
htdocs/admin/system/phpinfo.php

@@ -183,6 +183,22 @@ print "<td>".$name."</td>";
 print getResultColumn($name, $activatedExtensions, $loadedExtensions, $functions);
 print "</tr>";
 
+$functions = ["easter_date"];
+$name      = "Calendar";
+
+print "<tr>";
+print "<td>".$name."</td>";
+print getResultColumn($name, $activatedExtensions, $loadedExtensions, $functions);
+print "</tr>";
+
+$functions = ["simplexml_load_string"];
+$name      = "Xml";
+
+print "<tr>";
+print "<td>".$name."</td>";
+print getResultColumn($name, $activatedExtensions, $loadedExtensions, $functions);
+print "</tr>";
+
 if (empty($_SERVER["SERVER_ADMIN"]) || $_SERVER["SERVER_ADMIN"] != 'doliwamp@localhost') {
 	$functions = ["locale_get_primary_language", "locale_get_region"];
 	$name      = "Intl";

+ 0 - 17
htdocs/admin/system/xcache.php

@@ -58,23 +58,6 @@ print $langs->trans("xcache.optimizer").': '.yn(ini_get('xcache.optimizer')).' (
 print $langs->trans("xcache.stat").': '.yn(ini_get('xcache.stat')).'<br>'."\n";
 print $langs->trans("xcache.coverager").': '.yn(ini_get('xcache.coverager')).'<br>'."\n";
 
-//print xcache_get();
-/*
-$cacheinfos = array();
-for ($i = 0; $i < 10; $i ++)
-{
-	$data = xcache_info(XC_TYPE_PHP, $i);
-	$data['cacheid'] = $i;
-	$cacheinfos[] = $data;
-}
-
-var_dump($cacheinfos);
-
-if ($action == 'clear')
-{
-	xcache_clear_cache();
-}
-*/
 
 // End of page
 llxFooter();

+ 70 - 106
htdocs/admin/ticket.php

@@ -99,6 +99,50 @@ if ($action == 'updateMask') {
 	// par appel methode canBeActivated
 
 	dolibarr_set_const($db, "TICKET_ADDON", $value, 'chaine', 0, '', $conf->entity);
+} elseif ($action == 'setvarworkflow') {
+	$param_auto_read = GETPOST('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'alpha');
+	$res = dolibarr_set_const($db, 'TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', $param_auto_read, 'chaine', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+	}
+
+	$param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha');
+	$res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+	}
+
+	$param_limit_view = GETPOST('TICKET_LIMIT_VIEW_ASSIGNED_ONLY', 'alpha');
+	$res = dolibarr_set_const($db, 'TICKET_LIMIT_VIEW_ASSIGNED_ONLY', $param_limit_view, 'chaine', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+	}
+
+	if (GETPOSTISSET('product_category_id')) {
+		$param_ticket_product_category = GETPOST('product_category_id', 'int');
+		$res = dolibarr_set_const($db, 'TICKET_PRODUCT_CATEGORY', $param_ticket_product_category, 'chaine', 0, '', $conf->entity);
+		if (!($res > 0)) {
+			$error++;
+		}
+	}
+
+	$param_delay_first_response = GETPOST('delay_first_response', 'int');
+	$res = dolibarr_set_const($db, 'TICKET_DELAY_BEFORE_FIRST_RESPONSE', $param_delay_first_response, 'chaine', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+	}
+
+	$param_delay_between_responses = GETPOST('delay_between_responses', 'int');
+	$res = dolibarr_set_const($db, 'TICKET_DELAY_SINCE_LAST_RESPONSE', $param_delay_between_responses, 'chaine', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+	}
+
+	$param_auto_notify_close = GETPOST('TICKET_NOTIFY_AT_CLOSING', 'alpha');
+	$res = dolibarr_set_const($db, 'TICKET_NOTIFY_AT_CLOSING', $param_auto_notify_close, 'chaine', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+	}
 } elseif ($action == 'setvar') {
 	include_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
 
@@ -146,50 +190,6 @@ if ($action == 'updateMask') {
 	if (!($res > 0)) {
 		$error++;
 	}
-}
-
-if ($action == 'setvarworkflow') {
-	$param_auto_read = GETPOST('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', $param_auto_read, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-}
-
-if ($action == 'setvarworkflowother' || $action == 'setvarworkflow') {
-	$param_ticket_product_category = GETPOST('product_category_id', 'int');
-	$res = dolibarr_set_const($db, 'TICKET_PRODUCT_CATEGORY', $param_ticket_product_category, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-}
-
-if ($action == 'setvarother') {
-	$param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_disable_email = GETPOST('TICKET_DISABLE_NOTIFICATION_MAILS', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_DISABLE_NOTIFICATION_MAILS', $param_disable_email, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	if ($conf->global->MAIN_FEATURES_LEVEL >= 2) {
-		$param_show_module_logo = GETPOST('TICKET_SHOW_MODULE_LOGO', 'alpha');
-		$res = dolibarr_set_const($db, 'TICKET_SHOW_MODULE_LOGO', $param_show_module_logo, 'chaine', 0, '', $conf->entity);
-		if (!($res > 0)) {
-			$error++;
-		}
-	}
 
 	if ($conf->global->MAIN_FEATURES_LEVEL >= 2) {
 		$param_notification_also_main_addressemail = GETPOST('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS', 'alpha');
@@ -198,34 +198,9 @@ if ($action == 'setvarother') {
 			$error++;
 		}
 	}
-
-	$param_limit_view = GETPOST('TICKET_LIMIT_VIEW_ASSIGNED_ONLY', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_LIMIT_VIEW_ASSIGNED_ONLY', $param_limit_view, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_delay_first_response = GETPOST('delay_first_response', 'int');
-	$res = dolibarr_set_const($db, 'TICKET_DELAY_BEFORE_FIRST_RESPONSE', $param_delay_first_response, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_delay_between_responses = GETPOST('delay_between_responses', 'int');
-	$res = dolibarr_set_const($db, 'TICKET_DELAY_SINCE_LAST_RESPONSE', $param_delay_between_responses, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_auto_notify_close = GETPOST('TICKET_NOTIFY_AT_CLOSING', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_NOTIFY_AT_CLOSING', $param_auto_notify_close, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
 }
 
 
-
 /*
  * View
  */
@@ -384,8 +359,8 @@ if ($resql) {
 
 
 print '<div class="div-table-responsive-no-min">';
-print "<table class=\"noborder\" width=\"100%\">\n";
-print "<tr class=\"liste_titre\">\n";
+print '<table class="noborder cenpercent">'."\n";
+print '<tr class="liste_titre">'."\n";
 print '<td>'.$langs->trans("Name").'</td>';
 print '<td>'.$langs->trans("Description").'</td>';
 print '<td class="center" width="60">'.$langs->trans("Status")."</td>\n";
@@ -502,13 +477,14 @@ foreach ($dirmodels as $reldir) {
 print '</table>';
 print '</div><br>';
 
-if (empty($conf->use_javascript_ajax)) {
-	print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
-	print '<input type="hidden" name="token" value="'.newToken().'">';
-	print '<input type="hidden" name="action" value="setvarworkflow">';
-}
+
+print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
+print '<input type="hidden" name="token" value="'.newToken().'">';
+print '<input type="hidden" name="action" value="setvarworkflow">';
+print '<input type="hidden" name="page_y" value="">';
 
 print load_fiche_titre($langs->trans("Other"), '', '');
+print '<div class="div-table-responsive-no-min">';
 print '<table class="noborder centpercent">';
 
 print '<tr class="liste_titre">';
@@ -563,34 +539,24 @@ print $formcategory->textwithpicto('', $langs->trans("TicketsAutoNotifyCloseHelp
 print '</td>';
 print '</tr>';
 
-// Choose which product category is used for tickets
-if ($conf->use_javascript_ajax) {
-	print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
-	print '<input type="hidden" name="token" value="'.newToken().'">';
-	print '<input type="hidden" name="action" value="setvarworkflowother">';
-}
-
-print '<tr class="oddeven"><td>'.$langs->trans("TicketChooseProductCategory").'</td>';
-print '<td class="left">';
-$formcategory->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id');
-if ($conf->use_javascript_ajax) {
-	print ajax_combobox('select_'.$htmlname);
+if (! empty($conf->product->enabled)) {
+	print '<tr class="oddeven"><td>'.$langs->trans("TicketChooseProductCategory").'</td>';
+	print '<td class="left">';
+	$formcategory->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id');
+	if ($conf->use_javascript_ajax) {
+		print ajax_combobox('select_'.$htmlname);
+	}
+	print '</td>';
+	print '<td class="center">';
+	print $formcategory->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help');
+	print '</td>';
+	print '</tr>';
 }
-print '</td>';
-print '<td class="center">';
-print $formcategory->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help');
-print '</td>';
-print '</tr>';
-
-// Define wanted maximum time elapsed before answers to tickets
-print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
-print '<input type="hidden" name="action" value="setvarother">';
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("TicketsDelayBeforeFirstAnswer")."</td>";
 print '<td class="left">
-	<input type="number" value="'.$conf->global->TICKET_DELAY_BEFORE_FIRST_RESPONSE.'" name="delay_first_response">
-	<input type="submit" class="button small" value="'.$langs->trans("Save").'">
+	<input type="number" value="'.$conf->global->TICKET_DELAY_BEFORE_FIRST_RESPONSE.'" name="delay_first_response" class="width50">
 	</td>';
 print '<td class="center">';
 print $formcategory->textwithpicto('', $langs->trans("TicketsDelayBeforeFirstAnswerHelp"), 1, 'help');
@@ -600,8 +566,7 @@ print '</tr>';
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("TicketsDelayBetweenAnswers")."</td>";
 print '<td class="left">
-	<input type="number" value="'.$conf->global->TICKET_DELAY_SINCE_LAST_RESPONSE.'" name="delay_between_responses">
-	<input type="submit" class="button small" value="'.$langs->trans("Save").'">
+	<input type="number" value="'.$conf->global->TICKET_DELAY_SINCE_LAST_RESPONSE.'" name="delay_between_responses" class="width50">
 	</td>';
 print '<td class="center">';
 print $formcategory->textwithpicto('', $langs->trans("TicketsDelayBetweenAnswersHelp"), 1, 'help');
@@ -610,9 +575,7 @@ print '</tr>';
 
 print '</table><br>';
 
-print '<div class="center">';
-print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
-print '</div>';
+print $formcategory->buttonsSaveCancel("Save", '', array(), 0, 'reposition');
 
 print '</form>';
 
@@ -622,9 +585,10 @@ print load_fiche_titre($langs->trans("Notification"), '', '');
 
 print '<table class="noborder centpercent">';
 
-print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
+print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
 print '<input type="hidden" name="token" value="'.newToken().'">';
 print '<input type="hidden" name="action" value="setvar">';
+print '<input type="hidden" name="page_y" value="">';
 
 print '<tr class="liste_titre">';
 print '<td colspan="3">'.$langs->trans("Email").'</td>';
@@ -699,7 +663,7 @@ print '</td></tr>';
 
 print '</table>';
 
-print $formcategory->buttonsSaveCancel("Save", '');
+print $formcategory->buttonsSaveCancel("Save", '', array(), 0, 'reposition');
 
 print '</form>';
 

+ 86 - 19
htdocs/admin/ticket_public.php

@@ -42,21 +42,24 @@ $label = GETPOST('label', 'alpha');
 $scandir = GETPOST('scandir', 'alpha');
 $type = 'ticket';
 
-$error = 0;
 
 /*
  * Actions
  */
+$error = 0;
+$errors = array();
 
 if ($action == 'setTICKET_ENABLE_PUBLIC_INTERFACE') {
 	if (GETPOST('value')) {
-		dolibarr_set_const($db, 'TICKET_ENABLE_PUBLIC_INTERFACE', 1, 'chaine', 0, '', $conf->entity);
+		$res = dolibarr_set_const($db, 'TICKET_ENABLE_PUBLIC_INTERFACE', 1, 'chaine', 0, '', $conf->entity);
 	} else {
-		dolibarr_set_const($db, 'TICKET_ENABLE_PUBLIC_INTERFACE', 0, 'chaine', 0, '', $conf->entity);
+		$res = dolibarr_set_const($db, 'TICKET_ENABLE_PUBLIC_INTERFACE', 0, 'chaine', 0, '', $conf->entity);
 	}
-}
-
-if ($action == 'setvar') {
+	if (!($res > 0)) {
+		$error++;
+		$errors[] = $db->lasterror();
+	}
+} elseif ($action == 'setvar') {
 	include_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
 
 	if (GETPOSTISSET('TICKET_ENABLE_PUBLIC_INTERFACE')) {	// only for no js case
@@ -64,14 +67,7 @@ if ($action == 'setvar') {
 		$res = dolibarr_set_const($db, 'TICKET_ENABLE_PUBLIC_INTERFACE', $param_enable_public_interface, 'chaine', 0, '', $conf->entity);
 		if (!($res > 0)) {
 			$error++;
-		}
-	}
-
-	if (GETPOSTISSET('TICKET_EMAIL_MUST_EXISTS')) {	// only for no js case
-		$param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha');
-		$res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity);
-		if (!($res > 0)) {
-			$error++;
+			$errors[] = $db->lasterror();
 		}
 	}
 
@@ -80,6 +76,7 @@ if ($action == 'setvar') {
 		$res = dolibarr_set_const($db, 'TICKET_DISABLE_CUSTOMER_MAILS', $param_disable_email, 'chaine', 0, '', $conf->entity);
 		if (!($res > 0)) {
 			$error++;
+			$errors[] = $db->lasterror();
 		}
 	}
 
@@ -88,6 +85,7 @@ if ($action == 'setvar') {
 		$res = dolibarr_set_const($db, 'TICKET_SHOW_COMPANY_LOGO', $param_show_module_logo, 'chaine', 0, '', $conf->entity);
 		if (!($res > 0)) {
 			$error++;
+			$errors[] = $db->lasterror();
 		}
 	}
 
@@ -99,6 +97,7 @@ if ($action == 'setvar') {
 	}
 	if (!($res > 0)) {
 		$error++;
+		$errors[] = $db->lasterror();
 	}
 
 	$text_home = GETPOST('TICKET_PUBLIC_TEXT_HOME', 'restricthtml');
@@ -109,6 +108,7 @@ if ($action == 'setvar') {
 	}
 	if (!($res > 0)) {
 		$error++;
+		$errors[] = $db->lasterror();
 	}
 
 	$text_help = GETPOST('TICKET_PUBLIC_TEXT_HELP_MESSAGE', 'restricthtml');
@@ -119,6 +119,7 @@ if ($action == 'setvar') {
 	}
 	if (!($res > 0)) {
 		$error++;
+		$errors[] = $db->lasterror();
 	}
 
 	$mail_new_ticket = GETPOST('TICKET_MESSAGE_MAIL_NEW', 'restricthtml');
@@ -129,6 +130,7 @@ if ($action == 'setvar') {
 	}
 	if (!($res > 0)) {
 		$error++;
+		$errors[] = $db->lasterror();
 	}
 
 	$url_interface = GETPOST('TICKET_URL_PUBLIC_INTERFACE', 'alpha');
@@ -139,12 +141,14 @@ if ($action == 'setvar') {
 	}
 	if (!($res > 0)) {
 		$error++;
+		$errors[] = $db->lasterror();
 	}
 
 	$param_public_notification_new_message_default_email = GETPOST('TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL', 'alpha');
 	$res = dolibarr_set_const($db, 'TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL', $param_public_notification_new_message_default_email, 'chaine', 0, '', $conf->entity);
 	if (!($res > 0)) {
 		$error++;
+		$errors[] = $db->lasterror();
 	}
 
 	if ($conf->global->MAIN_FEATURES_LEVEL >= 2) {
@@ -152,10 +156,60 @@ if ($action == 'setvar') {
 		$res = dolibarr_set_const($db, 'TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS', $param_notification_also_main_addressemail, 'chaine', 0, '', $conf->entity);
 		if (!($res > 0)) {
 			$error++;
+			$errors[] = $db->lasterror();
+		}
+	}
+} elseif (preg_match('/set_(.*)/', $action, $reg)) {
+	$code = $reg[1];
+	$value = GETPOSTISSET($code) ? GETPOST($code, 'int') : 1;
+	$res = dolibarr_set_const($db, $code, $value, 'chaine', 0, '', $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+		$errors[] = $db->lasterror();
+	}
+
+	if (!$error) {
+		if ($code == 'TICKET_EMAIL_MUST_EXISTS') {
+			$res = dolibarr_del_const($db, 'TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST', $conf->entity);
+			if (!($res > 0)) {
+				$error++;
+				$errors[] = $db->lasterror();
+			}
+		} elseif ($code == 'TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST') {
+			$res = dolibarr_del_const($db, 'TICKET_EMAIL_MUST_EXISTS', $conf->entity);
+			if (!($res > 0)) {
+				$error++;
+				$errors[] = $db->lasterror();
+			}
+
+			// enable captcha by default
+			$res = dolibarr_set_const($db, 'MAIN_SECURITY_ENABLECAPTCHA', 1, 'chaine', 0, '', $conf->entity);
+			if (!($res > 0)) {
+				$error++;
+				$errors[] = $db->lasterror();
+			}
 		}
 	}
+} elseif (preg_match('/del_(.*)/', $action, $reg)) {
+	$code = $reg[1];
+	$res = dolibarr_del_const($db, $code, $conf->entity);
+	if (!($res > 0)) {
+		$error++;
+		$errors[] = $db->lasterror();
+	}
 }
 
+if ($action != '') {
+	if (!$error) {
+		$db->commit();
+		setEventMessage($langs->trans('SetupSaved'));
+		header("Location: " . $_SERVER['PHP_SELF']);
+		exit;
+	} else {
+		$db->rollback();
+		setEventMessages('', $errors, 'errors');
+	}
+}
 
 
 /*
@@ -180,7 +234,7 @@ $head = ticketAdminPrepareHead();
 
 print dol_get_fiche_head($head, 'public', $langs->trans("Module56000Name"), -1, "ticket");
 
-print '<span class="opacitymedium">'.$langs->trans("TicketPublicAccess").'</span> : <a class="wordbreak" href="'.DOL_URL_ROOT.'/public/ticket/index.php" target="_blank" rel="noopener noreferrer">'.dol_buildpath('/public/ticket/index.php', 2).'</a>';
+print '<span class="opacitymedium">'.$langs->trans("TicketPublicAccess").'</span> : <a class="wordbreak" href="'.DOL_URL_ROOT.'/public/ticket/index.php?entity='.$conf->entity.'" target="_blank" rel="noopener noreferrer">'.dol_buildpath('/public/ticket/index.php?entity='.$conf->entity, 2).'</a>';
 
 print dol_get_fiche_end();
 
@@ -220,11 +274,10 @@ if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
 	// Check if email exists
 	print '<tr class="oddeven"><td>'.$langs->trans("TicketsEmailMustExist").'</td>';
 	print '<td class="left">';
-	if ($conf->use_javascript_ajax) {
-		print ajax_constantonoff('TICKET_EMAIL_MUST_EXISTS');
+	if (empty(getDolGlobalInt('TICKET_EMAIL_MUST_EXISTS'))) {
+		print '<a href="' . $_SERVER['PHP_SELF'] . '?action=set_TICKET_EMAIL_MUST_EXISTS">' . img_picto($langs->trans('Disabled'), 'switch_off') . '</a>';
 	} else {
-		$arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
-		print $form->selectarray("TICKET_EMAIL_MUST_EXISTS", $arrval, $conf->global->TICKET_EMAIL_MUST_EXISTS);
+		print '<a href="' . $_SERVER['PHP_SELF'] . '?action=del_TICKET_EMAIL_MUST_EXISTS">' . img_picto($langs->trans('Enabled'), 'switch_on') . '</a>';
 	}
 	print '</td>';
 	print '<td class="center width75">';
@@ -232,6 +285,20 @@ if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
 	print '</td>';
 	print '</tr>';
 
+	// Create third-party with contact if email not linked to a contact
+	print '<tr class="oddeven"><td>'.$langs->trans("TicketCreateThirdPartyWithContactIfNotExist").'</td>';
+	print '<td class="left">';
+	if (empty(getDolGlobalInt('TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST'))) {
+		print '<a href="' . $_SERVER['PHP_SELF'] . '?action=set_TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST">' . img_picto($langs->trans('Disabled'), 'switch_off') . '</a>';
+	} else {
+		print '<a href="' . $_SERVER['PHP_SELF'] . '?action=del_TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST">' . img_picto($langs->trans('Enabled'), 'switch_on') . '</a>';
+	}
+	print '</td>';
+	print '<td class="center width75">';
+	print $form->textwithpicto('', $langs->trans("TicketCreateThirdPartyWithContactIfNotExistHelp"), 1, 'help');
+	print '</td>';
+	print '</tr>';
+
 	/*if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
 	{
 		// Show logo for module

+ 9 - 2
htdocs/admin/tools/update.php

@@ -61,7 +61,11 @@ $version = '0.0';
 if ($action == 'getlastversion') {
 	$result = getURLContent('https://sourceforge.net/projects/dolibarr/rss');
 	//var_dump($result['content']);
-	$sfurl = simplexml_load_string($result['content'], 'SimpleXMLElement', LIBXML_NOCDATA|LIBXML_NONET);
+	if (function_exists('simplexml_load_string')) {
+		$sfurl = simplexml_load_string($result['content'], 'SimpleXMLElement', LIBXML_NOCDATA|LIBXML_NONET);
+	} else {
+		$sfurl = 'xml_not_available';
+	}
 }
 
 
@@ -82,7 +86,10 @@ if (function_exists('curl_init')) {
 	$conf->global->MAIN_USE_RESPONSE_TIMEOUT = 10;
 
 	if ($action == 'getlastversion') {
-		if ($sfurl) {
+		if ($sfurl == 'xml_not_available') {
+			$langs->load("errors");
+			print $langs->trans("LastStableVersion").' : <b class="error">'.$langs->trans("ErrorFunctionNotAvailableInPHP", 'simplexml_load_string').'</b><br>';
+		} elseif ($sfurl) {
 			$i = 0;
 			while (!empty($sfurl->channel[0]->item[$i]->title) && $i < 10000) {
 				$title = $sfurl->channel[0]->item[$i]->title;

+ 4 - 4
htdocs/admin/translation.php

@@ -90,7 +90,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
 	$transkey = '';
 	$transvalue = '';
-	$toselect = '';
+	$toselect = array();
 	$search_array_options = array();
 }
 
@@ -444,9 +444,9 @@ if ($mode == 'overwrite') {
 
 if ($mode == 'searchkey') {
 	$nbempty = 0;
-	/*var_dump($langcode);
-	 var_dump($transkey);
-	 var_dump($transvalue);*/
+	//var_dump($langcode);
+	//var_dump($transkey);
+	//var_dump($transvalue);
 	if (empty($langcode) || $langcode == '-1') {
 		$nbempty++;
 	}

+ 2 - 2
htdocs/admin/workstation.php

@@ -295,7 +295,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 
 								print '<td class="center">';
 								$constforvar = 'WORKSTATION_'.strtoupper($myTmpObjectKey).'_ADDON';
-								if ($conf->global->$constforvar == $file) {
+								if (getDolGlobalString($constforvar) == $file) {
 									print img_picto($langs->trans("Activated"), 'switch_on');
 								} else {
 									print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmod&token='.newToken().'&object='.strtolower($myTmpObjectKey).'&value='.urlencode($file).'">';
@@ -437,7 +437,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 										// Default
 										print '<td class="center">';
 										$constforvar = 'WORKSTATION_'.strtoupper($myTmpObjectKey).'_ADDON';
-										if ($conf->global->$constforvar == $name) {
+										if (getDolGlobalString($constforvar) == $name) {
 											print img_picto($langs->trans("Default"), 'on');
 										} else {
 											print '<a href="'.$_SERVER["PHP_SELF"].'?action=setdoc&amp;token='.newToken().'&amp;value='.$name.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').'</a>';

+ 3 - 4
htdocs/api/class/api_documents.class.php

@@ -568,10 +568,9 @@ class Documents extends DolibarrApi
 	{
 		global $db, $conf;
 
-		/*var_dump($modulepart);
-		var_dump($filename);
-		var_dump($filecontent);
-		exit;*/
+		//var_dump($modulepart);
+		//var_dump($filename);
+		//var_dump($filecontent);exit;
 
 		if (empty($modulepart)) {
 			throw new RestException(400, 'Modulepart not provided.');

+ 2 - 2
htdocs/asset/admin/setup.php

@@ -266,7 +266,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 
 								print '<td class="center">';
 								$constforvar = 'ASSET_'.strtoupper($myTmpObjectKey).'_ADDON';
-								if ($conf->global->$constforvar == $file) {
+								if (getDolGlobalString($constforvar) == $file) {
 									print img_picto($langs->trans("Activated"), 'switch_on');
 								} else {
 									print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmod&token='.newToken().'&object='.strtolower($myTmpObjectKey).'&value='.urlencode($file).'">';
@@ -408,7 +408,7 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
 										// Default
 										print '<td class="center">';
 										$constforvar = 'ASSET_'.strtoupper($myTmpObjectKey).'_ADDON';
-										if ($conf->global->$constforvar == $name) {
+										if (getDolGlobalString($constforvar) == $name) {
 											//print img_picto($langs->trans("Default"), 'on');
 											// Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset
 											print '<a href="'.$_SERVER["PHP_SELF"].'?action=unsetdoc&token='.newToken().'&object='.urlencode(strtolower($myTmpObjectKey)).'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'&amp;type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').'</a>';

+ 1 - 1
htdocs/barcode/codeinit.php

@@ -286,7 +286,7 @@ if ($conf->product->enabled || $conf->product->service) {
 	print '<input type="submit" class="button" name="submitformbarcodeproductgen" id="submitformbarcodeproductgen" value="'.$langs->trans("InitEmptyBarCode", min($maxperinit, $nbno)).'"'.$moretags1.'>';
 	$moretags2 = (($nbno == $nbtotal) ? ' disabled' : '');
 	print ' &nbsp; ';
-	print '<input type="submit" class="button" name="eraseallbarcode" id="eraseallbarcode" value="'.$langs->trans("EraseAllCurrentBarCode").'"'.$moretags2.' onClick="return confirm_erase();">';
+	print '<input type="submit" class="button butActionDelete" name="eraseallbarcode" id="eraseallbarcode" value="'.$langs->trans("EraseAllCurrentBarCode").'"'.$moretags2.' onClick="return confirm_erase();">';
 	print '<br><br><br><br>';
 }
 

+ 1 - 1
htdocs/blockedlog/admin/blockedlog_list.php

@@ -118,7 +118,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
 	$search_ref = '';
 	$search_amount = '';
 	$search_showonlyerrors = 0;
-	$toselect = '';
+	$toselect = array();
 	$search_array_options = array();
 }
 

+ 5 - 5
htdocs/blockedlog/ajax/block-info.php

@@ -92,11 +92,11 @@ function formatObject($objtoshow, $prefix)
 				$s .= '<tr><td>'.($prefix ? $prefix.' > ' : '').$key.'</td>';
 				$s .= '<td>';
 				if (in_array($key, array('date', 'datef', 'dateh', 'datec', 'datem', 'datep'))) {
-					/*var_dump(is_object($val));
-					var_dump(is_array($val));
-					var_dump(is_array($val));
-					var_dump(@get_class($val));
-					var_dump($val);*/
+					//var_dump(is_object($val));
+					//var_dump(is_array($val));
+					//var_dump(is_array($val));
+					//var_dump(@get_class($val));
+					//var_dump($val);
 					$s .= dol_print_date($val, 'dayhour');
 				} else {
 					$s .= $val;

+ 2 - 1
htdocs/categories/index.php

@@ -102,7 +102,8 @@ if (empty($nosearch)) {
 	print '<td colspan="3">'.$langs->trans("Search").'</td>';
 	print '</tr>';
 	print '<tr class="oddeven nohover"><td>';
-	print $langs->trans("Name").':</td><td><input class="flat inputsearch" type="text" name="catname" value="'.$catname.'"/></td><td><input type="submit" class="button" value="'.$langs->trans("Search").'"></td></tr>';
+	print $langs->trans("Name").':</td><td><input class="flat inputsearch" type="text" name="catname" value="'.dol_escape_htmltag($catname).'"></td>';
+	print '<td><input type="submit" class="button small" value="'.$langs->trans("Search").'"></td></tr>';
 	print '</table></form>';
 
 

+ 2 - 2
htdocs/categories/viewcat.php

@@ -734,9 +734,9 @@ if ($type == Categorie::TYPE_MEMBER) {
 			print '<input type="hidden" name="action" value="addintocategory">';
 			print '<table class="noborder centpercent">';
 			print '<tr class="liste_titre"><td>';
-			print $langs->trans("AddMemberIntoCategory").' &nbsp;';
+			print $langs->trans("AssignCategoryTo").' &nbsp;';
 			print $form->selectMembers('', 'elemid');
-			print '<input type="submit" class="button buttongen" value="'.$langs->trans("ClassifyInCategory").'"></td>';
+			print '<input type="submit" class="button buttongen" value="'.$langs->trans("Save").'"></td>';
 			print '</tr>';
 			print '</table>';
 			print '</form>';

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

@@ -1598,7 +1598,7 @@ class ActionComm extends CommonObject
 			//$tooltip .= '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
 			$tooltip .= '<br><b>'.$langs->trans('MailTopic').':</b> '.$this->email_subject;
 			$tooltip .= '<br><b>'.$langs->trans('MailFrom').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_from);
-			$tooltip .= '<br><b>'.$langs->trans('MailTo').':</b>, '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_to);
+			$tooltip .= '<br><b>'.$langs->trans('MailTo').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_to);
 			if (!empty($this->email_tocc)) {
 				$tooltip .= '<br><b>'.$langs->trans('MailCC').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
 			}

+ 2 - 1
htdocs/comm/action/index.php

@@ -1191,7 +1191,8 @@ if (count($listofextcals)) {
 			foreach ($icalevents as $icalevent) {
 				//var_dump($icalevent);
 
-				//print $icalevent['SUMMARY'].'->'.var_dump($icalevent).'<br>';exit;
+				//print $icalevent['SUMMARY'].'->';
+				//var_dump($icalevent);exit;
 				if (!empty($icalevent['RRULE'])) {
 					continue; // We found a repeatable event. It was already split into unitary events, so we discard general rule.
 				}

+ 1 - 1
htdocs/comm/action/list.php

@@ -217,7 +217,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
 	$dateend_dtstart = '';
 	$dateend_dtend = '';
 	$search_status = '';
-	$toselect = '';
+	$toselect = array();
 	$search_array_options = array();
 }
 

+ 3 - 1
htdocs/comm/action/pertype.php

@@ -961,7 +961,9 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s
 	$ymd = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $day);
 
 	$nextindextouse = count($colorindexused); // At first run, this is 0, so fist user has 0, next 1, ...
-	//if ($username->id && $day==1) var_dump($eventarray);
+	//if ($username->id && $day==1) {
+	//var_dump($eventarray);
+	//}
 
 	// We are in a particular day for $username, now we scan all events
 	foreach ($eventarray as $daykey => $notused) {

+ 3 - 1
htdocs/comm/action/peruser.php

@@ -1130,7 +1130,9 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, &
 
 	$colorindexused[$user->id] = 0; // Color index for current user (user->id) is always 0
 	$nextindextouse = count($colorindexused); // At first run this is 0, so first user has 0, next 1, ...
-	//if ($username->id && $day==1) var_dump($eventarray);
+	//if ($username->id && $day==1) {
+	//var_dump($eventarray);
+	//}
 
 	// We are in a particular day for $username, now we scan all events
 	foreach ($eventarray as $daykey => $notused) {

+ 3 - 3
htdocs/comm/card.php

@@ -173,7 +173,7 @@ if (empty($reshook)) {
 	// terms of the settlement
 	if ($action == 'setconditions' && $user->rights->societe->creer) {
 		$object->fetch($id);
-		$result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
+		$result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'alpha'));
 		if ($result < 0) {
 			setEventMessages($object->error, $object->errors, 'errors');
 		}
@@ -415,9 +415,9 @@ if ($object->id > 0) {
 	print '</tr></table>';
 	print '</td><td>';
 	if ($action == 'editconditions') {
-		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1);
+		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
 	} else {
-		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'none');
+		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'none', 0, '', 1, $object->deposit_percent);
 	}
 	print "</td>";
 	print '</tr>';

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

@@ -103,7 +103,7 @@ if (empty($reshook)) {
 		}*/
 		$search_ref = '';
 		$search_all = '';
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 	if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')

+ 183 - 6
htdocs/comm/propal/card.php

@@ -402,6 +402,7 @@ if (empty($reshook)) {
 					$object->warehouse_id = GETPOST('warehouse_id', 'int');
 					$object->duree_validite = $duration;
 					$object->cond_reglement_id = GETPOST('cond_reglement_id');
+					$object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
 					$object->mode_reglement_id = GETPOST('mode_reglement_id');
 					$object->fk_account = GETPOST('fk_account', 'int');
 					$object->remise_absolue = price2num(GETPOST('remise_absolue'), 'MU', 2);	// deprecated
@@ -434,6 +435,7 @@ if (empty($reshook)) {
 				$object->warehouse_id = GETPOST('warehouse_id', 'int');
 				$object->duree_validite = price2num(GETPOST('duree_validite', 'alpha'));
 				$object->cond_reglement_id = GETPOST('cond_reglement_id', 'int');
+				$object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
 				$object->mode_reglement_id = GETPOST('mode_reglement_id', 'int');
 				$object->fk_account = GETPOST('fk_account', 'int');
 				$object->contact_id = GETPOST('contactid', 'int');
@@ -687,10 +689,62 @@ if (empty($reshook)) {
 					$error++;
 				}
 
+				$deposit = null;
+				$locationTarget = '';
+
+				$deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
+
+				if (
+					!$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'alpha') == 'on'
+					&& ! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer)
+				) {
+					require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
+
+					$date = dol_mktime(0, 0, 0, GETPOST('datefmonth', 'int'), GETPOST('datefday', 'int'), GETPOST('datefyear', 'int'));
+					$forceFields = array();
+
+					if (GETPOSTISSET('date_pointoftax')) {
+						$forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOST('date_pointoftaxmonth', 'int'), GETPOST('date_pointoftaxday', 'int'), GETPOST('date_pointoftaxyear', 'int'));
+					}
+
+					$deposit = Facture::createDepositFromOrigin($object, $date, GETPOST('cond_reglement_id', 'int'), $user, 0, GETPOST('validate_generated_deposit', 'alpha') == 'on', $forceFields);
+
+					if ($deposit) {
+						setEventMessage('DepositGenerated');
+						$locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
+					} else {
+						$error++;
+						setEventMessages($object->error, $object->errors, 'errors');
+					}
+				}
+
 				if (!$error) {
 					$db->commit();
+
+					if ($deposit && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
+						$ret = $deposit->fetch($deposit->id); // Reload to get new records
+						$outputlangs = $langs;
+
+						if ($conf->global->MAIN_MULTILANGS) {
+							$outputlangs = new Translate('', $conf);
+							$outputlangs->setDefaultLang($deposit->thirdparty->default_lang);
+							$outputlangs->load('products');
+						}
+
+						$result = $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
+
+						if ($result < 0) {
+							setEventMessages($deposit->error, $deposit->errors, 'errors');
+						}
+					}
+
+					if ($locationTarget) {
+						header('Location: ' . $locationTarget);
+						exit;
+					}
 				} else {
 					$db->rollback();
+					$action = '';
 				}
 			}
 		}
@@ -1370,7 +1424,7 @@ if (empty($reshook)) {
 		$result = $object->set_demand_reason($user, GETPOST('demand_reason_id', 'int'));
 	} elseif ($action == 'setconditions' && $usercancreate) {
 		// Terms of payment
-		$result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
+		$result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'alpha'));
 	} elseif ($action == 'setremisepercent' && $usercancreate) {
 		$result = $object->set_remise_percent($user, price2num(GETPOST('remise_percent'), '', 2));
 	} elseif ($action == 'setremiseabsolue' && $usercancreate) {
@@ -1656,9 +1710,9 @@ if ($action == 'create') {
 	print '<tr class="field_duree_validitee"><td class="titlefieldcreate fieldrequired">'.$langs->trans("ValidityDuration").'</td><td class="valuefieldcreate">'.img_picto('', 'clock', 'class="paddingright"').'<input name="duree_validite" class="width50" value="'.(GETPOSTISSET('duree_validite') ? GETPOST('duree_validite', 'alphanohtml') : $conf->global->PROPALE_VALIDITY_DURATION).'"> '.$langs->trans("days").'</td></tr>';
 
 	// Terms of payment
-	print '<tr class="field_cond_reglement_id"><td class="titlefieldcreate nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td class="valuefieldcreate">';
-	print img_picto('', 'payment', 'class="pictofixedwidth"');
-	$form->select_conditions_paiements((GETPOSTISSET('cond_reglement_id') && GETPOST('cond_reglement_id') != 0) ? GETPOST('cond_reglement_id', 'int') : $soc->cond_reglement_id, 'cond_reglement_id', -1, 1);
+	print '<tr class="field_cond_reglement_id"><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
+	print img_picto('', 'paiment');
+	$form->select_conditions_paiements((GETPOSTISSET('cond_reglement_id') && GETPOST('cond_reglement_id') != 0) ? GETPOST('cond_reglement_id', 'int') : $soc->cond_reglement_id, 'cond_reglement_id', 1, 1, 0, '', (GETPOSTISSET('cond_reglement_id_deposit_percent') ? GETPOST('cond_reglement_id_deposit_percent', 'alpha') : $soc->deposit_percent));
 	print '</td></tr>';
 
 	// Mode of payment
@@ -1945,6 +1999,129 @@ if ($action == 'create') {
 			array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"), 'value' => '')				// Field to complete private note (not replace)
 		);
 
+		$deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
+
+		if (! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer)) {
+			require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
+
+			$object->fetchObjectLinked();
+
+			$eligibleForDepositGeneration = true;
+
+			if (array_key_exists('facture', $object->linkedObjects)) {
+				foreach ($object->linkedObjects['facture'] as $invoice) {
+					if ($invoice->type == Facture::TYPE_DEPOSIT) {
+						$eligibleForDepositGeneration = false;
+						break;
+					}
+				}
+			}
+
+			if ($eligibleForDepositGeneration && array_key_exists('commande', $object->linkedObjects)) {
+				foreach ($object->linkedObjects['commande'] as $order) {
+					$order->fetchObjectLinked();
+
+					if (array_key_exists('facture', $order->linkedObjects)) {
+						foreach ($order->linkedObjects['facture'] as $invoice) {
+							if ($invoice->type == Facture::TYPE_DEPOSIT) {
+								$eligibleForDepositGeneration = false;
+								break 2;
+							}
+						}
+					}
+				}
+			}
+
+
+			if ($eligibleForDepositGeneration) {
+				$formquestion[] = array(
+					'type' => 'checkbox',
+					'tdclass' => 'showonlyifsigned',
+					'name' => 'generate_deposit',
+					'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
+				);
+
+				$formquestion[] = array(
+					'type' => 'date',
+					'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
+					'name' => 'datef',
+					'label' => $langs->trans('DateInvoice'),
+					'value' => dol_now(),
+					'datenow' => true
+				);
+
+				if (! empty($conf->global->INVOICE_POINTOFTAX_DATE)) {
+					$formquestion[] = array(
+						'type' => 'date',
+						'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
+						'name' => 'date_pointoftax',
+						'label' => $langs->trans('DatePointOfTax'),
+						'value' => dol_now(),
+						'datenow' => true
+					);
+				}
+
+				ob_start();
+				$form->select_conditions_paiements(0, 'cond_reglement_id', -1, 0, 0, 'minwidth200');
+				$paymentTermsSelect = ob_get_clean();
+
+				$formquestion[] = array(
+					'type' => 'other',
+					'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
+					'name' => 'cond_reglement_id',
+					'label' => $langs->trans('PaymentTerm'),
+					'value' => $paymentTermsSelect
+				);
+
+				$formquestion[] = array(
+					'type' => 'checkbox',
+					'tdclass' => 'showonlyifgeneratedeposit',
+					'name' => 'validate_generated_deposit',
+					'label' => $langs->trans('ValidateGeneratedDeposit')
+				);
+
+				$formquestion[] = array(
+					'type' => 'onecolumn',
+					'value' => '
+						<script>
+							let signedValue = ' . $object::STATUS_SIGNED . ';
+
+							$(document).ready(function() {
+								$("[name=generate_deposit]").change(function () {
+									let $self = $(this);
+									let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
+
+									if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
+										$target.show();
+									} else {
+										$target.hide();
+									}
+
+									return true;
+								});
+
+								$("#statut").change(function() {
+									let $target = $(".showonlyifsigned").parent(".tagtr");
+
+									if ($(this).val() == signedValue) {
+										$target.show();
+									} else {
+										$target.hide();
+									}
+
+									$("[name=generate_deposit]").trigger("change");
+
+									return true;
+								});
+
+								$("#statut").trigger("change");
+							});
+						</script>
+					'
+				);
+			}
+		}
+
 		if (!empty($conf->notification->enabled)) {
 			require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
 			$notify = new Notify($db);
@@ -2171,9 +2348,9 @@ if ($action == 'create') {
 	print '</tr></table>';
 	print '</td><td class="valuefield">';
 	if ($action == 'editconditions' && $usercancreate && $caneditfield) {
-		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
+		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 0, '', 1, $object->deposit_percent);
 	} else {
-		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none');
+		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 0, '', 1, $object->deposit_percent);
 	}
 	print '</td>';
 	print '</tr>';

+ 3 - 1
htdocs/comm/propal/class/api_proposals.class.php

@@ -519,7 +519,9 @@ class Proposals extends DolibarrApi
 			isset($request_data->date_end) ? $request_data->date_end : $propalline->date_end,
 			isset($request_data->array_options) ? $request_data->array_options : $propalline->array_options,
 			isset($request_data->fk_unit) ? $request_data->fk_unit : $propalline->fk_unit,
-			isset($request_data->multicurrency_subprice) ? $request_data->multicurrency_subprice : $propalline->subprice
+			isset($request_data->multicurrency_subprice) ? $request_data->multicurrency_subprice : $propalline->subprice,
+			0,
+			isset($request_data->rang) ? $request_data->rang : $propalline->rang
 		);
 
 		if ($updateRes > 0) {

+ 11 - 2
htdocs/comm/propal/class/propal.class.php

@@ -206,6 +206,7 @@ class Propal extends CommonObject
 	public $total;
 
 	public $cond_reglement_code;
+	public $deposit_percent;
 	public $mode_reglement_code;
 	public $remise_percent;
 
@@ -319,6 +320,7 @@ class Propal extends CommonObject
 		'fk_account' =>array('type'=>'integer', 'label'=>'BankAccount', 'enabled'=>1, 'visible'=>-1, 'position'=>150),
 		'fk_currency' =>array('type'=>'varchar(3)', 'label'=>'Currency', 'enabled'=>1, 'visible'=>-1, 'position'=>155),
 		'fk_cond_reglement' =>array('type'=>'integer', 'label'=>'PaymentTerm', 'enabled'=>1, 'visible'=>-1, 'position'=>160),
+		'deposit_percent' =>array('type'=>'varchar(63)', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>161),
 		'fk_mode_reglement' =>array('type'=>'integer', 'label'=>'PaymentMode', 'enabled'=>1, 'visible'=>-1, 'position'=>165),
 		'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>170),
 		'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>175),
@@ -804,9 +806,10 @@ class Propal extends CommonObject
 	 * 	@param 		string		$fk_unit 			Code of the unit to use. Null to use the default one
 	 * 	@param		double		$pu_ht_devise		Unit price in currency
 	 * 	@param		int			$notrigger			disable line update trigger
+	 * @param       integer $rang   line rank
 	 *  @return     int     		        		0 if OK, <0 if KO
 	 */
-	public function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $desc = '', $price_base_type = 'HT', $info_bits = 0, $special_code = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = 0, $pa_ht = 0, $label = '', $type = 0, $date_start = '', $date_end = '', $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $notrigger = 0)
+	public function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $desc = '', $price_base_type = 'HT', $info_bits = 0, $special_code = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = 0, $pa_ht = 0, $label = '', $type = 0, $date_start = '', $date_end = '', $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $notrigger = 0, $rang = 0)
 	{
 		global $mysoc, $langs;
 
@@ -892,6 +895,7 @@ class Propal extends CommonObject
 			$line->oldline = $staticline;
 			$this->line = $line;
 			$this->line->context = $this->context;
+			$this->line->rang = $rang;
 
 			// Reorder if fk_parent_line change
 			if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
@@ -1100,6 +1104,7 @@ class Propal extends CommonObject
 		$sql .= ", model_pdf";
 		$sql .= ", fin_validite";
 		$sql .= ", fk_cond_reglement";
+		$sql .= ", deposit_percent";
 		$sql .= ", fk_mode_reglement";
 		$sql .= ", fk_account";
 		$sql .= ", ref_client";
@@ -1133,6 +1138,7 @@ class Propal extends CommonObject
 		$sql .= ", '".$this->db->escape($this->model_pdf)."'";
 		$sql .= ", ".($this->fin_validite != '' ? "'".$this->db->idate($this->fin_validite)."'" : "NULL");
 		$sql .= ", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) : 'NULL');
+		$sql .= ", ".(! empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : 'NULL');
 		$sql .= ", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) : 'NULL');
 		$sql .= ", ".($this->fk_account > 0 ? ((int) $this->fk_account) : 'NULL');
 		$sql .= ", '".$this->db->escape($this->ref_client)."'";
@@ -1360,6 +1366,7 @@ class Propal extends CommonObject
 			if ($objsoc->fetch($socid) > 0) {
 				$object->socid = $objsoc->id;
 				$object->cond_reglement_id	= (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
+				$object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent : null);
 				$object->mode_reglement_id	= (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
 				$object->fk_delivery_address = '';
 
@@ -1536,7 +1543,7 @@ class Propal extends CommonObject
 		$sql .= ", c.label as statut_label";
 		$sql .= ", ca.code as availability_code, ca.label as availability";
 		$sql .= ", dr.code as demand_reason_code, dr.label as demand_reason";
-		$sql .= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc";
+		$sql .= ", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent";
 		$sql .= ", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
 		$sql .= " FROM ".MAIN_DB_PREFIX."propal as p";
 		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_propalst as c ON p.fk_statut = c.id';
@@ -1619,6 +1626,7 @@ class Propal extends CommonObject
 				$this->cond_reglement_code  = $obj->cond_reglement_code;
 				$this->cond_reglement       = $obj->cond_reglement;
 				$this->cond_reglement_doc   = $obj->cond_reglement_libelle_doc;
+				$this->deposit_percent      = $obj->deposit_percent;
 
 				$this->extraparams = (array) json_decode($obj->extraparams, true);
 
@@ -1728,6 +1736,7 @@ class Propal extends CommonObject
 		$sql .= " fk_user_valid=".(isset($this->user_valid) ? $this->user_valid : "null").",";
 		$sql .= " fk_projet=".(isset($this->fk_project) ? $this->fk_project : "null").",";
 		$sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->cond_reglement_id : "null").",";
+		$sql .= " deposit_percent=".(! empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : "null").",";
 		$sql .= " fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->mode_reglement_id : "null").",";
 		$sql .= " fk_input_reason=".(isset($this->demand_reason_id) ? $this->demand_reason_id : "null").",";
 		$sql .= " note_private=".(isset($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null").",";

+ 16 - 5
htdocs/comm/propal/list.php

@@ -340,7 +340,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
 	$search_availability = '';
 	$search_status = '';
 	$object_statut = '';
-	$toselect = '';
+	$toselect = array();
 	$search_array_options = array();
 	$search_categ_cus = 0;
 	$search_fk_cond_reglement = '';
@@ -537,7 +537,7 @@ $sql .= ' p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multic
 $sql .= ' p.datec as date_creation, p.tms as date_update, p.date_cloture as date_cloture,';
 $sql .= ' p.date_signature as dsignature,';
 $sql .= ' p.note_public, p.note_private,';
-$sql .= ' p.fk_cond_reglement,p.fk_mode_reglement,p.fk_shipping_method,p.fk_input_reason,';
+$sql .= ' p.fk_cond_reglement,p.deposit_percent,p.fk_mode_reglement,p.fk_shipping_method,p.fk_input_reason,';
 $sql .= " pr.rowid as project_id, pr.ref as project_ref, pr.title as project_label,";
 $sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as user_statut, u.entity as user_entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender';
 if (empty($user->rights->societe->client->voir) && !$socid) {
@@ -1224,7 +1224,7 @@ if ($resql) {
 	// Payment term
 	if (!empty($arrayfields['p.fk_cond_reglement']['checked'])) {
 		print '<td class="liste_titre">';
-		$form->select_conditions_paiements($search_fk_cond_reglement, 'search_fk_cond_reglement', -1, 1, 1);
+		$form->select_conditions_paiements($search_fk_cond_reglement, 'search_fk_cond_reglement', 1, 1, 1);
 		print '</td>';
 	}
 	// Payment mode
@@ -1821,7 +1821,7 @@ if ($resql) {
 		// Payment terms
 		if (!empty($arrayfields['p.fk_cond_reglement']['checked'])) {
 			print '<td>';
-			$form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none');
+			$form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 0, '', 1, $obj->deposit_percent);
 			print '</td>';
 			if (!$i) {
 				$totalarray['nbfield']++;
@@ -2133,7 +2133,7 @@ if ($resql) {
 			$totalarray['nbfield']++;
 		}
 
-		print "</tr>\n";
+		print '</tr>'."\n";
 
 		$i++;
 	}
@@ -2141,6 +2141,17 @@ if ($resql) {
 	// Show total line
 	include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
 
+	// If no record found
+	if ($num == 0) {
+		$colspan = 1;
+		foreach ($arrayfields as $key => $val) {
+			if (!empty($val['checked'])) {
+				$colspan++;
+			}
+		}
+		print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
+	}
+
 	$db->free($resql);
 
 	$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);

+ 182 - 19
htdocs/commande/card.php

@@ -272,6 +272,7 @@ if (empty($reshook)) {
 			$object->ref_client = GETPOST('ref_client', 'alpha');
 			$object->model_pdf = GETPOST('model');
 			$object->cond_reglement_id = GETPOST('cond_reglement_id');
+			$object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
 			$object->mode_reglement_id = GETPOST('mode_reglement_id');
 			$object->fk_account = GETPOST('fk_account', 'int');
 			$object->availability_id = GETPOST('availability_id');
@@ -571,7 +572,7 @@ if (empty($reshook)) {
 			setEventMessages($object->error, $object->errors, 'errors');
 		}
 	} elseif ($action == 'setconditions' && $usercancreate) {
-		$result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
+		$result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'alpha'));
 		if ($result < 0) {
 			dol_print_error($db, $object->error);
 		} else {
@@ -1176,28 +1177,76 @@ if (empty($reshook)) {
 		}
 
 		if (!$error) {
+			$locationTarget = '';
+			$db->begin();
 			$result = $object->valid($user, $idwarehouse);
 			if ($result >= 0) {
-				// Define output language
-				if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
-					$outputlangs = $langs;
-					$newlang = '';
-					if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
-						$newlang = GETPOST('lang_id', 'aZ09');
+				$error = 0;
+				$deposit = null;
+
+				$deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
+
+				if (
+					GETPOST('generate_deposit', 'alpha') == 'on' && ! empty($deposit_percent_from_payment_terms)
+					&& ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer)
+				) {
+					require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
+
+					$date = dol_mktime(0, 0, 0, GETPOST('datefmonth', 'int'), GETPOST('datefday', 'int'), GETPOST('datefyear', 'int'));
+					$forceFields = array();
+
+					if (GETPOSTISSET('date_pointoftax')) {
+						$forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOST('date_pointoftaxmonth', 'int'), GETPOST('date_pointoftaxday', 'int'), GETPOST('date_pointoftaxyear', 'int'));
 					}
-					if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
-						$newlang = $object->thirdparty->default_lang;
+
+					$deposit = Facture::createDepositFromOrigin($object, $date, GETPOST('cond_reglement_id', 'int'), $user, 0, GETPOST('validate_generated_deposit', 'alpha') == 'on', $forceFields);
+
+					if ($deposit) {
+						setEventMessage('DepositGenerated');
+						$locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
+					} else {
+						$error++;
+						setEventMessages($object->error, $object->errors, 'errors');
 					}
-					if (!empty($newlang)) {
-						$outputlangs = new Translate("", $conf);
-						$outputlangs->setDefaultLang($newlang);
+				}
+
+				// Define output language
+				if (! $error) {
+					$db->commit();
+
+					if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
+						$outputlangs = $langs;
+						$newlang = '';
+						if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
+							$newlang = GETPOST('lang_id', 'aZ09');
+						}
+						if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
+							$newlang = $object->thirdparty->default_lang;
+						}
+						if (!empty($newlang)) {
+							$outputlangs = new Translate("", $conf);
+							$outputlangs->setDefaultLang($newlang);
+						}
+						$model = $object->model_pdf;
+						$ret = $object->fetch($id); // Reload to get new records
+
+						$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
+
+						if ($deposit) {
+							$deposit->fetch($deposit->id); // Reload to get new records
+							$deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
+						}
 					}
-					$model = $object->model_pdf;
-					$ret = $object->fetch($id); // Reload to get new records
 
-					$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
+					if ($locationTarget) {
+						header('Location: ' . $locationTarget);
+						exit;
+					}
+				} else {
+					$db->rollback();
 				}
 			} else {
+				$db->rollback();
 				setEventMessages($object->error, $object->errors, 'errors');
 			}
 		}
@@ -1460,6 +1509,10 @@ if ($action == 'create' && $usercancreate) {
 
 	$currency_code = $conf->currency;
 
+	$cond_reglement_id = GETPOST('cond_reglement_id', 'int');
+	$deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
+	$mode_reglement_id = GETPOST('mode_reglement_id', 'int');
+
 	if (!empty($origin) && !empty($originid)) {
 		// Parse element/subelement (ex: project_task)
 		$element = $subelement = $origin;
@@ -1475,6 +1528,9 @@ if ($action == 'create' && $usercancreate) {
 			if (!$cond_reglement_id) {
 				$cond_reglement_id = $soc->cond_reglement_id;
 			}
+			if (!$deposit_percent) {
+				$deposit_percent = $soc->deposit_percent;
+			}
 			if (!$mode_reglement_id) {
 				$mode_reglement_id = $soc->mode_reglement_id;
 			}
@@ -1515,6 +1571,7 @@ if ($action == 'create' && $usercancreate) {
 
 			$soc = $objectsrc->thirdparty;
 			$cond_reglement_id	= (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0)); // TODO maybe add default value option
+			$deposit_percent	= (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : null));
 			$mode_reglement_id	= (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
 			$fk_account         = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0));
 			$availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : 0);
@@ -1547,6 +1604,7 @@ if ($action == 'create' && $usercancreate) {
 		}
 	} else {
 		$cond_reglement_id  = $soc->cond_reglement_id;
+		$deposit_percent    = $soc->deposit_percent;
 		$mode_reglement_id  = $soc->mode_reglement_id;
 		$fk_account         = $soc->fk_account;
 		$availability_id    = 0;
@@ -1677,8 +1735,8 @@ if ($action == 'create' && $usercancreate) {
 
 	// Terms of the settlement
 	print '<tr><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
-	print img_picto('', 'payment', 'class="pictofixedwidth"');
-	$form->select_conditions_paiements($cond_reglement_id, 'cond_reglement_id', - 1, 1);
+	print img_picto('', 'paiment', 'class="pictofixedwidth"');
+	$form->select_conditions_paiements($cond_reglement_id, 'cond_reglement_id', 1, 1, 0, '', $deposit_percent);
 	print '</td></tr>';
 
 	// Payment mode
@@ -1967,6 +2025,111 @@ if ($action == 'create' && $usercancreate) {
 			if ($nbMandated > 0 ) $text .= '<div><span class="clearboth nowraponall warning">'.$langs->trans("mandatoryPeriodNeedTobeSetMsgValidate").'</span></div>';
 
 
+			$deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
+
+			if (! empty($deposit_percent_from_payment_terms) && ! empty($conf->facture->enabled) && ! empty($user->rights->facture->creer)) {
+				require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
+
+				$object->fetchObjectLinked();
+
+				$eligibleForDepositGeneration = true;
+
+				if (array_key_exists('facture', $object->linkedObjects)) {
+					foreach ($object->linkedObjects['facture'] as $invoice) {
+						if ($invoice->type == Facture::TYPE_DEPOSIT) {
+							$eligibleForDepositGeneration = false;
+							break;
+						}
+					}
+				}
+
+				if ($eligibleForDepositGeneration && array_key_exists('propal', $object->linkedObjects)) {
+					foreach ($object->linkedObjects['propal'] as $proposal) {
+						$proposal->fetchObjectLinked();
+
+						if (array_key_exists('facture', $proposal->linkedObjects)) {
+							foreach ($proposal->linkedObjects['facture'] as $invoice) {
+								if ($invoice->type == Facture::TYPE_DEPOSIT) {
+									$eligibleForDepositGeneration = false;
+									break 2;
+								}
+							}
+						}
+					}
+				}
+
+
+				if ($eligibleForDepositGeneration) {
+					$formquestion[] = array(
+						'type' => 'checkbox',
+						'tdclass' => '',
+						'name' => 'generate_deposit',
+						'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
+					);
+
+					$formquestion[] = array(
+						'type' => 'date',
+						'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
+						'name' => 'datef',
+						'label' => $langs->trans('DateInvoice'),
+						'value' => dol_now(),
+						'datenow' => true
+					);
+
+					if (! empty($conf->global->INVOICE_POINTOFTAX_DATE)) {
+						$formquestion[] = array(
+							'type' => 'date',
+							'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
+							'name' => 'date_pointoftax',
+							'label' => $langs->trans('DatePointOfTax'),
+							'value' => dol_now(),
+							'datenow' => true
+						);
+					}
+
+					ob_start();
+					$form->select_conditions_paiements(0, 'cond_reglement_id', -1, 0, 0, 'minwidth200');
+					$paymentTermsSelect = ob_get_clean();
+
+					$formquestion[] = array(
+						'type' => 'other',
+						'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
+						'name' => 'cond_reglement_id',
+						'label' => $langs->trans('PaymentTerm'),
+						'value' => $paymentTermsSelect
+					);
+
+					$formquestion[] = array(
+						'type' => 'checkbox',
+						'tdclass' => 'showonlyifgeneratedeposit',
+						'name' => 'validate_generated_deposit',
+						'label' => $langs->trans('ValidateGeneratedDeposit')
+					);
+
+					$formquestion[] = array(
+						'type' => 'onecolumn',
+						'value' => '
+							<script>
+								$(document).ready(function() {
+									$("[name=generate_deposit]").change(function () {
+										let $self = $(this);
+										let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
+
+										if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
+											$target.show();
+										} else {
+											$target.hide();
+										}
+
+										return true;
+									});
+								});
+							</script>
+						'
+					);
+				}
+			}
+
 			if (!$error) {
 				$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_validate', $formquestion, 0, 1, 220);
 			}
@@ -2270,9 +2433,9 @@ if ($action == 'create' && $usercancreate) {
 		print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, $editenable);
 		print '</td><td class="valuefield">';
 		if ($action == 'editconditions') {
-			$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1);
+			$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
 		} else {
-			$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 1);
+			$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent);
 		}
 		print '</td>';
 

+ 2 - 1
htdocs/commande/class/api_orders.class.php

@@ -439,7 +439,8 @@ class Orders extends DolibarrApi
 			$request_data->fk_unit,
 			$request_data->multicurrency_subprice,
 			0,
-			$request_data->ref_ext
+			$request_data->ref_ext,
+			$request_data->rang
 		);
 
 		if ($updateRes > 0) {

+ 16 - 3
htdocs/commande/class/commande.class.php

@@ -134,6 +134,11 @@ class Commande extends CommonOrder
 	 */
 	public $cond_reglement_code;
 
+	/**
+	 * @var double Deposit % for payment terms
+	 */
+	public $deposit_percent;
+
 	/**
 	 * @var int bank account ID
 	 */
@@ -332,6 +337,7 @@ class Commande extends CommonOrder
 		'fk_account' =>array('type'=>'integer', 'label'=>'BankAccount', 'enabled'=>1, 'visible'=>-1, 'position'=>170),
 		'fk_currency' =>array('type'=>'varchar(3)', 'label'=>'MulticurrencyID', 'enabled'=>1, 'visible'=>-1, 'position'=>175),
 		'fk_cond_reglement' =>array('type'=>'integer', 'label'=>'PaymentTerm', 'enabled'=>1, 'visible'=>-1, 'position'=>180),
+		'deposit_percent' =>array('type'=>'varchar(63)', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>181),
 		'fk_mode_reglement' =>array('type'=>'integer', 'label'=>'PaymentMode', 'enabled'=>1, 'visible'=>-1, 'position'=>185),
 		'date_livraison' =>array('type'=>'date', 'label'=>'DateDeliveryPlanned', 'enabled'=>1, 'visible'=>-1, 'position'=>190),
 		'fk_shipping_method' =>array('type'=>'integer', 'label'=>'ShippingMethod', 'enabled'=>1, 'visible'=>-1, 'position'=>195),
@@ -940,7 +946,7 @@ class Commande extends CommonOrder
 
 		$sql = "INSERT INTO ".MAIN_DB_PREFIX."commande (";
 		$sql .= " ref, fk_soc, date_creation, fk_user_author, fk_projet, date_commande, source, note_private, note_public, ref_ext, ref_client, ref_int";
-		$sql .= ", model_pdf, fk_cond_reglement, fk_mode_reglement, fk_account, fk_availability, fk_input_reason, date_livraison, fk_delivery_address";
+		$sql .= ", model_pdf, fk_cond_reglement, deposit_percent, fk_mode_reglement, fk_account, fk_availability, fk_input_reason, date_livraison, fk_delivery_address";
 		$sql .= ", fk_shipping_method";
 		$sql .= ", fk_warehouse";
 		$sql .= ", remise_absolue, remise_percent";
@@ -961,6 +967,7 @@ class Commande extends CommonOrder
 		$sql .= ", ".($this->ref_int ? "'".$this->db->escape($this->ref_int)."'" : "null");
 		$sql .= ", '".$this->db->escape($this->model_pdf)."'";
 		$sql .= ", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) : "null");
+		$sql .= ", ".(! empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : "null");
 		$sql .= ", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) : "null");
 		$sql .= ", ".($this->fk_account > 0 ? ((int) $this->fk_account) : 'NULL');
 		$sql .= ", ".($this->availability_id > 0 ? ((int) $this->availability_id) : "null");
@@ -1212,6 +1219,7 @@ class Commande extends CommonOrder
 			if ($objsoc->fetch($socid) > 0) {
 				$this->socid = $objsoc->id;
 				$this->cond_reglement_id	= (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
+				$this->deposit_percent		= (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent : null);
 				$this->mode_reglement_id	= (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
 				$this->fk_project = 0;
 				$this->fk_delivery_address = 0;
@@ -1354,6 +1362,7 @@ class Commande extends CommonOrder
 		$this->socid                = $object->socid;
 		$this->fk_project           = $object->fk_project;
 		$this->cond_reglement_id    = $object->cond_reglement_id;
+		$this->deposit_percent      = $object->deposit_percent;
 		$this->mode_reglement_id    = $object->mode_reglement_id;
 		$this->fk_account           = $object->fk_account;
 		$this->availability_id      = $object->availability_id;
@@ -1811,7 +1820,7 @@ class Commande extends CommonOrder
 		}
 
 		$sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_user_modif, c.fk_statut';
-		$sql .= ', c.amount_ht, c.total_ht, c.total_ttc, c.total_tva, c.localtax1 as total_localtax1, c.localtax2 as total_localtax2, c.fk_cond_reglement, c.fk_mode_reglement, c.fk_availability, c.fk_input_reason';
+		$sql .= ', c.amount_ht, c.total_ht, c.total_ttc, c.total_tva, c.localtax1 as total_localtax1, c.localtax2 as total_localtax2, c.fk_cond_reglement, c.deposit_percent, c.fk_mode_reglement, c.fk_availability, c.fk_input_reason';
 		$sql .= ', c.fk_account';
 		$sql .= ', c.date_commande, c.date_valid, c.tms';
 		$sql .= ', c.date_livraison as delivery_date';
@@ -1904,6 +1913,7 @@ class Commande extends CommonOrder
 				$this->cond_reglement_code	= $obj->cond_reglement_code;
 				$this->cond_reglement		= $obj->cond_reglement_libelle;
 				$this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
+				$this->deposit_percent = $obj->deposit_percent;
 				$this->fk_account = $obj->fk_account;
 				$this->availability_id = $obj->fk_availability;
 				$this->availability_code	= $obj->availability_code;
@@ -3077,9 +3087,10 @@ class Commande extends CommonOrder
 	 *  @param		double			$pu_ht_devise		Amount in currency
 	 * 	@param		int				$notrigger			disable line update trigger
 	 * 	@param		string			$ref_ext			external reference
+	 * @param       integer $rang   line rank
 	 *  @return   	int              					< 0 if KO, > 0 if OK
 	 */
-	public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $price_base_type = 'HT', $info_bits = 0, $date_start = '', $date_end = '', $type = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0, $label = '', $special_code = 0, $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $notrigger = 0, $ref_ext = '')
+	public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $price_base_type = 'HT', $info_bits = 0, $date_start = '', $date_end = '', $type = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0, $label = '', $special_code = 0, $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $notrigger = 0, $ref_ext = '', $rang = 0)
 	{
 		global $conf, $mysoc, $langs, $user;
 
@@ -3204,6 +3215,7 @@ class Commande extends CommonOrder
 			$line->oldline = $staticline;
 			$this->line = $line;
 			$this->line->context = $this->context;
+			$this->line->rang = $rang;
 
 			// Reorder if fk_parent_line change
 			if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
@@ -3340,6 +3352,7 @@ class Commande extends CommonOrder
 		$sql .= " fk_user_valid=".(isset($this->user_valid) ? $this->user_valid : "null").",";
 		$sql .= " fk_projet=".(isset($this->fk_project) ? $this->fk_project : "null").",";
 		$sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->cond_reglement_id : "null").",";
+		$sql .= " deposit_percent=".(! empty($this->deposit_percent) ? strval($this->deposit_percent) : "null").",";
 		$sql .= " fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->mode_reglement_id : "null").",";
 		$sql .= " date_livraison=".(strval($this->delivery_date) != '' ? "'".$this->db->idate($this->delivery_date)."'" : 'null').",";
 		$sql .= " fk_shipping_method=".(isset($this->shipping_method_id) ? $this->shipping_method_id : "null").",";

+ 8 - 8
htdocs/commande/list.php

@@ -267,7 +267,7 @@ if (empty($reshook)) {
 		$search_project = '';
 		$search_status = '';
 		$search_billed = '';
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 		$search_categ_cus = 0;
 		$search_datecloture_start = '';
@@ -787,7 +787,7 @@ $sql .= ' c.date_valid, c.date_commande, c.note_public, c.note_private, c.date_l
 $sql .= ' c.date_creation as date_creation, c.tms as date_update, c.date_cloture as date_cloture,';
 $sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label,';
 $sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as user_statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender,';
-$sql .= ' c.fk_cond_reglement,c.fk_mode_reglement,c.fk_shipping_method,';
+$sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shipping_method,';
 $sql .= ' c.fk_input_reason, c.import_key';
 if (($search_categ_cus > 0) || ($search_categ_cus == -2)) {
 	$sql .= ", cc.fk_categorie, cc.fk_soc";
@@ -1479,7 +1479,7 @@ if ($resql) {
 	// Payment term
 	if (!empty($arrayfields['c.fk_cond_reglement']['checked'])) {
 		print '<td class="liste_titre">';
-		$form->select_conditions_paiements($search_fk_cond_reglement, 'search_fk_cond_reglement', -1, 1, 1);
+		$form->select_conditions_paiements($search_fk_cond_reglement, 'search_fk_cond_reglement', 1, 1, 1);
 		print '</td>';
 	}
 	// Payment mode
@@ -2032,7 +2032,7 @@ if ($resql) {
 		// Payment terms
 		if (!empty($arrayfields['c.fk_cond_reglement']['checked'])) {
 			print '<td>';
-			$form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none');
+			$form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 0, '', 1, $obj->deposit_percent);
 			print '</td>';
 			if (!$i) {
 				$totalarray['nbfield']++;
@@ -2290,8 +2290,8 @@ if ($resql) {
 
 		// Note public
 		if (!empty($arrayfields['c.note_public']['checked'])) {
-			print '<td align="center" class="nowrap">';
-			print dol_escape_htmltag($obj->note_public);
+			print '<td class="center">';
+			print dol_string_nohtmltag($obj->note_public);
 			print '</td>';
 			if (!$i) {
 				$totalarray['nbfield']++;
@@ -2300,8 +2300,8 @@ if ($resql) {
 
 		// Note private
 		if (!empty($arrayfields['c.note_private']['checked'])) {
-			print '<td align="center" class="nowrap">';
-			print dol_escape_htmltag($obj->note_private);
+			print '<td class="center">';
+			print dol_string_nohtmltag($obj->note_private);
 			print '</td>';
 			if (!$i) {
 				$totalarray['nbfield']++;

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

@@ -214,7 +214,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
 	$search_thirdparty_user = '';
 	$search_num_releve = '';
 	$search_conciliated = '';
-	$toselect = '';
+	$toselect = array();
 
 	$search_account = "";
 	if ($id > 0 || !empty($ref)) {

+ 21 - 12
htdocs/compta/bank/line.php

@@ -52,11 +52,12 @@ if (!empty($conf->salaries->enabled)) {
 
 
 $id = GETPOST('rowid', 'int');
-$accountid = (GETPOST('id', 'int') ? GETPOST('id', 'int') : GETPOST('account', 'int'));
+$rowid = GETPOST("rowid", 'int');
+$accountoldid = GETPOST('account', 'int');		// GETPOST('account') is old account id
+$accountid = GETPOST('accountid', 'int');		// GETPOST('accountid') is new account id
 $ref = GETPOST('ref', 'alpha');
 $action = GETPOST('action', 'aZ09');
 $confirm = GETPOST('confirm', 'alpha');
-$rowid = GETPOST("rowid", 'int');
 $orig_account = GETPOST("orig_account");
 $backtopage = GETPOST('backtopage', 'alpha');
 $cancel = GETPOST('cancel', 'alpha');
@@ -69,7 +70,7 @@ if ($user->socid) {
 	$socid = $user->socid;
 }
 
-$result = restrictedArea($user, 'banque', $accountid, 'bank_account');
+$result = restrictedArea($user, 'banque', $accountoldid, 'bank_account');
 if (empty($user->rights->banque->lire) && empty($user->rights->banque->consolidate)) {
 	accessforbidden();
 }
@@ -124,18 +125,26 @@ if ($user->rights->banque->modifier && $action == "update") {
 	$error = 0;
 
 	$acline = new AccountLine($db);
-	$acline->fetch($rowid);
+	$result = $acline->fetch($rowid);
+	if ($result <= 0) {
+		dol_syslog('Failed to read bank line with id '.$rowid, LOG_WARNING);	// This happens due to old bug that has set fk_account to null.
+		$acline->id = $rowid;
+	}
 
 	$acsource = new Account($db);
-	$acsource->fetch($id);
+	$acsource->fetch($accountoldid);
 
 	$actarget = new Account($db);
 	if (GETPOST('accountid', 'int') > 0 && !$acline->rappro && !$acline->getVentilExportCompta()) {	// We ask to change bank account
 		$actarget->fetch(GETPOST('accountid', 'int'));
 	} else {
-		$actarget->fetch($id);
+		$actarget->fetch($accountoldid);
 	}
 
+	if (!($actarget->id > 0)) {
+		setEventMessages($langs->trans("ErrorFailedToLoadBankAccount"), null, 'errors');
+		$error++;
+	}
 	if ($actarget->courant == Account::TYPE_CASH && GETPOST('value', 'alpha') != 'LIQ') {
 		setEventMessages($langs->trans("ErrorCashAccountAcceptsOnlyCashMoney"), null, 'errors');
 		$error++;
@@ -229,7 +238,7 @@ if ($user->rights->banque->consolidate && ($action == 'num_releve' || $action ==
 		$db->begin();
 
 		$sql = "UPDATE ".MAIN_DB_PREFIX."bank";
-		$sql .= " SET num_releve=".($num_rel ? "'".$db->escape($num_rel)."'" : "null");
+		$sql .= " SET num_releve = ".($num_rel ? "'".$db->escape($num_rel)."'" : "null");
 		if (empty($num_rel)) {
 			$sql .= ", rappro = 0";
 		} else {
@@ -307,7 +316,6 @@ if ($result) {
 		print '<input type="hidden" name="action" value="update">';
 		print '<input type="hidden" name="orig_account" value="'.$orig_account.'">';
 		print '<input type="hidden" name="account" value="'.$acct->id.'">';
-		print '<input type="hidden" name="id" value="'.$acct->id.'">';
 
 		print dol_get_fiche_head($head, 'bankline', $langs->trans('LineRecord'), 0, 'accountline', 0);
 
@@ -326,11 +334,12 @@ if ($result) {
 		// Bank account
 		print '<tr><td class="titlefieldcreate">'.$langs->trans("Account").'</td>';
 		print '<td>';
-		if (!$objp->rappro && !$bankline->getVentilExportCompta()) {
-			print img_picto('', 'bank_account', 'class="paddingright"');
-			print $form->select_comptes($acct->id, 'accountid', 0, '', 0, '', 0, '', 1);
-		} else {
+		// $objp->fk_account may be not > 0 if data was lost by an old bug. In such a case, we let a chance to user to fix it.
+		if (($objp->rappro || $bankline->getVentilExportCompta()) && $objp->fk_account > 0) {
 			print $acct->getNomUrl(1, 'transactions', 'reflabel');
+		} else {
+			print img_picto('', 'bank_account', 'class="paddingright"');
+			print $form->select_comptes($acct->id, 'accountid', 0, '', ($acct->id > 0 ? $acct->id : 1), '', 0, '', 1);
 		}
 		print '</td>';
 		print '</tr>';

+ 34 - 14
htdocs/compta/bank/various_payment/list.php

@@ -40,7 +40,6 @@ $socid = GETPOST("socid", "int");
 if ($user->socid) {
 	$socid = $user->socid;
 }
-$result = restrictedArea($user, 'banque', '', '', '');
 
 $optioncss = GETPOST('optioncss', 'alpha');
 
@@ -173,6 +172,11 @@ $arrayfields = array(
 
 $arrayfields = dol_sort_array($arrayfields, 'position');
 
+$object = new PaymentVarious($db);
+
+$result = restrictedArea($user, 'banque', '', '', '');
+
+
 /*
  * Actions
  */
@@ -271,19 +275,19 @@ if ($search_all) {
 $sql .= $db->order($sortfield, $sortorder);
 
 $totalnboflines = 0;
-$result = $db->query($sql);
-if ($result) {
-	$totalnboflines = $db->num_rows($result);
+$resql = $db->query($sql);
+if ($resql) {
+	$totalnboflines = $db->num_rows($resql);
 }
 $sql .= $db->plimit($limit + 1, $offset);
 
-$result = $db->query($sql);
-if ($result) {
-	$num = $db->num_rows($result);
+$resql = $db->query($sql);
+if ($resql) {
+	$num = $db->num_rows($resql);
 
 	// Direct jump if only one record found
 	if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all) {
-		$obj = $db->fetch_object($result);
+		$obj = $db->fetch_object($resql);
 		$id = $obj->rowid;
 		header("Location: ".DOL_URL_ROOT.'/compta/bank/various_payment/card.php?id='.$id);
 		exit;
@@ -541,7 +545,7 @@ if ($result) {
 
 	$totalarray = array();
 	while ($i < min($num, $limit)) {
-		$obj = $db->fetch_object($result);
+		$obj = $db->fetch_object($resql);
 
 		$variousstatic->id = $obj->rowid;
 		$variousstatic->ref = $obj->rowid;
@@ -704,7 +708,7 @@ if ($result) {
 			$totalarray['nbfield']++;
 		}
 
-		print "</tr>";
+		print '</tr>'."\n";
 
 		$i++;
 	}
@@ -712,11 +716,27 @@ if ($result) {
 	// Show total line
 	include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
 
-	print "</table>";
-	print '</div>';
-	print '</form>';
+	// If no record found
+	if ($num == 0) {
+		$colspan = 1;
+		foreach ($arrayfields as $key => $val) {
+			if (!empty($val['checked'])) {
+				$colspan++;
+			}
+		}
+		print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
+	}
+
+	$db->free($resql);
+
+	$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
+	$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook
+	print $hookmanager->resPrint;
+
+	print '</table>'."\n";
+	print '</div>'."\n";
 
-	$db->free($result);
+	print '</form>'."\n";
 } else {
 	dol_print_error($db);
 }

+ 1 - 1
htdocs/compta/cashcontrol/cashcontrol_list.php

@@ -165,7 +165,7 @@ if (empty($reshook)) {
 				$search[$key.'_dtend'] = '';
 			}
 		}
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 	if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')

+ 14 - 1
htdocs/compta/facture/card-rec.php

@@ -1695,7 +1695,20 @@ if ($action == 'create') {
 		$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
 
 
-		print '</div></div>';
+		print '</div>';
+		print '<div class="fichehalfright">';
+
+		$MAXEVENT = 10;
+
+		//$morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-list-alt imgforviewmode', dol_buildpath('/mymodule/myobject_agenda.php', 1).'?id='.$object->id);
+
+		// List of actions on element
+		include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
+		$formactions = new FormActions($db);
+		$somethingshown = $formactions->showactions($object, $object->element, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
+
+		print '</div>';
+		print '</div>';
 	}
 }
 

+ 14 - 3
htdocs/compta/facture/card.php

@@ -305,7 +305,7 @@ if (empty($reshook)) {
 		$object->fetch($id);
 
 		if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) {
-			$last_of_type = $object->willBeLastOfSameType();
+			$last_of_type = $object->willBeLastOfSameType(true);
 			if (empty($object->date_validation) && !$last_of_type[0]) {
 				setEventMessages($langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $object->ref, dol_print_date($object->date, 'day'), dol_print_date($last_of_type[1], 'day')), null, 'errors');
 				$action = '';
@@ -3287,10 +3287,21 @@ if ($action == 'create') {
 					'variable' => $langs->transnoentitiesnoconv('VarAmountOneLine', $langs->transnoentitiesnoconv('Deposit')),
 					'variablealllines' => $langs->transnoentitiesnoconv('VarAmountAllLines')
 				);
-				print $form->selectarray('typedeposit', $arraylist, GETPOST('typedeposit', 'aZ09'), 0, 0, 0, '', 1);
+				$typedeposit = GETPOST('typedeposit', 'aZ09');
+				$valuedeposit = GETPOST('valuedeposit', 'int');
+				if (empty($typedeposit) && ! empty($objectsrc->deposit_percent)) {
+					$origin_payment_conditions_deposit_percent = getDictionaryValue('c_payment_term', 'deposit_percent', $objectsrc->cond_reglement_id);
+					if (! empty($origin_payment_conditions_deposit_percent)) {
+						$typedeposit = 'variable';
+					}
+				}
+				if (empty($valuedeposit) && $typedeposit == 'variable' && ! empty($objectsrc->deposit_percent)) {
+					$valuedeposit = $objectsrc->deposit_percent;
+				}
+				print $form->selectarray('typedeposit', $arraylist, $typedeposit, 0, 0, 0, '', 1);
 				print '</td>';
 				print '<td class="nowrap" style="padding-left: 5px">';
-				print '<span class="opacitymedium paddingleft">'.$langs->trans("AmountOrPercent").'</span><input type="text" id="valuedeposit" name="valuedeposit" class="width75 right" value="'.GETPOST('valuedeposit', 'int').'"/>';
+				print '<span class="opacitymedium paddingleft">'.$langs->trans("AmountOrPercent").'</span><input type="text" id="valuedeposit" name="valuedeposit" class="width75 right" value="'.$valuedeposit.'"/>';
 				print '</td>';
 			}
 			print '</tr></table>';

+ 2 - 1
htdocs/compta/facture/class/api_invoices.class.php

@@ -451,7 +451,8 @@ class Invoices extends DolibarrApi
 			$request_data->fk_unit,
 			$request_data->multicurrency_subprice,
 			0,
-			$request_data->ref_ext
+			$request_data->ref_ext,
+			$request_data->rang
 		);
 
 		if ($updateRes > 0) {

+ 100 - 8
htdocs/compta/facture/class/facture-rec.class.php

@@ -270,6 +270,7 @@ class FactureRec extends CommonInvoice
 		if ($result > 0) {
 			// On positionne en mode brouillon la facture
 			$this->brouillon = 1;
+			$this->fk_soc = $facsrc->socid;
 
 			$sql = "INSERT INTO ".MAIN_DB_PREFIX."facture_rec (";
 			$sql .= "titre";
@@ -301,7 +302,7 @@ class FactureRec extends CommonInvoice
 			$sql .= ", suspended";
 			$sql .= ") VALUES (";
 			$sql .= "'".$this->db->escape($this->titre ? $this->titre : $this->title)."'";
-			$sql .= ", ".((int) $facsrc->socid);
+			$sql .= ", ".((int) $this->fk_soc);
 			$sql .= ", ".((int) $conf->entity);
 			$sql .= ", '".$this->db->idate($now)."'";
 			$sql .= ", ".(!empty($facsrc->total_ttc) ? ((float) $facsrc->total_ttc) : '0');
@@ -1256,9 +1257,10 @@ class FactureRec extends CommonInvoice
 	 *
 	 *  @param	int		$restrictioninvoiceid		0=All qualified template invoices found. > 0 = restrict action on invoice ID
 	 *  @param	int		$forcevalidation		1=Force validation of invoice whatever is template auto_validate flag.
+	 *	@param     	int 	$notrigger 			Disable the trigger
 	 *  @return	int								0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
 	 */
-	public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidation = 0)
+	public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidation = 0, $notrigger = 0)
 	{
 		global $conf, $langs, $db, $user, $hookmanager;
 
@@ -1338,6 +1340,8 @@ class FactureRec extends CommonInvoice
 						$this->error = $facture->error;
 						$error++;
 					}
+
+
 					if (!$error && ($facturerec->auto_validate || $forcevalidation)) {
 						$result = $facture->validate($user);
 						if ($result <= 0) {
@@ -1356,6 +1360,16 @@ class FactureRec extends CommonInvoice
 							$error++;
 						}
 					}
+					if (!$error && !$notrigger) {
+						// Call trigger
+						$result = $facturerec->call_trigger('BILLREC_CREATEBILL', $user);
+						if ($result < 0) {
+							$this->errors = $facturerec->errors;
+							$this->error = $facturerec->error;
+							$error++;
+						}
+						// End call triggers
+					}
 				} else {
 					$error++;
 					$this->error = "Failed to load invoice template with id=".$line->rowid.", entity=".$conf->entity."\n";
@@ -1788,10 +1802,13 @@ class FactureRec extends CommonInvoice
 	 *
 	 *	@param     	int		$frequency		value of frequency
 	 *	@param     	string	$unit 			unit of frequency  (d, m, y)
+	 *	@param     	int 	$notrigger 		Disable the trigger
 	 *	@return		int						<0 if KO, >0 if OK
 	 */
-	public function setFrequencyAndUnit($frequency, $unit)
+	public function setFrequencyAndUnit($frequency, $unit, $notrigger = 0)
 	{
+		global $user;
+
 		if (!$this->table_element) {
 			dol_syslog(get_class($this)."::setFrequencyAndUnit was called on objet with property table_element not defined", LOG_ERR);
 			return -1;
@@ -1815,6 +1832,16 @@ class FactureRec extends CommonInvoice
 			if (!empty($unit)) {
 				$this->unit_frequency = $unit;
 			}
+
+			if (!$notrigger) {
+				// Call trigger
+				$result = $this->call_trigger('BILLREC_MODIFY', $user);
+				if ($result < 0) {
+					return $result;
+				}
+				// End call triggers
+			}
+
 			return 1;
 		} else {
 			dol_print_error($this->db);
@@ -1827,10 +1854,14 @@ class FactureRec extends CommonInvoice
 	 *
 	 *	@param     	datetime	$date					date of execution
 	 *	@param     	int			$increment_nb_gen_done	0 do nothing more, >0 increment nb_gen_done
+	 *	@param     	int 	    $notrigger		 		Disable the trigger
 	 *	@return		int									<0 if KO, >0 if OK
 	 */
-	public function setNextDate($date, $increment_nb_gen_done = 0)
+	public function setNextDate($date, $increment_nb_gen_done = 0, $notrigger = 0)
 	{
+
+		global $user;
+
 		if (!$this->table_element) {
 			dol_syslog(get_class($this)."::setNextDate was called on objet with property table_element not defined", LOG_ERR);
 			return -1;
@@ -1848,6 +1879,15 @@ class FactureRec extends CommonInvoice
 			if ($increment_nb_gen_done > 0) {
 				$this->nb_gen_done++;
 			}
+
+			if (!$notrigger) {
+				// Call trigger
+				$result = $this->call_trigger('BILLREC_MODIFY', $user);
+				if ($result < 0) {
+					return $result;
+				}
+				// End call triggers
+			}
 			return 1;
 		} else {
 			dol_print_error($this->db);
@@ -1859,10 +1899,14 @@ class FactureRec extends CommonInvoice
 	 *	Update the maximum period
 	 *
 	 *	@param     	int		$nb		number of maximum period
+	 *	@param     	int 	$notrigger Disable the trigger
 	 *	@return		int				<0 if KO, >0 if OK
 	 */
-	public function setMaxPeriod($nb)
+	public function setMaxPeriod($nb, $notrigger = 0)
 	{
+
+		global $user;
+
 		if (!$this->table_element) {
 			dol_syslog(get_class($this)."::setMaxPeriod was called on objet with property table_element not defined", LOG_ERR);
 			return -1;
@@ -1879,6 +1923,16 @@ class FactureRec extends CommonInvoice
 		dol_syslog(get_class($this)."::setMaxPeriod", LOG_DEBUG);
 		if ($this->db->query($sql)) {
 			$this->nb_gen_max = $nb;
+
+			if (!$notrigger) {
+				// Call trigger
+				$result = $this->call_trigger('BILLREC_MODIFY', $user);
+				if ($result < 0) {
+					return $result;
+				}
+				// End call triggers
+			}
+
 			return 1;
 		} else {
 			dol_print_error($this->db);
@@ -1890,10 +1944,13 @@ class FactureRec extends CommonInvoice
 	 *	Update the auto validate flag of invoice
 	 *
 	 *	@param     	int		$validate		0 to create in draft, 1 to create and validate invoice
+	 *	@param     	int 	$notrigger 		Disable the trigger
 	 *	@return		int						<0 if KO, >0 if OK
 	 */
-	public function setAutoValidate($validate)
+	public function setAutoValidate($validate, $notrigger = 0)
 	{
+		global $user;
+
 		if (!$this->table_element) {
 			dol_syslog(get_class($this)."::setAutoValidate was called on objet with property table_element not defined", LOG_ERR);
 			return -1;
@@ -1906,6 +1963,16 @@ class FactureRec extends CommonInvoice
 		dol_syslog(get_class($this)."::setAutoValidate", LOG_DEBUG);
 		if ($this->db->query($sql)) {
 			$this->auto_validate = $validate;
+
+			if (!$notrigger) {
+				// Call trigger
+				$result = $this->call_trigger('BILLREC_MODIFY', $user);
+				if ($result < 0) {
+					return $result;
+				}
+				// End call triggers
+			}
+
 			return 1;
 		} else {
 			dol_print_error($this->db);
@@ -1917,10 +1984,13 @@ class FactureRec extends CommonInvoice
 	 *	Update the auto generate documents
 	 *
 	 *	@param     	int		$validate		0 no document, 1 to generate document
+	 *	@param     	int 	$notrigger 		Disable the trigger
 	 *	@return		int						<0 if KO, >0 if OK
 	 */
-	public function setGeneratePdf($validate)
+	public function setGeneratePdf($validate, $notrigger = 0)
 	{
+		global $user;
+
 		if (!$this->table_element) {
 			dol_syslog(get_class($this)."::setGeneratePdf was called on objet with property table_element not defined", LOG_ERR);
 			return -1;
@@ -1933,6 +2003,16 @@ class FactureRec extends CommonInvoice
 		dol_syslog(get_class($this)."::setGeneratePdf", LOG_DEBUG);
 		if ($this->db->query($sql)) {
 			$this->generate_pdf = $validate;
+
+			if (!$notrigger) {
+				// Call trigger
+				$result = $this->call_trigger('BILLREC_MODIFY', $user);
+				if ($result < 0) {
+					return $result;
+				}
+				// End call triggers
+			}
+
 			return 1;
 		} else {
 			dol_print_error($this->db);
@@ -1944,10 +2024,12 @@ class FactureRec extends CommonInvoice
 	 *  Update the model for documents
 	 *
 	 *  @param     	string		$model		model of document generator
+	 *	@param     	int 	$notrigger 		Disable the trigger
 	 *  @return		int						<0 if KO, >0 if OK
 	 */
-	public function setModelPdf($model)
+	public function setModelPdf($model, $notrigger = 0)
 	{
+		global $user;
 		if (!$this->table_element) {
 			dol_syslog(get_class($this)."::setModelPdf was called on objet with property table_element not defined", LOG_ERR);
 			return -1;
@@ -1960,6 +2042,16 @@ class FactureRec extends CommonInvoice
 		dol_syslog(get_class($this)."::setModelPdf", LOG_DEBUG);
 		if ($this->db->query($sql)) {
 			$this->model_pdf = $model;
+
+			if (!$notrigger) {
+				// Call trigger
+				$result = $this->call_trigger('BILLREC_MODIFY', $user);
+				if ($result < 0) {
+					return $result;
+				}
+				// End call triggers
+			}
+
 			return 1;
 		} else {
 			dol_print_error($this->db);

+ 298 - 4
htdocs/compta/facture/class/facture.class.php

@@ -1463,6 +1463,292 @@ class Facture extends CommonInvoice
 		}
 	}
 
+	/**
+	 * Creates a deposit from a proposal or an order by grouping lines by VAT rates
+	 *
+	 * @param	Propal|Commande		$origin					The original proposal or order
+	 * @param	int					$date					Invoice date
+	 * @param	int					$payment_terms_id		Invoice payment terms
+	 * @param	User				$user					Object user
+	 * @param	int					$notrigger				1=Does not execute triggers, 0= execute triggers
+	 * @param	bool				$autoValidateDeposit	Whether to aumatically validate the deposit created
+	 * @param	array				$overrideFields			Array of fields to force values
+	 * @return	Facture|null								The deposit created, or null if error (populates $origin->error in this case)
+	 */
+	static public function createDepositFromOrigin(CommonObject $origin, $date, $payment_terms_id, User $user, $notrigger = 0, $autoValidateDeposit = false, $overrideFields = array())
+	{
+		global $conf, $langs, $hookmanager, $action;
+
+		if (! in_array($origin->element, array('propal', 'commande'))) {
+			$origin->error = 'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder';
+			return null;
+		}
+
+		if (empty($date)) {
+			$origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('DateInvoice'));
+			return null;
+		}
+
+		require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
+
+		if ($date > (dol_get_last_hour(dol_now('tzuserrel')) + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) {
+			$origin->error = 'ErrorDateIsInFuture';
+			return null;
+		}
+
+		if ($payment_terms_id <= 0) {
+			$origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('PaymentConditionsShort'));
+			return null;
+		}
+
+		$payment_conditions_deposit_percent = getDictionaryValue('c_payment_term', 'deposit_percent', $origin->cond_reglement_id);
+
+		if (empty($payment_conditions_deposit_percent)) {
+			$origin->error = 'ErrorPaymentConditionsNotEligibleToDepositCreation';
+			return null;
+		}
+
+		if (empty($origin->deposit_percent)) {
+			$origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('DepositPercent'));
+			return null;
+		}
+
+		$deposit = new self($origin->db);
+		$deposit->socid = $origin->socid;
+		$deposit->type = self::TYPE_DEPOSIT;
+		$deposit->fk_project = $origin->fk_project;
+		$deposit->ref_client = $origin->ref_client;
+		$deposit->date = $date;
+		$deposit->mode_reglement_id = $origin->mode_reglement_id;
+		$deposit->cond_reglement_id = $payment_terms_id;
+		$deposit->availability_id = $origin->availability_id;
+		$deposit->demand_reason_id = $origin->demand_reason_id;
+		$deposit->fk_account = $origin->fk_account;
+		$deposit->fk_incoterms = $origin->fk_incoterms;
+		$deposit->location_incoterms = $origin->location_incoterms;
+		$deposit->fk_multicurrency = $origin->fk_multicurrency;
+		$deposit->multicurrency_code = $origin->multicurrency_code;
+		$deposit->multicurrency_tx = $origin->multicurrency_tx;
+		$deposit->module_source = $origin->module_source;
+		$deposit->pos_source = $origin->pos_source;
+		$deposit->model_pdf = 'crabe';
+
+		$modelByTypeConfName = 'FACTURE_ADDON_PDF_' . $deposit->type;
+
+		if (!empty($conf->global->$modelByTypeConfName)) {
+			$deposit->model_pdf = $conf->global->$modelByTypeConfName;
+		} elseif (!empty($conf->global->FACTURE_ADDON_PDF)) {
+			$deposit->model_pdf = $conf->global->FACTURE_ADDON_PDF;
+		}
+
+		if (empty($conf->global->MAIN_DISABLE_PROPAGATE_NOTES_FROM_ORIGIN)) {
+			$deposit->note_private = $origin->note_private;
+			$deposit->note_public = $origin->note_public;
+		}
+
+		$deposit->origin = $origin->element;
+		$deposit->origin_id = $origin->id;
+
+		$origin->fetch_optionals();
+
+		foreach ($origin->array_options as $extrakey => $value) {
+			$deposit->array_options[$extrakey] = $value;
+		}
+
+		$deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
+
+		foreach ($overrideFields as $key => $value) {
+			$deposit->$key = $value;
+		}
+
+		$deposit->context['createdepositfromorigin'] = 'createdepositfromorigin';
+
+		$origin->db->begin();
+
+		// Facture::create() also imports contact from origin
+		$createReturn = $deposit->create($user, $notrigger);
+
+		if ($createReturn <= 0) {
+			$origin->db->rollback();
+			$origin->error = $deposit->error;
+			$origin->errors = $deposit->errors;
+			return null;
+		}
+
+		$amount_ttc_diff = 0;
+		$amountdeposit = array();
+		$descriptions = array();
+
+		if (! empty($conf->global->MAIN_DEPOSIT_MULTI_TVA)) {
+			$amount = $origin->total_ttc * ($origin->deposit_percent / 100);
+
+			$TTotalByTva = array();
+			foreach ($origin->lines as &$line) {
+				if (!empty($line->special_code)) {
+					continue;
+				}
+				$TTotalByTva[$line->tva_tx] += $line->total_ttc;
+				$descriptions[$line->tva_tx] .= '<li>' . (! empty($line->product_ref) ? $line->product_ref . ' - ' :  '');
+				$descriptions[$line->tva_tx] .= (! empty($line->product_label) ? $line->product_label . ' - ' : '');
+				$descriptions[$line->tva_tx] .= $langs->trans('Qty') . ' : ' . $line->qty;
+				$descriptions[$line->tva_tx] .= ' - ' . $langs->trans('TotalHT') . ' : ' . price($line->total_ht) . '</li>';
+			}
+
+			foreach ($TTotalByTva as $tva => &$total) {
+				$coef = $total / $origin->total_ttc; // Calc coef
+				$am = $amount * $coef;
+				$amount_ttc_diff += $am;
+				$amountdeposit[$tva] += $am / (1 + $tva / 100); // Convert into HT for the addline
+			}
+		} else {
+			$totalamount = 0;
+			$lines = $origin->lines;
+			$numlines = count($lines);
+			for ($i = 0; $i < $numlines; $i++) {
+				if (empty($lines[$i]->qty)) {
+					continue; // We discard qty=0, it is an option
+				}
+				if (!empty($lines[$i]->special_code)) {
+					continue; // We discard special_code (frais port, ecotaxe, option, ...)
+				}
+
+				$totalamount += $lines[$i]->total_ht; // Fixme : is it not for the customer ? Shouldn't we take total_ttc ?
+				$tva_tx = $lines[$i]->tva_tx;
+				$amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
+				$descriptions[$tva_tx] .= '<li>' . (! empty($lines[$i]->product_ref) ? $lines[$i]->product_ref . ' - ' :  '');
+				$descriptions[$tva_tx] .= (! empty($lines[$i]->product_label) ? $lines[$i]->product_label . ' - ' : '');
+				$descriptions[$tva_tx] .= $langs->trans('Qty') . ' : ' . $lines[$i]->qty;
+				$descriptions[$tva_tx] .= ' - ' . $langs->trans('TotalHT') . ' : ' . price($lines[$i]->total_ht) . '</li>';
+			}
+
+			if ($totalamount == 0) {
+				$amountdeposit[0] = 0;
+			}
+
+			$amount_ttc_diff = $amountdeposit[0];
+		}
+
+		foreach ($amountdeposit as $tva => $amount) {
+			if (empty($amount)) {
+				continue;
+			}
+
+			$descline = '(DEPOSIT) ('. $origin->deposit_percent .'%) - '.$origin->ref;
+
+			// Hidden conf
+			if (! empty($conf->global->INVOICE_DEPOSIT_VARIABLE_MODE_DETAIL_LINES_IN_DESCRIPTION) && ! empty($descriptions[$tva])) {
+				$descline .= '<ul>' . $descriptions[$tva] . '</ul>';
+			}
+
+			$addlineResult = $deposit->addline(
+				$descline,
+				$amount, // subprice
+				1, // quantity
+				$tva, // vat rate
+				0, // localtax1_tx
+				0, // localtax2_tx
+				(empty($conf->global->INVOICE_PRODUCTID_DEPOSIT) ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT), // fk_product
+				0, // remise_percent
+				0, // date_start
+				0, // date_end
+				0,
+				$lines[$i]->info_bits, // info_bits
+				0,
+				'HT',
+				0,
+				0, // product_type
+				1,
+				$lines[$i]->special_code,
+				$deposit->origin,
+				0,
+				0,
+				0,
+				0
+				//,$langs->trans('Deposit') //Deprecated
+			);
+
+			if ($addlineResult < 0) {
+				$origin->db->rollback();
+				$origin->error = $deposit->error;
+				$origin->errors = $deposit->errors;
+				return null;
+			}
+		}
+
+		$diff = $deposit->total_ttc - $amount_ttc_diff;
+
+		if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA) && $diff != 0) {
+			$deposit->fetch_lines();
+			$subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
+
+			$updatelineResult = $deposit->updateline(
+				$deposit->lines[0]->id,
+				$deposit->lines[0]->desc,
+				$subprice_diff,
+				$deposit->lines[0]->qty,
+				$deposit->lines[0]->remise_percent,
+				$deposit->lines[0]->date_start,
+				$deposit->lines[0]->date_end,
+				$deposit->lines[0]->tva_tx,
+				0,
+				0,
+				'HT',
+				$deposit->lines[0]->info_bits,
+				$deposit->lines[0]->product_type,
+				0,
+				0,
+				0,
+				$deposit->lines[0]->pa_ht,
+				$deposit->lines[0]->label,
+				0,
+				array(),
+				100
+			);
+
+			if ($updatelineResult < 0) {
+				$origin->db->rollback();
+				$origin->error = $deposit->error;
+				$origin->errors = $deposit->errors;
+				return null;
+			}
+		}
+
+
+		if (! is_object($hookmanager)) {
+			require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
+			$hookmanager = new HookManager($origin->db);
+		}
+
+		$hookmanager->initHooks(array('invoicedao'));
+
+		$parameters = array('objFrom' => $origin);
+		$reshook = $hookmanager->executeHooks('createFrom', $parameters, $deposit, $action); // Note that $action and $object may have been
+		// modified by hook
+		if ($reshook < 0) {
+			$origin->db->rollback();
+			$origin->error = $hookmanager->error;
+			$origin->errors = $hookmanager->errors;
+			return null;
+		}
+
+		if (! empty($autoValidateDeposit)) {
+			$validateReturn = $deposit->validate($user, '', 0, $notrigger);
+
+			if ($validateReturn < 0) {
+				$origin->db->rollback();
+				$origin->error = $deposit->error;
+				$origin->errors = $deposit->errors;
+				return null;
+			}
+		}
+
+		unset($deposit->context['createdepositfromorigin']);
+
+		$origin->db->commit();
+
+		return $deposit;
+	}
+
 	/**
 	 *  Return clicable link of object (with eventually picto)
 	 *
@@ -2723,7 +3009,7 @@ class Facture extends CommonInvoice
 			return -1;
 		}
 		if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) {
-			$last_of_type = $this->willBeLastOfSameType();
+			$last_of_type = $this->willBeLastOfSameType(true);
 			if (!$last_of_type[0]) {
 				$this->error = $langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $this->ref, dol_print_date($this->date, 'day'), dol_print_date($last_of_type[1], 'day'));
 				return -1;
@@ -3554,9 +3840,10 @@ class Facture extends CommonInvoice
 	 * 	@param		double		$pu_ht_devise		Unit price in currency
 	 * 	@param		int			$notrigger			disable line update trigger
 	 *  @param		string		$ref_ext		    External reference of the line
+	 *  @param		integer		$rang		    	rank of line
 	 *  @return    	int             				< 0 if KO, > 0 if OK
 	 */
-	public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $info_bits = 0, $type = self::TYPE_STANDARD, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0, $label = '', $special_code = 0, $array_options = 0, $situation_percent = 100, $fk_unit = null, $pu_ht_devise = 0, $notrigger = 0, $ref_ext = '')
+	public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $info_bits = 0, $type = self::TYPE_STANDARD, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0, $label = '', $special_code = 0, $array_options = 0, $situation_percent = 100, $fk_unit = null, $pu_ht_devise = 0, $notrigger = 0, $ref_ext = '', $rang = 0)
 	{
 		global $conf, $user;
 		// Deprecation warning
@@ -3684,6 +3971,7 @@ class Facture extends CommonInvoice
 			$line->oldline = $staticline;
 			$this->line = $line;
 			$this->line->context = $this->context;
+			$this->line->rang = $rang;
 
 			// Reorder if fk_parent_line change
 			if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
@@ -5279,9 +5567,10 @@ class Facture extends CommonInvoice
 
 	/**
 	 * See if current invoice date is posterior to the last invoice date among validated invoices of same type.
+	 * @param 	boolean 	$allow_validated_drafts			return true if the invoice has been validated before returning to DRAFT state.
 	 * @return boolean
 	 */
-	public function willBeLastOfSameType()
+	public function willBeLastOfSameType($allow_validated_drafts = false)
 	{
 		// get date of last validated invoices of same type
 		$sql  = "SELECT datef";
@@ -5298,7 +5587,12 @@ class Facture extends CommonInvoice
 				$last_date = $this->db->jdate($obj->datef);
 				$invoice_date = $this->date;
 
-				return [$invoice_date >= $last_date, $last_date];
+				$is_last_of_same_type = $invoice_date >= $last_date;
+				if ($allow_validated_drafts) {
+					$is_last_of_same_type = $is_last_of_same_type || (!strpos($this->ref, 'PROV') && $this->status == self::STATUS_DRAFT);
+				}
+
+				return [$is_last_of_same_type, $last_date];
 			} else {
 				// element is first of type to be validated
 				return [true];

+ 16 - 5
htdocs/compta/facture/list.php

@@ -366,7 +366,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter',
 	$search_fac_rec_source_title = '';
 	$option = '';
 	$filter = '';
-	$toselect = '';
+	$toselect = array();
 	$search_array_options = array();
 	$search_categ_cus = 0;
 }
@@ -2415,16 +2415,27 @@ if ($resql) {
 		include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
 	}
 
+	// If no record found
+	if ($num == 0) {
+		$colspan = 1;
+		foreach ($arrayfields as $key => $val) {
+			if (!empty($val['checked'])) {
+				$colspan++;
+			}
+		}
+		print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
+	}
+
 	$db->free($resql);
 
 	$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
-	$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook
+	$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook
 	print $hookmanager->resPrint;
 
-	print "</table>\n";
-	print '</div>';
+	print '</table>'."\n";
+	print '</div>'."\n";
 
-	print "</form>\n";
+	print '</form>'."\n";
 
 	// Show the file area only when this page is not opend from the Extended POS
 	if ($contextpage != 'poslist') {

+ 10 - 10
htdocs/compta/facture/prelevement.php

@@ -310,9 +310,9 @@ if ($object->id > 0) {
 	$sql .= " AND pfd.ext_payment_id IS NULL";
 	$sql .= " ORDER BY pfd.date_demande DESC";
 
-	$result_sql = $db->query($sql);
-	if ($result_sql) {
-		$num = $db->num_rows($result_sql);
+	$resql = $db->query($sql);
+	if ($resql) {
+		$num = $db->num_rows($resql);
 		$numopen = $num;
 	} else {
 		dol_print_error($db);
@@ -695,9 +695,9 @@ if ($object->id > 0) {
 	$sql .= " AND pfd.traite = 0";
 	$sql .= " AND pfd.ext_payment_id IS NULL";
 
-	$result_sql = $db->query($sql);
-	if ($result_sql) {
-		$obj = $db->fetch_object($result_sql);
+	$resql = $db->query($sql);
+	if ($resql) {
+		$obj = $db->fetch_object($resql);
 		if ($obj) {
 			$pending = $obj->amount;
 		}
@@ -797,17 +797,17 @@ if ($object->id > 0) {
 	$sql .= " AND pfd.ext_payment_id IS NULL";
 	$sql .= " ORDER BY pfd.date_demande DESC";
 
-	$result_sql = $db->query($sql);
+	$resql = $db->query($sql);
 
 	$num = 0;
-	if ($result_sql) {
+	if ($resql) {
 		$i = 0;
 
 		$tmpuser = new User($db);
 
 		$num = $db->num_rows($result);
 		while ($i < $num) {
-			$obj = $db->fetch_object($result_sql);
+			$obj = $db->fetch_object($resql);
 
 			$tmpuser->id = $obj->user_id;
 			$tmpuser->login = $obj->login;
@@ -840,7 +840,7 @@ if ($object->id > 0) {
 			$i++;
 		}
 
-		$db->free($result_sql);
+		$db->free($resql);
 	} else {
 		dol_print_error($db);
 	}

+ 1 - 1
htdocs/compta/facture/stats/index.php

@@ -102,7 +102,7 @@ if ($mode == 'customer') {
 		$stats->where .= ' AND f.fk_statut IN ('.$db->sanitize($object_status).')';
 	}
 	if (is_array($custcats) && !empty($custcats)) {
-		$stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cat OmdN (f.fk_soc = cat.fk_soc)';
+		$stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cat ON (f.fk_soc = cat.fk_soc)';
 		$stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')';
 	}
 }

+ 1 - 1
htdocs/compta/paiement/list.php

@@ -148,7 +148,7 @@ if (empty($reshook)) {
 		$search_company = '';
 		$search_status = '';
 		$option = '';
-		$toselect = '';
+		$toselect = array();
 		$search_array_options = array();
 	}
 }

+ 1 - 1
htdocs/compta/paiement_charge.php

@@ -198,7 +198,7 @@ if ($action == 'create') {
 	if ($resql) {
 		$obj = $db->fetch_object($resql);
 		$sumpaid = $obj->total;
-		$db->free();
+		$db->free($resql);
 	}
 	/*print '<tr><td>'.$langs->trans("AlreadyPaid").'</td><td>'.price($sumpaid,0,$outputlangs,1,-1,-1,$conf->currency).'</td></tr>';
 	print '<tr><td class="tdtop">'.$langs->trans("RemainderToPay").'</td><td>'.price($total-$sumpaid,0,$outputlangs,1,-1,-1,$conf->currency).'</td></tr>';*/

+ 1 - 1
htdocs/compta/paiement_vat.php

@@ -194,7 +194,7 @@ if ($action == 'create') {
 	if ($resql) {
 		$obj = $db->fetch_object($resql);
 		$sumpaid = $obj->total;
-		$db->free();
+		$db->free($resql);
 	}
 	/*print '<tr><td>'.$langs->trans("AlreadyPaid").'</td><td>'.price($sumpaid,0,$outputlangs,1,-1,-1,$conf->currency).'</td></tr>';
 	print '<tr><td class="tdtop">'.$langs->trans("RemainderToPay").'</td><td>'.price($total-$sumpaid,0,$outputlangs,1,-1,-1,$conf->currency).'</td></tr>';*/

+ 2 - 2
htdocs/compta/prelevement/class/bonprelevement.class.php

@@ -1066,8 +1066,8 @@ class BonPrelevement extends CommonObject
 					// This also set the property $this->total with amount that is included into file
 					$result = $this->generate($format, $executiondate, $type);
 					if ($result < 0) {
-						/*var_dump($this->error);
-						var_dump($this->invoice_in_error); */
+						//var_dump($this->error);
+						//var_dump($this->invoice_in_error);
 						$error++;
 					}
 				}

+ 2 - 1
htdocs/compta/prelevement/stats.php

@@ -143,7 +143,8 @@ if ($resql) {
 	print price($total);
 	print '</td><td class="right">&nbsp;</td>';
 	print "</tr></table>";
-	$db->free();
+
+	$db->free($resql);
 } else {
 	dol_print_error($db);
 }

+ 23 - 4
htdocs/compta/sociales/list.php

@@ -713,16 +713,35 @@ while ($i < min($num, $limit)) {
 		$totalarray['nbfield']++;
 	}
 
-	print '</tr>';
+	print '</tr>'."\n";
+
 	$i++;
 }
 
 // Show total line
 include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
 
-print '</table>';
-print '</div>';
-print '</form>';
+// If no record found
+if ($num == 0) {
+	$colspan = 1;
+	foreach ($arrayfields as $key => $val) {
+		if (!empty($val['checked'])) {
+			$colspan++;
+		}
+	}
+	print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
+}
+
+$db->free($resql);
+
+$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
+$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook
+print $hookmanager->resPrint;
+
+print '</table>'."\n";
+print '</div>'."\n";
+
+print '</form>'."\n";
 
 // End of page
 llxFooter();

+ 1 - 1
htdocs/compta/sociales/payments.php

@@ -80,7 +80,7 @@ $result = restrictedArea($user, 'tax', '', 'chargesociales', 'charges');
 // Purge search criteria
 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
 	$search_sc_type = '';
-	//$toselect = '';
+	//$toselect = array();
 	//$search_array_options = array();
 }
 

+ 26 - 10
htdocs/compta/tva/list.php

@@ -190,8 +190,8 @@ $sql .= $db->order($sortfield, $sortorder);
 
 $nbtotalofrecords = '';
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
-	$result = $db->query($sql);
-	$nbtotalofrecords = $db->num_rows($result);
+	$resql = $db->query($sql);
+	$nbtotalofrecords = $db->num_rows($resql);
 
 	// if total resultset is smaller then paging size (filtering), goto and load page 0
 	if (($page * $limit) > $nbtotalofrecords) {
@@ -202,15 +202,15 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
 
 $sql .= $db->plimit($limit + 1, $offset);
 
-$result = $db->query($sql);
-if (!$result) {
+$resql = $db->query($sql);
+if (!$resql) {
 	dol_print_error($db);
 	llxFooter();
 	$db->close();
 	exit;
 }
 
-$num = $db->num_rows($result);
+$num = $db->num_rows($resql);
 
 $param = '';
 if (!empty($contextpage) && $contextpage != $_SERVER['PHP_SELF']) {
@@ -429,7 +429,7 @@ print '</tr>';
 $i = 0;
 $totalarray = array();
 while ($i < min($num, $limit)) {
-	$obj = $db->fetch_object($result);
+	$obj = $db->fetch_object($resql);
 
 	$tva_static->id = $obj->rowid;
 	$tva_static->ref = $obj->rowid;
@@ -549,11 +549,27 @@ $totalarray['nbfield']++;
 // Show total line
 include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
 
-print '</table>';
-print '</div>';
-print '</form>';
+// If no record found
+if ($num == 0) {
+	$colspan = 1;
+	foreach ($arrayfields as $key => $val) {
+		if (!empty($val['checked'])) {
+			$colspan++;
+		}
+	}
+	print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
+}
+
+$db->free($resql);
+
+$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
+$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook
+print $hookmanager->resPrint;
+
+print '</table>'."\n";
+print '</div>'."\n";
 
-$db->free($result);
+print '</form>'."\n";
 
 // End of page
 llxFooter();

+ 1 - 1
htdocs/contact/card.php

@@ -856,7 +856,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 						if (!empty($value['icon'])) {
 							print '<span class="fa '.$value['icon'].'"></span>';
 						}
-						print '<input type="text" name="'.$key.'" id="'.$key.'" class="minwidth100" maxlength="80" value="'.dol_escape_htmltag(GETPOSTISSET($key) ?GETPOST($key, 'alphanohtml') : $object->socialnetworks[$key]).'">';
+						print '<input type="text" name="'.$key.'" id="'.$key.'" class="minwidth100" maxlength="80" value="'.dol_escape_htmltag(GETPOSTISSET($key) ?GETPOST($key, 'alphanohtml') : (!empty($object->socialnetworks[$key]) ? $object->socialnetworks[$key] : "")).'">';
 						print '</td>';
 						print '</tr>';
 					} elseif (!empty($object->socialnetworks[$key])) {

+ 1 - 1
htdocs/contact/consumption.php

@@ -355,7 +355,7 @@ if (empty($elementTypeArray) && !$object->thirdparty->client && !$object->thirdp
 
 // Define type of elements
 $typeElementString = $form->selectarray("type_element", $elementTypeArray, GETPOST('type_element'), $showempty, 0, 0, '', 0, 0, $disabled, '', 'maxwidth150onsmartphone');
-$button = '<input type="submit" class="button" name="button_third" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
+$button = '<input type="submit" class="button small" name="button_third" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
 
 $param = '';
 $param .= "&sref=".urlencode($sref);

+ 18 - 6
htdocs/contact/list.php

@@ -1309,19 +1309,31 @@ while ($i < min($num, $limit)) {
 	$i++;
 }
 
+// Show total line
+include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
+
+// If no record found
+if ($num == 0) {
+	$colspan = 1;
+	foreach ($arrayfields as $key => $val) {
+		if (!empty($val['checked'])) {
+			$colspan++;
+		}
+	}
+	print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
+}
+
 $db->free($resql);
 
 $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
 print $hookmanager->resPrint;
 
-print "</table>";
-print "</div>";
-
-//if ($num > $limit || $page) print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies.png', 0, '', '', $limit, 1);
-
-print '</form>';
+print '</table>'."\n";
+print '</div>'."\n";
 
+print '</form>'."\n";
 
+// End of page
 llxFooter();
 $db->close();

+ 1 - 11
htdocs/contrat/class/contrat.class.php

@@ -772,16 +772,6 @@ class Contrat extends CommonObject
 
 		$now = dol_now();
 
-		/*
-		if (!is_object($extrafields)) {
-			require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
-			$extrafields = new ExtraFields($this->db);
-		}
-
-		$line = new ContratLigne($this->db);
-		$extrafields->fetch_name_optionals_label(ContratLigne::$table_element, true);
-		*/
-
 		$this->lines = array();
 		$pos = 0;
 
@@ -875,7 +865,7 @@ class Contrat extends CommonObject
 				$line->date_fin_prevue   = $this->db->jdate($objp->date_fin_validite);
 				$line->date_fin_reel     = $this->db->jdate($objp->date_cloture);
 
-				// Retrieve all extrafields for contract
+				// Retrieve all extrafields for contract line
 				// fetch optionals attributes and labels
 				$line->fetch_optionals();
 

+ 15 - 8
htdocs/contrat/index.php

@@ -346,22 +346,28 @@ if ($result) {
 
 	while ($i < $num) {
 		$obj = $db->fetch_object($result);
+		$datem = $db->jdate($obj->tms);
 
-		print '<tr class="oddeven">';
-		print '<td class="nowraponall">';
 		$staticcontrat->ref = ($obj->ref ? $obj->ref : $obj->cid);
 		$staticcontrat->id = $obj->cid;
+
+		$staticcompany->id = $obj->socid;
+		$staticcompany->name = $obj->name;
+
+		print '<tr class="oddeven">';
+		print '<td class="nowraponall">';
 		print $staticcontrat->getNomUrl(1, 16);
 		if ($obj->nb_late) {
 			print img_warning($langs->trans("Late"));
 		}
 		print '</td>';
+
 		print '<td class="tdoverflowmax150">';
-		$staticcompany->id = $obj->socid;
-		$staticcompany->name = $obj->name;
 		print $staticcompany->getNomUrl(1, '', 20);
 		print '</td>';
-		print '<td class="center nowraponall">'.dol_print_date($db->jdate($obj->tms), 'dayhour').'</td>';
+		print '<td class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'">';
+		print dol_print_date($datem, 'dayhour');
+		print '</td>';
 		//print '<td class="left">'.$staticcontrat->LibStatut($obj->statut,2).'</td>';
 		print '<td class="right nowraponall" width="32">'.($obj->nb_initial > 0 ? '<span class="paddingright">'.$obj->nb_initial.'</span>'.$staticcontratligne->LibStatut(0, 3, -1, 'class="paddingleft"') : '').'</td>';
 		print '<td class="right nowraponall" width="32">'.($obj->nb_running > 0 ? '<span class="paddingright">'.$obj->nb_running.'</span>'.$staticcontratligne->LibStatut(4, 3, 0, 'class="marginleft"') : '').'</td>';
@@ -451,7 +457,7 @@ if ($resql) {
 		print "</tr>\n";
 		$i++;
 	}
-	$db->free();
+	$db->free($resql);
 
 	print "</table></div>";
 } else {
@@ -532,7 +538,8 @@ if ($resql) {
 		print "</tr>\n";
 		$i++;
 	}
-	$db->free();
+
+	$db->free($resql);
 
 	print "</table></div>";
 } else {
@@ -614,7 +621,7 @@ if ($resql) {
 		print "</tr>\n";
 		$i++;
 	}
-	$db->free();
+	$db->free($resql);
 
 	print "</table></div>";
 } else {

+ 7 - 1
htdocs/contrat/list.php

@@ -203,7 +203,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
 	$search_date_end = '';
 	$sall = "";
 	$search_status = "";
-	$toselect = '';
+	$toselect = array();
 	$search_type_thirdparty = '';
 	$search_array_options = array();
 }
@@ -312,6 +312,9 @@ if ($search_zip) {
 if ($search_town) {
 	$sql .= natural_search(array('s.town'), $search_town);
 }
+if ($search_country && $search_country != '-1') {
+	$sql .= " AND s.fk_pays IN (".$db->sanitize($search_country).')';
+}
 if ($search_sale > 0) {
 	$sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $search_sale);
 }
@@ -489,6 +492,9 @@ if ($search_user > 0) {
 if ($search_type_thirdparty > 0) {
 	$param .= '&search_type_thirdparty='.urlencode($search_type_thirdparty);
 }
+if ($search_country != '') {
+	$param .= "&search_country=".urlencode($search_country);
+}
 if ($search_product_category > 0) {
 	$param .= '&search_product_category='.urlencode($search_product_category);
 }

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