فهرست منبع

Merge branch 'develop' into oop-refactor-bankaccount-tostring

Marcos García de La Fuente 9 سال پیش
والد
کامیت
a41a80b8fe
100فایلهای تغییر یافته به همراه3592 افزوده شده و 3055 حذف شده
  1. 3 3
      .travis.yml
  2. 1 1
      COPYRIGHT
  3. 22 0
      ChangeLog
  4. 17 1124
      composer.lock
  5. 5 6
      dev/dolibarr_changes.txt
  6. 3 3
      dev/fixdosfiles.sh
  7. 7 6
      dev/skeletons/modMyModule.class.php
  8. 54 16
      dev/skeletons/skeleton_list.php
  9. 6 6
      htdocs/accountancy/admin/account.php
  10. 118 61
      htdocs/accountancy/admin/card.php
  11. 23 19
      htdocs/accountancy/bookkeeping/balance.php
  12. 1 2
      htdocs/accountancy/class/accountancyexport.class.php
  13. 27 15
      htdocs/accountancy/class/accountingaccount.class.php
  14. 43 1
      htdocs/accountancy/class/bookkeeping.class.php
  15. 34 45
      htdocs/accountancy/journal/bankjournal.php
  16. 21 7
      htdocs/accountancy/journal/purchasesjournal.php
  17. 38 21
      htdocs/accountancy/journal/sellsjournal.php
  18. 2 7
      htdocs/adherents/card.php
  19. 15 11
      htdocs/adherents/class/adherent_type.class.php
  20. 1 1
      htdocs/adherents/document.php
  21. 4 1
      htdocs/adherents/type.php
  22. 1 66
      htdocs/admin/bank.php
  23. 287 0
      htdocs/admin/chequereceipts.php
  24. 12 8
      htdocs/admin/company.php
  25. 4 3
      htdocs/admin/confexped.php
  26. 65 15
      htdocs/admin/dict.php
  27. 5 5
      htdocs/admin/facture.php
  28. 236 32
      htdocs/admin/modules.php
  29. 2 3
      htdocs/admin/security_file.php
  30. 22 214
      htdocs/admin/tools/export.php
  31. 1 1
      htdocs/admin/tools/index.php
  32. 35 21
      htdocs/admin/tools/listevents.php
  33. 2 2
      htdocs/admin/tools/update.php
  34. 7 1
      htdocs/admin/translation.php
  35. 1 1
      htdocs/cashdesk/affContenu.php
  36. 1 1
      htdocs/cashdesk/affIndex.php
  37. 25 25
      htdocs/cashdesk/class/Facturation.class.php
  38. 52 27
      htdocs/cashdesk/facturation_verif.php
  39. 1 1
      htdocs/cashdesk/index_verif.php
  40. 8 7
      htdocs/cashdesk/tpl/facturation1.tpl.php
  41. 1 1
      htdocs/cashdesk/tpl/menu.tpl.php
  42. 1 1
      htdocs/cashdesk/tpl/validation1.tpl.php
  43. 19 34
      htdocs/cashdesk/validation_verif.php
  44. 3 3
      htdocs/categories/class/categorie.class.php
  45. 1 1
      htdocs/categories/photos.php
  46. 23 18
      htdocs/comm/action/card.php
  47. 1 1
      htdocs/comm/action/document.php
  48. 31 2
      htdocs/comm/card.php
  49. 5 5
      htdocs/comm/propal.php
  50. 5 4
      htdocs/comm/propal/class/propal.class.php
  51. 1 1
      htdocs/comm/propal/document.php
  52. 578 202
      htdocs/comm/propal/list.php
  53. 1 1
      htdocs/comm/propal/stats/index.php
  54. 3 24
      htdocs/comm/propal/tpl/linkedobjectblock.tpl.php
  55. 37 23
      htdocs/commande/card.php
  56. 1 1
      htdocs/commande/class/api_commande.class.php
  57. 18 86
      htdocs/commande/class/commande.class.php
  58. 1 1
      htdocs/commande/contact.php
  59. 1 1
      htdocs/commande/document.php
  60. 638 250
      htdocs/commande/list.php
  61. 1 1
      htdocs/commande/orderstoinvoice.php
  62. 1 25
      htdocs/commande/tpl/linkedobjectblock.tpl.php
  63. 2 2
      htdocs/compta/bank/account.php
  64. 30 49
      htdocs/compta/bank/card.php
  65. 7 15
      htdocs/compta/bank/document.php
  66. 1 1
      htdocs/compta/deplacement/document.php
  67. 15 11
      htdocs/compta/facture.php
  68. 1 1
      htdocs/compta/facture/class/facture-rec.class.php
  69. 0 86
      htdocs/compta/facture/class/facture.class.php
  70. 1 1
      htdocs/compta/facture/document.php
  71. 1 1
      htdocs/compta/facture/fiche-rec.php
  72. 575 191
      htdocs/compta/facture/list.php
  73. 2 24
      htdocs/compta/facture/tpl/linkedobjectblock.tpl.php
  74. 5 18
      htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php
  75. 43 25
      htdocs/compta/localtax/card.php
  76. 6 2
      htdocs/compta/localtax/clients.php
  77. 21 15
      htdocs/compta/localtax/index.php
  78. 4 5
      htdocs/compta/localtax/quadri_detail.php
  79. 3 3
      htdocs/compta/paiement.php
  80. 8 8
      htdocs/compta/paiement/cheque/card.php
  81. 116 48
      htdocs/compta/paiement/cheque/class/remisecheque.class.php
  82. 2 1
      htdocs/compta/paiement/cheque/index.php
  83. 4 4
      htdocs/compta/paiement/cheque/list.php
  84. 1 1
      htdocs/compta/prelevement/card.php
  85. 7 5
      htdocs/compta/prelevement/class/bonprelevement.class.php
  86. 1 1
      htdocs/compta/resultat/clientfourn.php
  87. 1 1
      htdocs/compta/resultat/index.php
  88. 1 1
      htdocs/compta/salaries/document.php
  89. 1 1
      htdocs/compta/sociales/document.php
  90. 53 39
      htdocs/compta/tva/card.php
  91. 4 2
      htdocs/compta/tva/clients.php
  92. 4 2
      htdocs/compta/tva/index.php
  93. 3 1
      htdocs/compta/tva/quadri_detail.php
  94. 3 1
      htdocs/compta/tva/quarter_report.php
  95. 8 5
      htdocs/compta/tva/reglement.php
  96. 3 7
      htdocs/contact/card.php
  97. 1 0
      htdocs/contact/class/contact.class.php
  98. 1 1
      htdocs/contact/document.php
  99. 1 1
      htdocs/contact/list.php
  100. 69 0
      htdocs/contact/perso.php

+ 3 - 3
.travis.yml

@@ -266,7 +266,7 @@ script:
 - |
   echo "Upgrading Dolibarr"
   # Ensure we catch errors
-  set -e
+  set +e
   cd htdocs/install
   php upgrade.php 3.5.0 3.6.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade350360.log
   php upgrade2.php 3.5.0 3.6.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade350360-2.log
@@ -289,9 +289,9 @@ script:
 
 - |
   echo "Unit testing"
-  # Ensure we catch errors. Set this to +e if you want to go to this end to see log file.
+  # Ensure we catch errors. Set this to +e if you want to go to the end to see log file.
   set -e
-  phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php
+  #phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php
   set +e
 
 - |

+ 1 - 1
COPYRIGHT

@@ -14,7 +14,7 @@ Component              Version       License                     GPL Compatible
 PHP libraries:
 AdoDb-Date             0.36          Modified BSD License        Yes             Date convertion (not into rpm package)
 ChromePHP              4.1.0         Apache Software License 2.0 Yes             Return server log to chrome browser console
-CKEditor               4.5.6         LGPL-2.1+                   Yes             Editor WYSIWYG
+CKEditor               4.5.8         LGPL-2.1+                   Yes             Editor WYSIWYG
 EvalMath               1.0           BSD                         Yes             Safe math expressions evaluation
 Escpos-php                           MIT License                 Yes             Thermal receipt printer library, for use with ESC/POS compatible printers
 FPDI                   1.5.2         Apache Software License 2.0 Yes             PDF templates management

+ 22 - 0
ChangeLog

@@ -24,7 +24,12 @@ Dolibarr 4.0 should be compatible with PHP 7 but more feedbacks are still expect
 
 Following changes may create regression for some external modules, but were necessary to make
 Dolibarr better:
+- Function log() of class CommandeFournisseur has been removed. Using it is no more required.
 - Method select_type_comptes_financiers() has been renamed into selectTypeOfBankAccount() 
+- File '/core/tpl/document_actions_pre_headers.tpl.php' were renamed into '/core/actions_linkedfiles.inc.php'.
+So if you included it into your module, change your code like this to be compatible with all version:
+  $res=@include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
+  if (! $res) include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
 
 
 
@@ -712,6 +717,23 @@ Dolibarr better:
 - Function get_exdir require now 6 parameters. This is to prepare a future feature.
 
 
+***** ChangeLog for 3.7.4 compared to 3.7.3 *****
+FIX: #3694
+FIX: #4239
+FIX: #4291 Correctly filter external calendar GETPOSTs
+FIX: #4341
+FIX: #4414 Supplier invoices use FAC_FORCE_DATE_VALIDATION client invoices property
+FIX: #4440 Wrong price is filled by Product::fetch into multiprices arrays
+FIX: add missing global def for ttc column
+FIX: Contrat card don't consider user permissions to show active/unactive service button
+FIX: CVE CVE-2015-8685
+FIX: Email templates not compatible with Multicompany
+Fix: for avoid division by 0
+FIX: ISSUE #4506 : make working the PROPAL_CLONE_ON_CREATE_PAGE hidden constant
+FIX: $outputlangs is not defined (dolibarr 3.7, 3.8, 3.9)
+FIX: sql injection even when code is on several lines
+FIX: The third dashboard don't consider user permissions
+
 ***** ChangeLog for 3.7.3 compared to 3.7.2 *****
 FIX: #3734 Do not show empty links of deleted source objects in stock movement list
 FIX: #3890 Expected transactions bank account page, shows negative numbers

+ 17 - 1124
composer.lock

@@ -4,8 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "4a06567f53c5f081f9c961a0b3093da3",
-    "content-hash": "265061f1a1056df2e8c5184841993d0f",
+    "hash": "c2b53c577364dbe3a56137043081b511",
+    "content-hash": "8f7a86cfbc13f45e13b73c49531818cb",
     "packages": [
         {
             "name": "ccampbell/chromephp",
@@ -56,12 +56,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/ckeditor/ckeditor-releases.git",
-                "reference": "c1cefe7341e6910a1e6cb2f3f024bbdaf6cd1d4d"
+                "reference": "e3eb254641c4c349ffc19e49bd4a1a6831b5b6d0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/c1cefe7341e6910a1e6cb2f3f024bbdaf6cd1d4d",
-                "reference": "c1cefe7341e6910a1e6cb2f3f024bbdaf6cd1d4d",
+                "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/e3eb254641c4c349ffc19e49bd4a1a6831b5b6d0",
+                "reference": "e3eb254641c4c349ffc19e49bd4a1a6831b5b6d0",
                 "shasum": ""
             },
             "type": "library",
@@ -73,7 +73,7 @@
             ],
             "authors": [
                 {
-                    "name": "CKSource - Frederico Knabben",
+                    "name": "CKSource",
                     "homepage": "http://cksource.com"
                 }
             ],
@@ -89,7 +89,7 @@
                 "text",
                 "wysiwyg"
             ],
-            "time": "2015-12-09 15:49:34"
+            "time": "2016-03-31 16:19:25"
         },
         {
             "name": "mike42/escpos-php",
@@ -97,12 +97,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/mike42/escpos-php.git",
-                "reference": "63648d03d47b81e8f6c1020ac92f051a3f3b5793"
+                "reference": "96f05cbf460f5b67c2184ee4e91aedfbcedeb788"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/mike42/escpos-php/zipball/63648d03d47b81e8f6c1020ac92f051a3f3b5793",
-                "reference": "63648d03d47b81e8f6c1020ac92f051a3f3b5793",
+                "url": "https://api.github.com/repos/mike42/escpos-php/zipball/96f05cbf460f5b67c2184ee4e91aedfbcedeb788",
+                "reference": "96f05cbf460f5b67c2184ee4e91aedfbcedeb788",
                 "shasum": ""
             },
             "require": {
@@ -112,6 +112,11 @@
                 "phpunit/phpunit": "4.5.*"
             },
             "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Mike42\\": "src/Mike42"
+                }
+            },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
@@ -147,7 +152,7 @@
                 "print",
                 "receipt"
             ],
-            "time": "2015-12-04 10:23:55"
+            "time": "2016-03-27 23:08:27"
         },
         {
             "name": "mobiledetect/mobiledetectlib",
@@ -398,1119 +403,7 @@
             "time": "2015-09-12 10:08:34"
         }
     ],
-    "packages-dev": [
-        {
-            "name": "doctrine/instantiator",
-            "version": "1.0.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/instantiator.git",
-                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
-                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3,<8.0-DEV"
-            },
-            "require-dev": {
-                "athletic/athletic": "~0.1.8",
-                "ext-pdo": "*",
-                "ext-phar": "*",
-                "phpunit/phpunit": "~4.0",
-                "squizlabs/php_codesniffer": "~2.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Marco Pivetta",
-                    "email": "ocramius@gmail.com",
-                    "homepage": "http://ocramius.github.com/"
-                }
-            ],
-            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
-            "homepage": "https://github.com/doctrine/instantiator",
-            "keywords": [
-                "constructor",
-                "instantiate"
-            ],
-            "time": "2015-06-14 21:17:01"
-        },
-        {
-            "name": "myclabs/deep-copy",
-            "version": "1.5.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/myclabs/DeepCopy.git",
-                "reference": "e3abefcd7f106677fd352cd7c187d6c969aa9ddc"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e3abefcd7f106677fd352cd7c187d6c969aa9ddc",
-                "reference": "e3abefcd7f106677fd352cd7c187d6c969aa9ddc",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.4.0"
-            },
-            "require-dev": {
-                "doctrine/collections": "1.*",
-                "phpunit/phpunit": "~4.1"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "DeepCopy\\": "src/DeepCopy/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "description": "Create deep copies (clones) of your objects",
-            "homepage": "https://github.com/myclabs/DeepCopy",
-            "keywords": [
-                "clone",
-                "copy",
-                "duplicate",
-                "object",
-                "object graph"
-            ],
-            "time": "2015-11-07 22:20:37"
-        },
-        {
-            "name": "phpdocumentor/reflection-docblock",
-            "version": "2.0.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
-                "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
-                "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.0"
-            },
-            "suggest": {
-                "dflydev/markdown": "~1.0",
-                "erusev/parsedown": "~1.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "phpDocumentor": [
-                        "src/"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Mike van Riel",
-                    "email": "mike.vanriel@naenius.com"
-                }
-            ],
-            "time": "2015-02-03 12:10:50"
-        },
-        {
-            "name": "phpspec/prophecy",
-            "version": "v1.5.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpspec/prophecy.git",
-                "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7",
-                "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/instantiator": "^1.0.2",
-                "phpdocumentor/reflection-docblock": "~2.0",
-                "sebastian/comparator": "~1.1"
-            },
-            "require-dev": {
-                "phpspec/phpspec": "~2.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Prophecy\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Konstantin Kudryashov",
-                    "email": "ever.zet@gmail.com",
-                    "homepage": "http://everzet.com"
-                },
-                {
-                    "name": "Marcello Duarte",
-                    "email": "marcello.duarte@gmail.com"
-                }
-            ],
-            "description": "Highly opinionated mocking framework for PHP 5.3+",
-            "homepage": "https://github.com/phpspec/prophecy",
-            "keywords": [
-                "Double",
-                "Dummy",
-                "fake",
-                "mock",
-                "spy",
-                "stub"
-            ],
-            "time": "2015-08-13 10:07:40"
-        },
-        {
-            "name": "phpunit/php-code-coverage",
-            "version": "3.0.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "f7bb5cddf4ffe113eeb737b05241adb947b43f9d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7bb5cddf4ffe113eeb737b05241adb947b43f9d",
-                "reference": "f7bb5cddf4ffe113eeb737b05241adb947b43f9d",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.6",
-                "phpunit/php-file-iterator": "~1.3",
-                "phpunit/php-text-template": "~1.2",
-                "phpunit/php-token-stream": "~1.3",
-                "sebastian/environment": "^1.3.2",
-                "sebastian/version": "~1.0"
-            },
-            "require-dev": {
-                "ext-xdebug": ">=2.1.4",
-                "phpunit/phpunit": "~5"
-            },
-            "suggest": {
-                "ext-dom": "*",
-                "ext-xdebug": ">=2.2.1",
-                "ext-xmlwriter": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
-            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
-            "keywords": [
-                "coverage",
-                "testing",
-                "xunit"
-            ],
-            "time": "2015-11-12 21:08:20"
-        },
-        {
-            "name": "phpunit/php-file-iterator",
-            "version": "1.4.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
-                "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
-                "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
-            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
-            "keywords": [
-                "filesystem",
-                "iterator"
-            ],
-            "time": "2015-06-21 13:08:43"
-        },
-        {
-            "name": "phpunit/php-text-template",
-            "version": "1.2.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-text-template.git",
-                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Simple template engine.",
-            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
-            "keywords": [
-                "template"
-            ],
-            "time": "2015-06-21 13:50:34"
-        },
-        {
-            "name": "phpunit/php-timer",
-            "version": "1.0.7",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-timer.git",
-                "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
-                "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Utility class for timing",
-            "homepage": "https://github.com/sebastianbergmann/php-timer/",
-            "keywords": [
-                "timer"
-            ],
-            "time": "2015-06-21 08:01:12"
-        },
-        {
-            "name": "phpunit/php-token-stream",
-            "version": "1.4.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
-                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
-                "shasum": ""
-            },
-            "require": {
-                "ext-tokenizer": "*",
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Wrapper around PHP's tokenizer extension.",
-            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
-            "keywords": [
-                "tokenizer"
-            ],
-            "time": "2015-09-15 10:49:45"
-        },
-        {
-            "name": "phpunit/phpunit",
-            "version": "5.1.3",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "c047ff05d2279404af9a7e89e2a7151c32c88022"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c047ff05d2279404af9a7e89e2a7151c32c88022",
-                "reference": "c047ff05d2279404af9a7e89e2a7151c32c88022",
-                "shasum": ""
-            },
-            "require": {
-                "ext-dom": "*",
-                "ext-json": "*",
-                "ext-pcre": "*",
-                "ext-reflection": "*",
-                "ext-spl": "*",
-                "myclabs/deep-copy": "~1.3",
-                "php": ">=5.6",
-                "phpspec/prophecy": "^1.3.1",
-                "phpunit/php-code-coverage": "~3.0",
-                "phpunit/php-file-iterator": "~1.4",
-                "phpunit/php-text-template": "~1.2",
-                "phpunit/php-timer": ">=1.0.6",
-                "phpunit/phpunit-mock-objects": ">=3.0.5",
-                "sebastian/comparator": "~1.1",
-                "sebastian/diff": "~1.2",
-                "sebastian/environment": "~1.3",
-                "sebastian/exporter": "~1.2",
-                "sebastian/global-state": "~1.0",
-                "sebastian/resource-operations": "~1.0",
-                "sebastian/version": "~1.0",
-                "symfony/yaml": "~2.1|~3.0"
-            },
-            "suggest": {
-                "phpunit/php-invoker": "~1.1"
-            },
-            "bin": [
-                "phpunit"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "5.1.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "The PHP Unit Testing framework.",
-            "homepage": "https://phpunit.de/",
-            "keywords": [
-                "phpunit",
-                "testing",
-                "xunit"
-            ],
-            "time": "2015-12-10 07:54:54"
-        },
-        {
-            "name": "phpunit/phpunit-mock-objects",
-            "version": "3.0.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
-                "reference": "49bc700750196c04dd6bc2c4c99cb632b893836b"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/49bc700750196c04dd6bc2c4c99cb632b893836b",
-                "reference": "49bc700750196c04dd6bc2c4c99cb632b893836b",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/instantiator": "^1.0.2",
-                "php": ">=5.6",
-                "phpunit/php-text-template": "~1.2",
-                "sebastian/exporter": "~1.2"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~5"
-            },
-            "suggest": {
-                "ext-soap": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Mock Object library for PHPUnit",
-            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
-            "keywords": [
-                "mock",
-                "xunit"
-            ],
-            "time": "2015-12-08 08:47:06"
-        },
-        {
-            "name": "sebastian/comparator",
-            "version": "1.2.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/comparator.git",
-                "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
-                "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "sebastian/diff": "~1.2",
-                "sebastian/exporter": "~1.2"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.2.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Volker Dusch",
-                    "email": "github@wallbash.com"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@2bepublished.at"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides the functionality to compare PHP values for equality",
-            "homepage": "http://www.github.com/sebastianbergmann/comparator",
-            "keywords": [
-                "comparator",
-                "compare",
-                "equality"
-            ],
-            "time": "2015-07-26 15:48:44"
-        },
-        {
-            "name": "sebastian/diff",
-            "version": "1.4.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/diff.git",
-                "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
-                "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.8"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Kore Nordmann",
-                    "email": "mail@kore-nordmann.de"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Diff implementation",
-            "homepage": "https://github.com/sebastianbergmann/diff",
-            "keywords": [
-                "diff"
-            ],
-            "time": "2015-12-08 07:14:41"
-        },
-        {
-            "name": "sebastian/environment",
-            "version": "1.3.3",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/environment.git",
-                "reference": "6e7133793a8e5a5714a551a8324337374be209df"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df",
-                "reference": "6e7133793a8e5a5714a551a8324337374be209df",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.3.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides functionality to handle HHVM/PHP environments",
-            "homepage": "http://www.github.com/sebastianbergmann/environment",
-            "keywords": [
-                "Xdebug",
-                "environment",
-                "hhvm"
-            ],
-            "time": "2015-12-02 08:37:27"
-        },
-        {
-            "name": "sebastian/exporter",
-            "version": "1.2.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/exporter.git",
-                "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
-                "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "sebastian/recursion-context": "~1.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.2.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Volker Dusch",
-                    "email": "github@wallbash.com"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@2bepublished.at"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                },
-                {
-                    "name": "Adam Harvey",
-                    "email": "aharvey@php.net"
-                }
-            ],
-            "description": "Provides the functionality to export PHP variables for visualization",
-            "homepage": "http://www.github.com/sebastianbergmann/exporter",
-            "keywords": [
-                "export",
-                "exporter"
-            ],
-            "time": "2015-06-21 07:55:53"
-        },
-        {
-            "name": "sebastian/global-state",
-            "version": "1.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/global-state.git",
-                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
-                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.2"
-            },
-            "suggest": {
-                "ext-uopz": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Snapshotting of global state",
-            "homepage": "http://www.github.com/sebastianbergmann/global-state",
-            "keywords": [
-                "global state"
-            ],
-            "time": "2015-10-12 03:26:01"
-        },
-        {
-            "name": "sebastian/recursion-context",
-            "version": "1.0.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/recursion-context.git",
-                "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
-                "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                },
-                {
-                    "name": "Adam Harvey",
-                    "email": "aharvey@php.net"
-                }
-            ],
-            "description": "Provides functionality to recursively process PHP variables",
-            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
-            "time": "2015-11-11 19:50:13"
-        },
-        {
-            "name": "sebastian/resource-operations",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/resource-operations.git",
-                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
-                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.6.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides a list of PHP built-in functions that operate on resources",
-            "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
-            "time": "2015-07-28 20:34:47"
-        },
-        {
-            "name": "sebastian/version",
-            "version": "1.0.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/version.git",
-                "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
-                "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
-                "shasum": ""
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Library that helps with managing the version number of Git-hosted PHP projects",
-            "homepage": "https://github.com/sebastianbergmann/version",
-            "time": "2015-06-21 13:59:46"
-        },
-        {
-            "name": "squizlabs/php_codesniffer",
-            "version": "2.4.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
-                "reference": "32a879f4f35019d78d568db2885d7779ca084a33"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/32a879f4f35019d78d568db2885d7779ca084a33",
-                "reference": "32a879f4f35019d78d568db2885d7779ca084a33",
-                "shasum": ""
-            },
-            "require": {
-                "ext-tokenizer": "*",
-                "ext-xmlwriter": "*",
-                "php": ">=5.1.2"
-            },
-            "bin": [
-                "scripts/phpcs",
-                "scripts/phpcbf"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "CodeSniffer.php",
-                    "CodeSniffer/CLI.php",
-                    "CodeSniffer/Exception.php",
-                    "CodeSniffer/File.php",
-                    "CodeSniffer/Fixer.php",
-                    "CodeSniffer/Report.php",
-                    "CodeSniffer/Reporting.php",
-                    "CodeSniffer/Sniff.php",
-                    "CodeSniffer/Tokens.php",
-                    "CodeSniffer/Reports/",
-                    "CodeSniffer/Tokenizers/",
-                    "CodeSniffer/DocGenerators/",
-                    "CodeSniffer/Standards/AbstractPatternSniff.php",
-                    "CodeSniffer/Standards/AbstractScopeSniff.php",
-                    "CodeSniffer/Standards/AbstractVariableSniff.php",
-                    "CodeSniffer/Standards/IncorrectPatternException.php",
-                    "CodeSniffer/Standards/Generic/Sniffs/",
-                    "CodeSniffer/Standards/MySource/Sniffs/",
-                    "CodeSniffer/Standards/PEAR/Sniffs/",
-                    "CodeSniffer/Standards/PSR1/Sniffs/",
-                    "CodeSniffer/Standards/PSR2/Sniffs/",
-                    "CodeSniffer/Standards/Squiz/Sniffs/",
-                    "CodeSniffer/Standards/Zend/Sniffs/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Greg Sherwood",
-                    "role": "lead"
-                }
-            ],
-            "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
-            "homepage": "http://www.squizlabs.com/php-codesniffer",
-            "keywords": [
-                "phpcs",
-                "standards"
-            ],
-            "time": "2015-11-23 21:30:59"
-        },
-        {
-            "name": "symfony/yaml",
-            "version": "v3.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/yaml.git",
-                "reference": "177a015cb0e19ff4a49e0e2e2c5fc1c1bee07002"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/177a015cb0e19ff4a49e0e2e2c5fc1c1bee07002",
-                "reference": "177a015cb0e19ff4a49e0e2e2c5fc1c1bee07002",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5.9"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.0-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Yaml\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Yaml Component",
-            "homepage": "https://symfony.com",
-            "time": "2015-11-30 12:36:17"
-        }
-    ],
+    "packages-dev": [],
     "aliases": [],
     "minimum-stability": "stable",
     "stability-flags": {

+ 5 - 6
dev/dolibarr_changes.txt

@@ -40,6 +40,11 @@ with:
 
 TCPDF:
 ------
+* To avoid to have QRcode changed because generated with a random mask, replace
+define('QR_FIND_FROM_RANDOM', 2);
+with
+define('QR_FIND_FROM_RANDOM', false);
+
 * Removed all fonts except 
     dejavusans* (used by greek, arab, persan, romanian, turkish), 
     freemono* (russian), 
@@ -62,12 +67,6 @@ In htdocs/includes/tcpdf/tcpdf.php
 * Renamed getmypid into dol_getmypid().
 
 
-To avoid to have QRcode changed because generated with a random mask, replace
-define('QR_FIND_FROM_RANDOM', 2);
-with
-define('QR_FIND_FROM_RANDOM', false);
-
-
 
 TCPDI:
 ------

+ 3 - 3
dev/fixdosfiles.sh

@@ -17,16 +17,16 @@ fi
 # To detec
 if [ "x$1" = "xlist" ]
 then
-	find . \( -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.txt" -o -iname "*.xml" \) -exec file "{}" + | grep CRLF
+	find . \( -iname "functions" -o -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.txt" -o -iname "*.xml" \) -exec file "{}" + | grep CRLF
 #	find . \( -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.txt" -o -iname "*.xml" \) -exec file "{}" + | grep -v 'htdocs\/includes' | grep CRLF
 fi
 
 # To convert
 if [ "x$1" = "xfix" ]
 then
-	for fic in `find . \( -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.txt" -o -iname "*.xml" \) -exec file "{}" + | grep CRLF | awk -F':' '{ print $1 }' `
+	for fic in `find . \( -iname "functions" -o -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.txt" -o -iname "*.xml" \) -exec file "{}" + | grep CRLF | awk -F':' '{ print $1 }' `
 	do
 		echo "Fix file $fic"
-		dos2unix $fic
+		dos2unix "$fic"
 	done;
 fi

+ 7 - 6
dev/skeletons/modMyModule.class.php

@@ -50,25 +50,26 @@ class modMyModule extends DolibarrModules
 		// Key text used to identify module (for permissions, menus, etc...)
 		$this->rights_class = 'mymodule';
 
-		// Family can be 'crm','financial','hr','projects','products','ecm','technic','other'
-		// It is used to group modules in module setup page
+		// Family can be 'crm','financial','hr','projects','products','ecm','technic','interface','other'
+		// It is used to group modules by family in module setup page
 		$this->family = "other";
 		// Module position in the family
 		$this->module_position = 500;
 		// Gives the possibility to the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this)
-		$this->familyinfo = array('myownfamily' => array('position' => '001', 'label' => $langs->trans("MyOwnFamily")));
+		//$this->familyinfo = array('myownfamily' => array('position' => '001', 'label' => $langs->trans("MyOwnFamily")));
 
 		// Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module)
 		$this->name = preg_replace('/^mod/i','',get_class($this));
 		// Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module)
 		$this->description = "Description of module MyModule";
+		$this->descriptionlong = "A very lon description. Can be a full HTML content";
+		$this->editor_name = 'Editor name';
+		$this->editor_url = 'http://www.dolibarr.org';
 		
-		// Possible values for version are: 'development', 'experimental', 'dolibarr' or 'dolibarr_deprecated' or version
+		// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z'
 		$this->version = '1.0';
 		// Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase)
 		$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
-		// Where to store the module in setup page (0=common,1=interface,2=others,3=very specific)
-		$this->special = 0;
 		// Name of image file used for this module.
 		// If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue'
 		// If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module'

+ 54 - 16
dev/skeletons/skeleton_list.php

@@ -43,7 +43,9 @@ if (! $res && file_exists("../../../dolibarr/htdocs/main.inc.php")) $res=@includ
 if (! $res && file_exists("../../../../dolibarr/htdocs/main.inc.php")) $res=@include '../../../../dolibarr/htdocs/main.inc.php';   // Used on dev env only
 if (! $res) die("Include of main fails");
 // Change this following line to use the correct relative path from htdocs
-include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php');
+require_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php');
+require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
 dol_include_once('/mymodule/class/skeleton_class.class.php');
 
 // Load traductions files requiredby by page
@@ -124,6 +126,9 @@ if (is_array($extrafields->attribute_label) && count($extrafields->attribute_lab
 * Put here all code to do according to value of "action" parameter
 ********************************************************************/
 
+if (GETPOST('cancel')) { $action='list'; $massaction=''; }
+if (! GETPOST('confirmmassaction')) { $massaction=''; }
+
 $parameters=array();
 $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
@@ -142,6 +147,19 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") ||GETPO
 
 if (empty($reshook))
 {
+    // Mass actions. Controls on number of lines checked
+    $maxformassaction=1000;
+    if (! empty($massaction) && count($toselect) < 1)
+    {
+        $error++;
+        setEventMessages($langs->trans("NoLineChecked"), null, "warnings");
+    }
+    if (! $error && count($toselect) > $maxformassaction)
+    {
+        setEventMessages($langs->trans('TooManyRecordForMassAction',$maxformassaction), null, 'errors');
+        $error++;
+    }
+    
 	// Action to delete
 	if ($action == 'confirm_delete')
 	{
@@ -217,7 +235,7 @@ foreach ($search_array_options as $key => $val)
     $tmpkey=preg_replace('/search_options_/','',$key);
     $typ=$extrafields->attribute_type[$tmpkey];
     $mode=0;
-    if (in_array($typ, array('int'))) $mode=1;    // Search on a numeric
+    if (in_array($typ, array('int','double'))) $mode=1;    // Search on a numeric
     if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) 
     {
         $sql .= natural_search('ef.'.$tmpkey, $crit, $mode);
@@ -266,6 +284,7 @@ if ($resql)
     if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
 	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 	print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
+    print '<input type="hidden" name="action" value="list">';
 	print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 	print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
 	
@@ -297,8 +316,8 @@ if ($resql)
 
     // Fields title
     print '<tr class="liste_titre">';
-    if (! empty($arrayfields['t.field1']['checked'])) print_liste_field_titre($langs->trans('field1'),$_SERVER['PHP_SELF'],'t.field1','',$param,'',$sortfield,$sortorder);
-    if (! empty($arrayfields['t.field2']['checked'])) print_liste_field_titre($langs->trans('field2'),$_SERVER['PHP_SELF'],'t.field2','',$param,'',$sortfield,$sortorder);
+    if (! empty($arrayfields['t.field1']['checked'])) print_liste_field_titre($arrayfields['t.field1']['label'],$_SERVER['PHP_SELF'],'t.field1','',$param,'',$sortfield,$sortorder);
+    if (! empty($arrayfields['t.field2']['checked'])) print_liste_field_titre($arrayfields['t.field2']['label'],$_SERVER['PHP_SELF'],'t.field2','',$param,'',$sortfield,$sortorder);
 	// Extra fields
 	if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
 	{
@@ -315,8 +334,8 @@ if ($resql)
 	$parameters=array('arrayfields'=>$arrayfields);
     $reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters);    // Note that $action and $object may have been modified by hook
     print $hookmanager->resPrint;
-	if (! empty($arrayfields['t.datec']['checked']))  print_liste_field_titre($langs->trans("DateCreationShort"),$_SERVER["PHP_SELF"],"t.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
-	if (! empty($arrayfields['t.tms']['checked']))    print_liste_field_titre($langs->trans("DateModificationShort"),$_SERVER["PHP_SELF"],"t.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+	if (! empty($arrayfields['t.datec']['checked']))  print_liste_field_titre($arrayfields['t.datec']['label'],$_SERVER["PHP_SELF"],"t.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+	if (! empty($arrayfields['t.tms']['checked']))    print_liste_field_titre($arrayfields['t.tms']['label'],$_SERVER["PHP_SELF"],"t.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
 	//if (! empty($arrayfields['t.status']['checked'])) print_liste_field_titre($langs->trans("Status"),$_SERVER["PHP_SELF"],"t.status","",$param,'align="center"',$sortfield,$sortorder);
 	print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="right"',$sortfield,$sortorder,'maxwidthsearch ');
     print '</tr>'."\n";
@@ -335,12 +354,15 @@ if ($resql)
                 $align=$extrafields->getAlignFlag($key);
                 $typeofextrafield=$extrafields->attribute_type[$key];
                 print '<td class="liste_titre'.($align?' '.$align:'').'">';
-                if (in_array($typeofextrafield, array('varchar', 'int', 'select')))
-                {
-                   $crit=$val;
-                			$tmpkey=preg_replace('/search_options_/','',$key);
-                			print '<input class="flat" size="4" type="text" name="search_options_'.$tmpkey.'" value="'.dol_escape_htmltag($search_array_options['search_options_'.$tmpkey]).'">';
-                }
+            	if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')))
+				{
+				    $crit=$val;
+    				$tmpkey=preg_replace('/search_options_/','',$key);
+    				$searchclass='';
+    				if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring';
+    				if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum';
+    				print '<input class="flat'.($searchclass?' '.$searchclass:'').'" size="4" type="text" name="search_options_'.$tmpkey.'" value="'.dol_escape_htmltag($search_array_options['search_options_'.$tmpkey]).'">';
+				}
                 print '</td>';
             }
         }
@@ -376,7 +398,9 @@ if ($resql)
 	print '</tr>'."\n";
         
     
-    $i = 0;
+	$i=0;
+	$var=true;
+	$totalarray=array();
     while ($i < min($num, $limit))
     {
         $obj = $db->fetch_object($resql);
@@ -384,8 +408,16 @@ if ($resql)
         {
             // You can use here results
             print '<tr>';
-            if (! empty($arrayfields['t.field1']['checked'])) print '<td>'.$obj->field1.'</td>';
-            if (! empty($arrayfields['t.field2']['checked'])) print '<td>'.$obj->field2.'</td>';
+            if (! empty($arrayfields['t.field1']['checked'])) 
+            {
+                print '<td>'.$obj->field1.'</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+            }
+            if (! empty($arrayfields['t.field2']['checked'])) 
+            {
+                print '<td>'.$obj->field2.'</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+            }
         	// Extra fields
     		if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
     		{
@@ -400,6 +432,7 @@ if ($resql)
     					$tmpkey='options_'.$key;
     					print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1);
     					print '</td>';
+    		            if (! $i) $totalarray['nbfield']++;
     				}
     		   }
     		}
@@ -413,6 +446,7 @@ if ($resql)
                 print '<td align="center">';
                 print dol_print_date($db->jdate($obj->date_creation), 'dayhour');
                 print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
             }
             // Date modification
             if (! empty($arrayfields['t.tms']['checked']))
@@ -420,6 +454,7 @@ if ($resql)
                 print '<td align="center">';
                 print dol_print_date($db->jdate($obj->date_update), 'dayhour');
                 print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
             }
             // Status
             /*
@@ -428,9 +463,12 @@ if ($resql)
     		  $userstatic->statut=$obj->statut;
               print '<td align="center">'.$userstatic->getLibStatut(3).'</td>';
             }*/
+
             // Action column
             print '<td></td>';
-    		print '</tr>';
+            if (! $i) $totalarray['nbfield']++;
+
+            print '</tr>';
         }
         $i++;
     }

+ 6 - 6
htdocs/accountancy/admin/account.php

@@ -161,11 +161,11 @@ if ($result) {
 	print '</tr>';
 	
 	print '<tr class="liste_titre">';
-	print '<td class="liste_titre"><input type="text" class="flat" size="15" name="search_account" value="' . $search_account . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="15" name="search_label" value="' . $search_label . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="15" name="search_accountparent" value="' . $search_accountparent . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="15" name="search_pcgtype" value="' . $search_pcgtype . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="15" name="search_pcgsubtype" value="' . $search_pcgsubtype . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat" size="10" name="search_account" value="' . $search_account . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat" size="20" name="search_label" value="' . $search_label . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat" size="10" name="search_accountparent" value="' . $search_accountparent . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_pcgtype" value="' . $search_pcgtype . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_pcgsubtype" value="' . $search_pcgsubtype . '"></td>';
 	print '<td class="liste_titre">&nbsp;</td>';
 	print '<td align="right" colspan="2" class="liste_titre">';
 	print '<input type="image" class="liste_titre" src="' . img_picto($langs->trans("Search"), 'search.png', '', '', 1) . '" name="button_search" value="' . dol_escape_htmltag($langs->trans("Search")) . '" title="' . dol_escape_htmltag($langs->trans("Search")) . '">';
@@ -190,7 +190,7 @@ if ($result) {
 		print '<td>' . $accountstatic->getNomUrl(1) . '</td>';
 		print '<td>' . $obj->label . '</td>';
 
-		if ($obj->account_parent)
+		if (! empty($obj->account_parent))
         {
 			$accountparent->id = $obj->rowid2;
 			$accountparent->label = $obj->label2;

+ 118 - 61
htdocs/accountancy/admin/card.php

@@ -1,6 +1,6 @@
-<?PHP
+<?php
 /* Copyright (C) 2013-2014 Olivier Geffroy      <jeff@jeffinfo.com>
- * Copyright (C) 2013-2015 Alexandre Spangaro   <aspangaro.dolibarr@gmail.com>
+ * Copyright (C) 2013-2016 Alexandre Spangaro   <aspangaro.dolibarr@gmail.com>
  * Copyright (C) 2014	   Florian Henry		<florian.henry@open-concept.pro>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,9 @@
  */
 
 /**
- * \file htdocs/accountancy/admin/card.php
- * \ingroup Accounting Expert
- * \brief Card accounting account
+ * \file 		htdocs/accountancy/admin/card.php
+ * \ingroup 	Advanced accountancy
+ * \brief 		Card of accounting account
  */
 require '../../main.inc.php';
 
@@ -28,6 +28,7 @@ require '../../main.inc.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php';
 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/html.formventilation.class.php';
+require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php';
 
 $error = 0;
 
@@ -45,7 +46,7 @@ $cancel = GETPOST('cancel');
 if (! $user->admin)
 	accessforbidden();
 
-$accounting = new AccountingAccount($db);
+$object = new AccountingAccount($db);
 
 // Action
 if ($action == 'add') {
@@ -55,16 +56,25 @@ if ($action == 'add') {
 		dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
 		$result = $db->query($sql);
 		$obj = $db->fetch_object($result);
+
+		// Clean code
+		$account_number = clean_account(GETPOST('account_number')); // Accounting account without zero on the right
+		if (GETPOST('account_category') <= 0) {
+			$account_parent = '';
+		} else {
+			$account_parent = GETPOST('account_category','int');
+		}
 		
-		$accounting->fk_pcg_version = $obj->pcg_version;
-		$accounting->pcg_type = GETPOST('pcg_type');
-		$accounting->pcg_subtype = GETPOST('pcg_subtype');
-		$accounting->account_number = GETPOST('account_number');
-		$accounting->account_parent = GETPOST('account_parent', 'int');
-		$accounting->label = GETPOST('label', 'alpha');
-		$accounting->active = 1;
+		$object->fk_pcg_version = $obj->pcg_version;
+		$object->pcg_type = GETPOST('pcg_type');
+		$object->pcg_subtype = GETPOST('pcg_subtype');
+		$object->account_number = $account_number;
+		$object->account_parent = $account_parent;
+		$object->account_category = GETPOST('account_category');
+		$object->label = GETPOST('label', 'alpha');
+		$object->active = 1;
 		
-		$res = $accounting->create($user);
+		$res = $object->create($user);
 		
 		if ($res == 0) {
 		} else {
@@ -81,22 +91,31 @@ if ($action == 'add') {
 	Header("Location: account.php");
 } else if ($action == 'edit') {
 	if (! GETPOST('cancel', 'alpha')) {
-		$result = $accounting->fetch($id);
+		$result = $object->fetch($id);
 		
 		$sql = 'SELECT pcg_version FROM ' . MAIN_DB_PREFIX . 'accounting_system WHERE rowid=' . $conf->global->CHARTOFACCOUNTS;
 		
 		dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
 		$result2 = $db->query($sql);
 		$obj = $db->fetch_object($result2);
+
+		// Clean code
+		$account_number = clean_account(GETPOST('account_number')); // Accounting account without zero on the right
+		if (GETPOST('account_category') <= 0) {
+			$account_parent = '';
+		} else {
+			$account_parent = GETPOST('account_category','int');
+		}
+
+		$object->fk_pcg_version = $obj->pcg_version;
+		$object->pcg_type = GETPOST('pcg_type');
+		$object->pcg_subtype = GETPOST('pcg_subtype');
+		$object->account_number = $account_number;
+		$object->account_parent = $account_parent;
+		$object->account_category = GETPOST('account_category');
+		$object->label = GETPOST('label', 'alpha');
 		
-		$accounting->fk_pcg_version = $obj->pcg_version;
-		$accounting->pcg_type = GETPOST('pcg_type');
-		$accounting->pcg_subtype = GETPOST('pcg_subtype');
-		$accounting->account_number = GETPOST('account_number');
-		$accounting->account_parent = GETPOST('account_parent', 'int');
-		$accounting->label = GETPOST('label', 'alpha');
-		
-		$result = $accounting->update($user);
+		$result = $object->update($user);
 		
 		if ($result > 0) {
 			header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
@@ -109,10 +128,10 @@ if ($action == 'add') {
 		exit();
 	}
 } else if ($action == 'delete') {
-	$result = $accounting->fetch($id);
+	$result = $object->fetch($id);
 	
-	if (! empty($accounting->id)) {
-		$result = $accounting->delete($user);
+	if (! empty($object->id)) {
+		$result = $object->delete($user);
 		
 		if ($result > 0) {
 			Header("Location: account.php");
@@ -120,7 +139,7 @@ if ($action == 'add') {
 	}
 	
 	if ($result < 0) {
-		setEventMessages($accounting->error, $accounting->errors, 'errors');
+		setEventMessages($object->error, $object->errors, 'errors');
 	}
 }
 
@@ -131,7 +150,9 @@ llxheader('', $langs->trans('AccountAccounting'));
 
 $form = new Form($db);
 $htmlacc = new FormVentilation($db);
+$formaccounting = new FormAccounting($db);
 
+// Create mode
 if ($action == 'create') {
 	print load_fiche_titre($langs->trans('NewAccount'));
 	
@@ -142,22 +163,37 @@ if ($action == 'create') {
 	dol_fiche_head();
 	
 	print '<table class="border" width="100%">';
-	
+
+	// Account number
 	print '<tr><td width="25%"><span class="fieldrequired">' . $langs->trans("AccountNumber") . '</span></td>';
-	print '<td><input name="account_number" size="30" value="' . $accounting->account_number . '"</td></tr>';
+	print '<td><input name="account_number" size="30" value="' . $object->account_number . '"</td></tr>';
+
+	// Label
 	print '<tr><td><span class="fieldrequired">' . $langs->trans("Label") . '</span></td>';
-	print '<td><input name="label" size="70" value="' . $accounting->label . '"</td></tr>';
+	print '<td><input name="label" size="70" value="' . $object->label . '"</td></tr>';
+
+	// Account parent
 	print '<tr><td>' . $langs->trans("Accountparent") . '</td>';
 	print '<td>';
-	print $htmlacc->select_account($accounting->account_parent, 'account_parent', 1);
+	print $htmlacc->select_account($object->account_parent, 'account_parent', 1);
+	print '</td></tr>';
+
+	// Category
+	print '<tr><td>' . $langs->trans("AccountingCategory") . '</td>';
+	print '<td>';
+	$formaccounting->select_accounting_category($object->account_category, 'account_category', 1);
 	print '</td></tr>';
+
+	// Chart of accounts type
 	print '<tr><td>' . $langs->trans("Pcgtype") . '</td>';
 	print '<td>';
-	print $htmlacc->select_pcgtype($accounting->pcg_type, 'pcg_type');
+	print $htmlacc->select_pcgtype($object->pcg_type, 'pcg_type');
 	print '</td></tr>';
+
+	// Chart of acounts subtype
 	print '<tr><td>' . $langs->trans("Pcgsubtype") . '</td>';
 	print '<td>';
-	print $htmlacc->select_pcgsubtype($accounting->pcg_subtype, 'pcg_subtype');
+	print $htmlacc->select_pcgsubtype($object->pcg_subtype, 'pcg_subtype');
 	print '</td></tr>';
 	
 	print '</table>';
@@ -172,20 +208,16 @@ if ($action == 'create') {
 	
 	print '</form>';
 } else if ($id) {
-	$rowid = $id;
-	$account = $accounting->fetch($rowid);
+	$result = $object->fetch($id);
 	
-	if ($account > 0) {
+	if ($result > 0) {
 		dol_htmloutput_mesg($mesg);
 		
-		$head = accounting_prepare_head($accounting);
+		$head = accounting_prepare_head($object);
 		
-		if ($action == 'update') {
-			$soc = new Societe($db);
-			if ($object->socid) {
-				$soc->fetch($object->socid);
-			}
-			
+		// Edit mode
+		if ($action == 'update') 
+		{
 			dol_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'billr');
 			
 			print '<form name="update" action="' . $_SERVER["PHP_SELF"] . '" method="POST">' . "\n";
@@ -195,21 +227,36 @@ if ($action == 'create') {
 			
 			print '<table class="border" width="100%">';
 			
+			// Account number
 			print '<tr><td width="25%"><span class="fieldrequired">' . $langs->trans("AccountNumber") . '</span></td>';
-			print '<td><input name="account_number" size="30" value="' . $accounting->account_number . '"</td></tr>';
+			print '<td><input name="account_number" size="30" value="' . $object->account_number . '"</td></tr>';
+			
+			// Label
 			print '<tr><td><span class="fieldrequired">' . $langs->trans("Label") . '</span></td>';
-			print '<td><input name="label" size="70" value="' . $accounting->label . '"</td></tr>';
+			print '<td><input name="label" size="70" value="' . $object->label . '"</td></tr>';
+			
+			// Account parent
 			print '<tr><td>' . $langs->trans("Accountparent") . '</td>';
 			print '<td>';
-			print $htmlacc->select_account($accounting->account_parent, 'account_parent', 1);
+			print $htmlacc->select_account($object->account_parent, 'account_parent', 1);
 			print '</td></tr>';
+
+			// Category
+            print '<tr><td>'.$langs->trans("AccountingCategory").'</td>';
+			print '<td>';
+            $formaccounting->select_accounting_category($object->account_category, 'account_category', 1);
+            print '</td></tr>';
+
+			// Chart of accounts type
 			print '<tr><td>' . $langs->trans("Pcgtype") . '</td>';
 			print '<td>';
-			print $htmlacc->select_pcgtype($accounting->pcg_type, 'pcg_type');
+			print $htmlacc->select_pcgtype($object->pcg_type, 'pcg_type');
 			print '</td></tr>';
+
+			// Chart of accounts subtype
 			print '<tr><td>' . $langs->trans("Pcgsubtype") . '</td>';
 			print '<td>';
-			print $htmlacc->select_pcgsubtype($accounting->pcg_subtype, 'pcg_subtype');
+			print $htmlacc->select_pcgsubtype($object->pcg_subtype, 'pcg_subtype');
 			print '</td></tr>';
 			
 			print '</table>';
@@ -224,6 +271,8 @@ if ($action == 'create') {
 			
 			print '</form>';
 		} else {
+			
+			// View mode
 			$linkback = '<a href="../admin/account.php">' . $langs->trans("BackToChartofaccounts") . '</a>';
 			
 			dol_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'billr');
@@ -232,29 +281,37 @@ if ($action == 'create') {
 			
 			// Account number
 			print '<tr><td width="25%">' . $langs->trans("AccountNumber") . '</td>';
-			print '<td>' . $accounting->account_number . '</td>';
+			print '<td>' . $object->account_number . '</td>';
 			print '<td align="right" width="25%">' . $linkback . '</td></tr>';
-			
+
+			// Label
 			print '<tr><td>' . $langs->trans("Label") . '</td>';
-			print '<td colspan="2">' . $accounting->label . '</td></tr>';
-			
+			print '<td colspan="2">' . $object->label . '</td></tr>';
+
+			// Account parent
 			$accp = new AccountingAccount($db);
-			if (! empty($accounting->account_parent)) {
-				$accp->fetch($accounting->account_parent, '');
+			if (! empty($object->account_parent)) {
+				$accp->fetch($object->account_parent, '');
 			}
 			print '<tr><td>' . $langs->trans("Accountparent") . '</td>';
 			print '<td colspan="2">' . $accp->account_number . ' - ' . $accp->label . '</td></tr>';
-			
+
+			// Category
+			print "<tr><td>".$langs->trans("AccountingCategory")."</td><td colspan='2'>".$object->account_category_label."</td>";
+
+			// Chart of accounts type
 			print '<tr><td>' . $langs->trans("Pcgtype") . '</td>';
-			print '<td colspan="2">' . $accounting->pcg_type . '</td></tr>';
-			
+			print '<td colspan="2">' . $object->pcg_type . '</td></tr>';
+
+			// Chart of accounts subtype
 			print '<tr><td>' . $langs->trans("Pcgsubtype") . '</td>';
-			print '<td colspan="2">' . $accounting->pcg_subtype . '</td></tr>';
-			
+			print '<td colspan="2">' . $object->pcg_subtype . '</td></tr>';
+
+			// Active
 			print '<tr><td>' . $langs->trans("Activated") . '</td>';
 			print '<td colspan="2">';
 			
-			if (empty($accounting->active)) {
+			if (empty($object->active)) {
 				print img_picto($langs->trans("Disabled"), 'switch_off');
 			} else {
 				print img_picto($langs->trans("Activated"), 'switch_on');
@@ -267,7 +324,7 @@ if ($action == 'create') {
 			dol_fiche_end();
 			
 			/*
-			 * Barre d'actions
+			 * Actions buttons
 			 */
 			
 			print '<div class="tabsAction">';

+ 23 - 19
htdocs/accountancy/bookkeeping/balance.php

@@ -1,7 +1,7 @@
 <?php
-/* Copyright (C) 2013-2014 Olivier Geffroy		<jeff@jeffinfo.com>
- * Copyright (C) 2013-2016 Florian Henry		<florian.henry@open-concept.pro>
- * Copyright (C) 2013-2015 Alexandre Spangaro	<aspangaro.dolibarr@gmail.com>
+/* Copyright (C) 2016 		Olivier Geffroy		<jeff@jeffinfo.com>
+ * Copyright (C) 2016 		Florian Henry		<florian.henry@open-concept.pro>
+ * Copyright (C) 2016 		Alexandre Spangaro	<aspangaro.dolibarr@gmail.com>
  *
  * 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
@@ -19,9 +19,9 @@
  */
 
 /**
- * \file htdocs/accountancy/bookkeeping/balance.php
- * \ingroup Accounting Expert
- * \brief Balance of book keeping
+ *  \file 		htdocs/accountancy/bookkeeping/balance.php
+ *  \ingroup 	Advanced accountancy
+ *  \brief 		Balance of book keeping
  */
 require '../../main.inc.php';
 
@@ -137,7 +137,6 @@ else {
 	/*
 	 * List
 	 */
-
 	$nbtotalofrecords = 0;
 	if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
 		$nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
@@ -150,13 +149,12 @@ else {
 	if ($result < 0) {
 		setEventMessages($object->error, $object->errors, 'errors');
 	}
-
-	print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result, $nbtotalofrecords);
-
+	
+	print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result);
+	
 	print '<form method="GET" id="searchFormList" action="' . $_SERVER["PHP_SELF"] . '">';
 	print '<div class="tabsAction">' . "\n";
 	print '<div class="inline-block divButAction"><input type="submit" name="button_export_csv" class="butAction" value="' . $langs->trans("Export") . '" /></div>';
-
 	print '</div>';
 
 	print '<div class="liste_titre">';
@@ -169,6 +167,7 @@ else {
 	print '<table class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
 	print_liste_field_titre($langs->trans("Numerocompte"), $_SERVER['PHP_SELF'], "t.numero_compte", "", $options, "", $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Labelcompte"), $_SERVER['PHP_SELF'], "t.label_compte", "", $options, "", $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Debit"), $_SERVER['PHP_SELF'], "t.debit", "", $options, 'align="right"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Credit"), $_SERVER['PHP_SELF'], "t.credit", "", $options, 'align="right"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Solde"), $_SERVER["PHP_SELF"], "", $options, "", 'width="60" align="center"', $sortfield, $sortorder);
@@ -176,11 +175,11 @@ else {
 	print "</tr>\n";
 
 	print '<tr class="liste_titre">';
-	print '<td>';
+	print '<td colspan="2">';
 	print $langs->trans('From');
 	print $formventilation->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array (), 1, 1, '');
 	print '<br>';
-	print $langs->trans('To');
+	print $langs->trans('to');
 	print $formventilation->select_account($search_accountancy_code_end, 'search_accountancy_code_end', 1, array (), 1, 1, '');
 	print '</td>';
 
@@ -203,23 +202,28 @@ else {
 
 	foreach ( $object->lines as $line ) {
 		$var = ! $var;
-
+		$link = '';
 		$total_debit += $line->debit;
 		$total_credit += $line->credit;
-
+		$description = $object->get_compte_desc($line->numero_compte); // Search description of the account
+		if(empty($description)){
+			$link = '<a href="../admin/card.php?action=create&compte=' . length_accountg($line->numero_compte) . '">' . img_edit_add() .'</a>';
+		}
 		print "<tr $bc[$var]>";
 
 		print '<td>' . length_accountg($line->numero_compte) . '</td>';
-		print '<td align="right">' . price($line->debit) . '</td>';
-		print '<td align="right">' . price($line->credit) . '</td>';
-		print '<td align="right">' . price($line->credit - $line->debit) . '</td>';
-		print '<td align="center">';
+		print '<td>' . $description . '</td>';
+		print '<td align="right">' .  number_format($line->debit, 2, ',', ' ') . '</td>';
+        print '<td align="right">' . number_format($line->credit, 2, ',', ' ') . '</td>';
+        print '<td align="right">' . number_format($line->credit - $line->debit, 2, ',', ' ') . '</td>';
+		print '<td align="center">' . $link;
 		print '</td>';
 		print "</tr>\n";
 	}
 
 	print '<tr class="liste_total">';
 	print '<td></td>';
+	print '<td></td>';
 	print '<td  align="right">';
 	print price($total_debit);
 	print '</td>';

+ 1 - 2
htdocs/accountancy/class/accountancyexport.class.php

@@ -69,7 +69,6 @@ class AccountancyExport
 		$this->db = &$db;
 		$this->separator = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 		$this->end_line = "\n";
-		return 1;
 	}
 
 	/**
@@ -277,7 +276,7 @@ class AccountancyExport
 	/**
 	 *
 	 * @param unknown $str data
-	 * @param unknown $size data
+	 * @param integer $size data
 	 */
 	public static function trunc($str, $size)
 	{

+ 27 - 15
htdocs/accountancy/class/accountingaccount.class.php

@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2013-2014 Olivier Geffroy      <jeff@jeffinfo.com>
- * Copyright (C) 2013-2015 Alexandre Spangaro   <aspangaro.dolibarr@gmail.com>
+ * Copyright (C) 2013-2016 Alexandre Spangaro   <aspangaro.dolibarr@gmail.com>
  * Copyright (C) 2013-2014 Florian Henry		<florian.henry@open-concept.pro>
  * Copyright (C) 2014 	   Juanjo Menent		<jmenent@2byte.es>
  * Copyright (C) 2015      Ari Elbaz (elarifr)  <github@accedinfo.com>
@@ -20,9 +20,9 @@
  */
 
 /**
- * \file htdocs/accountancy/class/accountingaccount.class.php
- * \ingroup Accounting Expert
- * \brief Fichier de la classe des comptes comptable
+ * \file		htdocs/accountancy/class/accountingaccount.class.php
+ * \ingroup		Accounting Expert
+ * \brief		Fichier de la classe des comptes comptable
  */
 
 /**
@@ -41,6 +41,7 @@ class AccountingAccount extends CommonObject
 	var $pcg_subtype;
 	var $account_number;
 	var $account_parent;
+	var $account_category;
 	var $label;
 	var $fk_user_author;
 	var $fk_user_modif;
@@ -58,25 +59,29 @@ class AccountingAccount extends CommonObject
 	/**
 	 * Load record in memory
 	 *
-	 * @param int $rowid Id
-	 * @param string $account_number Account number
-	 * @param int $limittocurentchart 1=Do not load record if it is into another accounting system
-	 * @return int <0 if KO, >0 if OK
+	 * @param 	int 	$rowid 				Id
+	 * @param 	string 	$account_number 	Account number
+	 * @param 	int 	$limittocurrentchart 1=Do not load record if it is into another accounting system
+	 * @return 	int <0 if KO, >0 if OK
 	 */
-	function fetch($rowid = null, $account_number = null, $limittocurentchart = 0) {
+	function fetch($rowid = null, $account_number = null, $limittocurrentchart = 0) {
 		global $conf;
 		
 		if ($rowid || $account_number) {
-			$sql = "SELECT rowid, datec, tms, fk_pcg_version, pcg_type, pcg_subtype, account_number, account_parent, label, fk_user_author, fk_user_modif, active";
-			$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account WHERE";
+			$sql  = "SELECT a.rowid as rowid, a.datec, a.tms, a.fk_pcg_version, a.pcg_type, a.pcg_subtype, a.account_number, a.account_parent, a.label, a.fk_accounting_category, a.fk_user_author, a.fk_user_modif, a.active";
+			$sql .= ", ca.label as category_label";
+			$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as a";
+			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_accounting_category as ca ON a.fk_accounting_category = ca.rowid";
+			$sql .= " WHERE";
 			if ($rowid) {
-				$sql .= " rowid = '" . $rowid . "'";
+				$sql .= " a.rowid = '" . $rowid . "'";
 			} elseif ($account_number) {
-				$sql .= " account_number = '" . $account_number . "'";
+				$sql .= " a.account_number = '" . $account_number . "'";
 			}
-			if (! empty($limittocurentchart)) {
-				$sql .= ' AND fk_pcg_version IN (SELECT pcg_version FROM ' . MAIN_DB_PREFIX . 'accounting_system WHERE rowid=' . $conf->global->CHARTOFACCOUNTS . ')';
+			if (! empty($limittocurrentchart)) {
+				$sql .= ' AND a.fk_pcg_version IN (SELECT pcg_version FROM ' . MAIN_DB_PREFIX . 'accounting_system WHERE rowid=' . $conf->global->CHARTOFACCOUNTS . ')';
 			}
+
 			dol_syslog(get_class($this) . "::fetch sql=" . $sql, LOG_DEBUG);
 			$result = $this->db->query($sql);
 			if ($result) {
@@ -93,6 +98,8 @@ class AccountingAccount extends CommonObject
 					$this->account_number = $obj->account_number;
 					$this->account_parent = $obj->account_parent;
 					$this->label = $obj->label;
+					$this->account_category = $obj->fk_accounting_category;
+					$this->account_category_label = $obj->category_label;
 					$this->fk_user_author = $obj->fk_user_author;
 					$this->fk_user_modif = $obj->fk_user_modif;
 					$this->active = $obj->active;
@@ -134,6 +141,8 @@ class AccountingAccount extends CommonObject
 			$this->account_parent = trim($this->account_parent);
 		if (isset($this->label))
 			$this->label = trim($this->label);
+		if (isset($this->account_category))
+			$this->account_category = trim($this->account_category);
 		if (isset($this->fk_user_author))
 			$this->fk_user_author = trim($this->fk_user_author);
 		if (isset($this->active))
@@ -153,6 +162,7 @@ class AccountingAccount extends CommonObject
 		$sql .= ", account_number";
 		$sql .= ", account_parent";
 		$sql .= ", label";
+		$sql .= ", fk_accounting_category";
 		$sql .= ", fk_user_author";
 		$sql .= ", active";
 		
@@ -166,6 +176,7 @@ class AccountingAccount extends CommonObject
 		$sql .= ", " . (! isset($this->account_number) ? 'NULL' : "'" . $this->account_number . "'");
 		$sql .= ", " . (! isset($this->account_parent) ? 'NULL' : "'" . $this->db->escape($this->account_parent) . "'");
 		$sql .= ", " . (! isset($this->label) ? 'NULL' : "'" . $this->db->escape($this->label) . "'");
+		$sql .= ", " . (! isset($this->account_category) ? 'NULL' : "'" . $this->db->escape($this->account_category) . "'");
 		$sql .= ", " . $user->id;
 		$sql .= ", " . (! isset($this->active) ? 'NULL' : "'" . $this->db->escape($this->active) . "'");
 		
@@ -226,6 +237,7 @@ class AccountingAccount extends CommonObject
 		$sql .= " , account_number = '" . $this->account_number . "'";
 		$sql .= " , account_parent = '" . $this->account_parent . "'";
 		$sql .= " , label = " . ($this->label ? "'" . $this->db->escape($this->label) . "'" : "null");
+		$sql .= " , fk_accounting_category = '" . $this->account_category . "'";
 		$sql .= " , fk_user_modif = " . $user->id;
 		$sql .= " , active = '" . $this->active . "'";
 		

+ 43 - 1
htdocs/accountancy/class/bookkeeping.class.php

@@ -1,7 +1,7 @@
 <?php
 /* Copyright (C) 2007-2012  Laurent Destailleur <eldy@users.sourceforge.net>
  * Copyright (C) 2014       Juanjo Menent       <jmenent@2byte.es>
- * Copyright (C) 2015-2016 Florian Henry       <florian.henry@open-concept.pro>
+ * Copyright (C) 2015-2016  Florian Henry       <florian.henry@open-concept.pro>
  * Copyright (C) 2015       Raphaël Doursenaud  <rdoursenaud@gpcsolutions.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -1207,6 +1207,48 @@ class BookKeeping extends CommonObject
 			return - 1;
 		}
 	}
+	
+	/**
+	* Description of accounting account
+	*
+	* @param 	string 	$account	Accounting account
+	* @return 	string 	
+	*/
+	function get_compte_desc($account = null)
+	{	
+		global $conf;
+		$pcgver = $conf->global->CHARTOFACCOUNTS;
+
+		$sql  = "SELECT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version, cat.label as category";
+		$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa ";
+		$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
+		$sql .= " AND aa.account_number = '" . $account . "'";
+		$sql .= " AND asy.rowid = " . $pcgver;
+		$sql .= " AND aa.active = 1";
+		$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid";
+
+		dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG);
+		$resql = $this->db->query($sql);
+		if ($resql) {
+			$obj = '';
+			if ($this->db->num_rows($resql)) {
+				$obj = $this->db->fetch_object($resql);	
+			}
+			
+			if(empty($obj->category)){				
+				return $obj->label;
+			}else{
+				return $obj->label.' ('.$obj->category.')';
+				
+			}
+		} else {
+			$this->error = "Error " . $this->db->lasterror();
+			dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR);
+
+			return -1;
+		}
+	}
+	
 }
 
 /**

+ 34 - 45
htdocs/accountancy/journal/bankjournal.php

@@ -52,8 +52,9 @@ require_once DOL_DOCUMENT_ROOT . '/societe/class/client.class.php';
 $langs->load("companies");
 $langs->load("other");
 $langs->load("compta");
-$langs->load("bank");
+$langs->load("banks");
 $langs->load('bills');
+$langs->load('donations');
 $langs->load("accountancy");
 
 $id_bank_account = GETPOST('id_account', 'int');
@@ -130,11 +131,12 @@ if ($result) {
 
 	$num = $db->num_rows($result);
 	// Variables
-	$cptfour = (! empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : $langs->trans("CodeNotDef"));
-	$cptcli = (! empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) ? $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER : $langs->trans("CodeNotDef"));
-	$accountancy_account_salary = (! empty($conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT) ? $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT : $langs->trans("CodeNotDef"));
-	$accountancy_account_pay_vat = (! empty($conf->global->ACCOUNTING_VAT_PAY_ACCOUNT) ? $conf->global->ACCOUNTING_VAT_PAY_ACCOUNT : $langs->trans("CodeNotDef"));
-	$accountancy_account_pay_donation = (! empty($conf->global->DONATION_ACCOUNTINGACCOUNT) ? $conf->global->DONATION_ACCOUNTINGACCOUNT : $langs->trans("CodeNotDef"));
+	$account_supplier = (! empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : $langs->trans("CodeNotDef"));
+	$account_customer = (! empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) ? $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER : $langs->trans("CodeNotDef"));
+	$account_employee = (! empty($conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT) ? $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT : $langs->trans("CodeNotDef"));
+	$account_pay_vat = (! empty($conf->global->ACCOUNTING_VAT_PAY_ACCOUNT) ? $conf->global->ACCOUNTING_VAT_PAY_ACCOUNT : $langs->trans("CodeNotDef"));
+	$account_pay_donation = (! empty($conf->global->DONATION_ACCOUNTINGACCOUNT) ? $conf->global->DONATION_ACCOUNTINGACCOUNT : $langs->trans("CodeNotDef"));
+	$account_transfer = (! empty($conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH) ? $conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH : $langs->trans("CodeNotDef"));
 
 	$tabpay = array ();
 	$tabbq = array ();
@@ -154,11 +156,9 @@ if ($result) {
 		// Controls
 		$compta_bank = $obj->account_number;
 		if ($obj->label == '(SupplierInvoicePayment)')
-			$compta_soc = (! empty($obj->code_compta_fournisseur) ? $obj->code_compta_fournisseur : $cptfour);
+			$compta_soc = (! empty($obj->code_compta_fournisseur) ? $obj->code_compta_fournisseur : $account_supplier);
 		if ($obj->label == '(CustomerInvoicePayment)')
-			$compta_soc = (! empty($obj->code_compta) ? $obj->code_compta : $cptcli);
-		if ($obj->typeop == '(BankTransfert)')
-			$compta_soc = $conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH;
+			$compta_soc = (! empty($obj->code_compta) ? $obj->code_compta : $account_customer);
 
 		// Variable bookkeeping
 		$tabpay[$obj->rowid]["date"] = $obj->do;
@@ -226,25 +226,23 @@ if ($result) {
 					$paymentdonstatic->id = $links[$key]['url_id'];
 					$paymentdonstatic->fk_donation = $links[$key]['url_id'];
 					$tabpay[$obj->rowid]["lib"] .= ' ' . $langs->trans("PaymentDonation");
-					$tabtp[$obj->rowid][$accountancy_account_pay_donation] += $obj->amount;
+					$tabtp[$obj->rowid][$account_pay_donation] += $obj->amount;
 				} else if ($links[$key]['type'] == 'payment_vat') {
 					$paymentvatstatic->id = $links[$key]['url_id'];
 					$paymentvatstatic->ref = $links[$key]['url_id'];
+					$paymentvatstatic->label = $links[$key]['label'];
 					$tabpay[$obj->rowid]["lib"] .= ' ' . $langs->trans("PaymentVat");
-					$tabtp[$obj->rowid][$accountancy_account_pay_vat] += $obj->amount;
+					$tabtp[$obj->rowid][$account_pay_vat] += $obj->amount;
 				} else if ($links[$key]['type'] == 'payment_salary') {
 					$paymentsalstatic->id = $links[$key]['url_id'];
 					$paymentsalstatic->ref = $links[$key]['url_id'];
 					$paymentsalstatic->label = $links[$key]['label'];
 					$tabpay[$obj->rowid]["lib"] .= ' ' . $paymentsalstatic->getNomUrl(2);
-					$tabtp[$obj->rowid][$accountancy_account_salary] += $obj->amount;
+					$tabtp[$obj->rowid][$account_employee ] += $obj->amount;
 				} else if ($links[$key]['type'] == 'banktransfert') {
-					$tabpay[$obj->rowid]["lib"] .= ' ' . $paymentvatstatic->getNomUrl(2);
-					$tabtp[$obj->rowid][$cpttva] += $obj->amount;
+					$tabpay[$obj->rowid]["lib"] .= ' ' . $langs->trans("BankTransfer");
+					$tabtp[$obj->rowid][$account_transfer] += $obj->amount;
 				}
-				/*else {
-				 $tabtp [$obj->rowid] [$accountancy_account_salary] += $obj->amount;
-				 }*/
 			}
 		}
 
@@ -588,24 +586,30 @@ else {
 	foreach ( $tabpay as $key => $val ) {
 		$date = dol_print_date($db->jdate($val["date"]), 'day');
 
-		if ($val["lib"] == '(SupplierInvoicePayment)') {
-			$reflabel = $langs->trans('SupplierInvoicePayment');
+		$reflabel = $val["ref"];
+		if ($reflabel == '(SupplierInvoicePayment)') {
+			$reflabel = $langs->trans('Supplier');
 		}
-		if ($val["lib"] == '(CustomerInvoicePayment)') {
-			$reflabel = $langs->trans('CustomerInvoicePayment');
+		if ($reflabel == '(CustomerInvoicePayment)') {
+			$reflabel = $langs->trans('Customer');
+		}		
+		if ($reflabel == '(SocialContributionPayment)') {
+			$reflabel = $langs->trans('SocialContribution');
+		}
+		if ($reflabel == '(DonationPayment)') {
+			$reflabel = $langs->trans('Donation');
 		}
 
 		// Bank
 		foreach ( $tabbq[$key] as $k => $mt ) {
 			print "<tr " . $bc[$var] . ">";
 			print "<td>" . $date . "</td>";
-			print "<td>" . $reflabel . "</td>";
+			print "<td>" . $ref . "</td>";
 			print "<td>" . length_accountg($k) . "</td>";
-			// print "<td>" . $langs->trans('Bank') . "</td>";
 			if ($val['soclib'] == '') {
-				print "<td>" . $langs->trans('Bank') . " - " . $val["ref"] . "</td>";
+				print "<td>" . $bank_code_journal->label . " - " . $val["ref"] . "</td>";
 			} else {
-				print "<td>" . $langs->trans("Bank") . " - " . $val['soclib'] . "</td>";
+				print "<td>" . $bank_code_journal->label . " - " . $val['soclib'] . "</td>";
 			}
 			print "<td>" . $val["type_payment"] . "</td>";
 			print "<td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";
@@ -619,19 +623,9 @@ else {
 				if ($k != 'type') {
 					print "<tr " . $bc[$var] . ">";
 					print "<td>" . $date . "</td>";
-					print "<td>" . $val["soclib"] . "</td>";
-					// print "<td>" . length_accounta($k) . "</td>";
-					if (length_accounta($k) == '') {
-						print "<td>" . length_accounta($conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH) . "</td>";
-					} else {
+					print "<td>" . $ref . "</td>";
 					print "<td>" . length_accounta($k) . "</td>";
-					}
-					// print "<td>" . $langs->trans('ThirdParty') . " (" . $val['soclib'] . ")</td>";
-					if ($val['soclib'] == '') {
-						print "<td>" . $langs->trans('ThirdParty') . " - " . $val["ref"] . "</td>";
-					} else {
-						print "<td>" . $langs->trans("ThirdParty") . ' - ' . $val['soclib'] . "</td>";
-					}
+					print "<td>" . $reflabel . ' ' . $val['soclib'] . "</td>";
 					print "<td>" . $val["type_payment"] . "</td>";
 					print "<td align='right'>" . ($mt < 0 ? price(- $mt) : '') . "</td>";
 					print "<td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";
@@ -642,14 +636,9 @@ else {
 			foreach ( $tabbq[$key] as $k => $mt ) {
 				print "<tr " . $bc[$var] . ">";
 				print "<td>" . $date . "</td>";
-				print "<td>" . $reflabel . "</td>";
+				print "<td>" . $ref . "</td>";
 				print "<td>" . length_accountg($conf->global->ACCOUNTING_ACCOUNT_SUSPENSE) . "</td>";
-				// print "<td>" . $langs->trans('ThirdParty') . "</td>";
-				if ($val['soclib'] == '') {
-					print "<td>" . $langs->trans('ThirdParty') . " - " . $val["ref"] . "</td>";
-				} else {
-					print "<td>" . $langs->trans("ThirdParty") . ' - ' . $val['soclib'] . "</td>";
-				}
+				print "<td>" . $reflabel . "</td>";
 				print "<td>&nbsp;</td>";
 				print "<td align='right'>" . ($mt < 0 ? price(- $mt) : '') . "</td>";
 				print "<td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";

+ 21 - 7
htdocs/accountancy/journal/purchasesjournal.php

@@ -4,7 +4,7 @@
  * Copyright (C) 2011		Juanjo Menent		<jmenent@2byte.es>
  * Copyright (C) 2012		Regis Houssin		<regis@dolibarr.fr>
  * Copyright (C) 2013-2015  Alexandre Spangaro	<aspangaro.dolibarr@gmail.com>
- * Copyright (C) 2013-2014  Olivier Geffroy		<jeff@jeffinfo.com>
+ * Copyright (C) 2013-2016  Olivier Geffroy		<jeff@jeffinfo.com>
  * Copyright (C) 2013-2016  Florian Henry	    <florian.henry@open-concept.pro>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -123,7 +123,7 @@ if ($result) {
 	$i = 0;
 	while ( $i < $num ) {
 		$obj = $db->fetch_object($result);
-		// contrôles
+		// contrôles
 		$compta_soc = (! empty($obj->code_compta_fournisseur)) ? $obj->code_compta_fournisseur : $cptfour;
 		$compta_prod = $obj->compte;
 		if (empty($compta_prod)) {
@@ -164,6 +164,19 @@ if ($action == 'writebookkeeping') {
 	$error = 0;
 
 	foreach ( $tabfac as $key => $val ) {
+	
+	$invoicestatic->id = $key;
+			$invoicestatic->ref = $val["ref"];
+			$invoicestatic->ref = $val["refsologest"];
+			$invoicestatic->refsupplier = $val["refsuppliersologest"];
+			$invoicestatic->type = $val["type"];
+			$invoicestatic->description = html_entity_decode(dol_trunc($val["description"], 32));
+	
+	$companystatic->id = $tabcompany[$key]['id'];
+			$companystatic->name = $tabcompany[$key]['name'];
+			$companystatic->client = $tabcompany[$key]['code_client'];
+	
+	
 		foreach ( $tabttc[$key] as $k => $mt ) {
 			// get compte id and label
 
@@ -175,7 +188,7 @@ if ($action == 'writebookkeeping') {
 			$bookkeeping->fk_doc = $key;
 			$bookkeeping->fk_docdet = $val["fk_facturefourndet"];
 			$bookkeeping->code_tiers = $tabcompany[$key]['code_fournisseur'];
-			$bookkeeping->label_compte = $tabcompany[$key]['name'];
+			$bookkeeping->label_compte = utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->refsupplier . ' - ' . $langs->trans("Code_tiers");
 			$bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
 			$bookkeeping->montant = $mt;
 			$bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
@@ -193,6 +206,8 @@ if ($action == 'writebookkeeping') {
 
 		// Product / Service
 		foreach ( $tabht[$key] as $k => $mt ) {
+		$accountingaccount = new AccountingAccount($db);
+			$accountingaccount->fetch(null, $k);
 			if ($mt) {
 				// get compte id and label
 				$accountingaccount = new AccountingAccount($db);
@@ -205,7 +220,7 @@ if ($action == 'writebookkeeping') {
 					$bookkeeping->fk_doc = $key;
 					$bookkeeping->fk_docdet = $val["fk_facturefourndet"];
 					$bookkeeping->code_tiers = '';
-					$bookkeeping->label_compte = $accountingaccount->label;
+					$bookkeeping->label_compte = utf8_decode(dol_trunc($companystatic->name,16)). ' - ' . $invoicestatic->refsupplier  . ' - ' . utf8_decode($accountingaccount->label);
 					$bookkeeping->numero_compte = $k;
 					$bookkeeping->montant = $mt;
 					$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
@@ -236,7 +251,7 @@ if ($action == 'writebookkeeping') {
 				$bookkeeping->fk_doc = $key;
 				$bookkeeping->fk_docdet = $val["fk_facturefourndet"];
 				$bookkeeping->code_tiers = '';
-				$bookkeeping->label_compte = $langs->trans("VAT");
+				$bookkeeping->label_compte = utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->refsupplier .' - '. $langs->trans("VAT");
 				$bookkeeping->numero_compte = $k;
 				$bookkeeping->montant = $mt;
 				$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
@@ -248,7 +263,7 @@ if ($action == 'writebookkeeping') {
 				$result = $bookkeeping->create($user);
 				if ($result < 0) {
 					$error ++;
-					setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+					setEventMessages($object->error, $object->errors, 'errors');
 				}
 			}
 		}
@@ -517,5 +532,4 @@ if ($action == 'export_csv') {
 	// End of page
 	llxFooter();
 }
-
 $db->close();

+ 38 - 21
htdocs/accountancy/journal/sellsjournal.php

@@ -7,7 +7,7 @@
  * Copyright (C) 2013-2016	Alexandre Spangaro		<aspangaro.dolibarr@gmail.com>
  * Copyright (C) 2013-2016	Florian Henry			<florian.henry@open-concept.pro>
  * Copyright (C) 2013-2016	Olivier Geffroy			<jeff@jeffinfo.com>
- * Copyright (C) 2014       Raphaël Doursenaud      <rdoursenaud@gpcsolutions.fr>
+ * Copyright (C) 2014       Raphaël Doursenaud      <rdoursenaud@gpcsolutions.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,9 +24,9 @@
  */
 
 /**
- * \file 		htdocs/accountancy/journal/sellsjournal.php
- * \ingroup 	Advanced accountancy
- * \brief 		Page with sells journal
+ * \file		htdocs/accountancy/journal/sellsjournal.php
+ * \ingroup		Advanced accountancy
+ * \brief		Page with sells journal
  */
 require '../../main.inc.php';
 
@@ -142,15 +142,14 @@ if ($result) {
 
 		// Situation invoices handling
 		$line = new FactureLigne($db);
-		$line->fetch($obj->fdid); // id of line
-		$prev_progress = 0;
+		$line->fetch($obj->rowid);
+		$prev_progress = $line->get_prev_progress();
 		if ($obj->type == Facture::TYPE_SITUATION) {
-		    // Avoid divide by 0
+			// Avoid divide by 0
 			if ($obj->situation_percent == 0) {
 				$situation_ratio = 0;
 			} else {
-		        $prev_progress = $line->get_prev_progress($obj->rowid);   // id of invoice
-			    $situation_ratio = ($obj->situation_percent - $prev_progress) / $obj->situation_percent;
+				$situation_ratio = ($obj->situation_percent - $prev_progress) / $obj->situation_percent;
 			}
 		} else {
 			$situation_ratio = 1;
@@ -194,6 +193,14 @@ if ($action == 'writebookkeeping') {
 	$error = 0;
 
 	foreach ( $tabfac as $key => $val ) {
+			$companystatic->id = $tabcompany[$key]['id'];
+			$companystatic->name = $tabcompany[$key]['name'];
+			$companystatic->client = $tabcompany[$key]['code_client'];
+
+$invoicestatic->id = $key;
+		$invoicestatic->ref = $val["ref"];
+	
+	
 		foreach ( $tabttc[$key] as $k => $mt ) {
 			$bookkeeping = new BookKeeping($db);
 			$bookkeeping->doc_date = $val["date"];
@@ -204,7 +211,8 @@ if ($action == 'writebookkeeping') {
 			$bookkeeping->fk_docdet = $val["fk_facturedet"];
 			$bookkeeping->code_tiers = $tabcompany[$key]['code_client'];
 			$bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
-			$bookkeeping->label_compte = $tabcompany[$key]['name'];
+			//$bookkeeping->label_compte = $tabcompany[$key]['name'];
+			$bookkeeping->label_compte = utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers");
 			$bookkeeping->montant = $mt;
 			$bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
 			$bookkeeping->debit = ($mt >= 0) ? $mt : 0;
@@ -234,7 +242,7 @@ if ($action == 'writebookkeeping') {
 					$bookkeeping->fk_docdet = $val["fk_facturedet"];
 					$bookkeeping->code_tiers = '';
 					$bookkeeping->numero_compte = $k;
-					$bookkeeping->label_compte = $accountingaccount->label;
+					$bookkeeping->label_compte = utf8_decode(dol_trunc($companystatic->name,16)). ' - ' . $invoicestatic->ref  . ' - ' . utf8_decode($accountingaccount->label);
 					$bookkeeping->montant = $mt;
 					$bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
 					$bookkeeping->debit = ($mt < 0) ? $mt : 0;
@@ -264,7 +272,7 @@ if ($action == 'writebookkeeping') {
 				$bookkeeping->fk_docdet = $val["fk_facturedet"];
 				$bookkeeping->code_tiers = '';
 				$bookkeeping->numero_compte = $k;
-				$bookkeeping->label_compte = $langs->trans("VAT");
+				$bookkeeping->label_compte = utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->ref .' - '. $langs->trans("VAT");
 				$bookkeeping->montant = $mt;
 				$bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
 				$bookkeeping->debit = ($mt < 0) ? $mt : 0;
@@ -275,7 +283,7 @@ if ($action == 'writebookkeeping') {
 				$result = $bookkeeping->create($user);
 				if ($result < 0) {
 					$error ++;
-					setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+					setEventMessages($object->error, $object->errors, 'errors');
 				}
 			}
 		}
@@ -305,6 +313,9 @@ if ($action == 'export_csv') {
 			$companystatic->name = $tabcompany[$key]['name'];
 			$companystatic->client = $tabcompany[$key]['code_client'];
 
+$invoicestatic->id = $key;
+		$invoicestatic->ref = $val["ref"];
+		
 			$date = dol_print_date($db->jdate($val["date"]), '%d%m%Y');
 
 			foreach ( $tabttc[$key] as $k => $mt ) {
@@ -314,7 +325,8 @@ if ($action == 'export_csv') {
 				print length_accounta(html_entity_decode($k)) . $sep;
 				print ($mt < 0 ? 'C' : 'D') . $sep;
 				print ($mt <= 0 ? price(- $mt) : $mt) . $sep;
-				print utf8_decode($companystatic->name) . $sep;
+				print utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers")  . $sep;
+				//print utf8_decode($companystatic->name) . $sep;
 				print $val["ref"];
 				print "\n";
 			}
@@ -329,7 +341,8 @@ if ($action == 'export_csv') {
 					print $sep;
 					print ($mt < 0 ? 'D' : 'C') . $sep;
 					print ($mt <= 0 ? price(- $mt) : $mt) . $sep;
-					print dol_trunc($accountingaccount_static->label, 32) . $sep;
+					print utf8_decode(dol_trunc($companystatic->name,16)). ' - ' . $invoicestatic->ref  . ' - ' . utf8_decode ( utf8_decode ( $accountingaccount_static->label)) . $sep;
+					//print dol_trunc($accountingaccount_static->label, 32) . $sep;
 					print $val["ref"];
 					print "\n";
 				}
@@ -344,7 +357,8 @@ if ($action == 'export_csv') {
 					print $sep;
 					print ($mt < 0 ? 'D' : 'C') . $sep;
 					print ($mt <= 0 ? price(- $mt) : $mt) . $sep;
-					print $langs->trans("VAT") . $sep;
+					print utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->ref .' - '. $langs->trans("VAT") . $sep;
+					//print $langs->trans("VAT") . $sep;
 					print $val["ref"];
 					print "\n";
 				}
@@ -356,6 +370,9 @@ if ($action == 'export_csv') {
 			$companystatic->id = $tabcompany[$key]['id'];
 			$companystatic->name = $tabcompany[$key]['name'];
 			$companystatic->client = $tabcompany[$key]['code_client'];
+			
+			$invoicestatic->id = $key;
+		$invoicestatic->ref = $val["ref"];
 
 			$date = dol_print_date($db->jdate($val["date"]), 'day');
 
@@ -363,7 +380,7 @@ if ($action == 'export_csv') {
 				print '"' . $date . '"' . $sep;
 				print '"' . $val["ref"] . '"' . $sep;
 				print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep;
-				print '"' . utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $companystatic->ref_client . ' - ' . $langs->trans("Code_tiers") . '"' . $sep;
+				print '"' . utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers") . '"' . $sep;
 				//print '"' . utf8_decode($companystatic->name) . '"' . $sep;
 				print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep;
 				print '"' . ($mt < 0 ? price(- $mt) : '') . '"';
@@ -393,7 +410,7 @@ if ($action == 'export_csv') {
 					print '"' . $date . '"' . $sep;
 					print '"' . $val["ref"] . '"' . $sep;
 					print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
-					print '"' . utf8_decode(dol_trunc($companystatic->name,16)).' - '. $langs->trans("VAT") . '"' . $sep;
+					print '"' . utf8_decode(dol_trunc($companystatic->name,16)).' - ' . $invoicestatic->ref .' - '. $langs->trans("VAT") . '"' . $sep;
 					//print '"' . $langs->trans("VAT") . '"' . $sep;
 					print '"' . ($mt < 0 ? price(- $mt) : '') . '"' . $sep;
 					print '"' . ($mt >= 0 ? price($mt) : '') . '"';
@@ -481,7 +498,7 @@ if ($action == 'export_csv') {
 			print "<td>" . length_accounta($k);
 			//print "</td><td>" . $langs->trans("ThirdParty");
 			//print ' (' . $companystatic->getNomUrl(0, 'customer', 16) . ')';
-			print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref_client . ' - ' . $langs->trans("Code_tiers"). "</td>";
+			print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Code_tiers"). "</td>";
 			print "</td><td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";
 			print "<td align='right'>" . ($mt < 0 ? price(- $mt) : '') . "</td>";
 		}
@@ -498,7 +515,7 @@ if ($action == 'export_csv') {
 				print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
 				print "<td>" . length_accountg($k) . "</td>";
 				//print "<td>" . $accountingaccount->label . "</td>";
-				print "<td>" . $companystatic->getNomUrl(0, 'customer', 16). ' - ' . $invoicestatic->ref_client  . ' - ' . utf8_decode ( utf8_decode ( $accountingaccount->label)) . "</td>";
+				print "<td>" . $companystatic->getNomUrl(0, 'customer', 16). ' - ' . $invoicestatic->ref  . ' - ' . utf8_decode ( utf8_decode ( $accountingaccount->label)) . "</td>";
 				print "<td align='right'>" . ($mt < 0 ? price(- $mt) : '') . "</td>";
 				print "<td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";
 				print "</tr>";
@@ -512,7 +529,7 @@ if ($action == 'export_csv') {
 				print "<td>" . $date . "</td>";
 				print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
 				print "<td>" . length_accountg($k) . "</td>";
-				print "<td>" . $companystatic->getNomUrl(0, 'customer', 16). ' - ' . $invoicestatic->ref_client .' - '. $langs->trans("VAT")  . "</td>";
+				print "<td>" . $companystatic->getNomUrl(0, 'customer', 16). ' - ' . $invoicestatic->ref .' - '. $langs->trans("VAT")  . "</td>";
 				//print "<td>" . $langs->trans("VAT") . "</td>";
 				print "<td align='right'>" . ($mt < 0 ? price(- $mt) : '') . "</td>";
 				print "<td align='right'>" . ($mt >= 0 ? price($mt) : '') . "</td>";

+ 2 - 7
htdocs/adherents/card.php

@@ -356,13 +356,8 @@ if (empty($reshook))
 							}
 							else
 							{
-								// Create small thumbs for company (Ratio is near 16/9)
-								// Used on logon for example
-								$imgThumbSmall = vignette($newfile, $maxwidthsmall, $maxheightsmall, '_small', $quality);
-
-								// Create mini thumbs for company (Ratio is near 16/9)
-								// Used on menu or for setup page for example
-								$imgThumbMini = vignette($newfile, $maxwidthmini, $maxheightmini, '_mini', $quality);
+							    // Create thumbs
+							    $object->addThumbs($newfile);
 							}
 						}
 					}

+ 15 - 11
htdocs/adherents/class/adherent_type.class.php

@@ -2,6 +2,7 @@
 /* Copyright (C) 2002      Rodolphe Quiedeville <rodolphe@quiedeville.org>
  * Copyright (C) 2004-2008 Laurent Destailleur  <eldy@users.sourceforge.net>
  * Copyright (C) 2009      Regis Houssin        <regis.houssin@capnetworks.com>
+ * Copyright (C) 2016      Charlie Benke	<charlie@patas-monkey.com>
  *
  * 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
@@ -35,10 +36,14 @@ class AdherentType extends CommonObject
     public $table_element = 'adherent_type';
     public $element = 'adherent_type';
 
+    var $id;
+    var $ref;
     var $libelle;
-    var $cotisation;  // Soumis a la cotisation
-    var $vote;		  // droit de vote
-    var $mail_valid;  //mail envoye lors de la validation
+    var $cotisation;  	// Soumis a la cotisation
+    var $note;		
+    var $vote;		// droit de vote
+    var $mail_valid;  	//mail envoye lors de la validation
+    var $statut;
 
 
     /**
@@ -110,7 +115,7 @@ class AdherentType extends CommonObject
         $sql.= "note = '".$this->db->escape($this->note)."',";
         $sql.= "vote = '".$this->vote."',";
         $sql.= "mail_valid = '".$this->db->escape($this->mail_valid)."'";
-        $sql .= " WHERE rowid = $this->id";
+        $sql .= " WHERE rowid =".$this->id;
 
         $result = $this->db->query($sql);
         if ($result)
@@ -164,7 +169,7 @@ class AdherentType extends CommonObject
                 return 1;
             }
             else
-			{
+            {
                 return 0;
             }
         }
@@ -223,7 +228,7 @@ class AdherentType extends CommonObject
     {
         global $conf,$langs;
 
-        $projets = array();
+        $adherenttypes = array();
 
         $sql = "SELECT rowid, libelle";
         $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type";
@@ -241,7 +246,7 @@ class AdherentType extends CommonObject
                 {
                     $obj = $this->db->fetch_object($resql);
 
-                    $projets[$obj->rowid] = $langs->trans($obj->libelle);
+                    $adherenttypes[$obj->rowid] = $langs->trans($obj->libelle);
                     $i++;
                 }
             }
@@ -250,8 +255,7 @@ class AdherentType extends CommonObject
         {
             print $this->db->error();
         }
-
-        return $projets;
+        return $adherenttypes;
     }
 
 
@@ -308,7 +312,7 @@ class AdherentType extends CommonObject
     function getMailOnSubscription()
     {
         global $conf;
-
+	// mail_subscription not  defined so never used
         if (! empty($this->mail_subscription) && trim(dol_htmlentitiesbr_decode($this->mail_subscription)))  // Property not yet defined
         {
             return $this->mail_subscription;
@@ -327,7 +331,7 @@ class AdherentType extends CommonObject
     function getMailOnResiliate()
     {
         global $conf;
-
+	// NOTE mail_resiliate not defined so never used
         if (! empty($this->mail_resiliate) && trim(dol_htmlentitiesbr_decode($this->mail_resiliate)))  // Property not yet defined
         {
             return $this->mail_resiliate;

+ 1 - 1
htdocs/adherents/document.php

@@ -76,7 +76,7 @@ $upload_dir = $conf->adherent->dir_output . "/" . get_exdir($object->id,2,0,1,$o
  * Actions
  */
 
-include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

+ 4 - 1
htdocs/adherents/type.php

@@ -200,7 +200,10 @@ if (! $rowid && $action != 'create' && $action != 'edit')
 			print '<td>'.dol_escape_htmltag($objp->libelle).'</td>';
 			print '<td align="center">'.yn($objp->cotisation).'</td>';
 			print '<td align="center">'.yn($objp->vote).'</td>';
-			print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=edit&rowid='.$objp->rowid.'">'.img_edit().'</a></td>';
+			if ($user->rights->adherent->configurer)
+				print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=edit&rowid='.$objp->rowid.'">'.img_edit().'</a></td>';
+			else
+				print '<td align="right">&nbsp;</td>';
 			print "</tr>";
 			$i++;
 		}

+ 1 - 66
htdocs/admin/bank.php

@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2009       Laurent Destailleur        <eldy@users.sourceforge.net>
- * Copyright (C) 2010-2013  Juanjo Menent	       <jmenent@2byte.es>
+ * Copyright (C) 2010-2016  Juanjo Menent	       <jmenent@2byte.es>
  * Copyright (C) 2013-2014  Philippe Grand             <philippe.grand@atoo-net.com>
  * Copyright (C) 2015       Jean-François Ferry         <jfefe@aternatik.fr>
  *
@@ -46,24 +46,6 @@ $action = GETPOST('action','alpha');
  * Actions
  */
 
-if ($action == 'set_BANK_CHEQUERECEIPT_FREE_TEXT')
-{
-	$freetext = GETPOST('BANK_CHEQUERECEIPT_FREE_TEXT');	// No alpha here, we want exact string
-
-    $res = dolibarr_set_const($db, "BANK_CHEQUERECEIPT_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity);
-
-	if (! $res > 0) $error++;
-
- 	if (! $error)
-    {
-        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        setEventMessages($langs->trans("Error"), null, 'errors');
-    }
-}
-
 //Order display of bank account
 if ($action == 'setbankorder')
 {
@@ -89,58 +71,13 @@ $form=new Form($db);
 $linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
 print load_fiche_titre($langs->trans("BankSetupModule"),$linkback,'title_setup');
 
-
-print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
-print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-print '<input type="hidden" name="action" value="set_BANK_CHEQUERECEIPT_FREE_TEXT">';
-
 $head = bank_admin_prepare_head(null);
 dol_fiche_head($head, 'general', $langs->trans("BankSetupModule"), 0, 'account');
 
-print '<table class="noborder" width="100%">';
-print '<tr class="liste_titre">';
-print '<td>'.$langs->trans("Parameters").'</td>';
-print '<td align="center" width="60">&nbsp;</td>';
-print '<td width="80">&nbsp;</td>';
-print "</tr>\n";
 $var=true;
 
 $var=! $var;
 
-print '<tr '.$bc[$var].'><td colspan="2">';
-print $langs->trans("FreeLegalTextOnChequeReceipts").' ('.$langs->trans("AddCRIfTooLong").')<br>';
-$variablename='BANK_CHEQUERECEIPT_FREE_TEXT';
-if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
-{
-    print '<textarea name="'.$variablename.'" class="flat" cols="120">'.$conf->global->$variablename.'</textarea>';
-}
-else
-{
-    include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-    $doleditor=new DolEditor($variablename, $conf->global->$variablename,'',80,'dolibarr_details');
-    print $doleditor->Create();
-}
-print '</td><td align="right">';
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print "</td></tr>\n";
-print '</table>';
-print "<br>";
-
-/*
-$var=!$var;
-print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
-print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-print "<input type=\"hidden\" name=\"action\" value=\"set_BANK_CHEQUERECEIPT_DRAFT_WATERMARK\">";
-print '<tr '.$bc[$var].'><td colspan="2">';
-print $langs->trans("WatermarkOnDraftChequeReceipt").'<br>';
-print '<input size="50" class="flat" type="text" name="BANK_CHEQUERECEIPT_DRAFT_WATERMARK" value="'.$conf->global->BANK_CHEQUERECEIPT_DRAFT_WATERMARK.'">';
-print '</td><td align="right">';
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print "</td></tr>\n";
-print '</form>';
-*/
-
-
 //Show bank account order
 print load_fiche_titre($langs->trans("BankOrderShow"));
 
@@ -202,8 +139,6 @@ print '</table>'."\n";
 
 dol_fiche_end();
 
-print '</form>';
-
 llxFooter();
 
 $db->close();

+ 287 - 0
htdocs/admin/chequereceipts.php

@@ -0,0 +1,287 @@
+<?php
+/* Copyright (C) 2009       Laurent Destailleur        <eldy@users.sourceforge.net>
+ * Copyright (C) 2010-2016  Juanjo Menent	       <jmenent@2byte.es>
+ * Copyright (C) 2013-2014  Philippe Grand             <philippe.grand@atoo-net.com>
+ * Copyright (C) 2015       Jean-François Ferry         <jfefe@aternatik.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+/**
+ *      \file       htdocs/admin/bank.php
+ *		\ingroup    bank
+ *		\brief      Page to setup the bank module
+ */
+
+require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/compta/paiement/cheque/class/remisecheque.class.php';
+
+$langs->load("admin");
+$langs->load("companies");
+$langs->load("bills");
+$langs->load("other");
+$langs->load("banks");
+
+if (!$user->admin)
+  accessforbidden();
+
+$action = GETPOST('action','alpha');
+$value = GETPOST('value','alpha');
+
+
+if (empty($conf->global->CHEQUERECEIPTS_ADDON)) $conf->global->CHEQUERECEIPTS_ADDON = 'mod_chequereceipts_mint.php';
+
+
+
+/*
+ * Actions
+ */
+
+if ($action == 'updateMask')
+{
+	$maskconstchequereceipts=GETPOST('maskconstchequereceipts','alpha');
+	$maskchequereceipts=GETPOST('maskchequereceipts','alpha');
+	if ($maskconstchequereceipts) $res = dolibarr_set_const($db,$maskconstchequereceipts,$maskchequereceipts,'chaine',0,'',$conf->entity);
+
+	if (! $res > 0) $error++;
+
+	if (! $error)
+	{
+		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+	}
+	else
+	{
+		setEventMessages($langs->trans("Error"), null, 'errors');
+	}
+}
+
+if ($action == 'setmod')
+{
+	dolibarr_set_const($db, "CHEQUERECEIPTS_ADDON",$value,'chaine',0,'',$conf->entity);
+}
+
+if ($action == 'set_BANK_CHEQUERECEIPT_FREE_TEXT')
+{
+	$freetext = GETPOST('BANK_CHEQUERECEIPT_FREE_TEXT');	// No alpha here, we want exact string
+
+    $res = dolibarr_set_const($db, "BANK_CHEQUERECEIPT_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity);
+
+	if (! $res > 0) $error++;
+
+ 	if (! $error)
+    {
+        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+    }
+    else
+    {
+        setEventMessages($langs->trans("Error"), null, 'errors');
+    }
+}
+
+/*
+ * view
+ */
+
+$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
+llxHeader("",$langs->trans("BankSetupModule"));
+
+$form=new Form($db);
+
+$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+print load_fiche_titre($langs->trans("BankSetupModule"),$linkback,'title_setup');
+
+$head = bank_admin_prepare_head(null);
+dol_fiche_head($head, 'checkreceipts', $langs->trans("BankSetupModule"), 0, 'account');
+
+/*
+ *  Numbering module
+ */
+
+print load_fiche_titre($langs->trans("ChequeReceiptsNumberingModule"), '', '');
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Name").'</td>';
+print '<td>'.$langs->trans("Description").'</td>';
+print '<td class="nowrap">'.$langs->trans("Example").'</td>';
+print '<td align="center" width="60">'.$langs->trans("Status").'</td>';
+print '<td align="center" width="16">'.$langs->trans("ShortInfo").'</td>';
+print '</tr>'."\n";
+
+clearstatcache();
+
+foreach ($dirmodels as $reldir)
+{
+	$dir = dol_buildpath($reldir."core/modules/cheque/");
+	if (is_dir($dir))
+	{
+		$handle = opendir($dir);
+		if (is_resource($handle))
+		{
+			$var=true;
+
+			while (($file = readdir($handle))!==false)
+			{
+				if (! is_dir($dir.$file) || (substr($file, 0, 1) <> '.' && substr($file, 0, 3) <> 'CVS'))
+				{
+					$filebis = $file;
+					$name = substr($file, 4, dol_strlen($file) -16);
+					$classname = preg_replace('/\.php$/','',$file);
+					// For compatibility
+					if (! is_file($dir.$filebis))
+					{
+						$filebis = $file."/".$file.".modules.php";
+						$classname = "mod_chequereceipt_".$file;
+					}
+					// Check if there is a filter on country
+					preg_match('/\-(.*)_(.*)$/',$classname,$reg);
+					if (! empty($reg[2]) && $reg[2] != strtoupper($mysoc->country_code)) continue;
+
+					$classname = preg_replace('/\-.*$/','',$classname);
+					if (! class_exists($classname) && is_readable($dir.$filebis) && (preg_match('/mod_/',$filebis) || preg_match('/mod_/',$classname)) && substr($filebis, dol_strlen($filebis)-3, 3) == 'php')
+					{
+						// Charging the numbering class
+						require_once $dir.$filebis;
+
+						$module = new $classname($db);
+
+						// Show modules according to features level
+						if ($module->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
+						if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
+
+						if ($module->isEnabled())
+						{
+							$var = !$var;
+							print '<tr '.$bc[$var].'><td width="100">';
+							print (empty($module->name)?$name:$module->name);
+							print "</td><td>\n";
+
+							print $module->info();
+
+							print '</td>';
+
+							// Show example of numbering module
+							print '<td class="nowrap">';
+							$tmp=$module->getExample();
+							if (preg_match('/^Error/',$tmp)) print '<div class="error">'.$langs->trans($tmp).'</div>';
+							elseif ($tmp=='NotConfigured') print $langs->trans($tmp);
+							else print $tmp;
+							print '</td>'."\n";
+
+							print '<td align="center">';
+							if ($conf->global->CHEQUERECEIPTS_ADDON == $file || $conf->global->CHEQUERECEIPTS_ADDON.'.php' == $file)
+							{
+								print img_picto($langs->trans("Activated"),'switch_on');
+							}
+							else
+							{
+								print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmod&value='.preg_replace('/\.php$/','',$file).'&scandir='.$module->scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'switch_off').'</a>';
+							}
+							print '</td>';
+
+							$chequereceipts=new RemiseCheque($db);
+							$chequereceipts->initAsSpecimen();
+
+							// Example
+							$htmltooltip='';
+							$htmltooltip.=''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
+							$nextval=$module->getNextValue($mysoc,$chequereceipts);
+							if ("$nextval" != $langs->trans("NotAvailable")) {  // Keep " on nextval
+								$htmltooltip.=$langs->trans("NextValue").': ';
+								if ($nextval) {
+									if (preg_match('/^Error/',$nextval) || $nextval=='NotConfigured')
+										$nextval = $langs->trans($nextval);
+									$htmltooltip.=$nextval.'<br>';
+								} else {
+									$htmltooltip.=$langs->trans($module->error).'<br>';
+								}
+							}
+
+							print '<td align="center">';
+							print $form->textwithpicto('',$htmltooltip,1,0);
+
+							if ($conf->global->CHEQUERECEIPTS_ADDON.'.php' == $file)  // If module is the one used, we show existing errors
+							{
+								if (! empty($module->error)) dol_htmloutput_mesg($module->error,'','error',1);
+							}
+
+							print '</td>';
+
+							print "</tr>\n";
+
+						}
+					}
+				}
+			}
+			closedir($handle);
+		}
+	}
+}
+
+print '</table>';
+
+print '<br>';
+
+
+/*
+ * Other options
+ *
+ */
+print load_fiche_titre($langs->trans("OtherOptions"),'','');
+
+print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
+print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+print '<input type="hidden" name="action" value="set_BANK_CHEQUERECEIPT_FREE_TEXT">';
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td>'.$langs->trans("Parameters").'</td>';
+print '<td align="center" width="60">&nbsp;</td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+$var=true;
+
+$var=! $var;
+
+print '<tr '.$bc[$var].'><td colspan="2">';
+print $langs->trans("FreeLegalTextOnChequeReceipts").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+$variablename='BANK_CHEQUERECEIPT_FREE_TEXT';
+if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
+{
+    print '<textarea name="'.$variablename.'" class="flat" cols="120">'.$conf->global->$variablename.'</textarea>';
+}
+else
+{
+    include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
+    $doleditor=new DolEditor($variablename, $conf->global->$variablename,'',80,'dolibarr_details');
+    print $doleditor->Create();
+}
+print '</td><td align="right">';
+print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
+print "</td></tr>\n";
+print '</table>';
+print "<br>";
+
+print '</table>'."\n";
+
+dol_fiche_end();
+
+print '</form>';
+
+llxFooter();
+
+$db->close();

+ 12 - 8
htdocs/admin/company.php

@@ -98,12 +98,14 @@ if ( ($action == 'update' && empty($_POST["cancel"]))
 					// Create thumbs of logo (Note that PDF use original file and not thumbs)
 					if ($isimage > 0)
 					{
-						// Create small thumbs for company (Ratio is near 16/9)
+					    // Create thumbs
+					    //$object->addThumbs($newfile);    // We can't use addThumbs here yet because we need name of generated thumbs to add them into constants. TODO Check if need such constants. We should be able to retreive value with get... 
+					    	
 						// Used on logon for example
 						$imgThumbSmall = vignette($conf->mycompany->dir_output.'/logos/'.$original_file, $maxwidthsmall, $maxheightsmall, '_small', $quality);
-						if (preg_match('/([^\\/:]+)$/i',$imgThumbSmall,$reg))
+						if (image_format_supported($imgThumbSmall) >= 0 && preg_match('/([^\\/:]+)$/i',$imgThumbSmall,$reg))
 						{
-							$imgThumbSmall = $reg[1];
+							$imgThumbSmall = $reg[1];    // Save only basename
 							dolibarr_set_const($db, "MAIN_INFO_SOCIETE_LOGO_SMALL",$imgThumbSmall,'chaine',0,'',$conf->entity);
 						}
 						else dol_syslog($imgThumbSmall);
@@ -111,9 +113,9 @@ if ( ($action == 'update' && empty($_POST["cancel"]))
 						// Create mini thumbs for company (Ratio is near 16/9)
 						// Used on menu or for setup page for example
 						$imgThumbMini = vignette($conf->mycompany->dir_output.'/logos/'.$original_file, $maxwidthmini, $maxheightmini, '_mini', $quality);
-						if (preg_match('/([^\\/:]+)$/i',$imgThumbMini,$reg))
+						if (image_format_supported($imgThumbMini) >= 0 && preg_match('/([^\\/:]+)$/i',$imgThumbMini,$reg))
 						{
-							$imgThumbMini = $reg[1];
+							$imgThumbMini = $reg[1];     // Save only basename
 							dolibarr_set_const($db, "MAIN_INFO_SOCIETE_LOGO_MINI",$imgThumbMini,'chaine',0,'',$conf->entity);
 						}
 						else dol_syslog($imgThumbMini);
@@ -203,12 +205,14 @@ if ($action == 'addthumb')
 		// Create thumbs of logo
 		if ($isimage > 0)
 		{
-			// Create small thumbs for company (Ratio is near 16/9)
+		    // Create thumbs
+		    //$object->addThumbs($newfile);    // We can't use addThumbs here yet because we need name of generated thumbs to add them into constants. TODO Check if need such constants. We should be able to retreive value with get... 
+
 			// Used on logon for example
 			$imgThumbSmall = vignette($conf->mycompany->dir_output.'/logos/'.$_GET["file"], $maxwidthsmall, $maxheightsmall, '_small',$quality);
 			if (image_format_supported($imgThumbSmall) >= 0 && preg_match('/([^\\/:]+)$/i',$imgThumbSmall,$reg))
 			{
-				$imgThumbSmall = $reg[1];
+				$imgThumbSmall = $reg[1];   // Save only basename
 				dolibarr_set_const($db, "MAIN_INFO_SOCIETE_LOGO_SMALL",$imgThumbSmall,'chaine',0,'',$conf->entity);
 			}
 			else dol_syslog($imgThumbSmall);
@@ -218,7 +222,7 @@ if ($action == 'addthumb')
 			$imgThumbMini = vignette($conf->mycompany->dir_output.'/logos/'.$_GET["file"], $maxwidthmini, $maxheightmini, '_mini',$quality);
 			if (image_format_supported($imgThumbSmall) >= 0 && preg_match('/([^\\/:]+)$/i',$imgThumbMini,$reg))
 			{
-				$imgThumbMini = $reg[1];
+				$imgThumbMini = $reg[1];   // Save only basename
 				dolibarr_set_const($db, "MAIN_INFO_SOCIETE_LOGO_MINI",$imgThumbMini,'chaine',0,'',$conf->entity);
 			}
 			else dol_syslog($imgThumbMini);

+ 4 - 3
htdocs/admin/confexped.php

@@ -131,7 +131,10 @@ print '</tr>';
 // Bon de livraison activation/desactivation
 $var=!$var;
 print '<tr '.$bc[$var].'>';
-print '<td>'.$langs->trans("DeliveriesOrderAbility").'</td>';
+print '<td>';
+print $langs->trans("DeliveriesOrderAbility");
+print '<br>'.info_admin($langs->trans("NoNeedForDeliveryReceipts"), 0, 1);
+print '</td>';
 print '<td align="center" width="20">';
 print '</td>';
 print '<td align="center" width="100">';
@@ -151,7 +154,5 @@ print '</table>';
 
 print '</div>';
 
-print info_admin($langs->trans("NoNeedForDeliveryReceipts"));
-
 llxFooter();
 $db->close();

+ 65 - 15
htdocs/admin/dict.php

@@ -8,7 +8,7 @@
  * Copyright (C) 2011       Remy Younes             <ryounes@gmail.com>
  * Copyright (C) 2012-2015  Marcos García           <marcosgdf@gmail.com>
  * Copyright (C) 2012       Christophe Battarel     <christophe.battarel@ltairis.fr>
- * Copyright (C) 2011-2015  Alexandre Spangaro      <aspangaro.dolibarr@gmail.com>
+ * Copyright (C) 2011-2016  Alexandre Spangaro      <aspangaro.dolibarr@gmail.com>
  * Copyright (C) 2015       Ferran Marcet           <fmarcet@2byte.es>
  * Copyright (C) 2016       Raphaël Doursenaud      <rdoursenaud@gpcsolutions.fr>
  *
@@ -46,6 +46,8 @@ $langs->load("admin");
 $langs->load("companies");
 $langs->load("resource");
 $langs->load("holiday");
+$langs->load("accountancy");
+$langs->load("hrm");
 
 $action=GETPOST('action','alpha')?GETPOST('action','alpha'):'view';
 $confirm=GETPOST('confirm','alpha');
@@ -78,7 +80,7 @@ $hookmanager->initHooks(array('admin'));
 // Put here declaration of dictionaries properties
 
 // Sort order to show dictionary (0 is space). All other dictionaries (added by modules) will be at end of this.
-$taborder=array(9,0,4,3,2,0,1,8,19,16,27,0,5,11,0,6,0,29,0,7,17,24,28,0,10,23,12,13,0,14,0,22,20,18,21,0,15,30,0,25,0,26);
+$taborder=array(9,0,4,3,2,0,1,8,19,16,27,0,5,11,33,34,0,6,0,29,0,7,17,24,28,0,10,23,12,13,0,14,0,22,20,18,21,0,15,30,0,25,0,26,0,31,32,0);
 
 // Name of SQL tables of dictionaries
 $tabname=array();
@@ -112,6 +114,10 @@ $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_accounting_category";
+$tabname[33]= MAIN_DB_PREFIX."c_hrm_department";
+$tabname[34]= MAIN_DB_PREFIX."c_hrm_function";
 
 // Dictionary labels
 $tablib=array();
@@ -145,6 +151,10 @@ $tablib[27]= "DictionaryProspectStatus";
 $tablib[28]= "DictionaryHolidayTypes";
 $tablib[29]= "DictionaryOpportunityStatus";
 $tablib[30]= "DictionaryFormatCards";
+$tablib[31]= "DictionaryAccountancysystem";
+$tablib[32]= "DictionaryAccountancyCategory";
+$tablib[33]= "DictionaryDepartment";
+$tablib[34]= "DictionaryFunction";
 
 // Requests to extract data
 $tabsql=array();
@@ -172,12 +182,16 @@ $tabsql[21]= "SELECT c.rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX
 $tabsql[22]= "SELECT rowid   as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_input_reason";
 $tabsql[23]= "SELECT t.rowid as rowid, t.taux, c.label as country, c.code as country_code, t.fk_pays as country_id, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_revenuestamp as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid";
 $tabsql[24]= "SELECT rowid   as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_type_resource";
-$tabsql[25]= "SELECT rowid   as rowid, label, type_template, private, position, topic, content, active FROM ".MAIN_DB_PREFIX."c_email_templates";
+$tabsql[25]= "SELECT rowid   as rowid, label, type_template, private, position, topic, content, active FROM ".MAIN_DB_PREFIX."c_email_templates WHERE entity IN (".getEntity('email_template',1).")";
 $tabsql[26]= "SELECT rowid   as rowid, code, label, short_label, active FROM ".MAIN_DB_PREFIX."c_units";
 $tabsql[27]= "SELECT id      as rowid, code, libelle, active FROM ".MAIN_DB_PREFIX."c_stcomm";
-$tabsql[28]= "SELECT h.rowid as rowid, h.code, h.label, h.affect, h.delay, h.newByMonth, h.fk_country as country_id, c.code as country_code, c.label as country, h.active FROM ".MAIN_DB_PREFIX."c_holiday_types as h LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON h.fk_country=c.rowid";
+$tabsql[28]= "SELECT h.rowid as rowid, h.code, h.label, h.affect, h.delay, h.newbymonth, h.fk_country as country_id, c.code as country_code, c.label as country, h.active FROM ".MAIN_DB_PREFIX."c_holiday_types as h LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON h.fk_country=c.rowid";
 $tabsql[29]= "SELECT rowid   as rowid, code, label, percent, position, active FROM ".MAIN_DB_PREFIX."c_lead_status";
 $tabsql[30]= "SELECT rowid, code, name, paper_size, orientation, metric, leftmargin, topmargin, nx, ny, spacex, spacey, width, height, font_size, custom_x, custom_y, active FROM ".MAIN_DB_PREFIX."c_format_cards";
+$tabsql[31]= "SELECT s.rowid as rowid, pcg_version, s.fk_pays as country_id, c.code as country_code, c.label as country, s.label, s.active FROM ".MAIN_DB_PREFIX."accounting_system as s, ".MAIN_DB_PREFIX."c_country as c WHERE s.fk_pays=c.rowid and c.active=1";
+$tabsql[32]= "SELECT a.rowid as rowid, a.code as code, a.label, a.range_account, a.position, a.fk_country as country_id, c.code as country_code, c.label as country, a.active FROM ".MAIN_DB_PREFIX."c_accounting_category as a, ".MAIN_DB_PREFIX."c_country as c WHERE a.fk_country=c.rowid and c.active=1";
+$tabsql[33]= "SELECT rowid, pos, code, label, active FROM ".MAIN_DB_PREFIX."c_hrm_department";
+$tabsql[34]= "SELECT rowid, pos, code, label, c_level, active FROM ".MAIN_DB_PREFIX."c_hrm_function";
 
 // Criteria to sort dictionaries
 $tabsqlsort=array();
@@ -211,6 +225,10 @@ $tabsqlsort[27]="code ASC";
 $tabsqlsort[28]="country ASC, code ASC";
 $tabsqlsort[29]="position ASC";
 $tabsqlsort[30]="code ASC";
+$tabsqlsort[31]="pcg_version ASC";
+$tabsqlsort[32]="code ASC, label ASC";
+$tabsqlsort[33]="code ASC";
+$tabsqlsort[34]="code ASC";
 
 // Nom des champs en resultat de select pour affichage du dictionnaire
 $tabfield=array();
@@ -241,9 +259,13 @@ $tabfield[24]= "code,label";
 $tabfield[25]= "label,type_template,position,topic,content";
 $tabfield[26]= "code,label,short_label";
 $tabfield[27]= "code,libelle";
-$tabfield[28]= "code,label,affect,delay,newByMonth,country_id,country";
+$tabfield[28]= "code,label,affect,delay,newbymonth,country_id,country";
 $tabfield[29]= "code,label,percent,position";
 $tabfield[30]= "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y";
+$tabfield[31]= "pcg_version,country_id,country,label";
+$tabfield[32]= "code,label,range,position,country_id,country";
+$tabfield[33]= "code,label";
+$tabfield[34]= "code,label";
 
 // Nom des champs d'edition pour modification d'un enregistrement
 $tabfieldvalue=array();
@@ -274,9 +296,13 @@ $tabfieldvalue[24]= "code,label";
 $tabfieldvalue[25]= "label,type_template,position,topic,content";
 $tabfieldvalue[26]= "code,label,short_label";
 $tabfieldvalue[27]= "code,libelle";
-$tabfieldvalue[28]= "code,label,affect,delay,newByMonth,country";
+$tabfieldvalue[28]= "code,label,affect,delay,newbymonth,country";
 $tabfieldvalue[29]= "code,label,percent,position";
 $tabfieldvalue[30]= "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y";
+$tabfieldvalue[31]= "pcg_version,country,label";
+$tabfieldvalue[32]= "code,label,range_account,position,country";
+$tabfieldvalue[33]= "code,label";
+$tabfieldvalue[34]= "code,label";
 
 // Nom des champs dans la table pour insertion d'un enregistrement
 $tabfieldinsert=array();
@@ -304,12 +330,16 @@ $tabfieldinsert[21]= "code,label";
 $tabfieldinsert[22]= "code,label";
 $tabfieldinsert[23]= "fk_pays,taux,accountancy_code_sell,accountancy_code_buy,note";
 $tabfieldinsert[24]= "code,label";
-$tabfieldinsert[25]= "label,type_template,position,topic,content";
+$tabfieldinsert[25]= "label,type_template,private,position,topic,content,entity";
 $tabfieldinsert[26]= "code,label,short_label";
 $tabfieldinsert[27]= "code,libelle";
-$tabfieldinsert[28]= "code,label,affect,delay,newByMonth,fk_country";
+$tabfieldinsert[28]= "code,label,affect,delay,newbymonth,fk_country";
 $tabfieldinsert[29]= "code,label,percent,position";
 $tabfieldinsert[30]= "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y";
+$tabfieldinsert[31]= "pcg_version,fk_pays,label";
+$tabfieldinsert[32]= "code,label,range_account,position,fk_country";
+$tabfieldinsert[33]= "code,label";
+$tabfieldinsert[34]= "code,label";
 
 // Nom du rowid si le champ n'est pas de type autoincrement
 // Example: "" if id field is "rowid" and has autoincrement on
@@ -345,6 +375,10 @@ $tabrowid[27]= "id";
 $tabrowid[28]= "";
 $tabrowid[29]= "";
 $tabrowid[30]= "";
+$tabrowid[31]= "";
+$tabrowid[32]= "";
+$tabrowid[33]= "rowid";
+$tabrowid[34]= "rowid";
 
 // Condition to show dictionary in setup page
 $tabcond=array();
@@ -378,6 +412,10 @@ $tabcond[27]= ! empty($conf->societe->enabled);
 $tabcond[28]= ! empty($conf->holiday->enabled);
 $tabcond[29]= ! empty($conf->projet->enabled);
 $tabcond[30]= ! empty($conf->label->enabled);
+$tabcond[31]= ! empty($conf->accounting->enabled);
+$tabcond[32]= ! empty($conf->accounting->enabled);
+$tabcond[33]= ! empty($conf->hrm->enabled);
+$tabcond[34]= ! empty($conf->hrm->enabled);
 
 // List of help for fields
 $tabhelp=array();
@@ -408,9 +446,13 @@ $tabhelp[24] = array('code'=>$langs->trans("EnterAnyCode"));
 $tabhelp[25] = array('topic'=>$langs->trans('SeeSubstitutionVars'),'content'=>$langs->trans('SeeSubstitutionVars'),'type_template'=>$langs->trans("TemplateForElement"),'private'=>$langs->trans("TemplateIsVisibleByOwnerOnly"), 'position'=>$langs->trans("PositionIntoComboList"));
 $tabhelp[26] = array('code'=>$langs->trans("EnterAnyCode"));
 $tabhelp[27] = array('code'=>$langs->trans("EnterAnyCode"));
-$tabhelp[28] = array('affect'=>$langs->trans("FollowedByACounter"),'delay'=>$langs->trans("MinimumNoticePeriod"), 'newByMonth'=>$langs->trans("NbAddedAutomatically"));
+$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"));
+$tabhelp[33] = array('code'=>$langs->trans("EnterAnyCode"));
+$tabhelp[34] = array('code'=>$langs->trans("EnterAnyCode"));
 
 // List of check for fields (NOT USED YET)
 $tabfieldcheck=array();
@@ -444,6 +486,10 @@ $tabfieldcheck[27] = array();
 $tabfieldcheck[28] = array();
 $tabfieldcheck[29] = array();
 $tabfieldcheck[30] = array();
+$tabfieldcheck[31] = array();
+$tabfieldcheck[32] = array();
+$tabfieldcheck[33] = array();
+$tabfieldcheck[34] = array();
 
 // Complete all arrays with entries found into modules
 complete_dictionary_with_modules($taborder,$tabname,$tablib,$tabsql,$tabsqlsort,$tabfield,$tabfieldvalue,$tabfieldinsert,$tabrowid,$tabcond,$tabhelp,$tabfieldcheck);
@@ -534,7 +580,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify'))
     $ok=1;
     foreach ($listfield as $f => $value)
     {
-        if ($value == 'country_id' && in_array($tablib[$id],array('DictionaryVAT','DictionaryRegion','DictionaryCompanyType','DictionaryHolidayTypes','DictionaryRevenueStamp'))) continue;		// For some pages, country is not mandatory
+        if ($value == 'country_id' && in_array($tablib[$id],array('DictionaryVAT','DictionaryRegion','DictionaryCompanyType','DictionaryHolidayTypes','DictionaryRevenueStamp','DictionaryAccountancysystem','DictionaryAccountancyCategory'))) continue;		// For some pages, country is not mandatory
     	if ($value == 'country' && in_array($tablib[$id],array('DictionaryCanton','DictionaryCompanyType','DictionaryRevenueStamp'))) continue;		// For some pages, country is not mandatory
         if ($value == 'localtax1' && empty($_POST['localtax1_type'])) continue;
         if ($value == 'localtax2' && empty($_POST['localtax2_type'])) continue;
@@ -952,6 +998,7 @@ if ($id)
             if ($fieldlist[$field]=='sortorder')       { $valuetoshow=$langs->trans("SortOrder"); }
 	        if ($fieldlist[$field]=='short_label')     { $valuetoshow=$langs->trans("ShortLabel"); }
             if ($fieldlist[$field]=='type_template')   { $valuetoshow=$langs->trans("TypeOfTemplate"); }
+			if ($fieldlist[$field]=='range_account')   { $valuetoshow=$langs->trans("Range"); }
 
             if ($id == 2)	// Special cas for state page
             {
@@ -1119,6 +1166,7 @@ if ($id)
                 if ($fieldlist[$field]=='sortorder')       { $valuetoshow=$langs->trans("SortOrder"); }
 	            if ($fieldlist[$field]=='short_label')     { $valuetoshow=$langs->trans("ShortLabel"); }
             	if ($fieldlist[$field]=='type_template')   { $valuetoshow=$langs->trans("TypeOfTemplate"); }
+				if ($fieldlist[$field]=='range_account')   { $valuetoshow=$langs->trans("Range"); }
 
                 // Affiche nom du champ
                 if ($showfield)
@@ -1341,8 +1389,10 @@ if ($id)
                                 $valuetoshow = length_accountg($valuetoshow);
                             }
 
+                            $class='tddict';
+                            if ($fieldlist[$field] == 'tracking') $class.=' tdoverflowauto';
 							// Show value for field
-							if ($showfield) print '<td align="'.$align.'">'.$valuetoshow.'</td>';
+							if ($showfield) print '<!-- '.$fieldlist[$field].' --><td align="'.$align.'" class="'.$class.'">'.$valuetoshow.'</td>';
                         }
                     }
 
@@ -1642,13 +1692,13 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='')
 		else
 		{
 			print '<td>';
-			$size='';
+			$size=''; $class='';
 			if ($fieldlist[$field]=='code') $size='size="8" ';
 			if ($fieldlist[$field]=='position') $size='size="4" ';
-			if ($fieldlist[$field]=='libelle') $size='size="32" ';
-			if ($fieldlist[$field]=='tracking') $size='size="92" ';
+			if ($fieldlist[$field]=='libelle') $size='centpercent';
+			if ($fieldlist[$field]=='tracking') $class='centpercent';
 			if ($fieldlist[$field]=='sortorder') $size='size="2" ';
-			print '<input type="text" '.$size.' class="flat" value="'.(isset($obj->{$fieldlist[$field]})?$obj->{$fieldlist[$field]}:'').'" name="'.$fieldlist[$field].'">';
+			print '<input type="text" '.$size.' class="flat'.($class?' '.$class:'').'" value="'.(isset($obj->{$fieldlist[$field]})?$obj->{$fieldlist[$field]}:'').'" name="'.$fieldlist[$field].'">';
 			print '</td>';
 		}
 	}

+ 5 - 5
htdocs/admin/facture.php

@@ -262,11 +262,11 @@ if ($action == 'setforcedate')
     }
 }
 
-if ($action == 'set_FAC_AUTO_FILLJS')
+if ($action == 'set_INVOICE_AUTO_FILLJS')
 {
-	$freetext = GETPOST('FAC_AUTO_FILLJS');	// No alpha here, we want exact string
+	$freetext = GETPOST('INVOICE_AUTO_FILLJS');	// No alpha here, we want exact string
 
-	$res = dolibarr_set_const($db, "FAC_AUTO_FILLJS",$freetext,'chaine',0,'',$conf->entity);
+	$res = dolibarr_set_const($db, "INVOICE_AUTO_FILLJS",$freetext,'chaine',0,'',$conf->entity);
 
 	if (! $res > 0) $error++;
 
@@ -754,11 +754,11 @@ print '</form>';
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
-print '<input type="hidden" name="action" value="set_FAC_AUTO_FILLJS" />';
+print '<input type="hidden" name="action" value="set_INVOICE_AUTO_FILLJS" />';
 print '<tr '.$bc[$var].'><td>';
 print $langs->trans("JSOnPaimentBill");
 print '</td><td width="60" align="center">';
-print $form->selectyesno("FAC_AUTO_FILLJS",$conf->global->FAC_AUTO_FILLJS,1);
+print $form->selectyesno("INVOICE_AUTO_FILLJS",$conf->global->INVOICE_AUTO_FILLJS,1);
 print '</td><td align="right">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'" />';
 print "</td></tr>\n";

+ 236 - 32
htdocs/admin/modules.php

@@ -41,6 +41,7 @@ $page_y=GETPOST('page_y','int');
 $search_keyword=GETPOST('search_keyword','alpha');
 $search_status=GETPOST('search_status','alpha');
 $search_nature=GETPOST('search_nature','alpha');
+$search_version=GETPOST('search_version','alpha');
 
 if (! $user->admin)
 	accessforbidden();
@@ -64,8 +65,9 @@ $familyinfo=array(
 
 $param='';
 if ($search_keyword) $param.='&search_keyword='.urlencode($search_keyword);
-if ($search_status) $param.='&search_status='.urlencode($search_status);
-if ($search_nature) $param.='&search_nature='.urlencode($search_nature);
+if ($search_status)  $param.='&search_status='.urlencode($search_status);
+if ($search_nature)  $param.='&search_nature='.urlencode($search_nature);
+if ($search_version) $param.='&search_version='.urlencode($search_version);
 
 
 
@@ -94,6 +96,7 @@ if (GETPOST('buttonreset'))
     $search_keyword='';
     $search_status='';
     $search_nature='';
+    $search_version='';
 }
 
 
@@ -109,6 +112,7 @@ $_SESSION["mode"]=$mode;
 $help_url='EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones';
 llxHeader('',$langs->trans("Setup"),$help_url);
 
+$arrayofnatures=array('core'=>$langs->transnoentitiesnoconv("Core"), 'external'=>$langs->transnoentitiesnoconv("External").' - '.$langs->trans("AllPublishers"));
 
 // Search modules dirs
 $modulesdir = dolGetModulesDirs();
@@ -170,11 +174,30 @@ foreach ($modulesdir as $dir)
 		    					if ($objMod->version == 'development'  && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 2))) $modulequalified=0;
 		    					if ($objMod->version == 'experimental' && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 1))) $modulequalified=0;
 								if (preg_match('/deprecated/', $objMod->version) && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL >= 0))) $modulequalified=0;
+
 		    					// We discard modules according to property disabled
-		    					if (! empty($objMod->hidden)) $modulequalified=false;
+		    					if (! empty($objMod->hidden)) $modulequalified=0;
 
+		    					if ($modulequalified > 0)
+		    					{
+		    					    $publisher=dol_escape_htmltag($objMod->getPublisher());
+		    					    $external=($objMod->isCoreOrExternalModule() == 'external');
+		    					    if ($external)
+		    					    {
+		    					        if ($publisher)
+		    					        {
+		    					            $arrayofnatures['external_'.$publisher]=$langs->trans("External").' - '.$publisher;
+		    					        }
+		    					        else
+		    					        {
+		    					            $arrayofnatures['external_']=$langs->trans("External").' - '.$langs->trans("UnknownPublishers");
+		    					        }
+		    					    }
+		    					    ksort($arrayofnatures);
+		    					}
+		    					
 		    					// Define array $categ with categ with at least one qualified module
-		    					if ($modulequalified)
+		    					if ($modulequalified > 0)
 		    					{
 		    						$modules[$i] = $objMod;
 		    			            $filename[$i]= $modName;
@@ -199,6 +222,7 @@ foreach ($modulesdir as $dir)
 
 		    			            $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>';
 		    			            // Set categ[$i]
 		    						$specialstring = isset($specialtostring[$special])?$specialtostring[$special]:'unknown';
 		    			            if ($objMod->version == 'development' || $objMod->version == 'experimental') $specialstring='expdev';
@@ -254,15 +278,15 @@ if ($mode==='expdev')      print $langs->trans("ModuleFamilyExperimental")."<br>
 $h = 0;
 
 $categidx='common';    // Main
-if (! empty($categ[$categidx]))
-{
+//if (! empty($categ[$categidx]))
+//{
 	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
 	$head[$h][1] = $langs->trans("AvailableModules");
 	$head[$h][2] = 'common';
 	$h++;
-}
+//}
 
-$categidx='expdev';
+/*$categidx='expdev';
 if (! empty($categ[$categidx]))
 {
 	$categidx='expdev';
@@ -270,7 +294,7 @@ if (! empty($categ[$categidx]))
     $head[$h][1] = $form->textwithpicto($langs->trans("ModuleFamilyExperimental"), $langs->trans('DoNotUseInProduction'), 1, 'warning', '', 0, 3);
     $head[$h][2] = 'expdev';
     $h++;
-}
+}*/
 
 $categidx='marketplace';
 $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
@@ -299,10 +323,20 @@ if ($mode != 'marketplace')
     $moreforfilter.= $langs->trans('Keyword') . ': <input type="text" name="search_keyword" value="'.dol_escape_htmltag($search_keyword).'">';
     $moreforfilter.= '</div>';
     $moreforfilter.='<div class="divsearchfield">';
-    $moreforfilter.= $langs->trans('Status') . ': '.$form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, 1);
+    $moreforfilter.= $langs->trans('Origin') . ': '.$form->selectarray('search_nature', $arrayofnatures, $search_nature, 1);
     $moreforfilter.= '</div>';
+    if (! empty($conf->global->MAIN_FEATURES_LEVEL))
+    {
+        $array_version = array('stable'=>$langs->transnoentitiesnoconv("Stable"));
+        if ($conf->global->MAIN_FEATURES_LEVEL < 0) $array_version['deprecated']=$langs->trans("Deprecated");
+        if ($conf->global->MAIN_FEATURES_LEVEL > 0) $array_version['experimental']=$langs->trans("Experimental");
+        if ($conf->global->MAIN_FEATURES_LEVEL > 1) $array_version['development']=$langs->trans("Development");
+        $moreforfilter.='<div class="divsearchfield">';
+        $moreforfilter.= $langs->trans('Version') . ': '.$form->selectarray('search_version', $array_version, $search_version, 1);
+        $moreforfilter.= '</div>';
+    }
     $moreforfilter.='<div class="divsearchfield">';
-    $moreforfilter.= $langs->trans('Nature') . ': '.$form->selectarray('search_nature', array('standard'=>$langs->transnoentitiesnoconv("Standard"), 'external'=>$langs->transnoentitiesnoconv("External")), $search_nature, 1);
+    $moreforfilter.= $langs->trans('Status') . ': '.$form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, 1);
     $moreforfilter.= '</div>';
     $moreforfilter.=' ';
     $moreforfilter.='<div class="divsearchfield">';
@@ -337,7 +371,8 @@ if ($mode != 'marketplace')
 
         $modName = $filename[$key];
     	$objMod  = $modules[$key];
-
+    	$dirofmodule = $dirmod[$key];
+    	 
     	$special = $objMod->special;
 
     	//print $objMod->name." - ".$key." - ".$objMod->special.' - '.$objMod->version."<br>";
@@ -358,6 +393,8 @@ if ($mode != 'marketplace')
         $moduledesc=$objMod->getDesc();
         $moduledesclong=$objMod->getDescLong();
         $moduleauthor=$objMod->getPublisher();
+
+        // We discard showing according to filters
         if ($search_keyword)
         {
             $qualified=0;
@@ -375,8 +412,22 @@ if ($mode != 'marketplace')
         }
         if ($search_nature)
         {
-            if ($search_nature == 'external' && $objMod->isCoreOrExternalModule() != 'external') continue;
-            if ($search_nature == 'standard' && $objMod->isCoreOrExternalModule() == 'external') continue;
+            if (preg_match('/^external/',$search_nature) && $objMod->isCoreOrExternalModule() != 'external') continue;
+            if (preg_match('/^external_(.*)$/',$search_nature, $reg))
+            {
+                //print $reg[1].'-'.dol_escape_htmltag($objMod->getPublisher());
+                $publisher=dol_escape_htmltag($objMod->getPublisher());
+                if ($reg[1] && $reg[1] != $publisher) continue;
+                if (! $reg[1] && ! empty($publisher)) continue;
+            }
+            if ($search_nature == 'core' && $objMod->isCoreOrExternalModule() == 'external') continue;
+        }
+        if ($search_version)
+        {
+            if (($objMod->version == 'development' || $objMod->version == 'experimental' || preg_match('/deprecated/', $objMod->version)) && $search_version == 'stable') continue;
+            if ($objMod->version != 'development'  && ($search_version == 'development')) continue;
+            if ($objMod->version != 'experimental' && ($search_version == 'experimental')) continue;
+            if (! preg_match('/deprecated/', $objMod->version) && ($search_version == 'deprecated')) continue;
         }
 
         // Load all lang files of module
@@ -394,7 +445,7 @@ if ($mode != 'marketplace')
         if ($familykey!=$oldfamily)
         {
             print '<tr class="liste_titre">'."\n";
-            print '<td colspan="5">';
+            print '<td colspan="6">';
             $familytext=empty($familyinfo[$familykey]['label'])?$familykey:$familyinfo[$familykey]['label'];
             print $familytext;
             print "</td>\n";
@@ -442,18 +493,171 @@ if ($mode != 'marketplace')
         print nl2br($objMod->getDesc());
         print "</td>\n";
 
-        // Version
-        print '<td align="center" valign="top" class="nowrap">';
-        $version=$objMod->getVersion();
-        $dirofmodule=$dirmod[$key];
+        // Help
+        print '<td align="center" valign="top" class="nowrap" style="width: 82px;">';
+        $text='';
+        if ($objMod->getDescLong()) $text.=$objMod->getDesc().'<br>'.$objMod->getDescLong().'<br>';
+        else $text.=$objMod->getDesc().'<br>';
+        
+        $textexternal='';
         if ($objMod->isCoreOrExternalModule() == 'external')
         {
-        	$text=$langs->trans("ExternalModule",$dirofmodule);
-        	if (! empty($objMod->editor_name) && $objMod->editor_name != 'dolibarr') $text.=' - '.$objMod->editor_name;
-        	if (! empty($objMod->editor_web) && $objMod->editor_web != 'www.dolibarr.org') $text.=' - '.$objMod->editor_web;
-        	print $form->textwithpicto($version, $text, 1, 'help');
+            $textexternal.='<br><strong>'.$langs->trans("Origin").':</strong> '.$langs->trans("ExternalModule",$dirofmodule);
+            if ($objMod->editor_name != 'dolibarr') $textexternal.='<br><strong>'.$langs->trans("Publisher").':</strong> '.(empty($objMod->editor_name)?$langs->trans("Unknown"):$objMod->editor_name);
+            if (! empty($objMod->editor_url) && ! preg_match('/dolibarr\.org/i',$objMod->editor_url)) $textexternal.='<br><strong>'.$langs->trans("Url").':</strong> '.$objMod->editor_url;
+            $text.=$textexternal;
+            $text.='<br>';
+        }
+        else
+        {
+            $text.='<br><strong>'.$langs->trans("Origin").':</strong> '.$langs->trans("Core").'<br>';
+        }
+        $text.='<br><strong>'.$langs->trans("AddRemoveTabs").':</strong> ';
+        if (isset($objMod->tabs) && is_array($objMod->tabs) && count($objMod->tabs))
+        {
+            $i=0;
+            foreach($objMod->tabs as $val)
+            {
+                $tmp=explode(':',$val,3);
+                $text.=($i?', ':'').$tmp[0].':'.$tmp[1];
+                $i++;
+            }
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddDictionaries").':</strong> ';
+        if (isset($objMod->dictionaries) && isset($objMod->dictionaries['tablib']) && is_array($objMod->dictionaries['tablib']) && count($objMod->dictionaries['tablib']))
+        {
+            $i=0;
+            foreach($objMod->dictionaries['tablib'] as $val)
+            {
+                $text.=($i?', ':'').$val;
+                $i++;
+            }
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddBoxes").':</strong> ';
+        if (isset($objMod->boxes) && is_array($objMod->boxes) && count($objMod->boxes))
+        {
+            $i=0;
+            foreach($objMod->boxes as $val)
+            {
+                $text.=($i?', ':'').($val['file']?$val['file']:$val[0]);
+                $i++;
+            }
         }
-        else print $version;
+        else $text.=$langs->trans("No");
+
+        $text.='<br><strong>'.$langs->trans("AddModels").':</strong> ';
+        if (isset($objMod->module_parts) && isset($objMod->module_parts['models']) && $objMod->module_parts['models'])
+        {
+            $text.=$langs->trans("Yes");
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddSubstitutions").':</strong> ';
+        if (isset($objMod->module_parts) && isset($objMod->module_parts['substitutions']) && $objMod->module_parts['substitutions'])
+        {
+            $text.=$langs->trans("Yes");
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddSheduledJobs").':</strong> ';
+        if (isset($objMod->cronjobs) && is_array($objMod->cronjobs) && count($objMod->cronjobs))
+        {
+            $i=0;
+            foreach($objMod->cronjobs as $val)
+            {
+                $text.=($i?', ':'').($val['label']);
+                $i++;
+            }
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddTriggers").':</strong> ';
+        if (isset($objMod->module_parts) && isset($objMod->module_parts['triggers']) && $objMod->module_parts['triggers'])
+        {
+            $text.=$langs->trans("Yes");
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddHooks").':</strong> ';
+        if (isset($objMod->module_parts) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks']))
+        {
+            $i=0;
+            foreach($objMod->module_parts['hooks'] as $val)
+            {
+                $text.=($i?', ':'').($val);
+                $i++;
+            }
+        }
+        else $text.=$langs->trans("No");
+
+        $text.='<br><strong>'.$langs->trans("AddPermissions").':</strong> ';
+        if (isset($objMod->rights) && is_array($objMod->rights) && count($objMod->rights))
+        {
+            $i=0;
+            foreach($objMod->rights as $val)
+            {
+                $text.=($i?', ':'').($val[1]);
+                $i++;
+            }
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddMenus").':</strong> ';
+        if (isset($objMod->menu) && is_array($objMod->menu) && $objMod->menu)
+        {
+            $text.=$langs->trans("Yes");
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddExportProfiles").':</strong> ';
+        if (isset($objMod->export_label) && is_array($objMod->export_label) && count($objMod->export_label))
+        {
+            $i=0;
+            foreach($objMod->export_label as $val)
+            {
+                $text.=($i?', ':'').($val);
+                $i++;
+            }
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddImportProfiles").':</strong> ';
+        if (isset($objMod->import_label) && is_array($objMod->import_label) && count($objMod->import_label))
+        {
+            $i=0;
+            foreach($objMod->import_label as $val)
+            {
+                $text.=($i?', ':'').($val);
+                $i++;
+            }
+        }
+        else $text.=$langs->trans("No");
+        
+        $text.='<br><strong>'.$langs->trans("AddOtherPagesOrServices").':</strong> ';
+        $text.=$langs->trans("DetectionNotPossible");
+        
+        print $form->textwithpicto('', $text, 1, 'help', 'minheight20');
+
+        // Picto warning 
+        $version=$objMod->getVersion(0);
+        $versiontrans=$objMod->getVersion(1);
+        if (preg_match('/development/i', $version))  print img_warning($langs->trans("Development"), 'style="float: right"');
+        if (preg_match('/experimental/i', $version)) print img_warning($langs->trans("Experimental"), 'style="float: right"');
+        if (preg_match('/deprecated/i', $version))   print img_warning($langs->trans("Deprecated"), 'style="float: right"');
+        
+        // Picto external
+        if ($textexternal) print img_picto($langs->trans("ExternalModule",$dirofmodule), 'external', 'style="float: right"');
+        
+        
+        print '</td>';
+        
+        // Version
+        print '<td align="center" valign="top" class="nowrap">';
+        print $versiontrans;
         print "</td>\n";
 
         // Activate/Disable and Setup (2 columns)
@@ -484,25 +688,25 @@ if ($mode != 'marketplace')
         	{
         		if (is_array($objMod->config_page_url))
         		{
-        			print '  <td align="right" valign="top">';
+        			print '<td class="tdsetuppicto" align="right" valign="top">';
         			$i=0;
         			foreach ($objMod->config_page_url as $page)
         			{
         				$urlpage=$page;
         				if ($i++)
         				{
-        					print '<a href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(ucfirst($page),"setup").'</a>&nbsp;';
+        					print '<a href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(ucfirst($page),"setup").'</a>';
         					//    print '<a href="'.$page.'">'.ucfirst($page).'</a>&nbsp;';
         				}
         				else
         				{
         					if (preg_match('/^([^@]+)@([^@]+)$/i',$urlpage,$regs))
         					{
-        						print '<a href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1],1).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup").'</a>&nbsp;';
+        						print '<a href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1],1).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a>';
         					}
         					else
         					{
-        						print '<a href="'.$urlpage.'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup").'</a>&nbsp;';
+        						print '<a href="'.$urlpage.'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a>';
         					}
         				}
         			}
@@ -510,16 +714,16 @@ if ($mode != 'marketplace')
         		}
         		else if (preg_match('/^([^@]+)@([^@]+)$/i',$objMod->config_page_url,$regs))
         		{
-        			print '<td align="right" valign="middle"><a href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1],1).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup").'</a></td>';
+        			print '<td class="tdsetuppicto" align="right" valign="middle"><a href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1],1).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a></td>';
         		}
         		else
         		{
-        			print '<td align="right" valign="middle"><a href="'.$objMod->config_page_url.'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup").'</a></td>';
+        			print '<td class="tdsetuppicto" align="right" valign="middle"><a href="'.$objMod->config_page_url.'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a></td>';
         		}
         	}
         	else
         	{
-        		print "<td>&nbsp;</td>";
+        		print '<td class="tdsetuppicto" align="right" valign="middle">'.img_picto($langs->trans("NothingToSetup"),"setup",'class="opacitytransp" style="padding-right: 6px"').'</td>';
         	}
 
         }
@@ -542,7 +746,7 @@ if ($mode != 'marketplace')
 	        	print "</a>\n";
         	}
         	print "</td>\n";
-        	print "<td>&nbsp;</td>";
+        	print '<td class="tdsetuppicto" align="right" valign="middle">'.img_picto($langs->trans("NothingToSetup"),"setup",'class="opacitytransp" style="padding-right: 6px"').'</td>';
         }
 
         print "</tr>\n";

+ 2 - 3
htdocs/admin/security_file.php

@@ -114,9 +114,8 @@ llxHeader('',$langs->trans("Files"),$wikihelp);
 
 print load_fiche_titre($langs->trans("SecuritySetup"),'','title_setup');
 
-//print $langs->trans("FilesDesc")."<br>\n";
-//print "<br>\n";
-
+print $langs->trans("SecurityFilesDesc")."<br>\n";
+print "<br>\n";
 
 
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';

+ 22 - 214
htdocs/admin/tools/export.php

@@ -25,6 +25,7 @@
 require '../../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
 
 $langs->load("admin");
@@ -111,175 +112,34 @@ $outputdir  = $conf->admin->dir_output.'/backup';
 $result=dol_mkdir($outputdir);
 
 
+$utils = new Utils($db);
+
+
 // MYSQL
 if ($what == 'mysql')
 {
+    
     $cmddump=GETPOST("mysqldump");	// Do not sanitize here with 'alpha', will be sanitize later by escapeshellarg
     if ($cmddump)
     {
         dolibarr_set_const($db, 'SYSTEMTOOLS_MYSQLDUMP', $cmddump,'chaine',0,'',$conf->entity);
     }
 
-    $outputfile = $outputdir.'/'.$file;
-    // for compression format, we add extension
-    $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
-    if ($compression == 'gz') $outputfile.='.gz';
-    if ($compression == 'bz') $outputfile.='.bz2';
-    $outputerror = $outputfile.'.err';
-    dol_mkdir($conf->admin->dir_output.'/backup');
-
-    // Parameteres execution
-    $command=$cmddump;
-    if (preg_match("/\s/",$command)) $command=escapeshellarg($command);	// Use quotes on command
-
-    //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
-    $param=$dolibarr_main_db_name." -h ".$dolibarr_main_db_host;
-    $param.=" -u ".$dolibarr_main_db_user;
-    if (! empty($dolibarr_main_db_port)) $param.=" -P ".$dolibarr_main_db_port;
-    if (! GETPOST("use_transaction"))    $param.=" -l --single-transaction";
-    if (GETPOST("disable_fk"))           $param.=" -K";
-    if (GETPOST("sql_compat") && GETPOST("sql_compat") != 'NONE') $param.=" --compatible=".escapeshellarg(GETPOST("sql_compat","alpha"));
-    if (GETPOST("drop_database"))        $param.=" --add-drop-database";
-    if (GETPOST("sql_structure"))
-    {
-        if (GETPOST("drop"))			$param.=" --add-drop-table=TRUE";
-        else 							$param.=" --add-drop-table=FALSE";
-    }
-    else
-    {
-        $param.=" -t";
-    }
-    if (GETPOST("disable-add-locks")) $param.=" --add-locks=FALSE";
-    if (GETPOST("sql_data"))
-    {
-        $param.=" --tables";
-        if (GETPOST("showcolumns"))	 $param.=" -c";
-        if (GETPOST("extended_ins")) $param.=" -e";
-        else $param.=" --skip-extended-insert";
-        if (GETPOST("delayed"))	 	 $param.=" --delayed-insert";
-        if (GETPOST("sql_ignore"))	 $param.=" --insert-ignore";
-        if (GETPOST("hexforbinary")) $param.=" --hex-blob";
-    }
-    else
-    {
-        $param.=" -d";    // No row information (no data)
-    }
-    $param.=" --default-character-set=utf8";    // We always save output into utf8 charset
-    $paramcrypted=$param;
-    $paramclear=$param;
-    if (! empty($dolibarr_main_db_pass))
-    {
-        $paramcrypted.=' -p"'.preg_replace('/./i','*',$dolibarr_main_db_pass).'"';
-        $paramclear.=' -p"'.str_replace(array('"','`'),array('\"','\`'),$dolibarr_main_db_pass).'"';
-    }
-
-    $_SESSION["commandbackuplastdone"]=$command." ".$paramcrypted;
-    $_SESSION["commandbackuptorun"]="";
-    /*
-    print '<b>'.$langs->trans("RunCommandSummary").':</b><br>'."\n";
-    print '<textarea rows="'.ROWS_2.'" cols="120">'.$command." ".$paramcrypted.'</textarea><br>'."\n";
-    print '<br>';
-
-    //print $paramclear;
-
-    // Now run command and show result
-    print '<b>'.$langs->trans("BackupResult").':</b> ';
-	*/
-
-    $errormsg='';
-
-    // Debut appel methode execution
-    $fullcommandcrypted=$command." ".$paramcrypted." 2>&1";
-    $fullcommandclear=$command." ".$paramclear." 2>&1";
-    if ($compression == 'none') $handle = fopen($outputfile, 'w');
-    if ($compression == 'gz')   $handle = gzopen($outputfile, 'w');
-    if ($compression == 'bz')   $handle = bzopen($outputfile, 'w');
-
-    if ($handle)
-    {
-        $ok=0;
-        dol_syslog("Run command ".$fullcommandcrypted);
-        $handlein = popen($fullcommandclear, 'r');
-        $i=0;
-        while (!feof($handlein))
-        {
-            $i++;   // output line number
-            $read = fgets($handlein);
-            if ($i == 1 && preg_match('/'.preg_quote('Warning: Using a password').'/i', $read)) continue;
-            fwrite($handle,$read);
-            if (preg_match('/'.preg_quote('-- Dump completed').'/i',$read)) $ok=1;
-            elseif (preg_match('/'.preg_quote('SET SQL_NOTES=@OLD_SQL_NOTES').'/i',$read)) $ok=1;
-        }
-        pclose($handlein);
-
-        if ($compression == 'none') fclose($handle);
-        if ($compression == 'gz')   gzclose($handle);
-        if ($compression == 'bz')   bzclose($handle);
-
-        if (! empty($conf->global->MAIN_UMASK))
-        @chmod($outputfile, octdec($conf->global->MAIN_UMASK));
-    }
-    else
-    {
-        $langs->load("errors");
-        dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
-        $errormsg=$langs->trans("ErrorFailedToWriteInDir");
-    }
-
-    // Get errorstring
-    if ($compression == 'none') $handle = fopen($outputfile, 'r');
-    if ($compression == 'gz')   $handle = gzopen($outputfile, 'r');
-    if ($compression == 'bz')   $handle = bzopen($outputfile, 'r');
-    if ($handle)
-    {
-        // Get 2048 first chars of error message.
-        $errormsg = fgets($handle,2048);
-        // Close file
-        if ($compression == 'none') fclose($handle);
-        if ($compression == 'gz')   gzclose($handle);
-        if ($compression == 'bz')   bzclose($handle);
-        if ($ok && preg_match('/^-- MySql/i',$errormsg)) $errormsg='';	// Pas erreur
-        else
-        {
-            // Renommer fichier sortie en fichier erreur
-            //print "$outputfile -> $outputerror";
-            @dol_delete_file($outputerror,1);
-            @rename($outputfile,$outputerror);
-            // Si safe_mode on et command hors du parametre exec, on a un fichier out vide donc errormsg vide
-            if (! $errormsg)
-            {
-            	$langs->load("errors");
-            	$errormsg=$langs->trans("ErrorFailedToRunExternalCommand");
-            }
-        }
-    }
-    // Fin execution commande
+    $utils->dumpDatabase(GETPOST('compression','alpha'), $what, 0, $file);
+    
+    $errormsg=$utils->error;
+    $_SESSION["commandbackuplastdone"]=$utils->result['commandbackuplastdone'];
+    $_SESSION["commandbackuptorun"]=$utils->result['commandbackuptorun'];
 }
 
+// MYSQL NO BIN
 if ($what == 'mysqlnobin')
 {
-    $outputfile = $outputdir.'/'.$file;
-    $outputfiletemp = $outputfile.'-TMP.sql';
-    // for compression format, we add extension
-    $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
-    if ($compression == 'gz') $outputfile.='.gz';
-    if ($compression == 'bz') $outputfile.='.bz2';
-    $outputerror = $outputfile.'.err';
-    dol_mkdir($conf->admin->dir_output.'/backup');
-
-    if ($compression == 'gz' or $compression == 'bz')
-    {
-        backup_tables($outputfiletemp);
-        dol_compress_file($outputfiletemp, $outputfile, $compression);
-        unlink($outputfiletemp);
-    }
-    else
-    {
-        backup_tables($outputfile);
-    }
+    $utils->dumpDatabase(GETPOST('compression','alpha'), $what, 0, $file);
 
-    $_SESSION["commandbackuplastdone"]="";
-    $_SESSION["commandbackuptorun"]="";
+    $errormsg=$utils->error;
+    $_SESSION["commandbackuplastdone"]=$utils->result['commandbackuplastdone'];
+    $_SESSION["commandbackuptorun"]=$utils->result['commandbackuptorun'];
 }
 
 // POSTGRESQL
@@ -291,65 +151,13 @@ if ($what == 'postgresql')
         dolibarr_set_const($db, 'SYSTEMTOOLS_POSTGRESQLDUMP', $cmddump,'chaine',0,'',$conf->entity);
     }
 
-    $outputfile = $outputdir.'/'.$file;
-    // for compression format, we add extension
-    $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
-    if ($compression == 'gz') $outputfile.='.gz';
-    if ($compression == 'bz') $outputfile.='.bz2';
-    $outputerror = $outputfile.'.err';
-    dol_mkdir($conf->admin->dir_output.'/backup');
-
-    // Parameteres execution
-    $command=$cmddump;
-    if (preg_match("/\s/",$command)) $command=escapeshellarg($command);	// Use quotes on command
-
-    //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
-    //$param="-F c";
-    $param="-F p";
-    $param.=" --no-tablespaces --inserts -h ".$dolibarr_main_db_host;
-    $param.=" -U ".$dolibarr_main_db_user;
-    if (! empty($dolibarr_main_db_port)) $param.=" -p ".$dolibarr_main_db_port;
-    if (GETPOST("sql_compat") && GETPOST("sql_compat") == 'ANSI') $param.="  --disable-dollar-quoting";
-    if (GETPOST("drop_database"))        $param.=" -c -C";
-    if (GETPOST("sql_structure"))
-    {
-        if (GETPOST("drop"))			 $param.=" --add-drop-table";
-        if (! GETPOST("sql_data"))       $param.=" -s";
-    }
-    if (GETPOST("sql_data"))
-    {
-        if (! GETPOST("sql_structure"))	 $param.=" -a";
-        if (GETPOST("showcolumns"))	     $param.=" -c";
-    }
-    $param.=' -f "'.$outputfile.'"';
-    //if ($compression == 'none')
-    if ($compression == 'gz')   $param.=' -Z 9';
-    //if ($compression == 'bz')
-    $paramcrypted=$param;
-    $paramclear=$param;
-    /*if (! empty($dolibarr_main_db_pass))
-     {
-    $paramcrypted.=" -W".preg_replace('/./i','*',$dolibarr_main_db_pass);
-    $paramclear.=" -W".$dolibarr_main_db_pass;
-    }*/
-    $paramcrypted.=" -w ".$dolibarr_main_db_name;
-    $paramclear.=" -w ".$dolibarr_main_db_name;
-
-    $_SESSION["commandbackuplastdone"]="";
-    $_SESSION["commandbackuptorun"]=$command." ".$paramcrypted;
-    /*print $langs->trans("RunCommandSummaryToLaunch").':<br>'."\n";
-    print '<textarea rows="'.ROWS_3.'" cols="120">'.$command." ".$paramcrypted.'</textarea><br>'."\n";
-
-    print '<br>';
-
-
-    // Now show to ask to run command
-    print $langs->trans("YouMustRunCommandFromCommandLineAfterLoginToUser",$dolibarr_main_db_user,$dolibarr_main_db_user);
-
-    print '<br>';
-    print '<br>';*/
-
-    $what='';
+    $utils->dumpDatabase(GETPOST('compression','alpha'), $what, 0, $file);
+    
+    $errormsg=$utils->error;
+    $_SESSION["commandbackuplastdone"]=$utils->result['commandbackuplastdone'];
+    $_SESSION["commandbackuptorun"]=$utils->result['commandbackuptorun'];
+
+    $what='';   // Clear to show message to run command
 }
 
 

+ 1 - 1
htdocs/admin/tools/index.php

@@ -40,7 +40,7 @@ $form = new Form($db);
 $title=$langs->trans("SystemToolsArea");
 if (GETPOST('leftmenu') == 'admintools') $title=$langs->trans("ModulesSystemTools");
 
-llxHeader(array(),$title);
+llxHeader('', $title);
 
 print load_fiche_titre($title,'','title_setup');
 

+ 35 - 21
htdocs/admin/tools/listevents.php

@@ -61,11 +61,13 @@ $search_user = GETPOST("search_user");
 $search_desc = GETPOST("search_desc");
 $search_ua   = GETPOST("search_ua");
 
-$date_start=dol_mktime(0,0,0,$_REQUEST["date_startmonth"],$_REQUEST["date_startday"],$_REQUEST["date_startyear"]);
-$date_end=dol_mktime(23,59,59,$_REQUEST["date_endmonth"],$_REQUEST["date_endday"],$_REQUEST["date_endyear"]);
+if (!isset($_REQUEST["date_startmonth"]) || $_REQUEST["date_startmonth"] > 0) $date_start=dol_mktime(0,0,0,$_REQUEST["date_startmonth"],$_REQUEST["date_startday"],$_REQUEST["date_startyear"]);
+else $date_start=-1;
+if (!isset($_REQUEST["date_endmonth"]) || $_REQUEST["date_endmonth"] > 0) $date_end=dol_mktime(23,59,59,$_REQUEST["date_endmonth"],$_REQUEST["date_endday"],$_REQUEST["date_endyear"]);
+else $date_end=-1;
 
 // checks:if date_start>date_end  then date_end=date_start + 24 hours
-if ($date_start > $date_end) $date_end=$date_start+86400;
+if ($date_start > 0 && $date_end > 0 && $date_start > $date_end) $date_end=$date_start+86400;
 
 $now = dol_now();
 $nowarray = dol_getdate($now);
@@ -94,6 +96,18 @@ if (empty($date_end))
 
 $now=dol_now();
 
+// Purge search criteria
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
+{
+    $date_start=-1;
+    $date_end=-1;
+    $search_code='';
+    $search_ip='';
+    $search_user='';
+    $search_desc='';
+    $search_ua='';
+}
+
 // Purge audit events
 if ($action == 'confirm_purge' && $confirm == 'yes' && $user->admin)
 {
@@ -152,12 +166,13 @@ $sql.= " u.login";
 $sql.= " FROM ".MAIN_DB_PREFIX."events as e";
 $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON u.rowid = e.fk_user";
 $sql.= " WHERE e.entity IN (".getEntity('actioncomm', 1).")";
-$sql.= " AND e.dateevent >= '".$db->idate($date_start)."' AND e.dateevent <= '".$db->idate($date_end)."'";
-if ($search_code) { $usefilter++; $sql.=" AND e.type LIKE '%".$db->escape($search_code)."%'"; }
-if ($search_ip)   { $usefilter++; $sql.=" AND e.ip LIKE '%".$db->escape($search_ip)."%'"; }
-if ($search_user) { $usefilter++; $sql.=" AND u.login LIKE '%".$db->escape($search_user)."%'"; }
-if ($search_desc) { $usefilter++; $sql.=" AND e.description LIKE '%".$db->escape($search_desc)."%'"; }
-if ($search_ua)   { $usefilter++; $sql.=" AND e.user_agent LIKE '%".$db->escape($search_ua)."%'"; }
+if ($date_start > 0) $sql.= " AND e.dateevent >= '".$db->idate($date_start)."'";
+if ($date_end > 0)   $sql.= " AND e.dateevent <= '".$db->idate($date_end)."'";
+if ($search_code) { $usefilter++; $sql.=natural_search("e.type", $search_code, 0); }
+if ($search_ip)   { $usefilter++; $sql.=natural_search("e.ip", $search_ip, 0); }
+if ($search_user) { $usefilter++; $sql.=natural_search("u.login", $search_user, 0); }
+if ($search_desc) { $usefilter++; $sql.=natural_search("e.description", $search_desc, 0); }
+if ($search_ua)   { $usefilter++; $sql.=natural_search("e.user_agent", $search_ua, 0); }
 $sql.= $db->order($sortfield,$sortorder);
 $sql.= $db->plimit($conf->liste_limit+1, $offset);
 //print $sql;
@@ -169,13 +184,18 @@ if ($result)
 
 	$param='';
 	if ($search_code) $param.='&search_code='.$search_code;
-	if ($search_ip) $param.='&search_ip='.$search_ip;
+	if ($search_ip)   $param.='&search_ip='.$search_ip;
 	if ($search_user) $param.='&search_user='.$search_user;
 	if ($search_desc) $param.='&search_desc='.$search_desc;
-	if ($search_ua) $param.='&search_ua='.$search_ua;
+	if ($search_ua)   $param.='&search_ua='.$search_ua;
 
-        $langs->load('withdrawals');
-	print_barre_liste($langs->trans("ListOfSecurityEvents").' : '.$num.' '.strtolower($langs->trans("Lines")), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, 0, 'setup');
+    $langs->load('withdrawals');
+    if ($num)
+    {
+        $center='<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=purge">'.$langs->trans("Purge").'</a>';
+    }
+    
+	print_barre_liste($langs->trans("ListOfSecurityEvents").' ('.$num.')', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $center, $num, 0, 'setup');
 
 	if ($action == 'purge')
 	{
@@ -218,7 +238,8 @@ if ($result)
 	print '</td>';
 
 	print '<td align="right" class="liste_titre">';
-	print '<input type="image" class="liste_titre" src="'.img_picto($langs->trans("Search"),'search.png','','',1).'" name="button_search" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
+	$searchpitco=$form->showFilterAndCheckAddButtons(0);
+	print $searchpitco;
 	print '</td>';
 
 	print "</tr>\n";
@@ -284,13 +305,6 @@ if ($result)
 	}
 	print "</table></form>";
 	$db->free($result);
-
-	if ($num)
-	{
-		print '<div class="tabsAction">';
-		print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=purge">'.$langs->trans("Purge").'</a>';
-		print '</div>';
-	}
 }
 else
 {

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

@@ -40,8 +40,8 @@ if (GETPOST('msg','alpha')) {
 
 
 $urldolibarr='http://www.dolibarr.org/downloads/';
-$urldolibarrmodules='http://www.dolistore.com/';
-$urldolibarrthemes='http://www.dolistore.com/';
+$urldolibarrmodules='https://www.dolistore.com/';
+$urldolibarrthemes='https://www.dolistore.com/';
 $dolibarrroot=preg_replace('/([\\/]+)$/i','',DOL_DOCUMENT_ROOT);
 $dolibarrroot=preg_replace('/([^\\/]+)$/i','',$dolibarrroot);
 $dolibarrdataroot=preg_replace('/([\\/]+)$/i','',DOL_DATA_ROOT);

+ 7 - 1
htdocs/admin/translation.php

@@ -23,6 +23,7 @@
 
 require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
 
 $langs->load("companies");
 $langs->load("products");
@@ -107,6 +108,8 @@ if ($action == 'delete')
  * View
  */
 
+$formadmin = new FormAdmin($db);
+
 $wikihelp='EN:Setup|FR:Paramétrage|ES:Configuración';
 llxHeader('',$langs->trans("Setup"),$wikihelp);
 
@@ -146,7 +149,10 @@ print "</tr>\n";
 $var=false;
 print "\n";
 
-print '<tr '.$bc[$var].'><td><input type="text" class="flat" size="24" name="langcode" value="'.GETPOST('langcode').'"></td>'."\n";
+print '<tr '.$bc[$var].'><td>';
+print $formadmin->select_language(GETPOST('langcode'),'langcode',0,null,1,0,0,'',1);
+//print '<input type="text" class="flat" size="24" name="langcode" value="'.GETPOST('langcode').'">';
+print '</td>'."\n";
 print '<td>';
 print '<input type="text" class="flat" size="30" name="transkey" value="">';
 print '</td><td>';

+ 1 - 1
htdocs/cashdesk/affContenu.php

@@ -59,7 +59,7 @@ exit;*/
 print '<div class="inline-block" style="vertical-align: top">';
 print '<div class="principal">';
 
-$page=GETPOST('menu','alpha');
+$page=GETPOST('menutpl','alpha');
 if (empty($page)) $page='facturation';
 
 if (in_array(

+ 1 - 1
htdocs/cashdesk/affIndex.php

@@ -42,7 +42,7 @@ $langs->load("cashdesk");
  */
 
 //header("Content-type: text/html; charset=UTF-8");
-header("Content-type: text/html; charset=".$conf->file->character_set_client);
+//header("Content-type: text/html; charset=".$conf->file->character_set_client);
 
 $arrayofjs=array();
 $arrayofcss=array('/cashdesk/css/style.css');

+ 25 - 25
htdocs/cashdesk/class/Facturation.class.php

@@ -99,31 +99,24 @@ class Facturation
         $product = new Product($db);
         $product->fetch($this->id);
 
-        $sql = "SELECT taux";
-        $sql.= " FROM ".MAIN_DB_PREFIX."c_tva";
-        $sql.= " WHERE rowid = ".$this->tva();
-
-        dol_syslog("ajoutArticle", LOG_DEBUG);
-        $resql = $db->query($sql);
-
-        if ($resql)
-        {
-            $obj = $db->fetch_object($resql);
-            $vat_rate=$obj->taux;
-            //var_dump($vat_rate);exit;
-        }
-        else
-       {
-            dol_print_error($db);
-        }
-
+        
+        $vatrowid = $this->tva();
+        
+        $tmp = getTaxesFromId($vatrowid);
+        $vat_rate = $tmp['rate'];
+        $vat_npr = $tmp['npr'];
+        
+        $localtaxarray = getLocalTaxesFromRate($vatrowid, 0, $societe, $mysoc, 1);
+        
         // Define part of HT, VAT, TTC
-        $resultarray=calcul_price_total($this->qte,$this->prix(),$this->remisePercent(),$vat_rate,0,0,0,'HT',0,$product->type,$mysoc);
+        $resultarray=calcul_price_total($this->qte, $this->prix(), $this->remisePercent(), $vat_rate, -1, -1, 0, 'HT', $use_npr, $product->type, $mysoc, $localtaxarray);
 
         // Calcul du total ht sans remise
         $total_ht = $resultarray[0];
         $total_vat = $resultarray[1];
         $total_ttc = $resultarray[2];
+        $total_localtax1 = $resultarray[9];
+        $total_localtax2 = $resultarray[10];
 
         // Calcul du montant de la remise
         if ($this->remisePercent())
@@ -143,7 +136,7 @@ class Facturation
         $newcartarray[$i]['label']=$product->label;
         $newcartarray[$i]['price']=$product->price;
         $newcartarray[$i]['price_ttc']=$product->price_ttc;
-
+        
         if (! empty($conf->global->PRODUIT_MULTIPRICES))
         {
             if (isset($product->multiprices[$societe->price_level]))
@@ -160,6 +153,9 @@ class Facturation
         $newcartarray[$i]['remise']=price2num($montant_remise_ht);
         $newcartarray[$i]['total_ht']=price2num($total_ht,'MT');
         $newcartarray[$i]['total_ttc']=price2num($total_ttc,'MT');
+        $newcartarray[$i]['total_vat']=price2num($total_vat, 'MT');
+        $newcartarray[$i]['total_localtax1']=price2num($total_localtax1, 'MT');
+        $newcartarray[$i]['total_localtax2']=price2num($total_localtax2, 'MT');
         $_SESSION['poscart']=$newcartarray;
 
         $this->raz();
@@ -213,12 +209,18 @@ class Facturation
             // Total HT
             $remise = $tab[$i]['remise'];
             $total_ht += ($tab[$i]['total_ht']);
+            $total_vat += ($tab[$i]['total_vat']);
             $total_ttc += ($tab[$i]['total_ttc']);
+            $total_localtax1 += ($tab[$i]['total_localtax1']);
+            $total_localtax2 += ($tab[$i]['total_localtax2']);
         }
 
         $this->prix_total_ttc = $total_ttc;
         $this->prix_total_ht = $total_ht;
-
+        $this->prix_total_vat = $total_vat;
+        $this->prix_total_localtax1 = $total_localtax1;
+        $this->prix_total_localtax2 = $total_localtax2;
+        
         $this->montant_tva = $total_ttc - $total_ht;
         //print $this->prix_total_ttc.'eeee'; exit;
     }
@@ -442,9 +444,8 @@ class Facturation
      * @param	int		$aTva		Vat
      * @return	int					Vat
      */
-    public function tva ( $aTva=null )
+    public function tva($aTva=null)
     {
-
         if ( !$aTva ) {
 
             return $this->tva;
@@ -467,9 +468,8 @@ class Facturation
      * @param string	$aNumFacture		Invoice ref
      * @return	string						Invoice ref
      */
-    public function numInvoice( $aNumFacture=null )
+    public function numInvoice($aNumFacture=null)
     {
-
         if ( !$aNumFacture ) {
 
             return $this->num_facture;

+ 52 - 27
htdocs/cashdesk/facturation_verif.php

@@ -37,7 +37,7 @@ switch ( $_GET['action'] )
 	default:
 		if ( $_POST['hdnSource'] != 'NULL' )
 		{
-			$sql = "SELECT p.rowid, p.ref, p.price, p.tva_tx";
+			$sql = "SELECT p.rowid, p.ref, p.price, p.tva_tx, p.recuperableonly";
 			if (! empty($conf->stock->enabled) && !empty($conf_fkentrepot)) $sql.= ", ps.reel";
 			$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
 			if (! empty($conf->stock->enabled) && !empty($conf_fkentrepot)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON p.rowid = ps.fk_product AND ps.fk_entrepot = ".$conf_fkentrepot;
@@ -66,19 +66,23 @@ switch ( $_GET['action'] )
 					{
 						$ret[$key] = $value;
 					}
-
-					/** add Ditto for MultiPrix*/
-					if (! empty($conf->global->PRODUIT_MULTIPRICES))
+                    // Here $ret['tva_tx'] is vat rate of product but we want to not use the one into table but found by function
+                    
+					$productid = $ret['rowid'];
+					$product = new Product($db);
+                    $product->fetch($productid);
+
+					$thirdpartyid = $_SESSION['CASHDESK_ID_THIRDPARTY'];
+                    $societe = new Societe($db);
+					$societe->fetch($thirdpartyid);
+
+					$tva_tx = get_default_tva($mysoc,$societe,$productid);
+					$tva_npr = get_default_npr($mysoc,$societe,$productid);
+					if (empty($tva_tx)) $tva_npr=0;
+					dol_syslog('tva_tx='.$tva_tx.'-tva_npr='.$tva_npr);
+					
+					if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($societe->price_level))
 					{
-						$thirdpartyid = $_SESSION['CASHDESK_ID_THIRDPARTY'];
-						$productid = $ret['rowid'];
-
-						$societe = new Societe($db);
-						$societe->fetch($thirdpartyid);
-
-						$product = new Product($db);
-                        $product->fetch($productid);
-
 						if(isset($product->multiprices[$societe->price_level]))
 						{
 							$ret['price'] = $product->multiprices[$societe->price_level];
@@ -86,16 +90,39 @@ switch ( $_GET['action'] )
 							// $product->multiprices_min[$societe->price_level];
 							// $product->multiprices_min_ttc[$societe->price_level];
 							// $product->multiprices_base_type[$societe->price_level];
-							$ret['tva_tx'] = $product->multiprices_tva_tx[$societe->price_level];
+							if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL))  // using this option is a bug. kept for backward compatibility
+							{
+							    if (isset($prod->multiprices_tva_tx[$societe->price_level])) $tva_tx=$prod->multiprices_tva_tx[$societe->price_level];
+							    if (isset($prod->multiprices_recuperableonly[$societe->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$societe->price_level];
+							    if (empty($tva_tx)) $tva_npr=0;
+							}
 						}
 					}
-					/** end add Ditto */
 
+					$ret['tva_tx'] = $tva_tx;
+					$ret['tva_npr'] = $tva_npr;
+                    //var_dump('tva_tx='.$ret['tva_tx'].'-tva_npr='.$ret['tva_npr'].'-'.$conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL);exit;
+                    
 					$obj_facturation->id($ret['rowid']);
 					$obj_facturation->ref($ret['ref']);
 					$obj_facturation->stock($ret['reel']);
 					$obj_facturation->prix($ret['price']);
-					$obj_facturation->tva($ret['tva_tx']);
+					
+					// Use $ret['tva_tx'] / ret['tva_npr'] to find vat id
+					$vatrowid = null;
+					$sqlfindvatid = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'c_tva';
+					$sqlfindvatid.= ' WHERE taux = '.$ret['tva_tx'].' AND recuperableonly = '.(int) $ret['tva_npr'];
+					$sqlfindvatid.= ' AND fk_pays = '.$mysoc->country_id;
+					$resqlfindvatid=$db->query($sqlfindvatid);
+					if ($resqlfindvatid)
+					{
+					    $obj = $db->fetch_object($resqlfindvatid);
+					    if ($obj) $vatrowid = $obj->rowid;
+					}
+					else dol_print_error($db);
+					
+					dol_syslog("save vatrowid=".$vatrowid);
+					$obj_facturation->tva($vatrowid);     // Save vat it for next use
 
 					// Definition du filtre pour n'afficher que le produit concerne
 					if ( $_POST['hdnSource'] == 'LISTE' )
@@ -107,7 +134,7 @@ switch ( $_GET['action'] )
 						$filtre = $_POST['txtRef'];
 					}
 
-					$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=facturation&filtre='.$filtre;
+					$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=facturation&filtre='.$filtre;
 				}
 				else
 				{
@@ -115,11 +142,11 @@ switch ( $_GET['action'] )
 
 					if ( $_POST['hdnSource'] == 'REF' )
 					{
-						$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=facturation&filtre='.$_POST['txtRef'];
+						$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=facturation&filtre='.$_POST['txtRef'];
 					}
 					else
 					{
-						$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=facturation';
+						$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=facturation';
 					}
 				}
 			}
@@ -130,40 +157,38 @@ switch ( $_GET['action'] )
 		}
 		else
 		{
-			$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=facturation';
+			$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=facturation';
 		}
 
 		break;
 
 	case 'ajout_article':	// We have clicked on button "Add product"
 
-		//var_dump('ajout_article');
-		//exit;
-
 		if (! empty($obj_facturation->id))	// A product was previously selected and stored in session, so we can add it
 		{
+		    dol_syslog("facturation_verif save vat ".$_POST['selTva']);
 			$obj_facturation->qte($_POST['txtQte']);
-			$obj_facturation->tva($_POST['selTva']);
+			$obj_facturation->tva($_POST['selTva']);                 // Save VAT selected so we can use it for next product
 			$obj_facturation->remisePercent($_POST['txtRemise']);
 			$obj_facturation->ajoutArticle();	// This add an entry into $_SESSION['poscart']
 			// We update prixTotalTtc
 			 
 		}
 
-		$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=facturation';
+		$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=facturation';
 		break;
 
 	case 'suppr_article':
 		$obj_facturation->supprArticle($_GET['suppr_id']);
 
-		$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=facturation';
+		$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=facturation';
 		break;
 
 }
 
 // We saved object obj_facturation
 $_SESSION['serObjFacturation'] = serialize($obj_facturation);
-
+//var_dump($_SESSION['serObjFacturation']);
 header('Location: '.$redirection);
 exit;
 

+ 1 - 1
htdocs/cashdesk/index_verif.php

@@ -125,7 +125,7 @@ if ( $retour >= 0 )
         $_SESSION['CASHDESK_ID_BANKACCOUNT_CB'] = ($bankid_cb > 0 ? $bankid_cb : '');
         //var_dump($_SESSION);exit;
 
-		header('Location: '.DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=facturation&id=NOUV');
+		header('Location: '.DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=facturation&id=NOUV');
 		exit;
 	}
 	else

+ 8 - 7
htdocs/cashdesk/tpl/facturation1.tpl.php

@@ -119,7 +119,7 @@ $langs->load("cashdesk");
 				<td></td>
     			<!-- Choix de la remise -->
     			<td><input class="texte1" type="text" id="txtRemise" name="txtRemise" value="0" onkeyup="javascript: modif();" onfocus="javascript: this.select();"/>
-<?php print genkeypad("txtRemise", "frmQte");?>
+					<?php print genkeypad("txtRemise", "frmQte");?>
     			</td>
     			<!-- Affichage du total HT -->
     			<td><input class="texte1_off" type="text" name="txtTotal" value="" disabled /></td><td></td>
@@ -128,16 +128,17 @@ $langs->load("cashdesk");
                 <?php //var_dump($tab_tva); ?>
                 <select name="selTva" onchange="javascript: modif();" >
                     <?php
-                        $tva_tx = $obj_facturation->tva();
-                        $tab_tva_size=count($tab_tva);
-                        for($i=0;$i < $tab_tva_size;$i++) {
+                        $tva_tx = $obj_facturation->tva();  // Try to get a previously entered VAT rowid. First time, this will return empty.
 
-                            if ( $tva_tx == $tab_tva[$i]['taux'] )
+                        $tab_tva_size=count($tab_tva);      // $tab_tva contains list of possible vat array('rowid'=> , 'taux'=> ) 
+                        for ($i=0;$i < $tab_tva_size;$i++) 
+                        {
+                            if ($tva_tx == $tab_tva[$i]['rowid'])
                                 $selected = 'selected';
                             else
-                            $selected = '';
+                                $selected = '';
 
-                            echo ('<option '.$selected.' value="'.$tab_tva[$i]['rowid'].'">'.$tab_tva[$i]['taux'].'</option>'."\n               ");
+                            echo '<option '.$selected.' value="'.$tab_tva[$i]['rowid'].'">'.$tab_tva[$i]['taux'].'</option>'."\n               ";
                         }
                     ?>
                 </select>

+ 1 - 1
htdocs/cashdesk/tpl/menu.tpl.php

@@ -62,7 +62,7 @@ $langs->load("main");
 print '<div class="menu_bloc">';
 print '<ul class="menu">';
 // Link to new sell
-print '<li class="menu_choix1"><a href="affIndex.php?menu=facturation&id=NOUV"><span>'.$langs->trans("NewSell").'</span></a></li>';
+print '<li class="menu_choix1"><a href="affIndex.php?menutpl=facturation&id=NOUV"><span>'.$langs->trans("NewSell").'</span></a></li>';
 // Open new tab on backoffice (this is not a disconnect from POS)
 print '<li class="menu_choix2"><a href=".." target="backoffice"><span>'.$langs->trans("BackOffice").'</span></a></li>';
 // Disconnect

+ 1 - 1
htdocs/cashdesk/tpl/validation1.tpl.php

@@ -113,7 +113,7 @@ $langs->load("bills");
 		<p class="note_label"><?php echo $langs->trans("Notes"); ?><br><textarea class="textarea_note" name="txtaNotes"></textarea></p>
 
 		<div class="center"><input class="button" type="submit" name="btnValider" value="<?php echo $langs->trans("ValidateInvoice"); ?>" /><br>
-		<br><a class="lien1" href="affIndex.php?menu=facturation"><?php echo $langs->trans("RestartSelling"); ?></a>
+		<br><a class="lien1" href="affIndex.php?menutpl=facturation"><?php echo $langs->trans("RestartSelling"); ?></a>
 		</div>
 	</form>
 

+ 19 - 34
htdocs/cashdesk/validation_verif.php

@@ -42,7 +42,7 @@ switch ($action)
 
 	default:
 
-		$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menu=validation';
+		$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=validation';
 		break;
 
 
@@ -85,13 +85,13 @@ switch ($action)
 			$obj_facturation->paiementLe($txtDatePaiement);
 		}
 
-		$redirection = 'affIndex.php?menu=validation';
+		$redirection = 'affIndex.php?menutpl=validation';
 		break;
 
 
 	case 'retour':
 
-		$redirection = 'affIndex.php?menu=facturation';
+		$redirection = 'affIndex.php?menutpl=facturation';
 		break;
 
 
@@ -158,45 +158,30 @@ switch ($action)
 		// Get content of cart
 		$tab_liste = $_SESSION['poscart'];
 
-		// Loop on each product
+		// Loop on each line into cart
 		$tab_liste_size=count($tab_liste);
-		for ($i=0;$i < $tab_liste_size;$i++)
+		for ($i=0; $i < $tab_liste_size; $i++)
 		{
-			// Recuperation de l'article
-			$product = new Product($db);
-			$product->fetch($tab_liste[$i]['fk_article']);
-			$ret=array('label'=>$product->label,'tva_tx'=>$product->tva_tx,'price'=>$product->price);
-
-	        if (! empty($conf->global->PRODUIT_MULTIPRICES))
-	        {
-	            if (isset($product->multiprices[$societe->price_level]))
-	            {
-	                $ret['price'] = $product->multiprices[$societe->price_level];
-	            }
-	        }
-			$tab_article = $ret;
-
-			$res = $db->query('SELECT taux FROM '.MAIN_DB_PREFIX.'c_tva WHERE rowid = '.$tab_liste[$i]['fk_tva']);
-			$ret=array();
-			$tab = $db->fetch_array($res);
-			foreach ( $tab as $cle => $valeur )
-			{
-				$ret[$cle] = $valeur;
-			}
-			$tab_tva = $ret;
+			$tmp = getTaxesFromId($tab_liste[$i]['fk_tva']);
+			$vat_rate = $tmp['rate'];
+			$vat_npr = $tmp['npr'];
 
 			$invoiceline=new FactureLigne($db);
 			$invoiceline->fk_product=$tab_liste[$i]['fk_article'];
-			$invoiceline->desc=$tab_article['label'];
-			$invoiceline->tva_tx=empty($tab_tva['taux'])?0:$tab_tva['taux'];	// works even if vat_rate is ''
-			//$invoiceline->tva_tx=$tab_tva['taux'];
+			$invoiceline->desc=$tab_liste[$i]['label'];
 			$invoiceline->qty=$tab_liste[$i]['qte'];
 			$invoiceline->remise_percent=$tab_liste[$i]['remise_percent'];
-			$invoiceline->price=$tab_article['price'];
-			$invoiceline->subprice=$tab_article['price'];
+			$invoiceline->price=$tab_liste[$i]['price'];
+			$invoiceline->subprice=$tab_liste[$i]['price'];
+			
+			$invoiceline->tva_tx=empty($vat_rate)?0:$vat_rate;	// works even if vat_rate is ''
+			$invoiceline->info_bits=empty($vat_npr)?0:$vat_npr;
+				
 			$invoiceline->total_ht=$tab_liste[$i]['total_ht'];
 			$invoiceline->total_ttc=$tab_liste[$i]['total_ttc'];
-			$invoiceline->total_tva=($tab_liste[$i]['total_ttc']-$tab_liste[$i]['total_ht']);
+			$invoiceline->total_tva=$tab_liste[$i]['total_vat'];
+			$invoiceline->total_localtax1=$tab_liste[$i]['total_localtax1'];
+			$invoiceline->total_localtax2=$tab_liste[$i]['total_localtax2'];
 			$invoice->lines[]=$invoiceline;
 		}
 
@@ -336,7 +321,7 @@ switch ($action)
 		if (! $error)
 		{
 			$db->commit();
-			$redirection = 'affIndex.php?menu=validation_ok&facid='.$id;	// Ajout de l'id de la facture, pour l'inclure dans un lien pointant directement vers celle-ci dans Dolibarr
+			$redirection = 'affIndex.php?menutpl=validation_ok&facid='.$id;	// Ajout de l'id de la facture, pour l'inclure dans un lien pointant directement vers celle-ci dans Dolibarr
 		}
 		else
 		{

+ 3 - 3
htdocs/categories/class/categorie.class.php

@@ -1451,8 +1451,8 @@ class Categorie extends CommonObject
 
 			if (file_exists($originImage))
 			{
-				// Cree fichier en taille vignette
-				$this->add_thumb($originImage);
+			    // Create thumbs
+				$this->addThumbs($originImage);
 			}
 		}
 	}
@@ -1478,7 +1478,7 @@ class Categorie extends CommonObject
 			$handle=opendir($dir);
             if (is_resource($handle))
             {
-    			while (($file = readdir($handle)) != false)
+    			while (($file = readdir($handle)) !== false)
     			{
     				if (dol_is_file($dir.$file) && preg_match('/(\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i',$dir.$file))
     				{

+ 1 - 1
htdocs/categories/photos.php

@@ -79,7 +79,7 @@ if ($action == 'confirm_delete' && $_GET["file"] && $confirm == 'yes' && $user->
 
 if ($action == 'addthumb' && $_GET["file"])
 {
-    $object->add_thumb($upload_dir."/".$_GET["file"]);
+    $object->addThumbs($upload_dir."/".$_GET["file"]);
 }
 
 

+ 23 - 18
htdocs/comm/action/card.php

@@ -649,14 +649,14 @@ if ($action == 'create')
 	// Type of event
 	if (! empty($conf->global->AGENDA_USE_EVENT_TYPE))
 	{
-		print '<tr><td width="30%"><span class="fieldrequired">'.$langs->trans("Type").'</span></b></td><td>';
+		print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Type").'</span></b></td><td>';
 		$default=(empty($conf->global->AGENDA_USE_EVENT_TYPE_DEFAULT)?'':$conf->global->AGENDA_USE_EVENT_TYPE_DEFAULT);
 		$formactions->select_type_actions(GETPOST("actioncode")?GETPOST("actioncode"):($object->type_code?$object->type_code:$default), "actioncode", "systemauto", 0, -1);
 		print '</td></tr>';
 	}
 
 	// Title
-	print '<tr><td'.(empty($conf->global->AGENDA_USE_EVENT_TYPE)?' class="fieldrequired"':'').'>'.$langs->trans("Title").'</td><td><input type="text" id="label" name="label" size="60" value="'.GETPOST('label').'"></td></tr>';
+	print '<tr><td'.(empty($conf->global->AGENDA_USE_EVENT_TYPE)?' class="fieldrequired titlefieldcreate"':'').'>'.$langs->trans("Title").'</td><td><input type="text" id="label" name="label" class="soixantepercent" value="'.GETPOST('label').'"></td></tr>';
 
     // Full day
     print '<tr><td>'.$langs->trans("EventOnFullDay").'</td><td><input type="checkbox" id="fullday" name="fullday" '.(GETPOST('fullday')?' checked':'').'></td></tr>';
@@ -664,7 +664,7 @@ if ($action == 'create')
 	// Date start
 	$datep=($datep?$datep:$object->datep);
 	if (GETPOST('datep','int',1)) $datep=dol_stringtotime(GETPOST('datep','int',1),0);
-	print '<tr><td width="30%" class="nowrap"><span class="fieldrequired">'.$langs->trans("DateActionStart").'</span></td><td>';
+	print '<tr><td class="nowrap"><span class="fieldrequired">'.$langs->trans("DateActionStart").'</span></td><td>';
 	if (GETPOST("afaire") == 1) $form->select_date($datep,'ap',1,1,0,"action",1,1,0,0,'fulldayend');
 	else if (GETPOST("afaire") == 2) $form->select_date($datep,'ap',1,1,1,"action",1,1,0,0,'fulldayend');
 	else $form->select_date($datep,'ap',1,1,1,"action",1,1,0,0,'fulldaystart');
@@ -684,7 +684,7 @@ if ($action == 'create')
 	print '</td></tr>';
 
 	// Status
-	print '<tr><td width="10%">'.$langs->trans("Status").' / '.$langs->trans("Percentage").'</td>';
+	print '<tr><td>'.$langs->trans("Status").' / '.$langs->trans("Percentage").'</td>';
 	print '<td>';
 	$percent=-1;
 	if (isset($_GET['status']) || isset($_POST['status'])) $percent=GETPOST('status');
@@ -743,7 +743,7 @@ if ($action == 'create')
 	print '<table class="border" width="100%">';
 
 	// Societe, contact
-	print '<tr><td width="30%" class="nowrap">'.$langs->trans("ActionOnCompany").'</td><td>';
+	print '<tr><td class="titlefieldcreate nowrap">'.$langs->trans("ActionOnCompany").'</td><td>';
 	if (GETPOST('socid','int') > 0)
 	{
 		$societe = new Societe($db);
@@ -834,7 +834,7 @@ if ($action == 'create')
 	print '<div class="center">';
 	print '<input type="submit" class="button" value="'.$langs->trans("Add").'">';
 	print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
-	print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
+	print '<input type="button" class="button" name="cancel" value="' . $langs->trans("Cancel") . '" onClick="javascript:history.go(-1)">';
 	print '</div>';
 
 	print "</form>";
@@ -1090,17 +1090,22 @@ if ($id > 0)
 		// Thirdparty - Contact
 		if ($conf->societe->enabled)
 		{
-			print '<tr><td width="30%">'.$langs->trans("ActionOnCompany").'</td>';
+			print '<tr><td class="titlefield">'.$langs->trans("ActionOnCompany").'</td>';
 			print '<td>';
+			print '<div class="maxwidth200onsmartphone">';
 			$events=array();
-			$events[]=array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php',1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
-			print $form->select_company($object->socid,'socid','',1,1,0,$events);
-			print '</td>';
+			$events[]=array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php?showempty=1',1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
+			print $form->select_company($object->socid, 'socid', '', 'SelectThirdParty', 1, 0, $events, 0);
+			print '</div>';
+			print '</td></tr>';
 
 			// Contact
-			print '<td>'.$langs->trans("Contact").'</td><td>';
+			print '<tr><td>'.$langs->trans("Contact").'</td><td>';
+			print '<div class="maxwidth200onsmartphone">';
 			$form->select_contacts($object->socid, $object->contactid, 'contactid', 1, '', '', 0, 'minwidth200');
-			print '</td></tr>';
+			print '</div>';
+			print '</td>';
+			print '</tr>';
 		}
 
 		// Project
@@ -1108,10 +1113,10 @@ if ($id > 0)
 		{
 			$formproject=new FormProjets($db);
 
-			$langs->load("project");
+			$langs->load("projects");
 
-			print '<tr><td width="30%">'.$langs->trans("Project").'</td><td colspan="3">';
-			$numprojet=$formproject->select_projects($object->socid,$object->fk_project,'projectid');
+			print '<tr><td class="titlefield">'.$langs->trans("Project").'</td><td colspan="3">';
+			$numprojet=$formproject->select_projects($object->socid, $object->fk_project, 'projectid');
 			if ($numprojet==0)
 			{
 				print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$object->socid.'&action=create&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit').'">'.$langs->trans("AddProject").'</a>';
@@ -1120,7 +1125,7 @@ if ($id > 0)
 		}
 
 		// Priority
-		print '<tr><td class="nowrap" width="30%">'.$langs->trans("Priority").'</td><td colspan="3">';
+		print '<tr><td class="titlefield nowrap">'.$langs->trans("Priority").'</td><td colspan="3">';
 		print '<input type="text" name="priority" value="'.($object->priority?$object->priority:'').'" size="5">';
 		print '</td></tr>';
 
@@ -1136,7 +1141,7 @@ if ($id > 0)
         print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
         // Editeur wysiwyg
         require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-        $doleditor=new DolEditor('note',$object->note,'',240,'dolibarr_notes','In',true,true,$conf->fckeditor->enabled,ROWS_5,90);
+        $doleditor=new DolEditor('note',$object->note,'',200,'dolibarr_notes','In',true,true,$conf->fckeditor->enabled,ROWS_5,90);
         $doleditor->Create();
         print '</td></tr>';
 
@@ -1281,7 +1286,7 @@ if ($id > 0)
 		// Third party - Contact
 		if ($conf->societe->enabled)
 		{
-			print '<tr><td width="30%">'.$langs->trans("ActionOnCompany").'</td><td>'.($object->thirdparty->id?$object->thirdparty->getNomUrl(1):$langs->trans("None"));
+			print '<tr><td>'.$langs->trans("ActionOnCompany").'</td><td>'.($object->thirdparty->id?$object->thirdparty->getNomUrl(1):$langs->trans("None"));
 			if (is_object($object->thirdparty) && $object->thirdparty->id > 0 && $object->type_code == 'AC_TEL')
 			{
 				if ($object->thirdparty->fetch($object->thirdparty->id))

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

@@ -81,7 +81,7 @@ $modulepart='contract';
 /*
  * Actions
  */
-include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

+ 31 - 2
htdocs/comm/card.php

@@ -124,6 +124,14 @@ if (empty($reshook))
 		if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
 	}
 
+    // customer preferred shipping method
+    if ($action == 'setshippingmethod' && $user->rights->societe->creer)
+    {
+        $object->fetch($id);
+        $result = $object->setShippingMethod(GETPOST('shipping_method_id','int'));
+        if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
+    }
+
 	// assujetissement a la TVA
 	if ($action == 'setassujtva' && $user->rights->societe->creer)
 	{
@@ -239,8 +247,8 @@ if ($id > 0)
     if (! empty($conf->global->SOCIETE_USEPREFIX))  // Old not used prefix field
     {
         print '<tr><td>'.$langs->trans("Prefix").'</td><td colspan="3">';
-	   print ($object->prefix_comm?$object->prefix_comm:'&nbsp;');
-	   print '</td></tr>';
+	    print ($object->prefix_comm?$object->prefix_comm:'&nbsp;');
+	    print '</td></tr>';
     }
 
 	if ($object->client)
@@ -431,6 +439,27 @@ if ($id > 0)
 		print '</div></td></tr>';
 	}
 
+    // Preferred shipping Method
+    if (! empty($conf->global->SOCIETE_ASK_FOR_SHIPPING_METHOD)) {
+        print '<tr><td class="nowrap">';
+        print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
+        print $langs->trans('SendingMethod');
+        print '<td>';
+        if (($action != 'editshipping') && $user->rights->societe->creer) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editshipping&amp;socid='.$object->id.'">'.img_edit($langs->trans('SetMode'),1).'</a></td>';
+        print '</tr></table>';
+        print '</td><td colspan="3">';
+        if ($action == 'editshipping')
+        {
+            $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?socid='.$object->id,$object->shipping_method_id,'shipping_method_id');
+        }
+        else
+        {
+            $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?socid='.$object->id,$object->shipping_method_id,'none');
+        }
+        print "</td>";
+        print '</tr>';
+    }
+
 	// Categories
 	if (!empty( $conf->categorie->enabled ) && !empty( $user->rights->categorie->lire )) {
 		print '<tr><td>' . $langs->trans( "Categories" ) . '</td>';

+ 5 - 5
htdocs/comm/propal.php

@@ -1305,7 +1305,7 @@ if ($action == 'create')
 	print '<table class="border" width="100%">';
 
 	// Reference
-	print '<tr><td width="25%" class="fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans("Draft") . '</td></tr>';
+	print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans("Draft") . '</td></tr>';
 
 	// Ref customer
 	print '<tr><td>' . $langs->trans('RefCustomer') . '</td><td colspan="2">';
@@ -1320,6 +1320,9 @@ if ($action == 'create')
 		print $soc->getNomUrl(1);
 		print '<input type="hidden" name="socid" value="' . $soc->id . '">';
 		print '</td>';
+        if (! empty($conf->global->SOCIETE_ASK_FOR_SHIPPING_METHOD) && ! empty($soc->shipping_method_id)) {
+            $shipping_method_id = $soc->shipping_method_id;
+        }
 	} else {
 		print '<td colspan="2">';
 		print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1', 1);
@@ -2421,10 +2424,7 @@ if ($action == 'create')
 		$formmail->fromid = $user->id;
 		$formmail->fromname = $user->getFullName($langs);
 		$formmail->frommail = $user->email;
-		if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 1))	// If bit 1 is set
-		{
-			$formmail->trackid='pro'.$object->id;
-		}
+		$formmail->trackid='pro'.$object->id;
 		if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2))	// If bit 2 is set
 		{
 			include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';

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

@@ -547,7 +547,7 @@ class Propal extends CommonObject
                 if (! empty($fk_parent_line)) $this->line_order(true,'DESC');
 
                 // Mise a jour informations denormalisees au niveau de la propale meme
-                $result=$this->update_price(1,'auto');	// This method is designed to add line from user input so total calculation must be done using 'auto' mode.
+                $result=$this->update_price(1,'auto',0,$mysoc);	// This method is designed to add line from user input so total calculation must be done using 'auto' mode.
                 if ($result > 0)
                 {
                     $this->db->commit();
@@ -2037,9 +2037,10 @@ class Propal extends CommonObject
      */
     function classer_facturee()
     {
+        global $user;
 		dol_syslog(__METHOD__ . " is deprecated", LOG_WARNING);
 
-    	return $this->classifyBilled();
+    	return $this->classifyBilled($user);
     }
 
     /**
@@ -2841,8 +2842,8 @@ class Propal extends CommonObject
 
     /**
      * 	Retrieve an array of propal lines
-     *
-     *	@return	int	<0 if ko, >0 if ok
+	 *
+	 * 	@return int		>0 if OK, <0 if KO
      */
     function getLinesArray()
     {

+ 1 - 1
htdocs/comm/propal/document.php

@@ -67,7 +67,7 @@ if ($object->id > 0)
 {
 	$object->fetch_thirdparty();
 	$upload_dir = $conf->propal->dir_output.'/'.dol_sanitizeFileName($object->ref);
-	include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+	include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 }
 
 /*

+ 578 - 202
htdocs/comm/propal/list.php

@@ -35,7 +35,9 @@ require '../../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formpropal.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
 if (! empty($conf->projet->enabled))
 	require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
@@ -55,17 +57,24 @@ $search_ref=GETPOST('sf_ref')?GETPOST('sf_ref','alpha'):GETPOST('search_ref','al
 $search_refcustomer=GETPOST('search_refcustomer','alpha');
 $search_societe=GETPOST('search_societe','alpha');
 $search_montant_ht=GETPOST('search_montant_ht','alpha');
-$search_author=GETPOST('search_author','alpha');
+$search_montant_vat=GETPOST('search_montant_vat','alpha');
+$search_montant_ttc=GETPOST('search_montant_ttc','alpha');
+$search_login=GETPOST('search_login','alpha');
 $search_product_category=GETPOST('search_product_category','int');
 $search_town=GETPOST('search_town','alpha');
+$search_zip=GETPOST('search_zip','alpha');
+$search_state=trim(GETPOST("search_state"));
+$search_country=GETPOST("search_country",'int');
+$search_type_thirdparty=GETPOST("search_type_thirdparty",'int');
 $viewstatut=GETPOST('viewstatut');
 $optioncss = GETPOST('optioncss','alpha');
 $object_statut=GETPOST('propal_statut');
 
 $sall=GETPOST("sall");
 $mesg=(GETPOST("msg") ? GETPOST("msg") : GETPOST("mesg"));
-$year=GETPOST("year");
-$month=GETPOST("month");
+$day=GETPOST("day","int");
+$year=GETPOST("year","int");
+$month=GETPOST("month","int");
 
 $limit = GETPOST("limit")?GETPOST("limit","int"):$conf->liste_limit;
 $sortfield = GETPOST("sortfield",'alpha');
@@ -78,9 +87,8 @@ $pagenext = $page + 1;
 if (! $sortfield) $sortfield='p.ref';
 if (! $sortorder) $sortorder='DESC';
 
-
-// Nombre de ligne pour choix de produit/service predefinis
-$NBLINES=4;
+// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
+$contextpage='proposallist';
 
 // Security check
 $module='propal';
@@ -95,30 +103,15 @@ if (! empty($socid))
 }
 $result = restrictedArea($user, $module, $objectid, $dbtable);
 
-if (GETPOST("button_removefilter") || GETPOST("button_removefilter_x"))	// Both tests are required to be compatible with all browsers
-{
-    $search_categ='';
-    $search_user='';
-    $search_sale='';
-    $search_ref='';
-    $search_refcustomer='';
-    $search_societe='';
-    $search_montant_ht='';
-    $search_author='';
-    $search_product_category='';
-    $search_town='';
-    $year='';
-    $month='';
-	$viewstatut='';
-	$object_statut='';
-}
-
-if($object_statut != '')
-$viewstatut=$object_statut;
-
+$diroutputmassaction=$conf->propal->dir_output . '/temp/massgeneration/'.$user->id;
 
 // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
 $hookmanager->initHooks(array('propallist'));
+$extrafields = new ExtraFields($db);
+
+// fetch optionals attributes and labels
+$extralabels = $extrafields->fetch_name_optionals_label('propal');
+$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_');
 
 // List of fields to search into when doing a "search in all"
 $fieldstosearchall = array(
@@ -131,15 +124,98 @@ $fieldstosearchall = array(
 if (empty($user->socid)) $fieldstosearchall["p.note_private"]="NotePrivate";
 
 
+$checkedtypetiers=0;
+$arrayfields=array(
+    'p.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1),
+    'p.ref_client'=>array('label'=>$langs->trans("RefCustomer"), 'checked'=>1),
+    's.nom'=>array('label'=>$langs->trans("ThirdParty"), 'checked'=>1),
+    's.town'=>array('label'=>$langs->trans("Town"), 'checked'=>1),
+    's.zip'=>array('label'=>$langs->trans("Zip"), 'checked'=>1),
+    'state.nom'=>array('label'=>$langs->trans("StateShort"), 'checked'=>0),
+    'country.code_iso'=>array('label'=>$langs->trans("Country"), 'checked'=>0),
+    'typent.code'=>array('label'=>$langs->trans("ThirdPartyType"), 'checked'=>$checkedtypetiers),
+    'p.date'=>array('label'=>$langs->trans("Date"), 'checked'=>1),
+    'p.fin_validite'=>array('label'=>$langs->trans("DateEnd"), 'checked'=>1),
+    'p.total_ht'=>array('label'=>$langs->trans("AmountHT"), 'checked'=>1),
+    'p.total_vat'=>array('label'=>$langs->trans("AmountVAT"), 'checked'=>0),
+    'p.total_ttc'=>array('label'=>$langs->trans("AmountTTC"), 'checked'=>0),
+    'u.login'=>array('label'=>$langs->trans("Author"), 'checked'=>1, 'position'=>10),
+    'p.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500),
+    'p.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500),
+    'p.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000),
+);
+// Extra fields
+if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+{
+    foreach($extrafields->attribute_label as $key => $val)
+    {
+        $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]);
+    }
+}
+
+
 /*
  * Actions
  */
 
+if (GETPOST('cancel')) { $action='list'; $massaction=''; }
+if (! GETPOST('confirmmassaction')) { $massaction=''; }
 
 $parameters=array('socid'=>$socid);
 $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
 
+include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
+
+// Do we click on purge search criteria ?
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
+{
+    $search_categ='';
+    $search_user='';
+    $search_sale='';
+    $search_ref='';
+    $search_refcustomer='';
+    $search_societe='';
+    $search_montant_ht='';
+    $search_montant_vat='';
+    $search_montant_ttc='';
+    $search_login='';
+    $search_product_category='';
+    $search_town='';
+	$search_zip="";
+    $search_state="";
+	$search_type='';
+	$search_country='';
+	$search_type_thirdparty='';
+	$year='';
+    $month='';
+    $day='';
+	$viewstatut='';
+	$object_statut='';
+    $search_array_options=array();
+}
+if ($object_statut != '') $viewstatut=$object_statut;
+
+if (empty($reshook))
+{
+    // Mass actions. Controls on number of lines checked
+    $maxformassaction=1000;
+    if (! empty($massaction) && count($toselect) < 1)
+    {
+        $error++;
+        setEventMessages($langs->trans("NoLineChecked"), null, "warnings");
+    }
+    if (! $error && count($toselect) > $maxformassaction)
+    {
+        setEventMessages($langs->trans('TooManyRecordForMassAction',$maxformassaction), null, 'errors');
+        $error++;
+    }
+
+
+    
+    
+}
+
 
 
 /*
@@ -153,16 +229,31 @@ $formother = new FormOther($db);
 $formfile = new FormFile($db);
 $formpropal = new FormPropal($db);
 $companystatic=new Societe($db);
+$formcompany=new FormCompany($db);
 
 $now=dol_now();
 
 $sql = 'SELECT';
 if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT';
-$sql.= ' s.rowid, s.nom as name, s.town, s.client, s.code_client,';
-$sql.= ' p.rowid as propalid, p.note_private, p.total_ht, p.ref, p.ref_client, p.fk_statut, p.fk_user_author, p.datep as dp, p.fin_validite as dfv,';
+$sql.= ' s.rowid, s.nom as name, s.town, s.zip, s.fk_pays, s.client, s.code_client, ';
+$sql.= " typent.code as typent_code,";
+$sql.= " state.code_departement as state_code, state.nom as state_name,";
+$sql.= ' p.rowid as propalid, p.note_private, p.total_ht, p.tva as total_vat, p.total as total_ttc, p.localtax1, p.localtax2, p.ref, p.ref_client, p.fk_statut, p.fk_user_author, p.datep as dp, p.fin_validite as dfv,';
+$sql.= ' p.datec as date_creation, p.tms as date_update,';
 if (! $user->rights->societe->client->voir && ! $socid) $sql .= " sc.fk_soc, sc.fk_user,";
 $sql.= ' u.login';
-$sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s, '.MAIN_DB_PREFIX.'propal as p';
+// Add fields from extrafields
+foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
+// Add fields from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+$sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s';
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)";
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_typent as typent on (typent.id = s.fk_typent)";
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = s.fk_departement)";
+$sql.= ', '.MAIN_DB_PREFIX.'propal as p';
+if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."propal_extrafields as ef on (p.rowid = ef.fk_object)";
 if ($sall || $search_product_category > 0) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'propaldet as pd ON p.rowid=pd.fk_propal';
 if ($search_product_category > 0) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=pd.fk_product';
 $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'user as u ON p.fk_user_author = u.rowid';
@@ -179,26 +270,18 @@ if (! $user->rights->societe->client->voir && ! $socid) //restriction
 {
 	$sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
 }
-if ($search_town) {//restriction
-	$sql .= natural_search('s.town', $search_town);
-}
-if ($search_ref) {
-	$sql .= natural_search('p.ref', $search_ref);
-}
-if ($search_refcustomer) {
-	$sql .= natural_search('p.ref_client', $search_refcustomer);
-}
-if ($search_societe) {
-	$sql .= natural_search('s.nom', $search_societe);
-}
-if ($search_author)
-{
-	$sql.= " AND u.login LIKE '%".$db->escape(trim($search_author))."%'";
-}
-if ($search_montant_ht != '')
-{
-	$sql.= natural_search("p.total_ht", $search_montant_ht, 1);
-}
+if ($search_town)  $sql.= natural_search('s.town', $search_town);
+if ($search_zip)   $sql.= natural_search("s.zip",$search_zip);
+if ($search_state) $sql.= natural_search("state.nom",$search_state);
+if ($search_country) $sql .= " AND s.fk_pays IN (".$search_country.')';
+if ($search_type_thirdparty) $sql .= " AND s.fk_typent IN (".$search_type_thirdparty.')';
+if ($search_ref)   $sql .= natural_search('p.ref', $search_ref);
+if ($search_refcustomer) $sql .= natural_search('p.ref_client', $search_refcustomer);
+if ($search_societe) $sql .= natural_search('s.nom', $search_societe);
+if ($search_login) $sql.= " AND u.login LIKE '%".$db->escape(trim($search_login))."%'";
+if ($search_montant_ht != '')  $sql.= natural_search("p.total_ht", $search_montant_ht, 1);
+if ($search_montant_vat != '') $sql.= natural_search("p.tva", $search_montant_vat, 1);
+if ($search_montant_ttc != '') $sql.= natural_search("p.total", $search_montant_ttc, 1);
 if ($sall) {
     $sql .= natural_search(array_keys($fieldstosearchall), $sall);
 }
@@ -226,19 +309,38 @@ if ($search_user > 0)
 {
     $sql.= " AND c.fk_c_type_contact = tc.rowid AND tc.element='propal' AND tc.source='internal' AND c.element_id = p.rowid AND c.fk_socpeople = ".$search_user;
 }
-$sql.= ' ORDER BY '.$sortfield.' '.$sortorder.', p.ref DESC';
+// Add where from extra fields
+foreach ($search_array_options as $key => $val)
+{
+    $crit=$val;
+    $tmpkey=preg_replace('/search_options_/','',$key);
+    $typ=$extrafields->attribute_type[$tmpkey];
+    $mode=0;
+    if (in_array($typ, array('int','double'))) $mode=1;    // Search on a numeric
+    if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit)))
+    {
+        $sql .= natural_search('ef.'.$tmpkey, $crit, $mode);
+    }
+}
+// Add where from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
 
+$sql.= $db->order($sortfield,$sortorder);
+$sql.=', p.ref DESC';
+
+// Count total nb of records
 $nbtotalofrecords = 0;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
-	$result = $db->query($sql);
-	$nbtotalofrecords = $db->num_rows($result);
+    $result = $db->query($sql);
+    $nbtotalofrecords = $db->num_rows($result);
 }
-//print $sql;
 
-$sql.= $db->plimit($limit + 1,$offset);
-$result=$db->query($sql);
+$sql.= $db->plimit($limit+1, $offset);
 
+$result=$db->query($sql);
 if ($result)
 {
 	$objectstatic=new Propal($db);
@@ -261,14 +363,24 @@ if ($result)
 	if ($search_user > 0)    $param.='&search_user='.$search_user;
 	if ($search_sale > 0)    $param.='&search_sale='.$search_sale;
 	if ($search_montant_ht)  $param.='&search_montant_ht='.$search_montant_ht;
-	if ($search_author)  	 $param.='&search_author='.$search_author;
+	if ($search_login)  	 $param.='&search_login='.$search_login;
 	if ($search_town)		 $param.='&search_town='.$search_town;
 	if ($optioncss != '') $param.='&optioncss='.$optioncss;
-
+	// Add $param from extra fields
+	foreach ($search_array_options as $key => $val)
+	{
+	    $crit=$val;
+	    $tmpkey=preg_replace('/search_options_/','',$key);
+	    if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val);
+	}
+	
+	//$massactionbutton=$form->selectMassAction('', $massaction == 'presend' ? array() : array('presend'=>$langs->trans("SendByMail"), 'builddoc'=>$langs->trans("PDFMerge")));
+	
 	// Lignes des champs de filtre
 	print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
     if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
 	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
 	print '<input type="hidden" name="action" value="list">';
 	print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 	print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
@@ -320,181 +432,445 @@ if ($result)
 	    print '</div>';
 	}
 
+    $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
+    $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
+	
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans('Ref'),$_SERVER["PHP_SELF"],'p.ref','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('RefCustomer'),$_SERVER["PHP_SELF"],'p.ref_client','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('Company'),$_SERVER["PHP_SELF"],'s.nom','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('Town'),$_SERVER["PHP_SELF"],'s.town','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('Date'),$_SERVER["PHP_SELF"],'p.datep','',$param, 'align="center"',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('DateEndPropalShort'),$_SERVER["PHP_SELF"],'dfv','',$param, 'align="center"',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('AmountHT'),$_SERVER["PHP_SELF"],'p.total_ht','',$param, 'align="right"',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('Author'),$_SERVER["PHP_SELF"],'u.login','',$param,'align="center"',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('Status'),$_SERVER["PHP_SELF"],'p.fk_statut','',$param,'align="right"',$sortfield,$sortorder);
-	print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'','','',$sortfield,$sortorder,'maxwidthsearch ');
+	if (! empty($arrayfields['p.ref']['checked']))            print_liste_field_titre($arrayfields['p.ref']['label'],$_SERVER["PHP_SELF"],'p.ref','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.ref_client']['checked']))     print_liste_field_titre($arrayfields['p.ref_client']['label'],$_SERVER["PHP_SELF"],'p.ref_client','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.nom']['checked']))            print_liste_field_titre($arrayfields['s.nom']['label'],$_SERVER["PHP_SELF"],'s.nom','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.town']['checked']))           print_liste_field_titre($arrayfields['s.town']['label'],$_SERVER["PHP_SELF"],'s.town','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.zip']['checked']))            print_liste_field_titre($arrayfields['s.zip']['label'],$_SERVER["PHP_SELF"],'s.zip','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['state.nom']['checked']))        print_liste_field_titre($arrayfields['state.nom']['label'],$_SERVER["PHP_SELF"],"state.nom","",$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['country.code_iso']['checked'])) print_liste_field_titre($arrayfields['country.code_iso']['label'],$_SERVER["PHP_SELF"],"country.code_iso","",$param,'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['typent.code']['checked']))      print_liste_field_titre($arrayfields['typent.code']['label'],$_SERVER["PHP_SELF"],"typent.code","",$param,'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.date']['checked']))           print_liste_field_titre($arrayfields['p.date']['label'],$_SERVER["PHP_SELF"],'p.datep','',$param, 'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.fin_validite']['checked']))   print_liste_field_titre($arrayfields['p.fin_validite']['label'],$_SERVER["PHP_SELF"],'dfv','',$param, 'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.total_ht']['checked']))       print_liste_field_titre($arrayfields['p.total_ht']['label'],$_SERVER["PHP_SELF"],'p.total_ht','',$param, 'align="right"',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.total_vat']['checked']))      print_liste_field_titre($arrayfields['p.total_vat']['label'],$_SERVER["PHP_SELF"],'p.tva','',$param, 'align="right"',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.total_ttc']['checked']))      print_liste_field_titre($arrayfields['p.total_ttc']['label'],$_SERVER["PHP_SELF"],'p.total','',$param, 'align="right"',$sortfield,$sortorder);
+	if (! empty($arrayfields['u.login']['checked']))       	  print_liste_field_titre($arrayfields['u.login']['label'],$_SERVER["PHP_SELF"],'u.login','',$param,'align="center"',$sortfield,$sortorder);
+	// Extra fields
+	if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+	{
+	   foreach($extrafields->attribute_label as $key => $val) 
+	   {
+           if (! empty($arrayfields["ef.".$key]['checked'])) 
+           {
+				$align=$extrafields->getAlignFlag($key);
+				print_liste_field_titre($extralabels[$key],$_SERVER["PHP_SELF"],"ef.".$key,"",$param,($align?'align="'.$align.'"':''),$sortfield,$sortorder);
+           }
+	   }
+	}
+	// Hook fields
+	$parameters=array('arrayfields'=>$arrayfields);
+    $reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters);    // Note that $action and $object may have been modified by hook
+    print $hookmanager->resPrint;
+	if (! empty($arrayfields['p.datec']['checked']))     print_liste_field_titre($arrayfields['p.datec']['label'],$_SERVER["PHP_SELF"],"p.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.tms']['checked']))       print_liste_field_titre($arrayfields['p.tms']['label'],$_SERVER["PHP_SELF"],"p.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+	if (! empty($arrayfields['p.fk_statut']['checked'])) print_liste_field_titre($arrayfields['p.fk_statut']['label'],$_SERVER["PHP_SELF"],"p.fk_statut","",$param,'align="right"',$sortfield,$sortorder);
+	print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="right"',$sortfield,$sortorder,'maxwidthsearch ');
 	print "</tr>\n";
 
 	print '<tr class="liste_titre">';
-	print '<td class="liste_titre">';
-	print '<input class="flat" size="6" type="text" name="search_ref" value="'.$search_ref.'">';
-	print '</td>';
-	print '<td class="liste_titre">';
-	print '<input class="flat" size="6" type="text" name="search_refcustomer" value="'.$search_refcustomer.'">';
-	print '</td>';
-	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" size="12" name="search_societe" value="'.$search_societe.'">';
-	print '</td>';
-	print '<td class="liste_titre"><input class="flat" type="text" size="10" name="search_town" value="'.$search_town.'"></td>';
+	if (! empty($arrayfields['p.ref']['checked']))            
+	{
+	    print '<td class="liste_titre">';
+    	print '<input class="flat" size="6" type="text" name="search_ref" value="'.$search_ref.'">';
+	   print '</td>';
+	}
+	if (! empty($arrayfields['p.ref_client']['checked']))
+	{
+    	print '<td class="liste_titre">';
+	   print '<input class="flat" size="6" type="text" name="search_refcustomer" value="'.$search_refcustomer.'">';
+	   print '</td>';
+	}
+	if (! empty($arrayfields['s.nom']['checked']))
+	{
+	    print '<td class="liste_titre" align="left">';
+    	print '<input class="flat" type="text" size="12" name="search_societe" value="'.$search_societe.'">';
+	   print '</td>';
+	}
+	if (! empty($arrayfields['s.town']['checked'])) print '<td class="liste_titre"><input class="flat" type="text" size="6" name="search_town" value="'.$search_town.'"></td>';
+	if (! empty($arrayfields['s.zip']['checked'])) print '<td class="liste_titre"><input class="flat" type="text" size="6" name="search_zip" value="'.$search_zip.'"></td>';
+	// State
+    if (! empty($arrayfields['state.nom']['checked']))
+    {
+        print '<td class="liste_titre">';
+    	print '<input class="flat" size="4" type="text" name="search_state" value="'.dol_escape_htmltag($search_state).'">';
+    	print '</td>';
+    }
+    // Country
+    if (! empty($arrayfields['country.code_iso']['checked']))
+    {
+        print '<td class="liste_titre" align="center">';
+    	print $form->select_country($search_country,'search_country','',0,'maxwidth100');
+    	print '</td>';
+    }
+	// Company type
+    if (! empty($arrayfields['typent.code']['checked']))
+    {
+        print '<td class="liste_titre maxwidthonsmartphone" align="center">';
+    	print $form->selectarray("search_type_thirdparty", $formcompany->typent_array(0), $search_type_thirdparty, 0, 0, 0, '', 0, 0, 0, (empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?'ASC':$conf->global->SOCIETE_SORT_ON_TYPEENT));
+    	print '</td>';
+    }
 	// Date
-	print '<td class="liste_titre" colspan="1" align="center">';
-	//print $langs->trans('Month').': ';
-	print '<input class="flat" type="text" size="1" maxlength="2" name="month" value="'.$month.'">';
-	//print '&nbsp;'.$langs->trans('Year').': ';
-	$syear = $year;
-	$formother->select_year($syear,'year',1, 20, 5);
-	print '</td>';
-	print '<td class="liste_titre" colspan="1">&nbsp;</td>';
-	// Amount
-	print '<td class="liste_titre" align="right">';
-	print '<input class="flat" type="text" size="6" name="search_montant_ht" value="'.$search_montant_ht.'">';
-	print '</td>';
-	// Author
-	print '<td class="liste_titre" align="center">';
-	print '<input class="flat" size="6" type="text" name="search_author" value="'.$search_author.'">';
-	print '</td>';
-	print '<td class="liste_titre" align="right">';
-	$formpropal->selectProposalStatus($viewstatut,1);
-	print '</td>';
-
-	print '<td class="liste_titre" align="right">';
-	print '<input type="image" name="button_search" class="liste_titre" src="'.img_picto($langs->trans("Search"),'search.png','','',1).'" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
-	print '<input type="image" name="button_removefilter" class="liste_titre" src="'.img_picto($langs->trans("RemoveFilter"),'searchclear.png','','',1).'" value="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'" title="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'">';
+	if (! empty($arrayfields['p.date']['checked'])) 
+	{
+	    print '<td class="liste_titre" colspan="1" align="center">';
+    	//print $langs->trans('Month').': ';
+    	if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="day" value="'.$day.'">';
+    	print '<input class="flat" type="text" size="1" maxlength="2" name="month" value="'.$month.'">';
+    	//print '&nbsp;'.$langs->trans('Year').': ';
+    	$syear = $year;
+    	$formother->select_year($syear,'year',1, 20, 5);
+    	print '</td>';
+	}
+	// Date end
+	if (! empty($arrayfields['p.fin_validite']['checked'])) 
+	{
+	   print '<td class="liste_titre" colspan="1">&nbsp;</td>';
+	}
+	if (! empty($arrayfields['p.total_ht']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_montant_ht" value="'.$search_montant_ht.'">';
+    	print '</td>';
+	}
+	if (! empty($arrayfields['p.total_vat']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_montant_vat" value="'.$search_montant_vat.'">';
+    	print '</td>';
+	}
+	if (! empty($arrayfields['p.total_ttc']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_montant_ttc" value="'.$search_montant_ttc.'">';
+    	print '</td>';
+	}
+	if (! empty($arrayfields['u.login']['checked']))
+	{
+    	// Author
+    	print '<td class="liste_titre" align="center">';
+    	print '<input class="flat" size="4" type="text" name="search_login" value="'.$search_login.'">';
+    	print '</td>';
+	}
+	// Extra fields
+	if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+	{
+	    foreach($extrafields->attribute_label as $key => $val)
+	    {
+	        if (! empty($arrayfields["ef.".$key]['checked']))
+	        {
+	            $align=$extrafields->getAlignFlag($key);
+	            $typeofextrafield=$extrafields->attribute_type[$key];
+	            print '<td class="liste_titre'.($align?' '.$align:'').'">';
+   			    if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')))
+				{
+				    $crit=$val;
+    				$tmpkey=preg_replace('/search_options_/','',$key);
+    				$searchclass='';
+    				if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring';
+    				if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum';
+    				print '<input class="flat'.($searchclass?' '.$searchclass:'').'" size="4" type="text" name="search_options_'.$tmpkey.'" value="'.dol_escape_htmltag($search_array_options['search_options_'.$tmpkey]).'">';
+				}
+	            print '</td>';
+	        }
+	    }
+	}
+	// Fields from hook
+	$parameters=array('arrayfields'=>$arrayfields);
+	$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters);    // Note that $action and $object may have been modified by hook
+	print $hookmanager->resPrint;
+	// Date creation
+	if (! empty($arrayfields['p.datec']['checked']))
+	{
+	    print '<td class="liste_titre">';
+	    print '</td>';
+	}
+	// Date modification
+	if (! empty($arrayfields['p.tms']['checked']))
+	{
+	    print '<td class="liste_titre">';
+	    print '</td>';
+	}
+	// Status
+	if (! empty($arrayfields['p.fk_statut']['checked']))
+	{
+	    print '<td class="liste_titre maxwidthonsmartphone" align="right">';
+	    $formpropal->selectProposalStatus($viewstatut,1);
+	    print '</td>';
+	}
+	// Action column
+	print '<td class="liste_titre" align="middle">';
+	$searchpitco=$form->showFilterAndCheckAddButtons(0);
+	print $searchpitco;
 	print '</td>';
-
+	
 	print "</tr>\n";
 
+	$now = dol_now();
+	$i=0;
 	$var=true;
-	$total=0;
-	$subtotal=0;
-
+	$totalarray=array();
 	while ($i < min($num,$limit))
 	{
-		$objp = $db->fetch_object($result);
-		$now = dol_now();
+		$obj = $db->fetch_object($result);
 		$var=!$var;
 		print '<tr '.$bc[$var].'>';
-		print '<td class="nowrap">';
-
-		$objectstatic->id=$objp->propalid;
-		$objectstatic->ref=$objp->ref;
-
-		print '<table class="nobordernopadding"><tr class="nocellnopadd">';
-		print '<td class="nobordernopadding nowrap">';
-		print $objectstatic->getNomUrl(1);
-		print '</td>';
-
-		print '<td style="min-width: 20px" class="nobordernopadding nowrap">';
-		if ($objp->fk_statut == 1 && $db->jdate($objp->dfv) < ($now - $conf->propal->cloture->warning_delay)) print img_warning($langs->trans("Late"));
-		if (! empty($objp->note_private))
+		
+		if (! empty($arrayfields['p.ref']['checked']))
 		{
-			print ' <span class="note">';
-			print '<a href="'.DOL_URL_ROOT.'/comm/propal/note.php?id='.$objp->propalid.'">'.img_picto($langs->trans("ViewPrivateNote"),'object_generic').'</a>';
-			print '</span>';
+    		print '<td class="nowrap">';
+    
+    		$objectstatic->id=$obj->propalid;
+    		$objectstatic->ref=$obj->ref;
+    
+    		print '<table class="nobordernopadding"><tr class="nocellnopadd">';
+    		print '<td class="nobordernopadding nowrap">';
+    		print $objectstatic->getNomUrl(1);
+    		print '</td>';
+    
+    		print '<td style="min-width: 20px" class="nobordernopadding nowrap">';
+    		if ($obj->fk_statut == 1 && $db->jdate($obj->dfv) < ($now - $conf->propal->cloture->warning_delay)) print img_warning($langs->trans("Late"));
+    		if (! empty($obj->note_private))
+    		{
+    			print ' <span class="note">';
+    			print '<a href="'.DOL_URL_ROOT.'/comm/propal/note.php?id='.$obj->propalid.'">'.img_picto($langs->trans("ViewPrivateNote"),'object_generic').'</a>';
+    			print '</span>';
+    		}
+    		print '</td>';
+    
+    		// Ref
+    		print '<td width="16" align="right" class="nobordernopadding hideonsmartphone">';
+    		$filename=dol_sanitizeFileName($obj->ref);
+    		$filedir=$conf->propal->dir_output . '/' . dol_sanitizeFileName($obj->ref);
+    		$urlsource=$_SERVER['PHP_SELF'].'?id='.$obj->propalid;
+    		print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir);
+    		print '</td></tr></table>';
+    
+    		print "</td>\n";
+    		if (! $i) $totalarray['nbfield']++;
 		}
-		print '</td>';
-
-		// Ref
-		print '<td width="16" align="right" class="nobordernopadding hideonsmartphone">';
-		$filename=dol_sanitizeFileName($objp->ref);
-		$filedir=$conf->propal->dir_output . '/' . dol_sanitizeFileName($objp->ref);
-		$urlsource=$_SERVER['PHP_SELF'].'?id='.$objp->propalid;
-		print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir);
-		print '</td></tr></table>';
-
-		print "</td>\n";
-
-		// Customer ref
-		print '<td class="nocellnopadd nowrap">';
-		print $objp->ref_client;
-		print '</td>';
-
-		$url = DOL_URL_ROOT.'/comm/card.php?socid='.$objp->rowid;
-
-		// Company
-		$companystatic->id=$objp->rowid;
-		$companystatic->name=$objp->name;
-		$companystatic->client=$objp->client;
-		$companystatic->code_client=$objp->code_client;
-		print '<td>';
-		print $companystatic->getNomUrl(1,'customer');
-		print '</td>';
-
-		// Town
-		print '<td class="nocellnopadd">';
-		print $objp->town;
-		print '</td>';
-
-		// Date proposal
-		print '<td align="center">';
-		print dol_print_date($db->jdate($objp->dp), 'day');
-		print "</td>\n";
-
-		// Date end validity
-		if ($objp->dfv)
+		
+		if (! empty($arrayfields['p.ref_client']['checked']))
 		{
-			print '<td align="center">'.dol_print_date($db->jdate($objp->dfv),'day');
-			print '</td>';
+    		// Customer ref
+    		print '<td class="nocellnopadd nowrap">';
+    		print $obj->ref_client;
+    		print '</td>';
+    		if (! $i) $totalarray['nbfield']++;
 		}
-		else
+		
+		$url = DOL_URL_ROOT.'/comm/card.php?socid='.$obj->rowid;
+
+		$companystatic->id=$obj->rowid;
+		$companystatic->name=$obj->name;
+		$companystatic->client=$obj->client;
+		$companystatic->code_client=$obj->code_client;
+		
+		// Thirdparty
+		if (! empty($arrayfields['s.nom']['checked']))
 		{
-			print '<td>&nbsp;</td>';
+    		print '<td>';
+    		print $companystatic->getNomUrl(1,'customer');
+    		print '</td>';
+    		if (! $i) $totalarray['nbfield']++;
 		}
-
-		print '<td align="right">'.price($objp->total_ht)."</td>\n";
-
-		$userstatic->id=$objp->fk_user_author;
-		$userstatic->login=$objp->login;
-		print '<td align="center">';
-		if ($userstatic->id) print $userstatic->getLoginUrl(1);
-		else print '&nbsp;';
-		print "</td>\n";
-
-		print '<td align="right">'.$objectstatic->LibStatut($objp->fk_statut,5)."</td>\n";
-
-		print '<td>&nbsp;</td>';
+		
+		// Town
+        if (! empty($arrayfields['s.town']['checked']))
+        {
+            print '<td class="nocellnopadd">';
+		    print $obj->town;
+    		print '</td>';
+    		if (! $i) $totalarray['nbfield']++;
+        }
+        // Zip
+        if (! empty($arrayfields['s.zip']['checked']))
+        {
+            print '<td class="nocellnopadd">';
+            print $obj->zip;
+            print '</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // State
+        if (! empty($arrayfields['state.nom']['checked']))
+        {
+            print "<td>".$obj->state_name."</td>\n";
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // Country
+        if (! empty($arrayfields['country.code_iso']['checked']))
+        {
+            print '<td align="center">';
+            $tmparray=getCountry($obj->fk_pays,'all');
+            print $tmparray['label'];
+            print '</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // Type ent
+        if (! empty($arrayfields['typent.code']['checked']))
+        {
+            print '<td align="center">';
+            if (count($typenArray)==0) $typenArray = $formcompany->typent_array(1);
+            print $typenArray[$obj->typent_code];
+            print '</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        
+		// Date proposal
+        if (! empty($arrayfields['p.date']['checked']))
+        {
+    		print '<td align="center">';
+    		print dol_print_date($db->jdate($obj->dp), 'day');
+    		print "</td>\n";
+    		if (! $i) $totalarray['nbfield']++;
+        }
+        
+		// Date end validity
+        if (! empty($arrayfields['p.fin_validite']['checked']))
+        {
+            if ($obj->dfv)
+    		{
+    			print '<td align="center">'.dol_print_date($db->jdate($obj->dfv),'day');
+    			print '</td>';
+    		}
+    		else
+    		{
+    			print '<td>&nbsp;</td>';
+    		}
+    		if (! $i) $totalarray['nbfield']++;
+        }
+        
+        // Amount HT
+        if (! empty($arrayfields['p.total_ht']['checked']))
+        {
+		      print '<td align="right">'.price($obj->total_ht)."</td>\n";
+		      if (! $i) $totalarray['nbfield']++;
+		      if (! $i) $totalarray['totalhtfield']=$totalarray['nbfield'];
+		      $totalarray['totalht'] += $obj->total_ht;
+        }
+        // Amount VAT
+        if (! empty($arrayfields['p.total_vat']['checked']))
+        {
+            print '<td align="right">'.price($obj->total_vat)."</td>\n";
+            if (! $i) $totalarray['nbfield']++;
+		    if (! $i) $totalarray['totalvatfield']=$totalarray['nbfield'];
+		    $totalarray['totalvat'] += $obj->total_vat;
+        }
+        // Amount TTC
+        if (! empty($arrayfields['p.total_ttc']['checked']))
+        {
+            print '<td align="right">'.price($obj->total_ttc)."</td>\n";
+            if (! $i) $totalarray['nbfield']++;
+		    if (! $i) $totalarray['totalttcfield']=$totalarray['nbfield'];
+		    $totalarray['totalttc'] += $obj->total_ttc;
+        }
+        
+        $userstatic->id=$obj->fk_user_author;
+		$userstatic->login=$obj->login;
+
+        // Author
+        if (! empty($arrayfields['u.login']['checked']))
+        {
+    		print '<td align="center">';
+    		if ($userstatic->id) print $userstatic->getLoginUrl(1);
+    		else print '&nbsp;';
+    		print "</td>\n";
+    		if (! $i) $totalarray['nbfield']++;
+        }
+        
+        // Extra fields
+        if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+        {
+            foreach($extrafields->attribute_label as $key => $val)
+            {
+                if (! empty($arrayfields["ef.".$key]['checked']))
+                {
+                    print '<td';
+                    $align=$extrafields->getAlignFlag($key);
+                    if ($align) print ' align="'.$align.'"';
+                    print '>';
+                    $tmpkey='options_'.$key;
+                    print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1);
+                    print '</td>';
+                    if (! $i) $totalarray['nbfield']++;
+                }
+            }
+        }
+        // Fields from hook
+        $parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj);
+        $reshook=$hookmanager->executeHooks('printFieldListValue',$parameters);    // Note that $action and $object may have been modified by hook
+        print $hookmanager->resPrint;
+        // Date creation
+        if (! empty($arrayfields['p.datec']['checked']))
+        {
+            print '<td align="center" class="nowrap">';
+            print dol_print_date($db->jdate($obj->date_creation), 'dayhour');
+            print '</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // Date modification
+        if (! empty($arrayfields['p.tms']['checked']))
+        {
+            print '<td align="center" class="nowrap">';
+            print dol_print_date($db->jdate($obj->date_update), 'dayhour');
+            print '</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // Status
+        if (! empty($arrayfields['p.fk_statut']['checked']))
+        {
+            print '<td align="right" class="nowrap">'.$objectstatic->LibStatut($obj->fk_statut,5).'</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // Action column
+        print '<td></td>';
+        if (! $i) $totalarray['nbfield']++;
 
 		print "</tr>\n";
 
-		$total += $objp->total_ht;
-		$subtotal += $objp->total_ht;
-
 		$i++;
 	}
 
-	if ($total>0)
-			{
-				if($num<$limit){
-					$var=!$var;
-					print '<tr class="liste_total"><td align="left">'.$langs->trans("TotalHT").'</td>';
-					print '<td colspan="6" align="right">'.price($total).'</td><td colspan="3"></td>';
-					print '</tr>';
-				}
-				else
-				{
-					$var=!$var;
-					print '<tr class="liste_total"><td align="left">'.$langs->trans("TotalHTforthispage").'</td>';
-					print '<td colspan="6" align="right">'.price($total).'</td><td colspan="3"></td>';
-					print '</tr>';
-				}
-
-			}
+	// Show total line
+	if (isset($totalarray['totalhtfield']))
+	{
+		print '<tr class="liste_total">';
+		$i=0;
+		while ($i < $totalarray['nbfield'])
+		{
+		   $i++;
+		   if ($i == 1)
+	       {
+        		if ($num < $limit) print '<td align="left">'.$langs->trans("Total").'</td>';
+        		else print '<td align="left">'.$langs->trans("Totalforthispage").'</td>';
+	       }
+		   elseif ($totalarray['totalhtfield'] == $i) print '<td align="right">'.price($totalarray['totalht']).'</td>';
+		   elseif ($totalarray['totalvatfield'] == $i) print '<td align="right">'.price($totalarray['totalvat']).'</td>';
+		   elseif ($totalarray['totalttcfield'] == $i) print '<td align="right">'.price($totalarray['totalttc']).'</td>';
+		   else print '<td></td>';
+		}
+		print '</tr>';
+		
+	}
 
+	$db->free($result);
+	
+	$parameters=array('arrayfields'=>$arrayfields, 'sql'=>$sql);
+	$reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters);    // Note that $action and $object may have been modified by hook
+	print $hookmanager->resPrint;
+				
 	print '</table>';
 
 	print '</form>';
-
-	$db->free($result);
 }
 else
 {

+ 1 - 1
htdocs/comm/propal/stats/index.php

@@ -178,7 +178,7 @@ if (! $mesg)
     $px2->draw($filenameamount,$fileurlamount);
 }
 
-$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear, $filter);
+$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
 
 $fileurl_avg='';
 if (!$user->rights->societe->client->voir || $user->societe_id)

+ 3 - 24
htdocs/comm/propal/tpl/linkedobjectblock.tpl.php

@@ -33,19 +33,8 @@ global $user;
 $langs = $GLOBALS['langs'];
 $linkedObjectBlock = $GLOBALS['linkedObjectBlock'];
 
-echo '<br>';
-print load_fiche_titre($langs->trans('RelatedCommercialProposals'), '', '');
-?>
-<table class="noborder allwidth">
-<tr class="liste_titre">
-	<td><?php echo $langs->trans("Ref"); ?></td>
-	<td><?php echo $langs->trans('RefCustomer'); ?></td>
-	<td align="center"><?php echo $langs->trans("Date"); ?></td>
-	<td align="right"><?php echo $langs->trans("AmountHTShort"); ?></td>
-	<td align="right"><?php echo $langs->trans("Status"); ?></td>
-	<td></td>
-</tr>
-<?php
+$langs->load("propal");
+
 $var=true;
 $total=0;
 foreach($linkedObjectBlock as $key => $objectlink)
@@ -53,6 +42,7 @@ foreach($linkedObjectBlock as $key => $objectlink)
 	$var=!$var;
 ?>
 <tr <?php echo $bc[$var]; ?> >
+    <td><?php echo $langs->trans("Proposal"); ?></td>
     <td><?php echo $objectlink->getNomUrl(1); ?></td>
 	<td><?php echo $objectlink->ref_client; ?></td>
 	<td align="center"><?php echo dol_print_date($objectlink->date,'day'); ?></td>
@@ -66,17 +56,6 @@ foreach($linkedObjectBlock as $key => $objectlink)
 </tr>
 <?php
 }
-
 ?>
-<tr class="liste_total">
-	<td align="left" colspan="3"><?php echo $langs->trans('TotalHT'); ?></td>
-	<td align="right"><?php
-		if ($user->rights->propale->lire) {
-			echo price($total);
-		} ?></td>
-	<td></td>
-	<td></td>
-</tr>
-</table>
 
 <!-- END PHP TEMPLATE -->

+ 37 - 23
htdocs/commande/card.php

@@ -466,7 +466,7 @@ if (empty($reshook))
 
 	else if ($action == 'classifybilled' && $user->rights->commande->creer)
 	{
-		$ret=$object->classifyBilled();
+		$ret=$object->classifyBilled($user);
 
 		if ($ret < 0) {
 			setEventMessages($object->error, $object->errors, 'errors');
@@ -1442,7 +1442,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 	print '<table class="border" width="100%">';
 
 	// Reference
-	print '<tr><td width="25%" class="fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans("Draft") . '</td></tr>';
+	print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans("Draft") . '</td></tr>';
 
 	// Reference client
 	print '<tr><td>' . $langs->trans('RefCustomer') . '</td><td colspan="2">';
@@ -1732,8 +1732,12 @@ if ($action == 'create' && $user->rights->commande->creer)
 	dol_fiche_end();
 
 	// Button "Create Draft"
-	print '<div class="center"><input type="submit" class="button" name="bouton" value="' . $langs->trans('CreateDraft') . '"></div>';
-
+	print '<div class="center">';
+	print '<input type="submit" class="button" name="bouton" value="' . $langs->trans('CreateDraft') . '">';
+	print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+	print '<input type="button" class="button" value="' . $langs->trans("Cancel") . '" onClick="javascript:history.go(-1)">';
+	print '</div>';
+	
 	print '</form>';
 
 	// Show origin lines
@@ -1949,7 +1953,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 		$linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
 
 		// Ref
-		print '<tr><td width="18%">' . $langs->trans('Ref') . '</td>';
+		print '<tr><td class="titlefield">' . $langs->trans('Ref') . '</td>';
 		print '<td colspan="3">';
 		print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref');
 		print '</td>';
@@ -1989,10 +1993,23 @@ if ($action == 'create' && $user->rights->commande->creer)
         if ($action == 'editthirdparty') {
             $form->form_thirdparty($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, 'socid','client>0');
         } else {
-            print ' &nbsp;' . $soc->getNomUrl(1, 'compta');
+            print $soc->getNomUrl(1, 'compta');
         }
 		print '</tr>';
 
+		if ($soc->outstanding_limit)
+		{
+		    // Outstanding Bill
+		    print '<tr><td>';
+		    print $langs->trans('OutstandingBill');
+		    print '</td><td colspan="3">';
+		    print price($soc->get_OutstandingBill()) . ' / ';
+		    print price($soc->outstanding_limit, 0, '', 1, - 1, - 1, $conf->currency);
+		    print '</td>';
+		    print '</tr>';
+		}
+		
+		// Relative and absolute discounts
 		if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
 			$filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final
 			                                                     // invoice
@@ -2002,7 +2019,6 @@ if ($action == 'create' && $user->rights->commande->creer)
 			$filtercreditnote = "fk_facture_source IS NOT NULL AND description <> '(DEPOSIT)'";
 		}
 
-		// Relative and absolute discounts
 		$addrelativediscount = '<a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditRelativeDiscounts") . '</a>';
 		$addabsolutediscount = '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditGlobalDiscounts") . '</a>';
 		$addcreditnote = '<a href="' . DOL_URL_ROOT . '/compta/facture.php?action=create&socid=' . $soc->id . '&type=2&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("AddCreditNote") . '</a>';
@@ -2232,6 +2248,19 @@ if ($action == 'create' && $user->rights->commande->creer)
 		// print '<a href="'.DOL_URL_ROOT.'/admin/dict.php?id=22&origin=order&originid='.$object->id.'">'.$langs->trans("DictionarySource").'</a>';
 		print '</td></tr>';
 
+		$tmparray=$object->getTotalWeightVolume();
+		$totalWeight=$tmparray['weight'];
+		$totalVolume=$tmparray['volume'];
+		if ($totalWeight || $totalVolume)
+		{
+    		print '<tr><td>'.$langs->trans("CalculatedWeight").' / '.$langs->trans("CalculatedVolume").'</td>';
+    		print '<td colspan="3">';
+    		print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
+        	print ' / ';
+    		print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
+    		print '</td></tr>';
+		}		
+		
     	// TODO How record was recorded OrderMode (llx_c_input_method)
 
 		// Project
@@ -2255,18 +2284,6 @@ if ($action == 'create' && $user->rights->commande->creer)
 			print '</td></tr>';
 		}
 
-		if ($soc->outstanding_limit)
-		{
-			// Outstanding Bill
-			print '<tr><td>';
-			print $langs->trans('OutstandingBill');
-			print '</td><td align=right colspan=3>';
-			print price($soc->get_OutstandingBill()) . ' / ';
-			print price($soc->outstanding_limit, 0, '', 1, - 1, - 1, $conf->currency);
-			print '</td>';
-			print '</tr>';
-		}
-
 		// Incoterms
 		if (!empty($conf->incoterm->enabled))
 		{
@@ -2655,10 +2672,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 			$formmail->fromid = $user->id;
 			$formmail->fromname = $user->getFullName($langs);
 			$formmail->frommail = $user->email;
-			if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 1))	// If bit 1 is set
-			{
-				$formmail->trackid='ord'.$object->id;
-			}
+			$formmail->trackid='ord'.$object->id;
 			if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2))	// If bit 2 is set
 			{
 				include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';

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

@@ -186,7 +186,7 @@ class CommandeApi extends DolibarrApi
      * 
      * @url     POST    order/
      * 
-     * @return  int     ID of commande
+     * @return  string     ID of commande
      */
     function post($request_data = NULL)
     {

+ 18 - 86
htdocs/commande/class/commande.class.php

@@ -166,9 +166,13 @@ class Commande extends CommonOrder
 	 */
 	const STATUS_VALIDATED = 1;
 	/**
-	 * Accepted/On process not managed for customer orders
+	 * Accepted (supplier orders)
 	 */
 	const STATUS_ACCEPTED = 2;
+	/**
+	 * Shipment on process (customer orders)
+	 */
+	const STATUS_SHIPMENTONPROCESS = 2;
 	/**
 	 * Closed (Sent/Received, billed or not)
 	 */
@@ -1714,7 +1718,8 @@ class Commande extends CommonOrder
         $sql.= ' l.total_ht, l.total_ttc, l.total_tva, l.total_localtax1, l.total_localtax2, l.date_start, l.date_end,';
 	    $sql.= ' l.fk_unit,';
 		$sql.= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
-        $sql.= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label';
+        $sql.= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label,';
+        $sql.= ' p.weight, p.weight_units, p.volume, p.volume_units';
         $sql.= ' FROM '.MAIN_DB_PREFIX.'commandedet as l';
         $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON (p.rowid = l.fk_product)';
         $sql.= ' WHERE l.fk_commande = '.$this->id;
@@ -1773,6 +1778,11 @@ class Commande extends CommonOrder
                 $line->product_desc     = $objp->product_desc;
                 $line->fk_product_type  = $objp->fk_product_type;	// Produit ou service
 	            $line->fk_unit          = $objp->fk_unit;
+	            
+	            $line->weight           = $objp->weight;
+	            $line->weight_units     = $objp->weight_units;
+	            $line->volume           = $objp->volume;
+	            $line->volume_units     = $objp->volume_units;
 
                 $line->date_start       = $this->db->jdate($objp->date_start);
                 $line->date_end         = $this->db->jdate($objp->date_end);
@@ -1833,7 +1843,7 @@ class Commande extends CommonOrder
     }
 
     /**
-     *	Load array this->expeditions of nb of products sent by line in order
+     *	Load array this->expeditions of lines of shipments with nb of products sent for each order line
      *
      *	@param      int		$filtre_statut      Filter on status
      * 	@return     int                			<0 if KO, Nb of lines found if OK
@@ -2410,9 +2420,10 @@ class Commande extends CommonOrder
 	/**
 	 * Classify the order as invoiced
 	 *
-	 * @return     int     <0 if ko, >0 if ok
+	 * @param      User    $user       Object user making the change
+	 * @return     int                 <0 if KO, >0 if OK
 	 */
-	function classifyBilled()
+	function classifyBilled(User $user)
 	{
 		global $conf, $user, $langs;
         $error = 0;
@@ -2466,9 +2477,10 @@ class Commande extends CommonOrder
 	 */
 	function classer_facturee()
 	{
+	    global $user;
 		dol_syslog(__METHOD__ . " is deprecated", LOG_WARNING);
 
-		return $this->classifyBilled();
+		return $this->classifyBilled($user);
 	}
 
 
@@ -3291,86 +3303,6 @@ class Commande extends CommonOrder
     function getLinesArray()
     {
         return $this->fetch_lines();
-        /*
-        $lines = array();
-
-        $sql = 'SELECT l.rowid, l.fk_product, l.product_type, l.label as custom_label, l.description, l.price, l.qty, l.tva_tx, ';
-        $sql.= ' l.fk_remise_except, l.remise_percent, l.subprice, l.info_bits, l.rang, l.special_code, l.fk_parent_line,';
-        $sql.= ' l.total_ht, l.total_tva, l.total_ttc, l.fk_product_fournisseur_price as fk_fournprice, l.buy_price_ht as pa_ht, l.localtax1_tx, l.localtax2_tx,';
-        $sql.= ' l.date_start, l.date_end,';
-	    $sql.= ' l.fk_unit,';
-		$sql.= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
-        $sql.= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, ';
-        $sql.= ' p.description as product_desc, p.stock as stock_reel,';
-        $sql.= ' p.entity';
-        $sql.= ' FROM '.MAIN_DB_PREFIX.'commandedet as l';
-        $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product=p.rowid';
-        $sql.= ' WHERE l.fk_commande = '.$this->id;
-        $sql.= ' ORDER BY l.rang ASC, l.rowid';
-
-        $resql = $this->db->query($sql);
-        if ($resql)
-        {
-            $num = $this->db->num_rows($resql);
-            $i = 0;
-
-            while ($i < $num)
-            {
-                $obj = $this->db->fetch_object($resql);
-
-				$this->lines[$i]					= new OrderLine($this->db);
-                $this->lines[$i]->id				= $obj->rowid;
-                $this->lines[$i]->label 			= $obj->custom_label;
-                $this->lines[$i]->description 		= $obj->description;
-                $this->lines[$i]->fk_product		= $obj->fk_product;
-                $this->lines[$i]->ref				= $obj->ref;
-                $this->lines[$i]->entity            = $obj->entity;         // Product entity
-                $this->lines[$i]->product_label		= $obj->product_label;
-                $this->lines[$i]->product_desc		= $obj->product_desc;
-                $this->lines[$i]->fk_product_type	= $obj->fk_product_type;
-                $this->lines[$i]->product_type		= $obj->product_type;
-                $this->lines[$i]->qty				= $obj->qty;
-                $this->lines[$i]->subprice			= $obj->subprice;
-                $this->lines[$i]->fk_remise_except 	= $obj->fk_remise_except;
-                $this->lines[$i]->remise_percent	= $obj->remise_percent;
-                $this->lines[$i]->tva_tx			= $obj->tva_tx;
-                $this->lines[$i]->info_bits			= $obj->info_bits;
-                $this->lines[$i]->total_ht			= $obj->total_ht;
-                $this->lines[$i]->total_tva			= $obj->total_tva;
-                $this->lines[$i]->total_ttc			= $obj->total_ttc;
-                $this->lines[$i]->fk_parent_line	= $obj->fk_parent_line;
-                $this->lines[$i]->special_code		= $obj->special_code;
-				$this->lines[$i]->stock				= $obj->stock_reel;
-                $this->lines[$i]->rang				= $obj->rang;
-                $this->lines[$i]->date_start		= $this->db->jdate($obj->date_start);
-                $this->lines[$i]->date_end			= $this->db->jdate($obj->date_end);
-				$this->lines[$i]->fk_fournprice		= $obj->fk_fournprice;
-				$marginInfos						= getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->lines[$i]->fk_fournprice, $obj->pa_ht);
-				$this->lines[$i]->pa_ht				= $marginInfos[0];
-				$this->lines[$i]->marge_tx			= $marginInfos[1];
-				$this->lines[$i]->marque_tx			= $marginInfos[2];
-	            $this->lines[$i]->fk_unit			= $obj->fk_unit;
-				
-				// Multicurrency
-				$this->lines[$i]->fk_multicurrency 			= $obj->fk_multicurrency;
-				$this->lines[$i]->multicurrency_code 		= $obj->multicurrency_code;
-				$this->lines[$i]->multicurrency_subprice 	= $obj->multicurrency_subprice;
-				$this->lines[$i]->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
-				$this->lines[$i]->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
-				$this->lines[$i]->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
-				
-                $i++;
-            }
-
-            $this->db->free($resql);
-
-            return 1;
-        }
-        else
-        {
-            $this->error=$this->db->error();
-            return -1;
-        }*/
     }
 
 	/**

+ 1 - 1
htdocs/commande/contact.php

@@ -155,7 +155,7 @@ if ($id > 0 || ! empty($ref))
 		$linkback = '<a href="'.DOL_URL_ROOT.'/commande/list.php'.(! empty($socid)?'?socid='.$socid:'').'">'.$langs->trans("BackToList").'</a>';
 
 		// Ref
-		print '<tr><td width="18%">'.$langs->trans("Ref").'</td><td colspan="3">';
+		print '<tr><td class="titlefield">'.$langs->trans("Ref").'</td><td colspan="3">';
 		print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref');
 		print "</td></tr>";
 

+ 1 - 1
htdocs/commande/document.php

@@ -72,7 +72,7 @@ if ($object->fetch($id))
 	$upload_dir = $conf->commande->dir_output . "/" . dol_sanitizeFileName($object->ref);
 }
 
-include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

+ 638 - 250
htdocs/commande/list.php

@@ -34,12 +34,15 @@
 
 require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
-require_once DOL_DOCUMENT_ROOT .'/product/class/product.class.php';
+require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
 
 $langs->load('orders');
+$langs->load('sendings');
 $langs->load('deliveries');
 $langs->load('companies');
 $langs->load('compta');
@@ -55,6 +58,11 @@ $search_product_category=GETPOST('search_product_category','int');
 $search_ref=GETPOST('search_ref','alpha')!=''?GETPOST('search_ref','alpha'):GETPOST('sref','alpha');
 $search_ref_customer=GETPOST('search_ref_customer','alpha');
 $search_company=GETPOST('search_company','alpha');
+$search_town=GETPOST('search_town','alpha');
+$search_zip=GETPOST('search_zip','alpha');
+$search_state=trim(GETPOST("search_state"));
+$search_country=GETPOST("search_country",'int');
+$search_type_thirdparty=GETPOST("search_type_thirdparty",'int');
 $sall=GETPOST('sall');
 $socid=GETPOST('socid','int');
 $search_user=GETPOST('search_user','int');
@@ -68,6 +76,8 @@ $id = (GETPOST('orderid')?GETPOST('orderid'):GETPOST('id','int'));
 if ($user->societe_id) $socid=$user->societe_id;
 $result = restrictedArea($user, 'commande', $id,'');
 
+$diroutputmassaction=$conf->commande->dir_output . '/temp/massgeneration/'.$user->id;
+
 $limit = GETPOST("limit")?GETPOST("limit","int"):$conf->liste_limit;
 $sortfield = GETPOST("sortfield",'alpha');
 $sortorder = GETPOST("sortorder",'alpha');
@@ -79,10 +89,18 @@ $pagenext = $page + 1;
 if (! $sortfield) $sortfield='c.ref';
 if (! $sortorder) $sortorder='DESC';
 
+// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
+$contextpage='orderlist';
+
 $viewstatut=GETPOST('viewstatut');
 
 // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
 $hookmanager->initHooks(array('orderlist'));
+$extrafields = new ExtraFields($db);
+
+// fetch optionals attributes and labels
+$extralabels = $extrafields->fetch_name_optionals_label('commande');
+$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_');
 
 // List of fields to search into when doing a "search in all"
 $fieldstosearchall = array(
@@ -94,24 +112,47 @@ $fieldstosearchall = array(
 );
 if (empty($user->socid)) $fieldstosearchall["c.note_private"]="NotePrivate";
 
+$checkedtypetiers=0;
 $arrayfields=array(
+    'c.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1),
+    'c.ref_client'=>array('label'=>$langs->trans("RefCustomerOrder"), 'checked'=>1),
+    's.nom'=>array('label'=>$langs->trans("ThirdParty"), 'checked'=>1),
+    's.town'=>array('label'=>$langs->trans("Town"), 'checked'=>1),
+    's.zip'=>array('label'=>$langs->trans("Zip"), 'checked'=>1),
+    'state.nom'=>array('label'=>$langs->trans("StateShort"), 'checked'=>0),
+    'country.code_iso'=>array('label'=>$langs->trans("Country"), 'checked'=>0),
+    'typent.code'=>array('label'=>$langs->trans("ThirdPartyType"), 'checked'=>$checkedtypetiers),
+    'c.date_commande'=>array('label'=>$langs->trans("OrderDateShort"), 'checked'=>1),
+    'c.date_delivery'=>array('label'=>$langs->trans("DateDeliveryPlanned"), 'checked'=>1, 'enabled'=>empty($conf->global->ORDER_DISABLE_DELIVERY_DATE)),
+    'c.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500),
+    'c.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500),
+    'c.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000),
+    'e.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000, 'enabled'=>(empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)))
 );
 // Extra fields
-/*
- if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
- {
- foreach($extrafields->attribute_label as $key => $val)
- {
- $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]);
- }
- }
- */
+if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+{
+    foreach($extrafields->attribute_label as $key => $val)
+    {
+        $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]);
+    }
+}
+
 
 
 /*
  * Actions
  */
 
+if (GETPOST('cancel')) { $action='list'; $massaction=''; }
+if (! GETPOST('confirmmassaction')) { $massaction=''; }
+
+$parameters=array('socid'=>$socid);
+$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+
+include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
+
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
 {
@@ -122,7 +163,15 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
     $search_ref='';
     $search_ref_customer='';
     $search_company='';
+    $search_town='';
+	$search_zip="";
+    $search_state="";
+	$search_type='';
+	$search_country='';
+	$search_type_thirdparty='';
     $search_total_ht='';
+    $search_total_vat='';
+    $search_total_ttc='';
     $orderyear='';
     $ordermonth='';
 	$orderday='';
@@ -131,11 +180,27 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
     $deliveryyear='';
     $viewstatut='';
     $billed='';
+    $search_array_options=array();
 }
 
-$parameters=array('socid'=>$socid);
-$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hook
-if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+if (empty($reshook))
+{
+    // Mass actions. Controls on number of lines checked
+    $maxformassaction=1000;
+    if (! empty($massaction) && count($toselect) < 1)
+    {
+        $error++;
+        setEventMessages($langs->trans("NoLineChecked"), null, "warnings");
+    }
+    if (! $error && count($toselect) > $maxformassaction)
+    {
+        setEventMessages($langs->trans('TooManyRecordForMassAction',$maxformassaction), null, 'errors');
+        $error++;
+    }
+
+}
+
+
 
 
 /*
@@ -148,16 +213,31 @@ $form = new Form($db);
 $formother = new FormOther($db);
 $formfile = new FormFile($db);
 $companystatic = new Societe($db);
+$formcompany=new FormCompany($db);
 
 $help_url="EN:Module_Customers_Orders|FR:Module_Commandes_Clients|ES:Módulo_Pedidos_de_clientes";
 llxHeader('',$langs->trans("Orders"),$help_url);
 
 $sql = 'SELECT';
 if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT';
-$sql.= ' s.nom as name, s.rowid as socid, s.client, s.code_client, c.rowid, c.ref, c.total_ht, c.tva as total_tva, c.total_ttc, c.ref_client,';
-$sql.= ' c.date_valid, c.date_commande, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed';
+$sql.= ' s.rowid as socid, s.nom as name, s.town, s.zip, s.fk_pays, s.client, s.code_client, ';
+$sql.= " typent.code as typent_code,";
+$sql.= " state.code_departement as state_code, state.nom as state_name,";
+$sql.= ' c.rowid, c.ref, c.total_ht, c.tva as total_tva, c.total_ttc, c.ref_client,';
+$sql.= ' c.date_valid, c.date_commande, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed,';
+$sql.= ' c.date_creation as date_creation, c.tms as date_update';
+// Add fields from extrafields
+foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
+// Add fields from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
 $sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s';
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)";
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_typent as typent on (typent.id = s.fk_typent)";
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = s.fk_departement)";
 $sql.= ', '.MAIN_DB_PREFIX.'commande as c';
+if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."commande_extrafields as ef on (c.rowid = ef.fk_object)";
 if ($sall || $search_product_category > 0) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'commandedet as pd ON c.rowid=pd.fk_commande';
 if ($search_product_category > 0) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=pd.fk_product';
 // We'll need this table joined to the select in order to filter by sale
@@ -224,11 +304,35 @@ else if ($deliveryyear > 0)
 {
     $sql.= " AND c.date_livraison BETWEEN '".$db->idate(dol_get_first_day($deliveryyear,1,false))."' AND '".$db->idate(dol_get_last_day($deliveryyear,12,false))."'";
 }
-if (!empty($search_company)) $sql .= natural_search('s.nom', $search_company);
-if (!empty($search_ref_customer)) $sql.= natural_search('c.ref_client', $search_ref_customer);
+if ($search_town)  $sql.= natural_search('s.town', $search_town);
+if ($search_zip)   $sql.= natural_search("s.zip",$search_zip);
+if ($search_state) $sql.= natural_search("state.nom",$search_state);
+if ($search_country) $sql .= " AND s.fk_pays IN (".$search_country.')';
+if ($search_type_thirdparty) $sql .= " AND s.fk_typent IN (".$search_type_thirdparty.')';
+if ($search_company) $sql .= natural_search('s.nom', $search_company);
+if ($search_ref_customer) $sql.= natural_search('c.ref_client', $search_ref_customer);
 if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$search_sale;
 if ($search_user > 0) $sql.= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='commande' AND tc.source='internal' AND ec.element_id = c.rowid AND ec.fk_socpeople = ".$search_user;
 if ($search_total_ht != '') $sql.= natural_search('c.total_ht', $search_total_ht, 1);
+
+// Add where from extra fields
+foreach ($search_array_options as $key => $val)
+{
+    $crit=$val;
+    $tmpkey=preg_replace('/search_options_/','',$key);
+    $typ=$extrafields->attribute_type[$tmpkey];
+    $mode=0;
+    if (in_array($typ, array('int','double'))) $mode=1;    // Search on a numeric
+    if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit)))
+    {
+        $sql .= natural_search('ef.'.$tmpkey, $crit, $mode);
+    }
+}
+// Add where from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+
 $sql.= $db->order($sortfield,$sortorder);
 
 $nbtotalofrecords = 0;
@@ -271,6 +375,8 @@ if ($resql)
 	if ($viewstatut == -3)
 	$title.=' - '.$langs->trans('StatusOrderValidated').', '.(empty($conf->expedition->enabled)?'':$langs->trans("StatusOrderSent").', ').$langs->trans('StatusOrderToBill');
 
+	$num = $db->num_rows($resql);
+	
 	$param='';
     if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit;
 	if ($socid > 0)             $param.='&socid='.$socid;
@@ -288,13 +394,21 @@ if ($resql)
 	if ($search_sale > 0) 		$param.='&search_sale='.$search_sale;
 	if ($search_total_ht != '') $param.='&search_total_ht='.$search_total_ht;
 	if ($optioncss != '')       $param.='&optioncss='.$optioncss;
-
-	$num = $db->num_rows($resql);
+	// Add $param from extra fields
+	foreach ($search_array_options as $key => $val)
+	{
+	    $crit=$val;
+	    $tmpkey=preg_replace('/search_options_/','',$key);
+	    if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val);
+	}
+	
+	//$massactionbutton=$form->selectMassAction('', $massaction == 'presend' ? array() : array('presend'=>$langs->trans("SendByMail"), 'builddoc'=>$langs->trans("PDFMerge")));
 	
 	// Lignes des champs de filtre
 	print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
     if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
 	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
 	print '<input type="hidden" name="action" value="list">';
 	print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 	print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
@@ -348,38 +462,105 @@ if ($resql)
     	print '</div>';
 	}
 
-    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">';
+    $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
+    $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
+	
+	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans('Ref'),$_SERVER["PHP_SELF"],'c.ref','',$param,'width="25%"',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('RefCustomerOrder'),$_SERVER["PHP_SELF"],'c.ref_client','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('ThirdParty'),$_SERVER["PHP_SELF"],'s.nom','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('OrderDate'),$_SERVER["PHP_SELF"],'c.date_commande','',$param, 'align="center"',$sortfield,$sortorder);
-	if (empty($conf->global->ORDER_DISABLE_DELIVERY_DATE)) print_liste_field_titre($langs->trans('DeliveryDate'),$_SERVER["PHP_SELF"],'c.date_livraison','',$param, 'align="center"',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('AmountHT'),$_SERVER["PHP_SELF"],'c.total_ht','',$param, 'align="right"',$sortfield,$sortorder);
-	$parameters=array();
+	if (! empty($arrayfields['c.ref']['checked']))            print_liste_field_titre($arrayfields['c.ref']['label'],$_SERVER["PHP_SELF"],'c.ref','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.ref_client']['checked']))     print_liste_field_titre($arrayfields['c.ref_client']['label'],$_SERVER["PHP_SELF"],'c.ref_client','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.nom']['checked']))            print_liste_field_titre($arrayfields['s.nom']['label'],$_SERVER["PHP_SELF"],'s.nom','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.town']['checked']))           print_liste_field_titre($arrayfields['s.town']['label'],$_SERVER["PHP_SELF"],'s.town','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.zip']['checked']))            print_liste_field_titre($arrayfields['s.zip']['label'],$_SERVER["PHP_SELF"],'s.zip','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['state.nom']['checked']))        print_liste_field_titre($arrayfields['state.nom']['label'],$_SERVER["PHP_SELF"],"state.nom","",$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['country.code_iso']['checked'])) print_liste_field_titre($arrayfields['country.code_iso']['label'],$_SERVER["PHP_SELF"],"country.code_iso","",$param,'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['typent.code']['checked']))      print_liste_field_titre($arrayfields['typent.code']['label'],$_SERVER["PHP_SELF"],"typent.code","",$param,'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.date_commande']['checked']))  print_liste_field_titre($arrayfields['c.date_commande']['label'],$_SERVER["PHP_SELF"],'c.date_commande','',$param, 'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.date_delivery']['checked']))  print_liste_field_titre($arrayfields['c.date_delivery']['label'],$_SERVER["PHP_SELF"],'c.date_livraison','',$param, 'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.total_ht']['checked']))       print_liste_field_titre($arrayfields['c.total_ht']['label'],$_SERVER["PHP_SELF"],'c.total_ht','',$param, 'align="right"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.tva']['checked']))            print_liste_field_titre($arrayfields['c.tva']['label'],$_SERVER["PHP_SELF"],'c.total_vat','',$param, 'align="right"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.total_ttc']['checked']))      print_liste_field_titre($arrayfields['c.total_ttc']['label'],$_SERVER["PHP_SELF"],'c.total_ttc','',$param, 'align="right"',$sortfield,$sortorder);
+	// Extra fields
+	if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+	{
+	   foreach($extrafields->attribute_label as $key => $val) 
+	   {
+           if (! empty($arrayfields["ef.".$key]['checked'])) 
+           {
+				$align=$extrafields->getAlignFlag($key);
+				print_liste_field_titre($extralabels[$key],$_SERVER["PHP_SELF"],"ef.".$key,"",$param,($align?'align="'.$align.'"':''),$sortfield,$sortorder);
+           }
+	   }
+	}
+	// Hook fields
+	$parameters=array('arrayfields'=>$arrayfields);
     $reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters);    // Note that $action and $object may have been modified by hook
     print $hookmanager->resPrint;
-	print_liste_field_titre($langs->trans('Status'),$_SERVER["PHP_SELF"],'c.fk_statut','',$param,'align="right"',$sortfield,$sortorder);
-	if (empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) print_liste_field_titre($langs->trans('Billed'),$_SERVER["PHP_SELF"],'c.facture','',$param,'align="center"',$sortfield,$sortorder,'');
-	print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'',$param,'',$sortfield,$sortorder,'maxwidthsearch ');
+	if (! empty($arrayfields['c.datec']['checked']))     print_liste_field_titre($arrayfields['c.datec']['label'],$_SERVER["PHP_SELF"],"c.date_creation","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.tms']['checked']))       print_liste_field_titre($arrayfields['c.tms']['label'],$_SERVER["PHP_SELF"],"c.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.fk_statut']['checked'])) print_liste_field_titre($arrayfields['c.fk_statut']['label'],$_SERVER["PHP_SELF"],"c.fk_statut","",$param,'align="right"',$sortfield,$sortorder);
+	if (! empty($arrayfields['c.facture']['checked']))   print_liste_field_titre($arrayfields['c.facture']['label'],$_SERVER["PHP_SELF"],'c.facture','',$param,'align="center"',$sortfield,$sortorder,'');
+	print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="right"',$sortfield,$sortorder,'maxwidthsearch ');
 	print '</tr>';
 
 	print '<tr class="liste_titre">';
-	print '<td class="liste_titre">';
-	print '<input class="flat" size="6" type="text" name="search_ref" value="'.$search_ref.'">';
-	print '</td>';
-	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" size="6" name="search_ref_customer" value="'.$search_ref_customer.'">';
-	print '</td>';
-	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_company" value="'.$search_company.'">';
-	print '</td>';
-	print '<td class="liste_titre" align="center">';
-    if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="orderday" value="'.$orderday.'">';
-    print '<input class="flat" type="text" size="1" maxlength="2" name="ordermonth" value="'.$ordermonth.'">';
-    $formother->select_year($orderyear?$orderyear:-1,'orderyear',1, 20, 5);
-	print '</td>';
-	if (empty($conf->global->ORDER_DISABLE_DELIVERY_DATE)) 
+	// Ref
+	if (! empty($arrayfields['c.ref']['checked'])) 
+	{
+	    print '<td class="liste_titre">';
+    	print '<input class="flat" size="6" type="text" name="search_ref" value="'.$search_ref.'">';
+	    print '</td>';
+	}
+	// Ref customer
+	if (! empty($arrayfields['c.ref_client']['checked'])) 
+	{
+    	print '<td class="liste_titre" align="left">';
+    	print '<input class="flat" type="text" size="6" name="search_ref_customer" value="'.$search_ref_customer.'">';
+    	print '</td>';
+	}
+	// Thirpdarty
+	if (! empty($arrayfields['s.nom']['checked'])) 
+	{
+    	print '<td class="liste_titre" align="left">';
+    	print '<input class="flat" type="text" name="search_company" value="'.$search_company.'">';
+    	print '</td>';
+	}
+	// Town
+	if (! empty($arrayfields['s.town']['checked'])) print '<td class="liste_titre"><input class="flat" type="text" size="6" name="search_town" value="'.$search_town.'"></td>';
+	// Zip
+	if (! empty($arrayfields['s.zip']['checked'])) print '<td class="liste_titre"><input class="flat" type="text" size="6" name="search_zip" value="'.$search_zip.'"></td>';
+	// State
+	if (! empty($arrayfields['state.nom']['checked']))
+	{
+	    print '<td class="liste_titre">';
+	    print '<input class="flat" size="4" type="text" name="search_state" value="'.dol_escape_htmltag($search_state).'">';
+	    print '</td>';
+	}
+	// Country
+	if (! empty($arrayfields['country.code_iso']['checked']))
+	{
+	    print '<td class="liste_titre" align="center">';
+	    print $form->select_country($search_country,'search_country','',0,'maxwidth100');
+	    print '</td>';
+	}
+	// Company type
+	if (! empty($arrayfields['typent.code']['checked']))
+	{
+	    print '<td class="liste_titre maxwidthonsmartphone" align="center">';
+	    print $form->selectarray("search_type_thirdparty", $formcompany->typent_array(0), $search_type_thirdparty, 0, 0, 0, '', 0, 0, 0, (empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?'ASC':$conf->global->SOCIETE_SORT_ON_TYPEENT));
+	    print '</td>';
+	}
+	// Date order
+	if (! empty($arrayfields['c.date_commande']['checked']))
+	{
+    	print '<td class="liste_titre" align="center">';
+        if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="orderday" value="'.$orderday.'">';
+        print '<input class="flat" type="text" size="1" maxlength="2" name="ordermonth" value="'.$ordermonth.'">';
+        $formother->select_year($orderyear?$orderyear:-1,'orderyear',1, 20, 5);
+    	print '</td>';
+	}
+	if (! empty($arrayfields['c.date_delivery']['checked'])) 
 	{
     	print '<td class="liste_titre" align="center">';
         if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="deliveryday" value="'.$deliveryday.'">';
@@ -387,266 +568,473 @@ if ($resql)
         $formother->select_year($deliveryyear?$deliveryyear:-1,'deliveryyear',1, 20, 5);
     	print '</td>';
 	}
-	print '<td class="liste_titre" align="right">';
-	print '<input class="flat" type="text" size="6" name="search_total_ht" value="'.$search_total_ht.'">';
-	print '</td>';
-	print '<td align="right">';
-	$liststatus=array(
-	    '0'=>$langs->trans("StatusOrderDraftShort"), 
-	    '1'=>$langs->trans("StatusOrderValidated"), 
-	    '2'=>$langs->trans("StatusOrderSentShort"), 
-	    '3'=>$langs->trans("StatusOrderDelivered"), 
-	    '-1'=>$langs->trans("StatusOrderCanceledShort")
-	);
-	print $form->selectarray('viewstatut', $liststatus, $viewstatut, -4);
-	print '</td>';
-	if (empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))
+	if (! empty($arrayfields['c.total_ht']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_total_ht" value="'.$search_total_ht.'">';
+    	print '</td>';
+	}
+	if (! empty($arrayfields['c.total_vat']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_total_vat" value="'.$search_total_vat.'">';
+    	print '</td>';
+	}
+	if (! empty($arrayfields['c.total_ttc']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_total_ttc" value="'.$search_total_ttc.'">';
+    	print '</td>';
+	}
+	// Extra fields
+	if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+	{
+	    foreach($extrafields->attribute_label as $key => $val)
+	    {
+	        if (! empty($arrayfields["ef.".$key]['checked']))
+	        {
+	            $align=$extrafields->getAlignFlag($key);
+	            $typeofextrafield=$extrafields->attribute_type[$key];
+	            print '<td class="liste_titre'.($align?' '.$align:'').'">';
+	            if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')))
+	            {
+	                $crit=$val;
+	                $tmpkey=preg_replace('/search_options_/','',$key);
+	                $searchclass='';
+	                if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring';
+	                if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum';
+	                print '<input class="flat'.($searchclass?' '.$searchclass:'').'" size="4" type="text" name="search_options_'.$tmpkey.'" value="'.dol_escape_htmltag($search_array_options['search_options_'.$tmpkey]).'">';
+	            }
+	            print '</td>';
+	        }
+	    }
+	}
+	// Fields from hook
+	$parameters=array('arrayfields'=>$arrayfields);
+	$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters);    // Note that $action and $object may have been modified by hook
+	print $hookmanager->resPrint;
+	// Date creation
+	if (! empty($arrayfields['c.datec']['checked']))
 	{
-	    print '<td align="center">';
-    	print $form->selectyesno('billed', $billed, 1, 0, 1);
+	    print '<td class="liste_titre">';
 	    print '</td>';
 	}
-    print '<td class="liste_titre" align="right">';
-    $searchpitco=$form->showFilterAndCheckAddButtons(0);
-    print $searchpitco;
-    print '</td>';
-	print "</tr>\n";
+	// Date modification
+	if (! empty($arrayfields['c.tms']['checked']))
+	{
+	    print '<td class="liste_titre">';
+	    print '</td>';
+	}
+	// Status
+	if (! empty($arrayfields['c.fk_statut']['checked']))
+	{
+	    print '<td class="liste_titre maxwidthonsmartphone" align="right">';
+    	$liststatus=array(
+    	    '0'=>$langs->trans("StatusOrderDraftShort"), 
+    	    '1'=>$langs->trans("StatusOrderValidated"), 
+    	    '2'=>$langs->trans("StatusOrderSentShort"), 
+    	    '3'=>$langs->trans("StatusOrderDelivered"), 
+    	    '-1'=>$langs->trans("StatusOrderCanceledShort")
+    	);
+    	print $form->selectarray('viewstatut', $liststatus, $viewstatut, -4);
+	    print '</td>';
+	}
+	// Status
+	if (! empty($arrayfields['c.facture']['checked']))
+	{
+	    print '<td class="liste_titre maxwidthonsmartphone" align="right">';
+	    print $form->selectyesno('billed', $billed, 1, 0, 1);
+	    print '</td>';
+	}
+	// Action column
+	print '<td class="liste_titre" align="middle">';
+	$searchpitco=$form->showFilterAndCheckAddButtons(0);
+	print $searchpitco;
+	print '</td>';
+	
+    print "</tr>\n";
 
-	$var=true;
 	$total=0;
 	$subtotal=0;
     $productstat_cache=array();
-    $i=0;
     
     $generic_commande = new Commande($db);
     $generic_product = new Product($db);
+	
+    $i=0;
+	$var=true;
+	$totalarray=array();
     while ($i < min($num,$limit))
     {
-        $objp = $db->fetch_object($resql);
+        $obj = $db->fetch_object($resql);
         $var=!$var;
         print '<tr '.$bc[$var].'>';
-        print '<td class="nowrap">';
-        $generic_commande->id=$objp->rowid;
-        $generic_commande->ref=$objp->ref;
-	    $generic_commande->statut = $objp->fk_statut;
-	    $generic_commande->date_commande = $db->jdate($objp->date_commande);
-	    $generic_commande->date_livraison = $db->jdate($objp->date_delivery);
-        $generic_commande->ref_client = $objp->ref_client;
-        $generic_commande->total_ht = $objp->total_ht;
-        $generic_commande->total_tva = $objp->total_tva;
-        $generic_commande->total_ttc = $objp->total_ttc;
-        $generic_commande->lines=array();
-        $generic_commande->getLinesArray();
-
-        print '<table class="nobordernopadding"><tr class="nocellnopadd">';
-        print '<td class="nobordernopadding nowrap">';
-        print $generic_commande->getNomUrl(1,($viewstatut != 2?0:$objp->fk_statut));
-        print '</td>';
-
-        // Show shippable Icon (create subloop, so may be slow)
-        if ($conf->stock->enabled) 
+
+        if (! empty($arrayfields['c.ref']['checked']))
         {
-            $langs->load("stocks");
-            if (($objp->fk_statut > 0) && ($objp->fk_statut < 3))
+            print '<td class="nowrap">';
+            $generic_commande->id=$obj->rowid;
+            $generic_commande->ref=$obj->ref;
+    	    $generic_commande->statut = $obj->fk_statut;
+    	    $generic_commande->date_commande = $db->jdate($obj->date_commande);
+    	    $generic_commande->date_livraison = $db->jdate($obj->date_delivery);
+            $generic_commande->ref_client = $obj->ref_client;
+            $generic_commande->total_ht = $obj->total_ht;
+            $generic_commande->total_tva = $obj->total_tva;
+            $generic_commande->total_ttc = $obj->total_ttc;
+            $generic_commande->lines=array();
+            $generic_commande->getLinesArray();
+    
+            print '<table class="nobordernopadding"><tr class="nocellnopadd">';
+            print '<td class="nobordernopadding nowrap">';
+            print $generic_commande->getNomUrl(1,($viewstatut != 2?0:$obj->fk_statut));
+            print '</td>';
+    		
+            // Show shippable Icon (create subloop, so may be slow)
+            if ($conf->stock->enabled) 
             {
-                $notshippable=0;
-                $warning = 0;
-                $text_info='';
-                $text_warning='';
-                $nbprod=0;
-                
-                $numlines = count($generic_commande->lines); // Loop on each line of order
-                for ($lig=0; $lig < $numlines; $lig++) 
+                $langs->load("stocks");
+                if (($obj->fk_statut > 0) && ($obj->fk_statut < 3))
                 {
-                    if ($generic_commande->lines[$lig]->product_type == 0 && $generic_commande->lines[$lig]->fk_product > 0)  // If line is a product and not a service
+                    $notshippable=0;
+                    $warning = 0;
+                    $text_info='';
+                    $text_warning='';
+                    $nbprod=0;
+                    
+                    $numlines = count($generic_commande->lines); // Loop on each line of order
+                    for ($lig=0; $lig < $numlines; $lig++) 
                     {
-                        $nbprod++; // order contains real products
-                        $generic_product->id = $generic_commande->lines[$lig]->fk_product;
-                        if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product])) {
-                            $generic_product->load_stock();
-                            $generic_product->load_virtual_stock();
-                            $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_reel;
-                            $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique;
-                        } else {
-                            $generic_product->stock_reel = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel'];
-                            $generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique;
-                        }
-                        
-                        if (empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST))  // Default code is when this option is not set, setting it create strange result
+                        if ($generic_commande->lines[$lig]->product_type == 0 && $generic_commande->lines[$lig]->fk_product > 0)  // If line is a product and not a service
                         {
-                            $text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 25);
-                            $text_info .= ' - '.$langs->trans("Stock").': '.$generic_product->stock_reel;
-                            $text_info .= ' - '.$langs->trans("VirtualStock").': '.$generic_product->stock_theorique;
-                            $text_info .= '<br>';
-                            
-                            if ($generic_commande->lines[$lig]->qty > $generic_product->stock_reel) 
-                            {
-                                $notshippable++;
+                            $nbprod++; // order contains real products
+                            $generic_product->id = $generic_commande->lines[$lig]->fk_product;
+                            if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product])) {
+                                $generic_product->load_stock();
+                                $generic_product->load_virtual_stock();
+                                $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_reel;
+                                $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique;
+                            } else {
+                                $generic_product->stock_reel = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel'];
+                                $generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique;
                             }
-                        }
-                        else {  // Detailed code, looks bugged
-                            // stock order and stock order_supplier
-                            $stock_order=0;
-                            $stock_order_supplier=0;
-                            if (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT))    // What about other options ?
+                            
+                            if (empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST))  // Default code is when this option is not set, setting it create strange result
                             {
-                                if (! empty($conf->commande->enabled))
+                                $text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 25);
+                                $text_info .= ' - '.$langs->trans("Stock").': '.$generic_product->stock_reel;
+                                $text_info .= ' - '.$langs->trans("VirtualStock").': '.$generic_product->stock_theorique;
+                                $text_info .= '<br>';
+                                
+                                if ($generic_commande->lines[$lig]->qty > $generic_product->stock_reel) 
                                 {
-                                    if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'])) {
-                                        $generic_product->load_stats_commande(0,'1,2');
-                                        $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'] = $generic_product->stats_commande['qty'];
-                                    } else {
-                                        $generic_product->stats_commande['qty'] = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'];
-                                    }
-                                    $stock_order=$generic_product->stats_commande['qty'];
+                                    $notshippable++;
                                 }
-                                if (! empty($conf->fournisseur->enabled))
+                            }
+                            else {  // Detailed code, looks bugged
+                                // stock order and stock order_supplier
+                                $stock_order=0;
+                                $stock_order_supplier=0;
+                                if (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT))    // What about other options ?
                                 {
-                                    if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'])) {
-                                        $generic_product->load_stats_commande_fournisseur(0,'3');
-                                        $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'] = $generic_product->stats_commande_fournisseur['qty'];
-                                    } else {
-                                        $generic_product->stats_commande_fournisseur['qty'] = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'];
+                                    if (! empty($conf->commande->enabled))
+                                    {
+                                        if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'])) {
+                                            $generic_product->load_stats_commande(0,'1,2');
+                                            $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'] = $generic_product->stats_commande['qty'];
+                                        } else {
+                                            $generic_product->stats_commande['qty'] = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'];
+                                        }
+                                        $stock_order=$generic_product->stats_commande['qty'];
+                                    }
+                                    if (! empty($conf->fournisseur->enabled))
+                                    {
+                                        if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'])) {
+                                            $generic_product->load_stats_commande_fournisseur(0,'3');
+                                            $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'] = $generic_product->stats_commande_fournisseur['qty'];
+                                        } else {
+                                            $generic_product->stats_commande_fournisseur['qty'] = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'];
+                                        }
+                                        $stock_order_supplier=$generic_product->stats_commande_fournisseur['qty'];
                                     }
-                                    $stock_order_supplier=$generic_product->stats_commande_fournisseur['qty'];
                                 }
-                            }
-                            $text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 25);
-                            $text_stock_reel = $generic_product->stock_reel.'/'.$stock_order;
-                            if ($stock_order > $generic_product->stock_reel && ! ($generic_product->stock_reel < $generic_commande->lines[$lig]->qty)) {
-                                $warning++;
-                                $text_warning.='<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
-                            }
-                            if ($generic_product->stock_reel < $generic_commande->lines[$lig]->qty) {
-                                $notshippable++;
-                                $text_info.='<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
-                            } else {
-                                $text_info.='<span class="ok">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
-                            }
-                            if (! empty($conf->fournisseur->enabled)) {
-                                $text_info.= '&nbsp;'.$langs->trans('SupplierOrder').'&nbsp;:&nbsp;'.$stock_order_supplier.'<br>';
-                            } else {
-                                $text_info.= '<br>';
+                                $text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->ref.'&nbsp;'.dol_trunc($generic_commande->lines[$lig]->product_label, 25);
+                                $text_stock_reel = $generic_product->stock_reel.'/'.$stock_order;
+                                if ($stock_order > $generic_product->stock_reel && ! ($generic_product->stock_reel < $generic_commande->lines[$lig]->qty)) {
+                                    $warning++;
+                                    $text_warning.='<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
+                                }
+                                if ($generic_product->stock_reel < $generic_commande->lines[$lig]->qty) {
+                                    $notshippable++;
+                                    $text_info.='<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
+                                } else {
+                                    $text_info.='<span class="ok">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
+                                }
+                                if (! empty($conf->fournisseur->enabled)) {
+                                    $text_info.= '&nbsp;'.$langs->trans('SupplierOrder').'&nbsp;:&nbsp;'.$stock_order_supplier.'<br>';
+                                } else {
+                                    $text_info.= '<br>';
+                                }
                             }
                         }
                     }
+                    if ($notshippable==0) {
+                        $text_icon = img_picto('', 'object_sending');
+                        $text_info = $langs->trans('Shippable').'<br>'.$text_info;
+                    } else {
+                        $text_icon = img_picto('', 'error');
+                        $text_info = $langs->trans('NonShippable').'<br>'.$text_info;
+                    }
                 }
-                if ($notshippable==0) {
-                    $text_icon = img_picto('', 'object_sending');
-                    $text_info = $langs->trans('Shippable').'<br>'.$text_info;
-                } else {
-                    $text_icon = img_picto('', 'error');
-                    $text_info = $langs->trans('NonShippable').'<br>'.$text_info;
+                
+                print '<td>';
+                if ($nbprod)
+                {
+                    print $form->textwithtooltip('',$text_info,2,1,$text_icon,'',2);
                 }
+                if ($warning) {
+                    print $form->textwithtooltip('', $langs->trans('NotEnoughForAllOrders').'<br>'.$text_warning, 2, 1, img_picto('', 'error'),'',2);
+                }
+                print '</td>';
             }
-            
-            print '<td>';
-            if ($nbprod)
-            {
-                print $form->textwithtooltip('',$text_info,2,1,$text_icon,'',2);
-            }
-            if ($warning) {
-                print $form->textwithtooltip('', $langs->trans('NotEnoughForAllOrders').'<br>'.$text_warning, 2, 1, img_picto('', 'error'),'',2);
-            }
-            print '</td>';
+    
+            // Warning late icon
+    		print '<td class="nobordernopadding nowrap">';
+    		if ($generic_commande->hasDelay()) {
+    			print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning");
+    		}
+    		if(!empty($obj->note_private))
+    		{
+    			print ' <span class="note">';
+    			print '<a href="'.DOL_URL_ROOT.'/commande/note.php?id='.$obj->rowid.'">'.img_picto($langs->trans("ViewPrivateNote"),'object_generic').'</a>';
+    			print '</span>';
+    		}
+    		print '</td>';
+    
+    		print '<td width="16" align="right" class="nobordernopadding hideonsmartphone">';
+    		$filename=dol_sanitizeFileName($obj->ref);
+    		$filedir=$conf->commande->dir_output . '/' . dol_sanitizeFileName($obj->ref);
+    		$urlsource=$_SERVER['PHP_SELF'].'?id='.$obj->rowid;
+    		print $formfile->getDocumentsLink($generic_commande->element, $filename, $filedir);
+    		print '</td>';
+    		print '</tr></table>';
+    
+    		print '</td>';
+    		if (! $i) $totalarray['nbfield']++;
         }
-
-        // Warning late icon
-		print '<td class="nobordernopadding nowrap">';
-		if ($generic_commande->hasDelay()) {
-			print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning");
-		}
-		if(!empty($objp->note_private))
+        
+		// Ref customer
+		if (! empty($arrayfields['c.ref_client']['checked']))
 		{
-			print ' <span class="note">';
-			print '<a href="'.DOL_URL_ROOT.'/commande/note.php?id='.$objp->rowid.'">'.img_picto($langs->trans("ViewPrivateNote"),'object_generic').'</a>';
-			print '</span>';
+            print '<td>'.$obj->ref_client.'</td>';
+    		if (! $i) $totalarray['nbfield']++;
 		}
-		print '</td>';
-
-		print '<td width="16" align="right" class="nobordernopadding hideonsmartphone">';
-		$filename=dol_sanitizeFileName($objp->ref);
-		$filedir=$conf->commande->dir_output . '/' . dol_sanitizeFileName($objp->ref);
-		$urlsource=$_SERVER['PHP_SELF'].'?id='.$objp->rowid;
-		print $formfile->getDocumentsLink($generic_commande->element, $filename, $filedir);
-		print '</td>';
-		print '</tr></table>';
 
-		print '</td>';
+		$companystatic->id=$obj->socid;
+        $companystatic->code_client = $obj->code_client;
+		$companystatic->name=$obj->name;
+		$companystatic->client=$obj->client;
 
-		// Ref customer
-		print '<td>'.$objp->ref_client.'</td>';
-
-		// Company
-		$companystatic->id=$objp->socid;
-        $companystatic->code_client = $objp->code_client;
-		$companystatic->name=$objp->name;
-		$companystatic->client=$objp->client;
-		print '<td>';
-		print $companystatic->getNomUrl(1,'customer');
-
-		// If module invoices enabled and user with invoice creation permissions
-		if (! empty($conf->facture->enabled) && ! empty($conf->global->ORDER_BILLING_ALL_CUSTOMER))
+		// Third party
+		if (! empty($arrayfields['s.nom']['checked']))
 		{
-			if ($user->rights->facture->creer)
-			{
-				if (($objp->fk_statut > 0 && $objp->fk_statut < 3) || ($objp->fk_statut == 3 && $objp->billed == 0))
-				{
-					print '&nbsp;<a href="'.DOL_URL_ROOT.'/commande/orderstoinvoice.php?socid='.$companystatic->id.'">';
-					print img_picto($langs->trans("CreateInvoiceForThisCustomer").' : '.$companystatic->name, 'object_bill', 'hideonsmartphone').'</a>';
-				}
-			}
+    		print '<td>';
+    		print $companystatic->getNomUrl(1,'customer');
+    
+    		// If module invoices enabled and user with invoice creation permissions
+    		if (! empty($conf->facture->enabled) && ! empty($conf->global->ORDER_BILLING_ALL_CUSTOMER))
+    		{
+    			if ($user->rights->facture->creer)
+    			{
+    				if (($obj->fk_statut > 0 && $obj->fk_statut < 3) || ($obj->fk_statut == 3 && $obj->billed == 0))
+    				{
+    					print '&nbsp;<a href="'.DOL_URL_ROOT.'/commande/orderstoinvoice.php?socid='.$companystatic->id.'">';
+    					print img_picto($langs->trans("CreateInvoiceForThisCustomer").' : '.$companystatic->name, 'object_bill', 'hideonsmartphone').'</a>';
+    				}
+    			}
+    		}
+    		print '</td>';
+    		if (! $i) $totalarray['nbfield']++;
 		}
-		print '</td>';
-
+		// Town
+		if (! empty($arrayfields['s.town']['checked']))
+		{
+		    print '<td class="nocellnopadd">';
+		    print $obj->town;
+		    print '</td>';
+		    if (! $i) $totalarray['nbfield']++;
+		}
+		// Zip
+		if (! empty($arrayfields['s.zip']['checked']))
+		{
+		    print '<td class="nocellnopadd">';
+		    print $obj->zip;
+		    print '</td>';
+		    if (! $i) $totalarray['nbfield']++;
+		}
+		// State
+		if (! empty($arrayfields['state.nom']['checked']))
+		{
+		    print "<td>".$obj->state_name."</td>\n";
+		    if (! $i) $totalarray['nbfield']++;
+		}
+		// Country
+		if (! empty($arrayfields['country.code_iso']['checked']))
+		{
+		    print '<td align="center">';
+		    $tmparray=getCountry($obj->fk_pays,'all');
+		    print $tmparray['label'];
+		    print '</td>';
+		    if (! $i) $totalarray['nbfield']++;
+		}
+		// Type ent
+		if (! empty($arrayfields['typent.code']['checked']))
+		{
+		    print '<td align="center">';
+		    if (count($typenArray)==0) $typenArray = $formcompany->typent_array(1);
+		    print $typenArray[$obj->typent_code];
+		    print '</td>';
+		    if (! $i) $totalarray['nbfield']++;
+		}
+		
 		// Order date
-		print '<td align="center">';
-		print dol_print_date($db->jdate($objp->date_commande), 'day');
-		print '</td>';
-
-		// Delivery date
-		print '<td align="center">';
-		print dol_print_date($db->jdate($objp->date_delivery), 'day');
-		print '</td>';
-
-		// Amount HT
-		print '<td align="right" class="nowrap">'.price($objp->total_ht).'</td>';
-
-		// Statut
-		print '<td align="right" class="nowrap">'.$generic_commande->LibStatut($objp->fk_statut, $objp->billed, 5, 1).'</td>';
-
+		if (! empty($arrayfields['c.date_commande']['checked']))
+		{
+    		print '<td align="center">';
+    		print dol_print_date($db->jdate($obj->date_commande), 'day');
+    		print '</td>';
+    		if (! $i) $totalarray['nbfield']++;
+		}
+		// Plannned date of delivery
+		if (! empty($arrayfields['c.date_delivery']['checked']))
+		{
+    		print '<td align="center">';
+    		print dol_print_date($db->jdate($obj->date_delivery), 'day');
+    		print '</td>';
+    		if (! $i) $totalarray['nbfield']++;
+		}
+        // Amount HT
+        if (! empty($arrayfields['c.total_ht']['checked']))
+        {
+		      print '<td align="right">'.price($obj->total_ht)."</td>\n";
+		      if (! $i) $totalarray['nbfield']++;
+		      if (! $i) $totalarray['totalhtfield']=$totalarray['nbfield'];
+		      $totalarray['totalht'] += $obj->total_ht;
+        }
+        // Amount VAT
+        if (! empty($arrayfields['c.total_vat']['checked']))
+        {
+            print '<td align="right">'.price($obj->total_vat)."</td>\n";
+            if (! $i) $totalarray['nbfield']++;
+		    if (! $i) $totalarray['totalvatfield']=$totalarray['nbfield'];
+		    $totalarray['totalvat'] += $obj->total_vat;
+        }
+        // Amount TTC
+        if (! empty($arrayfields['c.total_ttc']['checked']))
+        {
+            print '<td align="right">'.price($obj->total_ttc)."</td>\n";
+            if (! $i) $totalarray['nbfield']++;
+		    if (! $i) $totalarray['totalttcfield']=$totalarray['nbfield'];
+		    $totalarray['totalttc'] += $obj->total_ttc;
+        }
+		
+        // Extra fields
+        if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+        {
+            foreach($extrafields->attribute_label as $key => $val)
+            {
+                if (! empty($arrayfields["ef.".$key]['checked']))
+                {
+                    print '<td';
+                    $align=$extrafields->getAlignFlag($key);
+                    if ($align) print ' align="'.$align.'"';
+                    print '>';
+                    $tmpkey='options_'.$key;
+                    print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1);
+                    print '</td>';
+                    if (! $i) $totalarray['nbfield']++;
+                }
+            }
+        }
+        // Fields from hook
+        $parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj);
+        $reshook=$hookmanager->executeHooks('printFieldListValue',$parameters);    // Note that $action and $object may have been modified by hook
+        print $hookmanager->resPrint;
+        // Date creation
+        if (! empty($arrayfields['c.datec']['checked']))
+        {
+            print '<td align="center" class="nowrap">';
+            print dol_print_date($db->jdate($obj->date_creation), 'dayhour');
+            print '</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // Date modification
+        if (! empty($arrayfields['c.tms']['checked']))
+        {
+            print '<td align="center" class="nowrap">';
+            print dol_print_date($db->jdate($obj->date_update), 'dayhour');
+            print '</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
+        // Status
+        if (! empty($arrayfields['c.fk_statut']['checked']))
+        {
+            print '<td align="right" class="nowrap">'.$generic_commande->LibStatut($obj->fk_statut, $obj->billed, 5, 1).'</td>';
+            if (! $i) $totalarray['nbfield']++;
+        }
 		// Billed
-		if (empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) print '<td align="center">'.yn($objp->billed).'</td>';
+        if (! empty($arrayfields['c.facture']['checked']))
+        {
+            print '<td align="center">'.yn($obj->billed).'</td>';
+        }
+        
+        // Action column
+        print '<td></td>';
+        if (! $i) $totalarray['nbfield']++;
 		
-		print '<td></td>';
-
 		print '</tr>';
 
-		$total+=$objp->total_ht;
-		$subtotal+=$objp->total_ht;
+		$total+=$obj->total_ht;
+		$subtotal+=$obj->total_ht;
 		$i++;
 	}
 
-	if (! empty($conf->global->MAIN_SHOW_TOTAL_FOR_LIMITED_LIST))
+	// Show total line
+	if (isset($totalarray['totalhtfield']))
 	{
-		$var=!$var;
-		print '<tr '.$bc[$var].'>';
-		print '<td class="nowrap" colspan="5">'.$langs->trans('TotalHT').'</td>';
-		// Total HT
-		print '<td align="right" class="nowrap">'.price($total).'</td>';
-		print '<td></td>';
-		print '<td></td>';
-		print '<td></td>';
-		print '</tr>';
+	    print '<tr class="liste_total">';
+	    $i=0;
+	    while ($i < $totalarray['nbfield'])
+	    {
+	        $i++;
+	        if ($i == 1)
+	        {
+	            if ($num < $limit) print '<td align="left">'.$langs->trans("Total").'</td>';
+	            else print '<td align="left">'.$langs->trans("Totalforthispage").'</td>';
+	        }
+	        elseif ($totalarray['totalhtfield'] == $i) print '<td align="right">'.price($totalarray['totalht']).'</td>';
+	        elseif ($totalarray['totalvatfield'] == $i) print '<td align="right">'.price($totalarray['totalvat']).'</td>';
+	        elseif ($totalarray['totalttcfield'] == $i) print '<td align="right">'.price($totalarray['totalttc']).'</td>';
+	        else print '<td></td>';
+	    }
+	    print '</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
+	print $hookmanager->resPrint;
+				
 	print '</table>';
 
 	print '</form>'."\n";
 
 	print '<br>'.img_help(1,'').' '.$langs->trans("ToBillSeveralOrderSelectCustomer", $langs->transnoentitiesnoconv("CreateInvoiceForThisCustomer")).'<br>';
-
-	$db->free($resql);
 }
 else
 {

+ 1 - 1
htdocs/commande/orderstoinvoice.php

@@ -220,7 +220,7 @@ if (($action == 'create' || $action == 'add') && !$error)
 							{
 								if ($closeOrders)
 								{
-									$objectsrc->classifyBilled();
+									$objectsrc->classifyBilled($user);
 									$objectsrc->setStatut(3);
 								}
 								$lines = $objectsrc->lines;

+ 1 - 25
htdocs/commande/tpl/linkedobjectblock.tpl.php

@@ -27,22 +27,8 @@ global $user;
 
 $langs = $GLOBALS['langs'];
 $linkedObjectBlock = $GLOBALS['linkedObjectBlock'];
-
 $langs->load("orders");
-echo '<br>';
-print load_fiche_titre($langs->trans('RelatedCustomerOrders'), '', '');
 
-?>
-<table class="noborder allwidth">
-<tr class="liste_titre">
-	<td><?php echo $langs->trans("Ref"); ?></td>
-	<td align="center"><?php echo $langs->trans("RefCustomer"); ?></td>
-	<td align="center"><?php echo $langs->trans("Date"); ?></td>
-	<td align="right"><?php echo $langs->trans("AmountHTShort"); ?></td>
-	<td align="right"><?php echo $langs->trans("Status"); ?></td>
-	<td></td>
-</tr>
-<?php
 $var=true;
 $total=0;
 foreach($linkedObjectBlock as $key => $objectlink)
@@ -50,6 +36,7 @@ foreach($linkedObjectBlock as $key => $objectlink)
 	$var=!$var;
 ?>
 <tr <?php echo $GLOBALS['bc'][$var]; ?> >
+    <td><?php echo $langs->trans("CustomerOrder"); ?></td>
     <td><?php echo $objectlink->getNomUrl(1); ?></td>
 	<td align="center"><?php echo $objectlink->ref_client; ?></td>
 	<td align="center"><?php echo dol_print_date($objectlink->date,'day'); ?></td>
@@ -63,17 +50,6 @@ foreach($linkedObjectBlock as $key => $objectlink)
 </tr>
 <?php
 }
-
 ?>
-<tr class="liste_total">
-	<td align="left" colspan="3"><?php echo $langs->trans('TotalHT'); ?></td>
-	<td align="right"><?php
-		if ($user->rights->commande->lire) {
-			echo price($total);
-		} ?></td>
-	<td></td>
-	<td></td>
-</tr>
-</table>
 
 <!-- END PHP TEMPLATE -->

+ 2 - 2
htdocs/compta/bank/account.php

@@ -521,9 +521,9 @@ if ($id > 0 || ! empty($ref))
 	print '<input type="hidden" name="action" value="search">';
 	print '<input type="hidden" name="id" value="'.$object->id.'">';
 
-	$period_filter .= $langs->trans('From').'&nbsp;'.$form->select_date($req_stdt,'req_stdt',0,0,1,null,1,1,1);
+	$period_filter .= $langs->trans('From').'&nbsp;'.$form->select_date($req_stdt,'req_stdt',0,0,1,null,1,0,1);
 	$period_filter .= '&nbsp;';
-	$period_filter .= $langs->trans('to').'&nbsp;'.$form->select_date($req_enddt,'req_enddt',0,0,1,null,1,1,1);
+	$period_filter .= $langs->trans('to').'&nbsp;'.$form->select_date($req_enddt,'req_enddt',0,0,1,null,1,0,1);
 	
 	print '<tr class="liste_titre">';
 	print '<td colspan="2">'.$period_filter.'</td>';

+ 30 - 49
htdocs/compta/bank/card.php

@@ -277,7 +277,7 @@ if ($action == 'create')
 	print '<table class="border" width="100%">';
 
 	// Ref
-	print '<tr><td class="fieldrequired" width="25%">'.$langs->trans("Ref").'</td>';
+	print '<tr><td class="fieldrequired titlefieldcreate">'.$langs->trans("Ref").'</td>';
 	print '<td colspan="3"><input size="8" type="text" class="flat" name="ref" value="'.($_POST["ref"]?$_POST["ref"]:$account->ref).'" maxlength="12"></td></tr>';
 
 	// Label
@@ -287,7 +287,7 @@ if ($action == 'create')
 	// Type
 	print '<tr><td class="fieldrequired">'.$langs->trans("AccountType").'</td>';
 	print '<td colspan="3">';
-	$formbank->selectTypeOfBankAccount(isset($_POST["type"])?$_POST["type"]:1,"type");
+	$formbank->selectTypeOfBankAccount(isset($_POST["type"])?$_POST["type"]: Account::TYPE_CURRENT,"type");
 	print '</td></tr>';
 
 	// Currency
@@ -361,7 +361,7 @@ if ($action == 'create')
 	print '<table class="border" width="100%">';
 
 	// Sold
-	print '<tr><td width="25%">'.$langs->trans("InitialBankBalance").'</td>';
+	print '<tr><td class="titlefieldcreate">'.$langs->trans("InitialBankBalance").'</td>';
 	print '<td colspan="3"><input size="12" type="text" class="flat" name="solde" value="'.(GETPOST("solde")?GETPOST("solde"):price2num($account->solde)).'"></td></tr>';
 
 	print '<tr><td>'.$langs->trans("Date").'</td>';
@@ -378,12 +378,12 @@ if ($action == 'create')
 	print '</table>';
 	print '<br>';
 
-	if ($_POST["type"] == 0 || $_POST["type"] == 1)
+	if ($_POST["type"] == Account::TYPE_SAVINGS || $_POST["type"] == Account::TYPE_CURRENT)
 	{
 		print '<table class="border" width="100%">';
 
 		// If bank account
-		print '<tr><td width="25%">'.$langs->trans("BankName").'</td>';
+		print '<tr><td class="titlefieldcreate">'.$langs->trans("BankName").'</td>';
 		print '<td colspan="3"><input size="30" type="text" class="flat" name="bank" value="'.$account->bank.'"></td>';
 		print '</tr>';
 
@@ -411,9 +411,8 @@ if ($action == 'create')
 			print '<td><input size="'.$size.'" type="text" class="flat" name="'.$name.'" value="'.$content.'"></td>';
 			print '</tr>';
 		}
-		$ibankey="IBANNumber";
+		$ibankey = FormBank::getIBANLabel($account);
 		$bickey="BICNumber";
-		if ($account->getCountryCode() == 'IN') $ibankey="IFSC";
 		if ($account->getCountryCode() == 'IN') $bickey="SWIFT";
 
 		// IBAN
@@ -447,14 +446,14 @@ if ($action == 'create')
     {
 		if (! empty($conf->accounting->enabled))
 		{
-			print '<tr><td class="fieldrequired" width="25%">'.$langs->trans("AccountancyCode").'</td>';
+			print '<tr><td class="fieldrequired titlefieldcreate">'.$langs->trans("AccountancyCode").'</td>';
 			print '<td>';
 			print $formaccountancy->select_account($account->account_number, 'account_number', 1, '', 1, 1);
 			print '</td></tr>';
 		}
 		else
 		{
-			print '<tr><td class="fieldrequired" width="25%">'.$langs->trans("AccountancyCode").'</td>';
+			print '<tr><td class="fieldrequired titlefieldcreate">'.$langs->trans("AccountancyCode").'</td>';
 			print '<td colspan="3"><input type="text" name="account_number" value="'.(GETPOST("account_number")?GETPOST('account_number', 'alpha'):$account->account_number).'"></td></tr>';
 		}
 	}
@@ -462,14 +461,14 @@ if ($action == 'create')
     {
 		if (! empty($conf->accounting->enabled))
 		{
-			print '<tr><td width="25%">'.$langs->trans("AccountancyCode").'</td>';
+			print '<tr><td class="titlefieldcreate">'.$langs->trans("AccountancyCode").'</td>';
 			print '<td>';
 			print $formaccountancy->select_account($account->account_number, 'account_number', 1, '', 1, 1);
 			print '</td></tr>';
 		}
 		else
 		{
-			print '<tr><td width="25%">'.$langs->trans("AccountancyCode").'</td>';
+			print '<tr><td class="titlefieldcreate">'.$langs->trans("AccountancyCode").'</td>';
 			print '<td colspan="3"><input type="text" name="account_number" value="'.(GETPOST("account_number")?GETPOST('account_number', 'alpha'):$account->account_number).'"></td></tr>';
 		}
 	}
@@ -531,7 +530,7 @@ else
 		$linkback = '<a href="'.DOL_URL_ROOT.'/compta/bank/index.php">'.$langs->trans("BackToList").'</a>';
 
 		// Ref
-		print '<tr><td width="25%">'.$langs->trans("Ref").'</td>';
+		print '<tr><td class="titlefield">'.$langs->trans("Ref").'</td>';
 		print '<td colspan="3">';
 		print $form->showrefnav($account, 'ref', $linkback, 1, 'ref');
 		print '</td></tr>';
@@ -611,7 +610,7 @@ else
 		{
 			print '<table class="border" width="100%">';
 
-			print '<tr><td valign="top" width="25%">'.$langs->trans("BankName").'</td>';
+			print '<tr><td valign="top" class="titlefield">'.$langs->trans("BankName").'</td>';
 			print '<td colspan="3">'.$account->bank.'</td></tr>';
 
 			// Show fields of bank account
@@ -631,9 +630,8 @@ else
 				print '</tr>';
 			}
 
-			$ibankey="IBANNumber";
+			$ibankey = FormBank::getIBANLabel($account);
 			$bickey="BICNumber";
-			if ($account->getCountryCode() == 'IN') $ibankey="IFSC";
 			if ($account->getCountryCode() == 'IN') $bickey="SWIFT";
 
 			print '<tr><td>'.$langs->trans($ibankey).'</td>';
@@ -676,7 +674,7 @@ else
 
 		print '<table class="border" width="100%">';
 		// Accountancy code
-		print '<tr><td width="25%">'.$langs->trans("AccountancyCode").'</td>';
+		print '<tr><td class="titlefield">'.$langs->trans("AccountancyCode").'</td>';
 		print '<td colspan="3">'.length_accountg($account->account_number).'</td></tr>';
 
 		// Accountancy journal
@@ -753,7 +751,7 @@ else
         print '<table class="border" width="100%">';
 
 		// Ref
-		print '<tr><td class="fieldrequired" width="25%">'.$langs->trans("Ref").'</td>';
+		print '<tr><td class="fieldrequired titlefieldcreate">'.$langs->trans("Ref").'</td>';
 		print '<td colspan="3"><input size="8" type="text" class="flat" name="ref" value="'.(isset($_POST["ref"])?$_POST["ref"]:$account->ref).'"></td></tr>';
 
 		// Label
@@ -849,12 +847,12 @@ else
 		print '</table>';
 		print '<br>';
 
-		if ($_POST["type"] == 0 || $_POST["type"] == 1)
+		if ($_POST["type"] == Account::TYPE_SAVINGS || $_POST["type"] == Account::TYPE_CURRENT)
 		{
 			print '<table class="border" width="100%">';
 
 			// If bank account
-			print '<tr><td width="25%">'.$langs->trans("BankName").'</td>';
+			print '<tr><td class="titlefieldcreate">'.$langs->trans("BankName").'</td>';
 			print '<td colspan="3"><input size="30" type="text" class="flat" name="bank" value="'.$account->bank.'"></td>';
 			print '</tr>';
 
@@ -883,9 +881,8 @@ else
 				print '</tr>';
 			}
 
-			$ibankey="IBANNumber";
+			$ibankey = FormBank::getIBANLabel($account);
 			$bickey="BICNumber";
-			if ($account->getCountryCode() == 'IN') $ibankey="IFSC";
 			if ($account->getCountryCode() == 'IN') $bickey="SWIFT";
 
 			// IBAN
@@ -916,36 +913,20 @@ else
 		print '<table class="border" width="100%">';
 
 		// Accountancy code
-		if (! empty($conf->global->MAIN_BANK_ACCOUNTANCY_CODE_ALWAYS_REQUIRED))
-		{
-			if (! empty($conf->accounting->enabled))
-			{
-				print '<tr><td class="fieldrequired" width="25%">'.$langs->trans("AccountancyCode").'</td>';
-				print '<td>';
-				print $formaccountancy->select_account($account->account_number, 'account_number', 1, '', 1, 1);
-				print '</td></tr>';
-			}
-			else
-			{
-				print '<tr><td class="fieldrequired" width="25%">'.$langs->trans("AccountancyCode").'</td>';
-				print '<td colspan="3"><input type="text" name="account_number" value="'.(GETPOST("account_number")?GETPOST("account_number"):$account->account_number).'"></td></tr>';
-			}
+		$tdextra = ' class="titlefieldcreate"';
+
+		if (!empty($conf->global->MAIN_BANK_ACCOUNTANCY_CODE_ALWAYS_REQUIRED)) {
+			$tdextra = ' class="fieldrequired titlefieldcreate"';
 		}
-		else
-		{
-			if (! empty($conf->accounting->enabled))
-			{
-				print '<tr><td width="25%">'.$langs->trans("AccountancyCode").'</td>';
-				print '<td>';
-				print $formaccountancy->select_account($account->account_number, 'account_number', 1, '', 1, 1);
-				print '</td></tr>';
-			}
-			else
-			{
-				print '<tr><td width="25%">'.$langs->trans("AccountancyCode").'</td>';
-				print '<td colspan="3"><input type="text" name="account_number" value="'.(GETPOST("account_number")?GETPOST("account_number"):$account->account_number).'"></td></tr>';
-			}
+
+		print '<tr><td'.$tdextra.'>'.$langs->trans("AccountancyCode").'</td>';
+		print '<td colspan="3">';
+		if (!empty($conf->accounting->enabled)) {
+			print $formaccountancy->select_account($account->account_number, 'account_number', 1, '', 1, 1);
+		} else {
+			print '<input type="text" name="account_number" value="'.(GETPOST("account_number") ? GETPOST("account_number") : $account->account_number).'">';
 		}
+		print '</td></tr>';
 
 		// Accountancy journal
 		if (! empty($conf->accounting->enabled))

+ 7 - 15
htdocs/compta/bank/document.php

@@ -92,18 +92,10 @@ if ($_POST["sendit"] && !empty($conf->global->MAIN_UPLOAD_DOC)) {
                     $upload_dir . "/" . dol_unescapefile($_FILES['userfile']['name']),
                     0, 0, $_FILES['userfile']['error']);
             if (is_numeric($resupload) && $resupload > 0) {
-                if (image_format_supported($upload_dir . "/" . $_FILES['userfile']['name'])
-                        == 1) {
-                    // Create small thumbs for image (Ratio is near 16/9)
-                    // Used on logon for example
-                    $imgThumbSmall = vignette($upload_dir . "/" . $_FILES['userfile']['name'],
-                            $maxwidthsmall, $maxheightsmall, '_small', $quality,
-                            "thumbs");
-                    // Create mini thumbs for image (Ratio is near 16/9)
-                    // Used on menu or for setup page for example
-                    $imgThumbMini = vignette($upload_dir . "/" . $_FILES['userfile']['name'],
-                            $maxwidthmini, $maxheightmini, '_mini', $quality,
-                            "thumbs");
+                if (image_format_supported($upload_dir . "/" . $_FILES['userfile']['name']) == 1) 
+                {
+                    // Create thumbs
+                    $object->addThumbs($upload_dir . "/" . $_FILES['userfile']['name']);
                 }
                 $mesg = '<div class="ok">' . $langs->trans("FileTransferComplete") . '</div>';
             }
@@ -172,14 +164,14 @@ if ($id > 0 || !empty($ref)) {
             $totalsize+=$file['size'];
         }
 
-
+        $linkback = '<a href="'.DOL_URL_ROOT.'/compta/bank/index.php">'.$langs->trans("BackToList").'</a>';
+        
         print '<table class="border"width="100%">';
 
-        // Ref
         // Ref
         print '<tr><td valign="top" width="25%">' . $langs->trans("Ref") . '</td>';
         print '<td colspan="3">';
-        print $form->showrefnav($object, 'ref', '', 1, 'ref');
+        print $form->showrefnav($object, 'ref', $linkback, 1, 'ref');
         print '</td></tr>';
 
         // Label

+ 1 - 1
htdocs/compta/deplacement/document.php

@@ -72,7 +72,7 @@ $modulepart='trip';
  * Actions
  */
 
-include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

+ 15 - 11
htdocs/compta/facture.php

@@ -1963,7 +1963,7 @@ if ($action == 'create')
 			$objectsrc->fetch_thirdparty();
 
 			$projectid = (! empty($projectid) ? $projectid : $objectsrc->fk_project);
-			$ref_client = (! empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
+			$ref_client = (! empty($objectsrc->ref_client) ? $objectsrc->ref_client : (! empty($objectsrc->ref_customer) ? $objectsrc->ref_customer:''));
 			$ref_int = (! empty($objectsrc->ref_int) ? $objectsrc->ref_int : '');
 
 			// only if socid not filled else it's allready done upper
@@ -2039,7 +2039,7 @@ if ($action == 'create')
 	print '<table class="border" width="100%">';
 
 	// Ref
-	print '<tr><td class="fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans('Draft') . '</td></tr>';
+	print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans('Draft') . '</td></tr>';
 
 	// Thirdparty
 	print '<td class="fieldrequired">' . $langs->trans('Customer') . '</td>';
@@ -2381,7 +2381,7 @@ if ($action == 'create')
 	{
 		$langs->load('projects');
 		print '<tr><td>' . $langs->trans('Project') . '</td><td colspan="2">';
-		$numprojet = $formproject->select_projects($soc->id, $projectid, 'projectid', 0);
+		$numprojet = $formproject->select_projects($socid, $projectid, 'projectid', 0);
 		print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid=' . $soc->id . '&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id).'">' . $langs->trans("AddProject") . '</a>';
 		print '</td></tr>';
 	}
@@ -3953,6 +3953,7 @@ else if ($id > 0 || ! empty($ref))
 			}
 
 			// Classify 'closed not completely paid' (possible si validee et pas encore classee payee)
+			
 			if ($object->statut == 1 && $object->paye == 0 && $resteapayer > 0 && $user->rights->facture->paiement)
 			{
 				if ($totalpaye > 0 || $totalcreditnotes > 0)
@@ -3962,10 +3963,16 @@ else if ($id > 0 || ! empty($ref))
 				}
 				else
 				{
-					if ($objectidnext) {
-						print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ClassifyCanceled') . '</span></div>';
-					} else {
-						print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=canceled">' . $langs->trans('ClassifyCanceled') . '</a></div>';
+					if ( empty($conf->global->INVOICE_CAN_NEVER_BE_CANCELED))
+					{
+						if ($objectidnext) 
+						{
+							print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ClassifyCanceled') . '</span></div>';
+						}
+						else 
+						{
+							print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=canceled">' . $langs->trans('ClassifyCanceled') . '</a></div>';
+						}
 					}
 				}
 			}
@@ -4134,10 +4141,7 @@ else if ($id > 0 || ! empty($ref))
 		$formmail->fromid = $user->id;
 		$formmail->fromname = $user->getFullName($langs);
 		$formmail->frommail = $user->email;
-		if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 1))	// If bit 1 is set
-		{
-			$formmail->trackid='inv'.$object->id;
-		}
+		$formmail->trackid='inv'.$object->id;
 		if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2))	// If bit 2 is set
 		{
 			include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';

+ 1 - 1
htdocs/compta/facture/class/facture-rec.class.php

@@ -36,7 +36,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
 /**
  *	Classe de gestion des factures recurrentes/Modeles
  */
-class FactureRec extends Facture
+class FactureRec extends CommonInvoice
 {
 	public $element='facturerec';
 	public $table_element='facture_rec';

+ 0 - 86
htdocs/compta/facture/class/facture.class.php

@@ -3681,92 +3681,6 @@ class Facture extends CommonInvoice
 	function getLinesArray()
 	{
 	    return $this->fetch_lines();
-	    /*
-		$sql = 'SELECT l.rowid, l.label as custom_label, l.description, l.fk_product, l.product_type, l.qty, l.tva_tx,';
-		$sql.= ' l.fk_remise_except, l.localtax1_tx, l.localtax2_tx,';
-		$sql .= ' l.situation_percent, l.fk_prev_id,';
-		$sql.= ' l.remise_percent, l.subprice, l.info_bits, l.rang, l.special_code, l.fk_parent_line,';
-		$sql.= ' l.total_ht, l.total_tva, l.total_ttc, l.fk_product_fournisseur_price as fk_fournprice, l.buy_price_ht as pa_ht,';
-		$sql.= ' l.date_start, l.date_end,';
-		$sql.= ' l.fk_unit,';
-		$sql.= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
-		$sql.= ' p.ref as product_ref, p.fk_product_type, p.label as product_label,';
-		$sql.= ' p.description as product_desc,';
-        $sql.= ' p.entity';
-		$sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet as l';
-		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product=p.rowid';
-		$sql.= ' WHERE l.fk_facture = '.$this->id;
-		$sql.= ' ORDER BY l.rang ASC, l.rowid';
-
-		dol_syslog(get_class($this).'::getLinesArray',LOG_DEBUG);
-		$resql = $this->db->query($sql);
-		if ($resql)
-		{
-			$num = $this->db->num_rows($resql);
-			$i = 0;
-
-			while ($i < $num)
-			{
-				$obj = $this->db->fetch_object($resql);
-
-				$this->lines[$i]					= new FactureLigne($this->db);
-				$this->lines[$i]->id				= $obj->rowid;
-				$this->lines[$i]->label 			= $obj->custom_label;	// deprecated
-				$this->lines[$i]->description 		= $obj->description;
-				$this->lines[$i]->fk_product		= $obj->fk_product;
-				$this->lines[$i]->ref				= $obj->product_ref;
-                $this->lines[$i]->product_ref		= $obj->product_ref;
-                $this->lines[$i]->product_label		= $obj->product_label;
-				$this->lines[$i]->product_desc		= $obj->product_desc;
-				$this->lines[$i]->fk_product_type	= $obj->fk_product_type;
-				$this->lines[$i]->product_type		= $obj->product_type;
-				$this->lines[$i]->entity            = $obj->entity;         // Product entity
-				$this->lines[$i]->qty				= $obj->qty;
-				$this->lines[$i]->subprice			= $obj->subprice;
-				$this->lines[$i]->fk_remise_except 	= $obj->fk_remise_except;
-				$this->lines[$i]->remise_percent	= $obj->remise_percent;
-				$this->lines[$i]->tva_tx			= $obj->tva_tx;
-				$this->lines[$i]->info_bits			= $obj->info_bits;
-				$this->lines[$i]->total_ht			= $obj->total_ht;
-				$this->lines[$i]->total_tva			= $obj->total_tva;
-				$this->lines[$i]->total_ttc			= $obj->total_ttc;
-				$this->lines[$i]->localtax1_tx      = $obj->localtax1_tx;
-				$this->lines[$i]->localtax2_tx      = $obj->localtax2_tx;
-				$this->lines[$i]->localtax1_type    = $obj->localtax1_type;
-				$this->lines[$i]->localtax2_type    = $obj->localtax2_type;
-				$this->lines[$i]->fk_parent_line	= $obj->fk_parent_line;
-				$this->lines[$i]->situation_percent = $obj->situation_percent;
-				$this->lines[$i]->fk_prev_id        = $obj->fk_prev_id;
-				$this->lines[$i]->special_code		= $obj->special_code;
-				$this->lines[$i]->rang				= $obj->rang;
-				$this->lines[$i]->date_start		= $this->db->jdate($obj->date_start);
-				$this->lines[$i]->date_end			= $this->db->jdate($obj->date_end);
-				$this->lines[$i]->fk_fournprice		= $obj->fk_fournprice;
-				$marginInfos						= getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->lines[$i]->fk_fournprice, $obj->pa_ht);
-				$this->lines[$i]->pa_ht				= $marginInfos[0];
-				$this->lines[$i]->marge_tx			= $marginInfos[1];
-				$this->lines[$i]->marque_tx			= $marginInfos[2];
-				$this->lines[$i]->fk_unit			= $obj->fk_unit;
-				
-				// Multicurrency
-				$this->lines[$i]->fk_multicurrency 			= $obj->fk_multicurrency;
-				$this->lines[$i]->multicurrency_code 		= $obj->multicurrency_code;
-				$this->lines[$i]->multicurrency_subprice 	= $obj->multicurrency_subprice;
-				$this->lines[$i]->multicurrency_total_ht 	= $obj->multicurrency_total_ht;
-				$this->lines[$i]->multicurrency_total_tva 	= $obj->multicurrency_total_tva;
-				$this->lines[$i]->multicurrency_total_ttc 	= $obj->multicurrency_total_ttc;
-				
-				$i++;
-			}
-			$this->db->free($resql);
-
-			return 1;
-		}
-		else
-		{
-			$this->error=$this->db->error();
-			return -1;
-		}*/
 	}
 
 	/**

+ 1 - 1
htdocs/compta/facture/document.php

@@ -75,7 +75,7 @@ if ($object->fetch($id))
 /*
  * Actions
  */
-include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

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

@@ -619,7 +619,7 @@ else
 		print "<tr><td>".$langs->trans("Author").'</td><td colspan="3">'.$author->getFullName($langs)."</td></tr>";
 
 		print '<tr><td>'.$langs->trans("AmountHT").'</td>';
-		print '<td colspan="3"><b>'.price($object->total_ht,'',$langs,1,-1,-1,$conf->currency).'</b></td>';
+		print '<td colspan="3">'.price($object->total_ht,'',$langs,1,-1,-1,$conf->currency).'</td>';
 		print '</tr>';
 
 		print '<tr><td>'.$langs->trans("AmountVAT").'</td><td colspan="3">'.price($object->total_tva,'',$langs,1,-1,-1,$conf->currency).'</td>';

+ 575 - 191
htdocs/compta/facture/list.php

@@ -35,6 +35,7 @@
 require '../../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
@@ -42,11 +43,9 @@ require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
 if (! empty($conf->commande->enabled)) require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
-if (! empty($conf->projet->enabled))
-{
-	require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
-}
+if (! empty($conf->projet->enabled))   require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
 
 $langs->load('bills');
 $langs->load('companies');
@@ -70,9 +69,15 @@ $search_ref=GETPOST('sf_ref')?GETPOST('sf_ref','alpha'):GETPOST('search_ref','al
 $search_refcustomer=GETPOST('search_refcustomer','alpha');
 $search_societe=GETPOST('search_societe','alpha');
 $search_montant_ht=GETPOST('search_montant_ht','alpha');
+$search_montant_vat=GETPOST('search_montant_vat','alpha');
 $search_montant_ttc=GETPOST('search_montant_ttc','alpha');
 $search_status=GETPOST('search_status','int');
 $search_paymentmode=GETPOST('search_paymentmode','int');
+$search_town=GETPOST('search_town','alpha');
+$search_zip=GETPOST('search_zip','alpha');
+$search_state=trim(GETPOST("search_state"));
+$search_country=GETPOST("search_country",'int');
+$search_type_thirdparty=GETPOST("search_type_thirdparty",'int');
 $option = GETPOST('option');
 if ($option == 'late') $filter = 'paye:0';
 
@@ -80,9 +85,7 @@ $limit = GETPOST('limit')?GETPOST('limit','int'):$conf->liste_limit;
 $sortfield = GETPOST("sortfield",'alpha');
 $sortorder = GETPOST("sortorder",'alpha');
 $page = GETPOST("page",'int');
-if ($page == -1) {
-    $page = 0;
-}
+if ($page == -1) { $page = 0; }
 $offset = $limit * $page;
 if (! $sortorder && ! empty($conf->global->INVOICE_DEFAULT_UNPAYED_SORT_ORDER) && $search_status == 1) $sortorder=$conf->global->INVOICE_DEFAULT_UNPAYED_SORT_ORDER;
 if (! $sortorder) $sortorder='DESC';
@@ -90,6 +93,9 @@ if (! $sortfield) $sortfield='f.datef';
 $pageprev = $page - 1;
 $pagenext = $page + 1;
 
+// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
+$contextpage='invoicelist';
+
 $search_user = GETPOST('search_user','int');
 $search_sale = GETPOST('search_sale','int');
 $day	= GETPOST('day','int');
@@ -106,15 +112,19 @@ $fieldid = (! empty($ref)?'facnumber':'rowid');
 if (! empty($user->societe_id)) $socid=$user->societe_id;
 $result = restrictedArea($user, 'facture', $id,'','','fk_soc',$fieldid);
 
-$diroutputpdf=$conf->facture->dir_output . '/unpaid/temp';
-if (! $user->rights->societe->client->voir || $socid) $diroutputpdf.='/private/'.$user->id;	// If user has no permission to see all, output dir is specific to user
+$diroutputmassaction=$conf->facture->dir_output . '/temp/massgeneration/'.$user->id;
 
 $object=new Facture($db);
 
+$now=dol_now();
+
 // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
 $hookmanager->initHooks(array('invoicelist'));
+$extrafields = new ExtraFields($db);
 
-$now=dol_now();
+// fetch optionals attributes and labels
+$extralabels = $extrafields->fetch_name_optionals_label('facture');
+$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_');
 
 // List of fields to search into when doing a "search in all"
 $fieldstosearchall = array(
@@ -126,6 +136,36 @@ $fieldstosearchall = array(
 );
 if (empty($user->socid)) $fieldstosearchall["f.note_private"]="NotePrivate";
 
+$checkedtypetiers=0;
+$arrayfields=array(
+    'f.facnumber'=>array('label'=>$langs->trans("Ref"), 'checked'=>1),
+    'f.ref_client'=>array('label'=>$langs->trans("RefCustomer"), 'checked'=>1),
+    's.nom'=>array('label'=>$langs->trans("ThirdParty"), 'checked'=>1),
+    's.town'=>array('label'=>$langs->trans("Town"), 'checked'=>1),
+    's.zip'=>array('label'=>$langs->trans("Zip"), 'checked'=>1),
+    'state.nom'=>array('label'=>$langs->trans("StateShort"), 'checked'=>0),
+    'country.code_iso'=>array('label'=>$langs->trans("Country"), 'checked'=>0),
+    'typent.code'=>array('label'=>$langs->trans("ThirdPartyType"), 'checked'=>$checkedtypetiers),
+    'f.date'=>array('label'=>$langs->trans("DateInvoice"), 'checked'=>1),
+    'f.date_lim_reglement'=>array('label'=>$langs->trans("DateDue"), 'checked'=>1),
+    'f.fk_mode_reglement'=>array('label'=>$langs->trans("PaymentMode"), 'checked'=>1),
+    'f.total_ht'=>array('label'=>$langs->trans("AmountHT"), 'checked'=>1),
+    'f.total_vat'=>array('label'=>$langs->trans("AmountVAT"), 'checked'=>0),
+    'f.total_ttc'=>array('label'=>$langs->trans("AmountTTC"), 'checked'=>0),
+    'am'=>array('label'=>$langs->trans("Received"), 'checked'=>0),
+    'f.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500),
+    'f.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500),
+    'f.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000),
+);
+// Extra fields
+if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+{
+    foreach($extrafields->attribute_label as $key => $val)
+    {
+        $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]);
+    }
+}
+
 
 /*
  * Actions
@@ -133,10 +173,45 @@ if (empty($user->socid)) $fieldstosearchall["f.note_private"]="NotePrivate";
 
 if (GETPOST('cancel')) { $action='list'; $massaction=''; }
 if (! GETPOST('confirmmassaction')) { $massaction=''; }
-    
+
 $parameters=array('socid'=>$socid);
 $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+
+include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
+
+// Do we click on purge search criteria ?
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
+{
+    $search_user='';
+    $search_sale='';
+    $search_product_category='';
+    $search_ref='';
+    $search_refcustomer='';
+    $search_societe='';
+    $search_montant_ht='';
+    $search_montant_vat='';
+    $search_montant_ttc='';
+    $search_status='';
+    $search_paymentmode='';
+    $search_town='';
+    $search_zip="";
+    $search_state="";
+    $search_type='';
+    $search_country='';
+    $search_type_thirdparty='';    
+    $day='';
+    $year='';
+    $month='';
+    $toselect='';
+    $option='';
+    $filter='';
+    $day_lim='';
+    $year_lim='';
+    $month_lim='';
+    $search_array_options=array();
+}
+
 if (empty($reshook))
 {
 	// Mass actions. Controls on number of lines checked
@@ -498,7 +573,7 @@ if (empty($reshook))
         }
 
         // Create output dir if not exists
-        dol_mkdir($diroutputpdf);
+        dol_mkdir($diroutputmassaction);
 
         // Save merged file
         $filename=strtolower(dol_sanitizeFileName($langs->transnoentities("Invoices")));
@@ -512,7 +587,7 @@ if (empty($reshook))
         if ($pagecount)
         {
             $now=dol_now();
-            $file=$diroutputpdf.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf';
+            $file=$diroutputmassaction.'/'.$filename.'_'.dol_print_date($now,'dayhourlog').'.pdf';
             $pdf->Output($file,'F');
             if (! empty($conf->global->MAIN_UMASK))
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
@@ -532,7 +607,7 @@ if (empty($reshook))
 	    require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
 	
 	    $langs->load("other");
-	    $upload_dir = $diroutputpdf;
+	    $upload_dir = $diroutputmassaction;
 	    $file = $upload_dir . '/' . GETPOST('file');
 	    $ret=dol_delete_file($file);
 	    if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
@@ -542,30 +617,6 @@ if (empty($reshook))
 	
 }
 
-// Do we click on purge search criteria ?
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
-{
-    $search_user='';
-    $search_sale='';
-    $search_product_category='';
-    $search_ref='';
-    $search_refcustomer='';
-    $search_societe='';
-    $search_montant_ht='';
-    $search_montant_ttc='';
-    $search_status='';
-    $search_paymentmode='';
-    $day='';
-    $year='';
-    $month='';
-    $toselect='';
-    $option='';
-    $filter='';
-    $day_lim='';
-    $year_lim='';
-    $month_lim='';
-}
-
     
 
 /*
@@ -579,16 +630,30 @@ $formother = new FormOther($db);
 $formfile = new FormFile($db);
 $bankaccountstatic=new Account($db);
 $facturestatic=new Facture($db);
+$formcompany=new FormCompany($db);
 
 $sql = 'SELECT';
 if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT';
-$sql.= ' f.rowid as facid, f.facnumber, f.ref_client, f.type, f.note_private, f.note_public, f.increment, f.fk_mode_reglement, f.total as total_ht, f.tva as total_tva, f.total_ttc,';
+$sql.= ' f.rowid as facid, f.facnumber, f.ref_client, f.type, f.note_private, f.note_public, f.increment, f.fk_mode_reglement, f.total as total_ht, f.tva as total_vat, f.total_ttc,';
 $sql.= ' f.datef as df, f.date_lim_reglement as datelimite,';
 $sql.= ' f.paye as paye, f.fk_statut,';
-$sql.= ' s.nom as name, s.rowid as socid, s.code_client, s.client ';
+$sql.= ' f.datec as date_creation, f.tms as date_update,';
+$sql.= ' s.rowid as socid, s.nom as name, s.town, s.zip, s.fk_pays, s.client, s.code_client, ';
+$sql.= " typent.code as typent_code,";
+$sql.= " state.code_departement as state_code, state.nom as state_name";
 if (! $sall) $sql.= ', SUM(pf.amount) as am';   // To be able to sort on status
+// Add fields from extrafields
+foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
+// Add fields from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
 $sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s';
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)";
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_typent as typent on (typent.id = s.fk_typent)";
+$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = s.fk_departement)";
 $sql.= ', '.MAIN_DB_PREFIX.'facture as f';
+if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."facture_extrafields as ef on (f.rowid = ef.fk_object)";
 if (! $sall) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON pf.fk_facture = f.rowid';
 else $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'facturedet as fd ON fd.fk_facture = f.rowid';
 if ($sall || $search_product_category > 0) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'facturedet as pd ON f.rowid=pd.fk_facture';
@@ -622,7 +687,14 @@ if ($filtre)
 if ($search_ref) $sql .= natural_search('f.facnumber', $search_ref);
 if ($search_refcustomer) $sql .= natural_search('f.ref_client', $search_refcustomer);
 if ($search_societe) $sql .= natural_search('s.nom', $search_societe);
+if ($search_town)  $sql.= natural_search('s.town', $search_town);
+if ($search_zip)   $sql.= natural_search("s.zip",$search_zip);
+if ($search_state) $sql.= natural_search("state.nom",$search_state);
+if ($search_country) $sql .= " AND s.fk_pays IN (".$search_country.')';
+if ($search_type_thirdparty) $sql .= " AND s.fk_typent IN (".$search_type_thirdparty.')';
+if ($search_company) $sql .= natural_search('s.nom', $search_company);
 if ($search_montant_ht != '') $sql.= natural_search('f.total', $search_montant_ht, 1);
+if ($search_montant_vat != '') $sql.= natural_search('f.total', $search_montant_vat, 1);
 if ($search_montant_ttc != '') $sql.= natural_search('f.total_ttc', $search_montant_ttc, 1);
 if ($search_status != '' && $search_status >= 0) $sql.= " AND f.fk_statut = ".$db->escape($search_status);
 if ($search_paymentmode > 0) $sql .= " AND f.fk_mode_reglement = ".$search_paymentmode."";
@@ -659,17 +731,37 @@ if ($search_user > 0)
 {
     $sql.= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='facture' AND tc.source='internal' AND ec.element_id = f.rowid AND ec.fk_socpeople = ".$search_user;
 }
+// Add where from extra fields
+foreach ($search_array_options as $key => $val)
+{
+    $crit=$val;
+    $tmpkey=preg_replace('/search_options_/','',$key);
+    $typ=$extrafields->attribute_type[$tmpkey];
+    $mode=0;
+    if (in_array($typ, array('int','double'))) $mode=1;    // Search on a numeric
+    if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit)))
+    {
+        $sql .= natural_search('ef.'.$tmpkey, $crit, $mode);
+    }
+}
+// Add where from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+
 if (! $sall)
 {
     $sql.= ' GROUP BY f.rowid, f.facnumber, ref_client, f.type, f.note_private, f.note_public, f.increment, f.total, f.tva, f.total_ttc,';
     $sql.= ' f.datef, f.date_lim_reglement,';
     $sql.= ' f.paye, f.fk_statut,';
-    $sql.= ' s.nom, s.rowid, s.code_client, s.client';
+    $sql.= ' f.datec, f.tms,';
+    $sql.= ' s.rowid, s.nom, s.town, s.zip, s.fk_pays, s.code_client, s.client';
 }
 else
 {
     $sql .= natural_search(array_keys($fieldstosearchall), $sall);
 }
+
 $sql.= ' ORDER BY ';
 $listfield=explode(',',$sortfield);
 foreach ($listfield as $key => $value) $sql.= $listfield[$key].' '.$sortorder.',';
@@ -713,11 +805,20 @@ if ($resql)
     if ($search_user > 0)    $param.='&search_user=' .$search_user;
     if ($search_product_category > 0)   $param.='$search_product_category=' .$search_product_category;
     if ($search_montant_ht != '')  $param.='&search_montant_ht='.$search_montant_ht;
+    if ($search_montant_vat != '')  $param.='&search_montant_vat='.$search_montant_vat;
     if ($search_montant_ttc != '') $param.='&search_montant_ttc='.$search_montant_ttc;
 	if ($search_status != '') $param.='&search_status='.$search_status;
 	if ($search_paymentmode > 0) $param.='search_paymentmode='.$search_paymentmode;
     if ($show_files)         $param.='&show_files=' .$show_files;
-	$param.=(! empty($option)?"&amp;option=".$option:"");
+	if ($option)             $param.="&option=".$option;
+	if ($optioncss != '')    $param.='&optioncss='.$optioncss;
+	// Add $param from extra fields
+	foreach ($search_array_options as $key => $val)
+	{
+	    $crit=$val;
+	    $tmpkey=preg_replace('/search_options_/','',$key);
+	    if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val);
+	}
 	
 	$massactionbutton=$form->selectMassAction('', $massaction == 'presend' ? array() : array('presend'=>$langs->trans("SendByMail"), 'builddoc'=>$langs->trans("PDFMerge")));
     
@@ -875,188 +976,471 @@ if ($resql)
         print '</div>';
     }
 
-    print '<table class="liste '.($moreforfilter?"listwithfilterbefore":"").'">';
+    $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
+    $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
+	
+	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
     		
     print '<tr class="liste_titre">';
-    print_liste_field_titre($langs->trans('Ref'),$_SERVER['PHP_SELF'],'f.facnumber','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans('RefCustomer'),$_SERVER["PHP_SELF"],'f.ref_client','',$param,'',$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans('Date'),$_SERVER['PHP_SELF'],'f.datef','',$param,'align="center"',$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans("DateDue"),$_SERVER['PHP_SELF'],"f.date_lim_reglement",'',$param,'align="center"',$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans('ThirdParty'),$_SERVER['PHP_SELF'],'s.nom','',$param,'',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans("PaymentModeShort"),$_SERVER["PHP_SELF"],"f.fk_mode_reglement","",$param,"",$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans('AmountHT'),$_SERVER['PHP_SELF'],'f.total','',$param,'align="right"',$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans('Taxes'),$_SERVER['PHP_SELF'],'f.tva','',$param,'align="right"',$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans('AmountTTC'),$_SERVER['PHP_SELF'],'f.total_ttc','',$param,'align="right"',$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans('Received'),$_SERVER['PHP_SELF'],'am','',$param,'align="right"',$sortfield,$sortorder);
-    print_liste_field_titre($langs->trans('Status'),$_SERVER['PHP_SELF'],'fk_statut,paye,am','',$param,'align="right"',$sortfield,$sortorder);
-    print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'','','',$sortfield,$sortorder,'maxwidthsearch ');
+    if (! empty($arrayfields['f.facnumber']['checked']))          print_liste_field_titre($arrayfields['f.facnumber']['label'],$_SERVER['PHP_SELF'],'f.facnumber','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['f.ref_client']['checked']))         print_liste_field_titre($arrayfields['f.ref_client']['label'],$_SERVER["PHP_SELF"],'f.ref_client','',$param,'',$sortfield,$sortorder);
+    if (! empty($arrayfields['f.date']['checked']))               print_liste_field_titre($arrayfields['f.date']['label'],$_SERVER['PHP_SELF'],'f.datef','',$param,'align="center"',$sortfield,$sortorder);
+    if (! empty($arrayfields['f.date_lim_reglement']['checked'])) print_liste_field_titre($arrayfields['f.date_lim_reglement']['label'],$_SERVER['PHP_SELF'],"f.date_lim_reglement",'',$param,'align="center"',$sortfield,$sortorder);
+    if (! empty($arrayfields['s.nom']['checked']))                print_liste_field_titre($arrayfields['s.nom']['label'],$_SERVER['PHP_SELF'],'s.nom','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.town']['checked']))               print_liste_field_titre($arrayfields['s.town']['label'],$_SERVER["PHP_SELF"],'s.town','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['s.zip']['checked']))                print_liste_field_titre($arrayfields['s.zip']['label'],$_SERVER["PHP_SELF"],'s.zip','',$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['state.nom']['checked']))            print_liste_field_titre($arrayfields['state.nom']['label'],$_SERVER["PHP_SELF"],"state.nom","",$param,'',$sortfield,$sortorder);
+	if (! empty($arrayfields['country.code_iso']['checked']))     print_liste_field_titre($arrayfields['country.code_iso']['label'],$_SERVER["PHP_SELF"],"country.code_iso","",$param,'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['typent.code']['checked']))          print_liste_field_titre($arrayfields['typent.code']['label'],$_SERVER["PHP_SELF"],"typent.code","",$param,'align="center"',$sortfield,$sortorder);
+    if (! empty($arrayfields['f.fk_mode_reglement']['checked']))  print_liste_field_titre($arrayfields['f.fk_mode_reglement']['label'],$_SERVER["PHP_SELF"],"f.fk_mode_reglement","",$param,"",$sortfield,$sortorder);
+    if (! empty($arrayfields['f.total_ht']['checked']))           print_liste_field_titre($arrayfields['f.total_ht']['label'],$_SERVER['PHP_SELF'],'f.total','',$param,'align="right"',$sortfield,$sortorder);
+    if (! empty($arrayfields['f.total_vat']['checked']))          print_liste_field_titre($arrayfields['f.total_vat']['label'],$_SERVER['PHP_SELF'],'f.tva','',$param,'align="right"',$sortfield,$sortorder);
+    if (! empty($arrayfields['f.total_ttc']['checked']))          print_liste_field_titre($arrayfields['f.total_ttc']['label'],$_SERVER['PHP_SELF'],'f.total_ttc','',$param,'align="right"',$sortfield,$sortorder);
+    if (! empty($arrayfields['am']['checked']))                   print_liste_field_titre($arrayfields['am']['label'],$_SERVER['PHP_SELF'],'am','',$param,'align="right"',$sortfield,$sortorder);
+    // Extra fields
+    if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+    {
+        foreach($extrafields->attribute_label as $key => $val)
+        {
+            if (! empty($arrayfields["ef.".$key]['checked']))
+            {
+                $align=$extrafields->getAlignFlag($key);
+                print_liste_field_titre($extralabels[$key],$_SERVER["PHP_SELF"],"ef.".$key,"",$param,($align?'align="'.$align.'"':''),$sortfield,$sortorder);
+            }
+        }
+    }
+    // Hook fields
+    $parameters=array('arrayfields'=>$arrayfields);
+    $reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters);    // Note that $action and $object may have been modified by hook
+    print $hookmanager->resPrint;
+    if (! empty($arrayfields['f.datec']['checked']))     print_liste_field_titre($arrayfields['f.datec']['label'],$_SERVER["PHP_SELF"],"f.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+    if (! empty($arrayfields['f.tms']['checked']))       print_liste_field_titre($arrayfields['f.tms']['label'],$_SERVER["PHP_SELF"],"f.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+    if (! empty($arrayfields['f.fk_statut']['checked'])) print_liste_field_titre($arrayfields['f.fk_statut']['label'],$_SERVER["PHP_SELF"],"fk_statut,paye,am","",$param,'align="right"',$sortfield,$sortorder);
+    print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="right"',$sortfield,$sortorder,'maxwidthsearch ');
     print "</tr>\n";
 
     // Filters lines
     print '<tr class="liste_titre">';
-    print '<td class="liste_titre" align="left">';
-    print '<input class="flat" size="6" type="text" name="search_ref" value="'.$search_ref.'">';
-    print '</td>';
-	print '<td class="liste_titre">';
-	print '<input class="flat" size="6" type="text" name="search_refcustomer" value="'.$search_refcustomer.'">';
-	print '</td>';
-    print '<td class="liste_titre" align="center">';
-    if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="day" value="'.$day.'">';
-    print '<input class="flat" type="text" size="1" maxlength="2" name="month" value="'.$month.'">';
-    $formother->select_year($year?$year:-1,'year',1, 20, 5);
-    print '</td>';
- 	print '<td class="liste_titre" align="center">';
-    if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="day_lim" value="'.$day_lim.'">';
-    print '<input class="flat" type="text" size="1" maxlength="2" name="month_lim" value="'.$month_lim.'">';
-    $formother->select_year($year_lim?$year_lim:-1,'year_lim',1, 20, 5);
-	print '<br><input type="checkbox" name="option" value="late"'.($option == 'late'?' checked':'').'> '.$langs->trans("Late");
-    print '</td>';
-    print '<td class="liste_titre" align="left"><input class="flat" type="text" size="8" name="search_societe" value="'.$search_societe.'"></td>';
-	print '<td class="liste_titre" align="left">';
-	$form->select_types_paiements($search_paymentmode, 'search_paymentmode', '', 0, 0, 1, 10);
-	print '</td>';
-    print '<td class="liste_titre" align="right"><input class="flat" type="text" size="6" name="search_montant_ht" value="'.$search_montant_ht.'"></td>';
-    print '<td class="liste_titre"></td>';
-    print '<td class="liste_titre" align="right"><input class="flat" type="text" size="6" name="search_montant_ttc" value="'.$search_montant_ttc.'"></td>';
-    print '<td class="liste_titre"></td>';
-    print '<td class="liste_titre" align="right">';
-	$liststatus=array('0'=>$langs->trans("BillShortStatusDraft"), '1'=>$langs->trans("BillShortStatusNotPaid"), '2'=>$langs->trans("BillShortStatusPaid"), '3'=>$langs->trans("BillShortStatusCanceled"));
-	print $form->selectarray('search_status', $liststatus, $search_status, 1);
-    print '</td>';
-    print '<td class="liste_titre" align="center">';
-    $searchpitco=$form->showFilterAndCheckAddButtons(1, 'checkforselect', 1);
-    print $searchpitco;
+	// Ref
+	if (! empty($arrayfields['f.facnumber']['checked'])) 
+	{
+        print '<td class="liste_titre" align="left">';
+        print '<input class="flat" size="6" type="text" name="search_ref" value="'.$search_ref.'">';
+        print '</td>';
+	}
+	// Ref customer
+	if (! empty($arrayfields['f.ref_client']['checked'])) 
+	{
+    	print '<td class="liste_titre">';
+    	print '<input class="flat" size="6" type="text" name="search_refcustomer" value="'.$search_refcustomer.'">';
+    	print '</td>';
+	}
+	// Date invoice
+	if (! empty($arrayfields['f.date']['checked'])) 
+	{
+    	print '<td class="liste_titre" align="center">';
+        if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="day" value="'.$day.'">';
+        print '<input class="flat" type="text" size="1" maxlength="2" name="month" value="'.$month.'">';
+        $formother->select_year($year?$year:-1,'year',1, 20, 5);
+        print '</td>';
+	}
+	// Date due
+	if (! empty($arrayfields['f.date_lim_reglement']['checked'])) 
+	{
+    	print '<td class="liste_titre" align="center">';
+        if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print '<input class="flat" type="text" size="1" maxlength="2" name="day_lim" value="'.$day_lim.'">';
+        print '<input class="flat" type="text" size="1" maxlength="2" name="month_lim" value="'.$month_lim.'">';
+        $formother->select_year($year_lim?$year_lim:-1,'year_lim',1, 20, 5);
+    	print '<br><input type="checkbox" name="option" value="late"'.($option == 'late'?' checked':'').'> '.$langs->trans("Late");
+        print '</td>';
+	}
+	// Thirpdarty
+	if (! empty($arrayfields['s.nom']['checked'])) 
+	{
+	   print '<td class="liste_titre" align="left"><input class="flat" type="text" size="8" name="search_societe" value="'.$search_societe.'"></td>';
+	}
+	// Town
+	if (! empty($arrayfields['s.town']['checked'])) print '<td class="liste_titre"><input class="flat" type="text" size="6" name="search_town" value="'.$search_town.'"></td>';
+	// Zip
+	if (! empty($arrayfields['s.zip']['checked'])) print '<td class="liste_titre"><input class="flat" type="text" size="6" name="search_zip" value="'.$search_zip.'"></td>';
+	// State
+	if (! empty($arrayfields['state.nom']['checked']))
+	{
+	    print '<td class="liste_titre">';
+	    print '<input class="flat" size="4" type="text" name="search_state" value="'.dol_escape_htmltag($search_state).'">';
+	    print '</td>';
+	}
+	// Country
+	if (! empty($arrayfields['country.code_iso']['checked']))
+	{
+	    print '<td class="liste_titre" align="center">';
+	    print $form->select_country($search_country,'search_country','',0,'maxwidth100');
+	    print '</td>';
+	}
+	// Company type
+	if (! empty($arrayfields['typent.code']['checked']))
+	{
+	    print '<td class="liste_titre maxwidthonsmartphone" align="center">';
+	    print $form->selectarray("search_type_thirdparty", $formcompany->typent_array(0), $search_type_thirdparty, 0, 0, 0, '', 0, 0, 0, (empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?'ASC':$conf->global->SOCIETE_SORT_ON_TYPEENT));
+	    print '</td>';
+	}
+	// Payment mode
+	if (! empty($arrayfields['f.fk_mode_reglement']['checked'])) 
+	{
+    	print '<td class="liste_titre" align="left">';
+    	$form->select_types_paiements($search_paymentmode, 'search_paymentmode', '', 0, 0, 1, 10);
+    	print '</td>';
+	}
+	if (! empty($arrayfields['f.total_ht']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_montant_ht" value="'.$search_montant_ht.'">';
+    	print '</td>';
+	}
+	if (! empty($arrayfields['f.total_vat']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_montant_vat" value="'.$search_montant_vat.'">';
+    	print '</td>';
+	}
+	if (! empty($arrayfields['f.total_ttc']['checked']))
+	{
+    	// Amount
+    	print '<td class="liste_titre" align="right">';
+    	print '<input class="flat" type="text" size="5" name="search_montant_ttc" value="'.$search_montant_ttc.'">';
+    	print '</td>';
+	}
+    if (! empty($arrayfields['am']['checked']))
+    {
+        print '<td class="liste_titre" align="right">';
+        print '</td>';
+    }
+    // Extra fields
+	if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+	{
+	    foreach($extrafields->attribute_label as $key => $val)
+	    {
+	        if (! empty($arrayfields["ef.".$key]['checked']))
+	        {
+	            $align=$extrafields->getAlignFlag($key);
+	            $typeofextrafield=$extrafields->attribute_type[$key];
+	            print '<td class="liste_titre'.($align?' '.$align:'').'">';
+	            if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')))
+	            {
+	                $crit=$val;
+	                $tmpkey=preg_replace('/search_options_/','',$key);
+	                $searchclass='';
+	                if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring';
+	                if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum';
+	                print '<input class="flat'.($searchclass?' '.$searchclass:'').'" size="4" type="text" name="search_options_'.$tmpkey.'" value="'.dol_escape_htmltag($search_array_options['search_options_'.$tmpkey]).'">';
+	            }
+	            print '</td>';
+	        }
+	    }
+	}
+	// Fields from hook
+	$parameters=array('arrayfields'=>$arrayfields);
+	$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters);    // Note that $action and $object may have been modified by hook
+	print $hookmanager->resPrint;
+	// Date creation
+	if (! empty($arrayfields['f.datec']['checked']))
+	{
+	    print '<td class="liste_titre">';
+	    print '</td>';
+	}
+	// Date modification
+	if (! empty($arrayfields['f.tms']['checked']))
+	{
+	    print '<td class="liste_titre">';
+	    print '</td>';
+	}
+	// Status
+	if (! empty($arrayfields['f.fk_statut']['checked']))
+	{
+	    print '<td class="liste_titre maxwidthonsmartphone" align="right">';
+    	$liststatus=array('0'=>$langs->trans("BillShortStatusDraft"), '1'=>$langs->trans("BillShortStatusNotPaid"), '2'=>$langs->trans("BillShortStatusPaid"), '3'=>$langs->trans("BillShortStatusCanceled"));
+    	print $form->selectarray('search_status', $liststatus, $search_status, 1);
+	    print '</td>';
+	}
+	// Action column
+	print '<td class="liste_titre" align="middle">';
+	$searchpitco=$form->showFilterAndCheckAddButtons(1, 'checkforselect', 1);
+	print $searchpitco;
     print '</td>';
     print "</tr>\n";
 
     if ($num > 0)
     {
+        $i=0;
         $var=true;
-        $total_ht=0;
-        $total_tva=0;
-        $total_ttc=0;
-        $totalrecu=0;
-
+        $totalarray=array();
         while ($i < min($num,$limit))
         {
-            $objp = $db->fetch_object($resql);
+            $obj = $db->fetch_object($resql);
             $var=!$var;
 
-            $datelimit=$db->jdate($objp->datelimite);
+            $datelimit=$db->jdate($obj->datelimite);
 
             print '<tr '.$bc[$var].'>';
-            print '<td class="nowrap">';
-
-            $facturestatic->id=$objp->facid;
-            $facturestatic->ref=$objp->facnumber;
-            $facturestatic->type=$objp->type;
-            $facturestatic->statut=$objp->fk_statut;
-            $facturestatic->date_lim_reglement=$db->jdate($objp->datelimite);
-            $notetoshow=dol_string_nohtmltag(($user->societe_id>0?$objp->note_public:$objp->note_private),1);
-            $paiement = $facturestatic->getSommePaiement();
-
-            print '<table class="nobordernopadding"><tr class="nocellnopadd">';
-
-            print '<td class="nobordernopadding nowrap">';
-            print $facturestatic->getNomUrl(1,'',200,0,$notetoshow);
-            print $objp->increment;
-            print '</td>';
-
-            print '<td style="min-width: 20px" class="nobordernopadding nowrap">';
-            if (! empty($objp->note_private))
-            {
-				print ' <span class="note">';
-				print '<a href="'.DOL_URL_ROOT.'/compta/facture/note.php?id='.$objp->facid.'">'.img_picto($langs->trans("ViewPrivateNote"),'object_generic').'</a>';
-				print '</span>';
-			}
-            $filename=dol_sanitizeFileName($objp->facnumber);
-            $filedir=$conf->facture->dir_output . '/' . dol_sanitizeFileName($objp->facnumber);
-            $urlsource=$_SERVER['PHP_SELF'].'?id='.$objp->facid;
-            print $formfile->getDocumentsLink($facturestatic->element, $filename, $filedir);
-			print '</td>';
-            print '</tr>';
-            print '</table>';
-
-            print "</td>\n";
-
+    		if (! empty($arrayfields['f.facnumber']['checked']))
+    		{
+                print '<td class="nowrap">';
+    
+                $facturestatic->id=$obj->facid;
+                $facturestatic->ref=$obj->facnumber;
+                $facturestatic->type=$obj->type;
+                $facturestatic->statut=$obj->fk_statut;
+                $facturestatic->date_lim_reglement=$db->jdate($obj->datelimite);
+                $notetoshow=dol_string_nohtmltag(($user->societe_id>0?$obj->note_public:$obj->note_private),1);
+                $paiement = $facturestatic->getSommePaiement();
+    
+                print '<table class="nobordernopadding"><tr class="nocellnopadd">';
+    
+                print '<td class="nobordernopadding nowrap">';
+                print $facturestatic->getNomUrl(1,'',200,0,$notetoshow);
+                print $obj->increment;
+                print '</td>';
+    
+                print '<td style="min-width: 20px" class="nobordernopadding nowrap">';
+                if (! empty($obj->note_private))
+                {
+    				print ' <span class="note">';
+    				print '<a href="'.DOL_URL_ROOT.'/compta/facture/note.php?id='.$obj->facid.'">'.img_picto($langs->trans("ViewPrivateNote"),'object_generic').'</a>';
+    				print '</span>';
+    			}
+                $filename=dol_sanitizeFileName($obj->facnumber);
+                $filedir=$conf->facture->dir_output . '/' . dol_sanitizeFileName($obj->facnumber);
+                $urlsource=$_SERVER['PHP_SELF'].'?id='.$obj->facid;
+                print $formfile->getDocumentsLink($facturestatic->element, $filename, $filedir);
+    			print '</td>';
+                print '</tr>';
+                print '</table>';
+    
+                print "</td>\n";
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		
 			// Customer ref
-			print '<td class="nowrap">';
-			print $objp->ref_client;
-			print '</td>';
-
+    		if (! empty($arrayfields['f.ref_client']['checked']))
+    		{
+        		print '<td class="nowrap">';
+    			print $obj->ref_client;
+    			print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		
 			// Date
-            print '<td align="center" class="nowrap">';
-            print dol_print_date($db->jdate($objp->df),'day');
-            print '</td>';
-
+    		if (! empty($arrayfields['f.date']['checked']))
+    		{
+        		print '<td align="center" class="nowrap">';
+                print dol_print_date($db->jdate($obj->df),'day');
+                print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		
             // Date limit
-            print '<td align="center" class="nowrap">'.dol_print_date($datelimit,'day');
-            if ($facturestatic->hasDelay())
+    		if (! empty($arrayfields['f.date_lim_reglement']['checked']))
+    		{
+        		print '<td align="center" class="nowrap">'.dol_print_date($datelimit,'day');
+                if ($facturestatic->hasDelay())
+                {
+                    print img_warning($langs->trans('Late'));
+                }
+                print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		
+    		// Third party
+    		if (! empty($arrayfields['s.nom']['checked']))
+    		{
+                print '<td>';
+                $thirdparty=new Societe($db);
+                $thirdparty->id=$obj->socid;
+                $thirdparty->name=$obj->name;
+                $thirdparty->client=$obj->client;
+                $thirdparty->code_client=$obj->code_client;
+                print $thirdparty->getNomUrl(1,'customer');
+                print '</td>';
+                if (! $i) $totalarray['nbfield']++;
+    		}
+    		// Town
+    		if (! empty($arrayfields['s.town']['checked']))
+    		{
+    		    print '<td class="nocellnopadd">';
+    		    print $obj->town;
+    		    print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		// Zip
+    		if (! empty($arrayfields['s.zip']['checked']))
+    		{
+    		    print '<td class="nocellnopadd">';
+    		    print $obj->zip;
+    		    print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		// State
+    		if (! empty($arrayfields['state.nom']['checked']))
+    		{
+    		    print "<td>".$obj->state_name."</td>\n";
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		// Country
+    		if (! empty($arrayfields['country.code_iso']['checked']))
+    		{
+    		    print '<td align="center">';
+    		    $tmparray=getCountry($obj->fk_pays,'all');
+    		    print $tmparray['label'];
+    		    print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		// Type ent
+    		if (! empty($arrayfields['typent.code']['checked']))
+    		{
+    		    print '<td align="center">';
+    		    if (count($typenArray)==0) $typenArray = $formcompany->typent_array(1);
+    		    print $typenArray[$obj->typent_code];
+    		    print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		
+            // Payment mode
+    		if (! empty($arrayfields['f.fk_mode_reglement']['checked']))
+    		{
+        		print '<td>';
+                $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1);
+                print '</td>';
+    		    if (! $i) $totalarray['nbfield']++;
+    		}
+    		
+            // Amount HT
+            if (! empty($arrayfields['f.total_ht']['checked']))
             {
-                print img_warning($langs->trans('Late'));
+    		      print '<td align="right">'.price($obj->total_ht)."</td>\n";
+    		      if (! $i) $totalarray['nbfield']++;
+    		      if (! $i) $totalarray['totalhtfield']=$totalarray['nbfield'];
+    		      $totalarray['totalht'] += $obj->total_ht;
+            }
+            // Amount VAT
+            if (! empty($arrayfields['f.total_vat']['checked']))
+            {
+                print '<td align="right">'.price($obj->total_vat)."</td>\n";
+                if (! $i) $totalarray['nbfield']++;
+    		    if (! $i) $totalarray['totalvatfield']=$totalarray['nbfield'];
+    		    $totalarray['totalvat'] += $obj->total_vat;
+            }
+            // Amount TTC
+            if (! empty($arrayfields['f.total_ttc']['checked']))
+            {
+                print '<td align="right">'.price($obj->total_ttc)."</td>\n";
+                if (! $i) $totalarray['nbfield']++;
+    		    if (! $i) $totalarray['totalttcfield']=$totalarray['nbfield'];
+    		    $totalarray['totalttc'] += $obj->total_ttc;
             }
-            print '</td>';
-
-            print '<td>';
-            $thirdparty=new Societe($db);
-            $thirdparty->id=$objp->socid;
-            $thirdparty->name=$objp->name;
-            $thirdparty->client=$objp->client;
-            $thirdparty->code_client=$objp->code_client;
-            print $thirdparty->getNomUrl(1,'customer');
-            print '</td>';
 
-            // Payment mode
-            print '<td>';
-            $form->form_modes_reglement($_SERVER['PHP_SELF'], $objp->fk_mode_reglement, 'none', '', -1);
-            print '</td>';
+            if (! empty($arrayfields['am']['checked']))
+            {
+                print '<td align="right">'.(! empty($paiement)?price($paiement,0,$langs):'&nbsp;').'</td>';
+                if (! $i) $totalarray['nbfield']++;
+    		    if (! $i) $totalarray['totalamfield']=$totalarray['nbfield'];
+    		    $totalarray['totalam'] += $paiement;
+            }
             
-            print '<td align="right">'.price($objp->total_ht,0,$langs).'</td>';
-
-            print '<td align="right">'.price($objp->total_tva,0,$langs).'</td>';
-
-            print '<td align="right">'.price($objp->total_ttc,0,$langs).'</td>';
-
-            print '<td align="right">'.(! empty($paiement)?price($paiement,0,$langs):'&nbsp;').'</td>';
-
+            // Extra fields
+            if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+            {
+                foreach($extrafields->attribute_label as $key => $val)
+                {
+                    if (! empty($arrayfields["ef.".$key]['checked']))
+                    {
+                        print '<td';
+                        $align=$extrafields->getAlignFlag($key);
+                        if ($align) print ' align="'.$align.'"';
+                        print '>';
+                        $tmpkey='options_'.$key;
+                        print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1);
+                        print '</td>';
+                        if (! $i) $totalarray['nbfield']++;
+                    }
+                }
+            }
+            // Fields from hook
+            $parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj);
+            $reshook=$hookmanager->executeHooks('printFieldListValue',$parameters);    // Note that $action and $object may have been modified by hook
+            print $hookmanager->resPrint;
+            // Date creation
+            if (! empty($arrayfields['f.datec']['checked']))
+            {
+                print '<td align="center" class="nowrap">';
+                print dol_print_date($db->jdate($obj->date_creation), 'dayhour');
+                print '</td>';
+                if (! $i) $totalarray['nbfield']++;
+            }
+            // Date modification
+            if (! empty($arrayfields['f.tms']['checked']))
+            {
+                print '<td align="center" class="nowrap">';
+                print dol_print_date($db->jdate($obj->date_update), 'dayhour');
+                print '</td>';
+                if (! $i) $totalarray['nbfield']++;
+            }
             // Status
-            print '<td align="right" class="nowrap">';
-            print $facturestatic->LibStatut($objp->paye,$objp->fk_statut,5,$paiement,$objp->type);
-            print "</td>";
-
-			// Checkbox
+            if (! empty($arrayfields['f.fk_statut']['checked']))
+            {
+                print '<td align="right" class="nowrap">';
+                print $facturestatic->LibStatut($obj->paye,$obj->fk_statut,5,$paiement,$obj->type);
+                print "</td>";
+                if (! $i) $totalarray['nbfield']++;
+            }
+            
+    		// Action column
             print '<td class="nowrap" align="center">';
             $selected=0;
-			if (in_array($objp->facid, $arrayofselected)) $selected=1;
-			print '<input id="cb'.$objp->facid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$objp->facid.'"'.($selected?' checked="checked"':'').'>';
-			print '</td>' ;
-
+    		if (in_array($obj->facid, $arrayofselected)) $selected=1;
+    		print '<input id="cb'.$obj->facid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->facid.'"'.($selected?' checked="checked"':'').'>';
+    		print '</td>' ;
+    		if (! $i) $totalarray['nbfield']++;
+				
             print "</tr>\n";
-            $total_ht+=$objp->total_ht;
-            $total_tva+=$objp->total_tva;
-            $total_ttc+=$objp->total_ttc;
-            $totalrecu+=$paiement;
+
             $i++;
         }
 
-        if (($offset + $num) <= $limit)
-        {
-            // Print total
-            print '<tr class="liste_total">';
-            print '<td class="liste_total" colspan="6" align="left">'.$langs->trans('Total').'</td>';
-            print '<td class="liste_total" align="right">'.price($total_ht,0,$langs).'</td>';
-            print '<td class="liste_total" align="right">'.price($total_tva,0,$langs).'</td>';
-            print '<td class="liste_total" align="right">'.price($total_ttc,0,$langs).'</td>';
-            print '<td class="liste_total" align="right">'.price($totalrecu,0,$langs).'</td>';
-            print '<td class="liste_total"></td>';
-            print '<td class="liste_total"></td>';
-            print '</tr>';
-        }
+    	// Show total line
+    	if (isset($totalarray['totalhtfield']))
+    	{
+    		print '<tr class="liste_total">';
+    		$i=0;
+    		while ($i < $totalarray['nbfield'])
+    		{
+    		   $i++;
+    		   if ($i == 1)
+    	       {
+            		if ($num < $limit) print '<td align="left">'.$langs->trans("Total").'</td>';
+            		else print '<td align="left">'.$langs->trans("Totalforthispage").'</td>';
+    	       }
+    		   elseif ($totalarray['totalhtfield'] == $i)  print '<td align="right">'.price($totalarray['totalht']).'</td>';
+    		   elseif ($totalarray['totalvatfield'] == $i) print '<td align="right">'.price($totalarray['totalvat']).'</td>';
+    		   elseif ($totalarray['totalttcfield'] == $i) print '<td align="right">'.price($totalarray['totalttc']).'</td>';
+    		   elseif ($totalarray['totalamfield'] == $i)  print '<td align="right">'.price($totalarray['totalam']).'</td>';
+    		   else print '<td></td>';
+    		}
+    		print '</tr>';
+    		
+    	}
     }
 
-    print "</table>\n";
-    print "</form>\n";
     $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
+	print $hookmanager->resPrint;
+    
+	print "</table>\n";
+    
+    print "</form>\n";
     
     if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files)
     {
@@ -1066,7 +1450,7 @@ if ($resql)
         $urlsource=$_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
         $urlsource.=str_replace('&amp;','&',$param);
         
-        $filedir=$diroutputpdf;
+        $filedir=$diroutputmassaction;
         $genallowed=$user->rights->facture->lire;
         $delallowed=$user->rights->facture->lire;
     
@@ -1074,7 +1458,7 @@ if ($resql)
         $paramwithoutshowfiles=preg_replace('/show_files=1&?/','',$param);
         $title=$langs->trans("MassFilesArea").' <a href="'.$_SERVER["PHP_SELF"].'?'.$paramwithoutshowfiles.'">('.$langs->trans("Hide").')</a>';
         
-        $formfile->show_documents('massfilesarea','',$filedir,$urlsource,0,$delallowed,'',1,1,0,48,1,$param,$title,'');
+        print $formfile->showdocuments('massfilesarea','',$filedir,$urlsource,0,$delallowed,'',1,1,0,48,1,$param,$title,'');
     }
     else
     {

+ 2 - 24
htdocs/compta/facture/tpl/linkedobjectblock.tpl.php

@@ -27,21 +27,8 @@ global $user;
 
 $langs = $GLOBALS['langs'];
 $linkedObjectBlock = $GLOBALS['linkedObjectBlock'];
-
 $langs->load("bills");
-echo '<br>';
-print load_fiche_titre($langs->trans("RelatedCustomerInvoices"), '', '');
-?>
-<table class="noborder allwidth">
-<tr class="liste_titre">
-	<td><?php echo $langs->trans("Ref"); ?></td>
-	<td align="center"><?php echo $langs->trans("RefCustomer"); ?></td>
-	<td align="center"><?php echo $langs->trans("Date"); ?></td>
-	<td align="right"><?php echo $langs->trans("AmountHTShort"); ?></td>
-	<td align="right"><?php echo $langs->trans("Status"); ?></td>
-	<td></td>
-</tr>
-<?php
+
 $var=true;
 $total=0;
 foreach($linkedObjectBlock as $key => $objectlink)
@@ -49,6 +36,7 @@ foreach($linkedObjectBlock as $key => $objectlink)
 	$var=!$var;
 ?>
 <tr <?php echo $GLOBALS['bc'][$var]; ?> >
+    <td><?php echo $langs->trans("CustomerInvoice"); ?></td>
     <td><?php echo $objectlink->getNomUrl(1); ?></td>
 	<td align="center"><?php echo $objectlink->ref_client; ?></td>
 	<td align="center"><?php echo dol_print_date($objectlink->date,'day'); ?></td>
@@ -63,15 +51,5 @@ foreach($linkedObjectBlock as $key => $objectlink)
 <?php
 }
 ?>
-<tr class="liste_total">
-	<td align="left" colspan="3"><?php echo $langs->trans("TotalHT"); ?></td>
-	<td align="right"><?php
-		if ($user->rights->facture->lire) {
-			echo price($total);
-		} ?></td>
-	<td></td>
-	<td></td>
-</tr>
-</table>
 
 <!-- END PHP TEMPLATE -->

+ 5 - 18
htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php

@@ -27,21 +27,8 @@ global $user;
 
 $langs = $GLOBALS['langs'];
 $linkedObjectBlock = $GLOBALS['linkedObjectBlock'];
-
 $langs->load("bills");
-echo '<br>';
-print load_fiche_titre($langs->trans("RelatedRecurringCustomerInvoices"), '', '');
-?>
-<table class="noborder allwidth">
-<tr class="liste_titre">
-	<td><?php echo $langs->trans("Ref"); ?></td>
-	<!-- <td align="center"><?php echo $langs->trans("RefCustomer"); ?></td>
-	<td align="center"><?php echo $langs->trans("Date"); ?></td>-->
-	<td align="right"><?php echo $langs->trans("AmountHTShort"); ?></td>
-	<!-- <td align="right"><?php echo $langs->trans("Status"); ?></td> -->
-	<td></td>
-</tr>
-<?php
+
 $var=true;
 $total=0;
 foreach($linkedObjectBlock as $key => $objectlink)
@@ -49,20 +36,20 @@ foreach($linkedObjectBlock as $key => $objectlink)
 	$var=!$var;
 ?>
 <tr <?php echo $GLOBALS['bc'][$var]; ?> >
+    <td><?php echo $langs->trans("RepeatableInvoice"); ?></td>
     <td><?php echo $objectlink->getNomUrl(1); ?></td>
-	<!-- <td align="center"><?php echo $objectlink->ref_client; ?></td>
-	<td align="center"><?php echo dol_print_date($objectlink->date,'day'); ?></td> -->
+	<td align="center"></td>
+	<td align="center"><?php echo dol_print_date($objectlink->date,'day'); ?></td>
 	<td align="right"><?php
 		if ($user->rights->facture->lire) {
 			$total = $total + $objectlink->total_ht;
 			echo price($objectlink->total_ht);
 		} ?></td>
-	<!-- <td align="right"><?php echo $objectlink->getLibStatut(3); ?></td> -->
+	<td align="right"></td>
 	<td align="right"><a href="<?php echo $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=dellink&dellinkid='.$key; ?>"><?php echo img_delete($langs->transnoentitiesnoconv("RemoveLink")); ?></a></td>
 </tr>
 <?php
 }
 ?>
-</table>
 
 <!-- END PHP TEMPLATE -->

+ 43 - 25
htdocs/compta/localtax/card.php

@@ -19,7 +19,7 @@
 /**
  *	    \file       htdocs/compta/localtax/card.php
  *      \ingroup    tax
- *		\brief      Page of IRPF payments
+ *		\brief      Page of second or third tax payments (like IRPF for spain, ...)
  */
 
 require '../../main.inc.php';
@@ -30,17 +30,25 @@ $langs->load("compta");
 $langs->load("banks");
 $langs->load("bills");
 
-$id=$_REQUEST["id"];
+$id=GETPOST("id",'int');
+$action=GETPOST("action","alpha");
+$refund=GETPOST("refund","int");
+if (empty($refund)) $refund=0;
+
 $lttype=GETPOST('localTaxType', 'int');
-$mesg = '';
 
 // Security check
 $socid = isset($_GET["socid"])?$_GET["socid"]:'';
 if ($user->societe_id) $socid=$user->societe_id;
 $result = restrictedArea($user, 'tax', '', '', 'charges');
 
+$localtax = new Localtax($db);
 
-/*
+// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
+$hookmanager->initHooks(array('localtaxvatcard','globalcard'));
+
+
+/**
  * Actions
  */
 
@@ -50,9 +58,8 @@ if($_POST["cancel"] == $langs->trans("Cancel")){
 	exit;
 }
 
-if ($_POST["action"] == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
+if ($action == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
 {
-    $localtax = new Localtax($db);
 
     $db->begin();
 
@@ -83,10 +90,9 @@ if ($_POST["action"] == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
 }
 
 //delete payment of localtax
-if ($_GET["action"] == 'delete')
+if ($action == 'delete')
 {
-    $localtax = new Localtax($db);
-    $result=$localtax->fetch($_GET['id']);
+    $result=$localtax->fetch($id);
 
 	if ($localtax->rappro == 0)
 	{
@@ -99,10 +105,10 @@ if ($_GET["action"] == 'delete')
 			{
 				$accountline=new AccountLine($db);
 				$result=$accountline->fetch($localtax->fk_bank);
-				$result=$accountline->delete($user);
+				if ($result > 0) $result=$accountline->delete($user);	// $result may be 0 if not found (when bank entry was deleted manually and fk_bank point to nothing)
 			}
 
-			if ($result > 0)
+			if ($result >= 0)
 			{
 				$db->commit();
 				header("Location: ".DOL_URL_ROOT.'/compta/localtax/reglement.php?localTaxType='.$localtax->ltt);
@@ -149,26 +155,26 @@ if ($id)
 }
 
 
-if ($_GET["action"] == 'create')
+if ($action == 'create')
 {
-    print "<form name='add' action=\"card.php\" method=\"post\">\n";
+    print load_fiche_titre($langs->transcountry($lttype==2?"newLT2Payment":"newLT1Payment",$mysoc->country_code));
+    
+    print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" name="formlocaltax" method="post">'."\n";
     print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
     print '<input type="hidden" name="localTaxType" value="'.$lttype.'">';
     print '<input type="hidden" name="action" value="add">';
 
-    print load_fiche_titre($langs->transcountry($lttype==2?"newLT2Payment":"newLT1Payment",$mysoc->country_code));
-    
-    if ($mesg) print $mesg;
+    dol_fiche_head();
 
     print '<table class="border" width="100%">';
 
     print "<tr>";
     print '<td class="fieldrequired">'.$langs->trans("DatePayment").'</td><td>';
-    print $form->select_date($datep,"datep",'','','','add');
+    print $form->select_date($datep,"datep",'','','','add',1,1);
     print '</td></tr>';
 
     print '<tr><td class="fieldrequired">'.$langs->trans("DateValue").'</td><td>';
-    print $form->select_date($datev,"datev",'','','','add');
+    print $form->select_date($datev,"datev",'','','','add',1,1);
     print '</td></tr>';
 
 	// Label
@@ -184,13 +190,22 @@ if ($_GET["action"] == 'create')
         print '</td></tr>';
 
 	    print '<tr><td class="fieldrequired">'.$langs->trans("PaymentMode").'</td><td>';
-	    $form->select_types_paiements($_POST["paiementtype"], "paiementtype");
+	    $form->select_types_paiements(GETPOST("paiementtype"), "paiementtype");
 	    print "</td>\n";
 	    print "</tr>";
-	}
+	
+		// Number
+		print '<tr><td>'.$langs->trans('Numero');
+		print ' <em>('.$langs->trans("ChequeOrTransferNumber").')</em>';
+		print '<td><input name="num_payment" type="text" value="'.GETPOST("num_payment").'"></td></tr>'."\n";
+    }
+    // Other attributes
+    $parameters=array('colspan' => ' colspan="1"');
+    $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action);    // Note that $action and $object may have been modified by hook
+
     print '</table>';
 
-	print "<br>";
+	dol_fiche_end();
 
 	print '<div class="center">';
 	print '<input type="submit" class="button" value="'.$langs->trans("Save").'">';
@@ -210,8 +225,6 @@ if ($_GET["action"] == 'create')
 
 if ($id)
 {
-    if ($mesg) print $mesg;
-
 	$h = 0;
 	$head[$h][0] = DOL_URL_ROOT.'/compta/localtax/card.php?id='.$vatpayment->id;
 	$head[$h][1] = $langs->trans('Card');
@@ -255,9 +268,14 @@ if ($id)
 		}
 	}
 
-	print '</table>';
+    // Other attributes
+    $parameters=array('colspan' => ' colspan="3"');
+    $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$vatpayment,$action);    // Note that $action and $object may have been modified by hook
+	
+    print '</table>';
 
-	print '</div>';
+	dol_fiche_end();
+	
 
 	/*
 	* Boutons d'actions

+ 6 - 2
htdocs/compta/localtax/clients.php

@@ -168,9 +168,11 @@ if($conf->global->$calc ==0 || $conf->global->$calc == 2)
 	$parameters["start"] = $date_start;
 	$parameters["end"] = $date_end;
 	$parameters["direction"] = 'sell';
+	$parameters["type"] = 'localtax'.$local;
+	
 	// Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
 	$hookmanager->initHooks(array('externalbalance'));
-	$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+	$reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 
 	if (is_array($coll_list))
 	{
@@ -244,7 +246,9 @@ if($conf->global->$calc ==0 || $conf->global->$calc == 1){
 
 	$coll_list = vat_by_thirdparty($db,0,$date_start,$date_end,$modetax,'buy');
 	$parameters["direction"] = 'buy';
-	$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+	$parameters["type"] = 'localtax'.$local;
+	
+	$reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 	if (is_array($coll_list))
 	{
 		$var=true;

+ 21 - 15
htdocs/compta/localtax/index.php

@@ -27,10 +27,15 @@ require_once DOL_DOCUMENT_ROOT.'/compta/tva/class/tva.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
 
 $langs->load("other");
+$langs->load("compta");
+$langs->load("banks");
+$langs->load("bills");
+
 $localTaxType=GETPOST('localTaxType', 'int');
 
-$year=$_GET["year"];
-if ($year == 0 ) {
+$year=GETPOST("year","int");
+if ($year == 0)
+{
     $year_current = strftime("%Y",time());
     $year_start = $year_current;
 } else {
@@ -122,25 +127,24 @@ if($localTaxType==1) {
 $textprevyear="<a href=\"index.php?localTaxType=".$localTaxType."&year=" . ($year_current-1) . "\">".img_previous()."</a>";
 $textnextyear=" <a href=\"index.php?localTaxType=".$localTaxType."&year=" . ($year_current+1) . "\">".img_next()."</a>";
 
-print load_fiche_titre($langs->transcountry($LT,$mysoc->country_code),"$textprevyear ".$langs->trans("Year")." $year_start $textnextyear");
+print load_fiche_titre($langs->transcountry($LT,$mysoc->country_code),"$textprevyear ".$langs->trans("Year")." $year_start $textnextyear", 'title_accountancy.png');
 
 print $langs->trans("LTReportBuildWithOptionDefinedInModule").'<br>';
 print '('.$langs->trans("TaxModuleSetupToModifyRulesLT",DOL_URL_ROOT.'/admin/company.php').')<br>';
 print '<br>';
 
-print '<table width="100%" class="nobordernopadding">';
-print '<tr><td>';
-print load_fiche_titre($langs->transcountry($LTSummary,$mysoc->country_code));
-
-print '</td><td width="5">&nbsp;</td><td>';
-print load_fiche_titre($langs->transcountry($LTPaid,$mysoc->country_code));
+print '<table width="100%" class="notopnoleftnoright">';
+print '<tr><td class="notopnoleft width="50%">';
+print load_fiche_titre($langs->transcountry($LTSummary,$mysoc->country_code), '', '');
+print '</td><td>&nbsp;</td><td>';
+print load_fiche_titre($langs->transcountry($LTPaid,$mysoc->country_code), '', '');
 print '</td></tr>';
 
-print '<tr><td width="50%" valign="top">';
+print '<tr><td class="notopnoleft" width="50%" valign="top">';
 
-print "<table class=\"noborder\" width=\"100%\">";
-print "<tr class=\"liste_titre\">";
-print "<td width=\"30%\">".$langs->trans("Year")." $y</td>";
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td width="30%">'.$langs->trans("Year")." ".$y."</td>";
 if($CalcLT==0) {
     print "<td align=\"right\">".$langs->transcountry($LTCustomer,$mysoc->country_code)."</td>";
     print "<td align=\"right\">".$langs->transcountry($LTSupplier,$mysoc->country_code)."</td>";
@@ -170,9 +174,11 @@ for ($m = 1 ; $m < 13 ; $m++ ) {
     $parameters["mode"] = $modetax;
     $parameters["year"] = $y;
     $parameters["month"] = $m;
+    $parameters["type"] = 'localtax'.$localTaxType;
+    
     // Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
     $hookmanager->initHooks(array('externalbalance'));
-    $reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+    $reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 
     if (! is_array($coll_listbuy) && $coll_listbuy == -1) {
         $langs->load("errors");
@@ -271,7 +277,7 @@ $sql.= " WHERE f.entity = ".$conf->entity;
 $sql.= " AND f.datev >= '".$db->idate(dol_get_first_day($y,1,false))."'";
 $sql.= " AND f.datev <= '".$db->idate(dol_get_last_day($y,12,false))."'";
 $sql.= " AND localtaxtype=".$localTaxType;
-$sql.= " GROUP BY dm ASC";
+$sql.= " GROUP BY dm ASC ORDER BY dm ASC";
 
 pt($db, $sql,$langs->trans("Year")." $y");
 

+ 4 - 5
htdocs/compta/localtax/quadri_detail.php

@@ -210,9 +210,8 @@ $total = 0;
 $i=0;
 
 // Load arrays of datas
-$x_coll= local_by_date($db, 0, 0, $date_start, $date_end, $modetax, 'sell', $local);
-//$x_coll = vat_by_date($db, 0, 0, $date_start, $date_end, $modetax, 'sell');
-$x_paye = local_by_date($db, 0, 0, $date_start, $date_end, $modetax, 'buy', $local);
+$x_coll = vat_by_date($db, 0, 0, $date_start, $date_end, $modetax, 'sell');
+$x_paye = vat_by_date($db, 0, 0, $date_start, $date_end, $modetax, 'buy');
 
 
 echo '<table class="noborder" width="100%">';
@@ -235,9 +234,9 @@ else
 	{
 		//foreach($x_coll[$my_coll_rate][localtax1_list]){
 		$x_both[$my_coll_rate]['coll']['totalht'] = $x_coll[$my_coll_rate]['totalht'];
-		$x_both[$my_coll_rate]['coll']['vat']     = $x_coll[$my_coll_rate]['vat'];
+		$x_both[$my_coll_rate]['coll']['localtax'.$local]     = $x_coll[$my_coll_rate]['localtax'.$local];
 		$x_both[$my_coll_rate]['paye']['totalht'] = 0;
-		$x_both[$my_coll_rate]['paye']['vat'] = 0;
+		$x_both[$my_coll_rate]['paye']['localtax'.$local] = 0;
 		$x_both[$my_coll_rate]['coll']['links'] = '';
 		$x_both[$my_coll_rate]['coll']['detail'] = array();
 		foreach($x_coll[$my_coll_rate]['facid'] as $id=>$dummy)

+ 3 - 3
htdocs/compta/paiement.php

@@ -432,7 +432,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
 			';
 
 			print '	});'."\n";
-			if(!empty($conf->global->FAC_AUTO_FILLJS)){
+			if(!empty($conf->global->INVOICE_AUTO_FILLJS)){
 				//Add js for AutoFill
 				print ' $(document).ready(function () {';
 				print ' 	$(".AutoFillAmout").on(\'click touchstart\', function(){
@@ -650,7 +650,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
 
                     if ($action != 'add_paiement')
                     {
-						if(!empty($conf->global->FAC_AUTO_FILLJS))
+						if(!empty($conf->global->INVOICE_AUTO_FILLJS))
 							print img_picto("Auto fill",'rightarrow', "class='AutoFillAmout' data-rowname='".$namef."' data-value='".($sign * $remaintopay)."'");
                         print '<input type=hidden class="remain" name="'.$nameRemain.'" value="'.$remaintopay.'">';
                         print '<input type="text" size="8" class="amount" name="'.$namef.'" value="'.$_POST[$namef].'">';
@@ -673,7 +673,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
 	
 	                    if ($action != 'add_paiement')
 	                    {
-							if(!empty($conf->global->FAC_AUTO_FILLJS))
+							if(!empty($conf->global->INVOICE_AUTO_FILLJS))
 								print img_picto("Auto fill",'rightarrow', "class='AutoFillAmout' data-rowname='".$namef."' data-value='".($sign * $multicurrency_remaintopay)."'");
 	                        print '<input type=hidden class="multicurrency_remain" name="'.$nameRemain.'" value="'.$multicurrency_remaintopay.'">';
 	                        print '<input type="text" size="8" class="multicurrency_amount" name="'.$namef.'" value="'.$_POST[$namef].'">';

+ 8 - 8
htdocs/compta/paiement/cheque/card.php

@@ -2,7 +2,7 @@
 /* Copyright (C) 2006		Rodolphe Quiedeville	<rodolphe@quiedeville.org>
  * Copyright (C) 2007-2011	Laurent Destailleur		<eldy@users.sourceforge.net>
  * Copyright (C) 2009-2012	Regis Houssin			<regis.houssin@capnetworks.com>
- * Copyright (C) 2011		Juanjo Menent			<jmenent@2byte.es>
+ * Copyright (C) 2011-2016	Juanjo Menent			<jmenent@2byte.es>
  * Copyright (C) 2013 		Philippe Grand      	<philippe.grand@atoo-net.com>
  * Copyright (C) 2015	    Alexandre Spangaro      <aspangaro.dolibarr@gmail.com>
  *
@@ -44,7 +44,7 @@ $action=GETPOST('action', 'alpha');
 $confirm=GETPOST('confirm', 'alpha');
 
 // Security check
-$fieldname = (! empty($ref)?'number':'rowid');
+$fieldname = (! empty($ref)?'ref':'rowid');
 if ($user->societe_id) $socid=$user->societe_id;
 $result = restrictedArea($user, 'cheque', $id, 'bordereau_cheque','','',$fieldname);
 
@@ -112,9 +112,9 @@ if ($action == 'setref' && $user->rights->banque->cheque)
 	$result = $object->fetch(GETPOST('id','int'));
 	if ($result > 0)
 	{
-		$number=GETPOST('number');
+		$ref=GETPOST('ref');
 
-		$result=$object->set_number($user,$number);
+		$result=$object->set_number($user,$ref);
 		if ($result < 0)
 		{
 			setEventMessages($object->error, $object->errors, 'errors');
@@ -280,7 +280,7 @@ else if ($action == 'remove_file' && $user->rights->banque->cheque)
 
 		$langs->load("other");
 
-		$file=$dir.get_exdir($object->number,0,1,0,$object,'cheque') . GETPOST('file');
+		$file=$dir.get_exdir($object->ref,0,1,0,$object,'cheque') . GETPOST('file');
 		$ret=dol_delete_file($file,0,0,0,$object);
 		if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
 		else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
@@ -576,13 +576,13 @@ else
 		print '<form name="setdate" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
 		print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 		print '<input type="hidden" name="action" value="setref">';
-		print '<input type="text" name="number" value="'.$object->number.'">';
+		print '<input type="text" name="ref" value="'.$object->ref.'">';
 		print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
 		print '</form>';
 	}
 	else
 	{
-	    print $form->showrefnav($object,'ref',$linkback, 1, 'number');
+	    print $form->showrefnav($object,'ref',$linkback, 1, 'ref');
 	}
 
 	print '</td>';
@@ -796,7 +796,7 @@ if ($action != 'new')
 	if ($object->statut == 1)
 	{
 		$filename=dol_sanitizeFileName($object->ref);
-		$filedir=$dir.get_exdir($object->number,0,1,0,$object,'cheque') . dol_sanitizeFileName($object->ref);
+		$filedir=$dir.get_exdir($object->ref,0,1,0,$object,'cheque') . dol_sanitizeFileName($object->ref);
 		$urlsource=$_SERVER["PHP_SELF"]."?id=".$object->id;
 
 		$formfile->show_documents('remisecheque', $filename, $filedir, $urlsource, 1, 1);

+ 116 - 48
htdocs/compta/paiement/cheque/class/remisecheque.class.php

@@ -2,7 +2,7 @@
 /* Copyright (C) 2006      Rodolphe Quiedeville <rodolphe@quiedeville.org>
  * Copyright (C) 2007-2011 Laurent Destailleur  <eldy@users.sourceforge.net>
  * Copyright (C) 2005-2009 Regis Houssin        <regis.houssin@capnetworks.com>
- * Copyright (C) 2011-2015 Juanjo Menent        <jmenent@2byte.es>
+ * Copyright (C) 2011-2016 Juanjo Menent        <jmenent@2byte.es>
  * Copyright (C) 2015      Marcos García        <marcosgdf@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -47,7 +47,7 @@ class RemiseCheque extends CommonObject
 	public $account_label;
 	public $author_id;
 	public $nbcheque;
-	public $number;
+	public $ref;
 
 	/**
 	 *	Constructor
@@ -72,14 +72,14 @@ class RemiseCheque extends CommonObject
 	{
 		global $conf;
 
-		$sql = "SELECT bc.rowid, bc.datec, bc.fk_user_author, bc.fk_bank_account, bc.amount, bc.number, bc.statut, bc.nbcheque, bc.ref_ext";
+		$sql = "SELECT bc.rowid, bc.datec, bc.fk_user_author, bc.fk_bank_account, bc.amount, bc.ref, bc.statut, bc.nbcheque, bc.ref_ext";
 		$sql.= ", bc.date_bordereau as date_bordereau";
 		$sql.= ", ba.label as account_label";
 		$sql.= " FROM ".MAIN_DB_PREFIX."bordereau_cheque as bc";
 		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."bank_account as ba ON bc.fk_bank_account = ba.rowid";
 		$sql.= " WHERE bc.entity = ".$conf->entity;
 		if ($id)  $sql.= " AND bc.rowid = ".$id;
-		if ($ref) $sql.= " AND bc.number = '".$this->db->escape($ref)."'";
+		if ($ref) $sql.= " AND bc.ref = '".$this->db->escape($ref)."'";
 
 		dol_syslog("RemiseCheque::fetch", LOG_DEBUG);
 		$resql = $this->db->query($sql);
@@ -99,13 +99,12 @@ class RemiseCheque extends CommonObject
 
 				if ($this->statut == 0)
 				{
-					$this->number         = "(PROV".$this->id.")";
+					$this->ref         = "(PROV".$this->id.")";
 				}
 				else
 				{
-					$this->number         = $obj->number;
+					$this->ref         = $obj->ref;
 				}
-				$this->ref            = $this->number;
 
 			}
 			$this->db->free($resql);
@@ -124,7 +123,7 @@ class RemiseCheque extends CommonObject
 	 *
 	 *	@param	User	$user 			User making creation
 	 *	@param  int		$account_id 	Bank account for cheque receipt
-	 *  @param  int		$limit          Limit number of cheque to this
+	 *  @param  int		$limit          Limit ref of cheque to this
 	 *  @param	array	$toRemise		array with cheques to remise
 	 *	@return	int						<0 if KO, >0 if OK
 	 */
@@ -146,7 +145,7 @@ class RemiseCheque extends CommonObject
 		$sql.= ", fk_bank_account";
 		$sql.= ", statut";
 		$sql.= ", amount";
-		$sql.= ", number";
+		$sql.= ", ref";
 		$sql.= ", entity";
 		$sql.= ", nbcheque";
 		$sql.= ", ref_ext";
@@ -177,7 +176,7 @@ class RemiseCheque extends CommonObject
 			if ($this->id > 0 && $this->errno == 0)
 			{
 				$sql = "UPDATE ".MAIN_DB_PREFIX."bordereau_cheque";
-				$sql.= " SET number='(PROV".$this->id.")'";
+				$sql.= " SET ref='(PROV".$this->id.")'";
 				$sql.= " WHERE rowid='".$this->id."';";
 
 				dol_syslog("RemiseCheque::Create", LOG_DEBUG);
@@ -345,13 +344,13 @@ class RemiseCheque extends CommonObject
 		$this->errno = 0;
 
 		$this->db->begin();
-
-		$numref=$this->getNextNumber();
+		
+		$numref = $this->getNextNumRef();
 
 		if ($this->errno == 0 && $numref)
 		{
 			$sql = "UPDATE ".MAIN_DB_PREFIX."bordereau_cheque";
-			$sql.= " SET statut = 1, number = '".$numref."'";
+			$sql.= " SET statut = 1, ref = '".$numref."'";
 			$sql.= " WHERE rowid = ".$this->id;
 			$sql.= " AND entity = ".$conf->entity;
 			$sql.= " AND statut = 0";
@@ -364,7 +363,7 @@ class RemiseCheque extends CommonObject
 
 				if ($num == 1)
 				{
-				    $this->number = $numref;
+				    $this->ref = $numref;
 					$this->statut = 1;
 				}
 				else
@@ -394,46 +393,92 @@ class RemiseCheque extends CommonObject
 		}
 	}
 
-
 	/**
-	 * Old module for cheque receipt numbering
+	 *      Return next reference of cheque receipts not already used (or last reference)
+	 *      according to numbering module defined into constant FACTURE_ADDON
 	 *
-	 * @return 	int		Next number of cheque
+	 *      @param     string		$mode		'next' for next value or 'last' for last value
+	 *      @return    string					free ref or last ref
 	 */
-	function getNextNumber()
+	function getNextNumRef($mode='next')
 	{
-		global $conf;
-
-		$num=0;
+		global $conf, $db, $langs, $mysoc;
+		$langs->load("bills");
 
-		// We use +0 to convert varchar to number for mysql, use ::integer for postgres.
-		// We must found a generic solution (Use a $db->toint function ?)
-		$sql = "SELECT ";
-		if ($this->db->type == 'pgsql') $sql.="MAX(number::integer)";
-		else $sql.="MAX(number+0)";
-		$sql.= " FROM ".MAIN_DB_PREFIX."bordereau_cheque";
-		$sql.= " WHERE entity = ".$conf->entity;
-		$sql.= " AND number not like '(%'";
+		// Clean parameters (if not defined or using deprecated value)
+		if (empty($conf->global->CHEQUERECEIPTS_ADDON)) $conf->global->CHEQUERECEIPTS_ADDON='mod_chequereceipt_mint';
+		else if ($conf->global->CHEQUERECEIPTS_ADDON=='thyme') $conf->global->CHEQUERECEIPTS_ADDON='mod_chequereceipt_thyme';
+		else if ($conf->global->CHEQUERECEIPTS_ADDON=='mint') $conf->global->CHEQUERECEIPTS_ADDON='mod_chequereceipt_mint';
 
-		dol_syslog("Remisecheque::getNextNumber", LOG_DEBUG);
-		$resql = $this->db->query($sql);
-		if ($resql)
+		if (! empty($conf->global->CHEQUERECEIPTS_ADDON))
 		{
-			$row = $this->db->fetch_row($resql);
-			$num = $row[0];
-			$this->db->free($resql);
+			$mybool=false;
+
+			$file = $conf->global->CHEQUERECEIPTS_ADDON.".php";
+			$classname = $conf->global->CHEQUERECEIPTS_ADDON;
+
+			// Include file with class
+			$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
+
+			foreach ($dirmodels as $reldir) {
+
+				$dir = dol_buildpath($reldir."core/modules/cheque/");
+
+				// Load file with numbering class (if found)
+				if (is_file($dir.$file) && is_readable($dir.$file))
+				{
+					$mybool |= include_once $dir . $file;
+				}
+			}
+
+			// For compatibility
+			if (! $mybool)
+			{
+				$file = $conf->global->CHEQUERECEIPTS_ADDON.".php";
+				$classname = "mod_chequereceipt_".$conf->global->CHEQUERECEIPTS_ADDON;
+				$classname = preg_replace('/\-.*$/','',$classname);
+				// Include file with class
+				foreach ($conf->file->dol_document_root as $dirroot)
+				{
+					$dir = $dirroot."/core/modules/cheque/";
+
+					// Load file with numbering class (if found)
+					if (is_file($dir.$file) && is_readable($dir.$file)) {
+						$mybool |= include_once $dir . $file;
+					}
+				}
+			}
+
+			if (! $mybool)
+			{
+				dol_print_error('',"Failed to include file ".$file);
+				return '';
+			}
+
+			$obj = new $classname();
+			$numref = "";
+			$numref = $obj->getNextValue($mysoc,$this);
+
+			/**
+			 * $numref can be empty in case we ask for the last value because if there is no invoice created with the
+			 * set up mask.
+			 */
+			if ($mode != 'last' && !$numref) {
+				dol_print_error($db,"ChequeReceipts::getNextNumRef ".$obj->error);
+				return "";
+			}
+
+			return $numref;
 		}
 		else
 		{
-			$this->errno = -1034;
-			dol_syslog("Remisecheque::Validate Erreur SELECT ($this->errno)", LOG_ERR);
+			$langs->load("errors");
+			print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete");
+			return "";
 		}
-
-		$num++;
-
-		return $num;
 	}
 
+
 	/**
      *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
      *
@@ -502,7 +547,7 @@ class RemiseCheque extends CommonObject
 
 		dol_syslog("RemiseCheque::generatePdf model=".$model." id=".$this->id, LOG_DEBUG);
 
-		$dir=DOL_DOCUMENT_ROOT ."/core/modules/cheque/pdf/";
+		$dir=DOL_DOCUMENT_ROOT ."/core/modules/cheque/doc/";
 
 		// Charge le modele
 		$file = "pdf_".$model.".class.php";
@@ -540,7 +585,7 @@ class RemiseCheque extends CommonObject
 				}
 			}
 			$docmodel->nbcheque = $this->nbcheque;
-			$docmodel->number = $this->number;
+			$docmodel->ref = $this->ref;
 			$docmodel->amount = $this->amount;
 			$docmodel->date   = $this->date_bordereau;
 
@@ -552,7 +597,7 @@ class RemiseCheque extends CommonObject
 			// We save charset_output to restore it because write_file can change it if needed for
 			// output format that does not support UTF8.
 			$sav_charseSupprimert_output=$outputlangs->charset_output;
-			$result=$docmodel->write_file($this, $conf->banque->dir_output.'/bordereau', $this->number, $outputlangs);
+			$result=$docmodel->write_file($this, $conf->banque->dir_output.'/bordereau', $this->ref, $outputlangs);
 			if ($result > 0)
 			{
 				//$outputlangs->charset_output=$sav_charset_output;
@@ -838,18 +883,18 @@ class RemiseCheque extends CommonObject
     }
 
 	/**
-	 *      Set the number of bordereau
+	 *      Set the ref of bordereau
 	 *
 	 *      @param	User		$user           Object user
-	 *      @param  int   $number         number of bordereau
+	 *      @param  int   $ref         ref of bordereau
 	 *      @return int                 		<0 if KO, >0 if OK
 	 */
-	function set_number($user, $number)
+	function set_number($user, $ref)
 	{
 		if ($user->rights->banque->cheque)
 		{
 			$sql = "UPDATE ".MAIN_DB_PREFIX."bordereau_cheque";
-			$sql.= " SET number = '".$number."'" ;
+			$sql.= " SET ref = '".$ref."'" ;
 			$sql.= " WHERE rowid = ".$this->id;
 
 			dol_syslog("RemiseCheque::set_number", LOG_DEBUG);
@@ -870,6 +915,29 @@ class RemiseCheque extends CommonObject
 		}
 	}
 
+	/**
+	 *  Initialise an instance with random values.
+	 *  Used to build previews or test instances.
+	 *	id must be 0 if object instance is a specimen.
+	 *
+	 *	@param	string		$option		''=Create a specimen invoice with lines, 'nolines'=No lines
+	 *  @return	void
+	 */
+	function initAsSpecimen($option='')
+	{
+		global $user,$langs,$conf;
+
+		$now=dol_now();
+		$arraynow=dol_getdate($now);
+		$nownotime=dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
+
+		// Initialize parameters
+		$this->id=0;
+		$this->ref = 'SPECIMEN';
+		$this->specimen=1;
+		$this->date_bordereau = $nownotime;
+	}
+
 	/**
 	 *    	Return clicable name (with picto eventually)
 	 *

+ 2 - 1
htdocs/compta/paiement/cheque/index.php

@@ -2,6 +2,7 @@
 /* Copyright (C) 2006      Rodolphe Quiedeville <rodolphe@quiedeville.org>
  * Copyright (C) 2007-2011 Laurent Destailleur  <eldy@users.sourceforge.net>
  * Copyright (C) 2009      Regis Houssin        <regis.houssin@capnetworks.com>
+ * Copyright (C) 2016      Juanjo Menent	    <jmenent@2byte.es>
  *
  * 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
@@ -94,7 +95,7 @@ print '</div><div class="fichetwothirdright"><div class="ficheaddleft">';
 
 $max=10;
 
-$sql = "SELECT bc.rowid, bc.date_bordereau as db, bc.amount, bc.number as ref";
+$sql = "SELECT bc.rowid, bc.date_bordereau as db, bc.amount, bc.ref as ref";
 $sql.= ", bc.statut, bc.nbcheque";
 $sql.= ", ba.label, ba.rowid as bid";
 $sql.= " FROM ".MAIN_DB_PREFIX."bordereau_cheque as bc";

+ 4 - 4
htdocs/compta/paiement/cheque/list.php

@@ -3,6 +3,7 @@
  * Copyright (C) 2007-2009	Laurent Destailleur		<eldy@users.sourceforge.net>
  * Copyright (C) 2009-2012	Regis Houssin			<regis.houssin@capnetworks.com>
  * Copyright (C) 2014		Alexandre Spangaro		<aspangaro.dolibarr@gmail.com>
+ * Copyright (C) 2016		Juanjo Menent   		<jmenent@2byte.es>
  *
  * 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
@@ -77,7 +78,7 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both
 
 llxHeader('',$langs->trans("ChequesReceipts"));
 
-$sql = "SELECT bc.rowid, bc.number as ref, bc.date_bordereau as dp,";
+$sql = "SELECT bc.rowid, bc.ref as ref, bc.date_bordereau as dp,";
 $sql.= " bc.nbcheque, bc.amount, bc.statut,";
 $sql.= " ba.rowid as bid, ba.label";
 $sql.= " FROM ".MAIN_DB_PREFIX."bordereau_cheque as bc,";
@@ -86,7 +87,7 @@ $sql.= " WHERE bc.fk_bank_account = ba.rowid";
 $sql.= " AND bc.entity = ".$conf->entity;
 
 // Search criteria
-if ($search_ref)			$sql.=" AND bc.number=".$search_ref;
+if ($search_ref)			$sql.=" AND bc.ref=".$search_ref;
 if ($search_account > 0)	$sql.=" AND bc.fk_bank_account=".$search_account;
 if ($search_amount)			$sql.=" AND bc.amount='".$db->escape(price2num(trim($search_amount)))."'";
 if ($month > 0)
@@ -134,7 +135,7 @@ if ($resql)
 	
 	print '<table class="liste">';
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"bc.number","",$param,"",$sortfield,$sortorder);
+	print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"bc.ref","",$param,"",$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("DateCreation"),$_SERVER["PHP_SELF"],"dp","",$param,'align="center"',$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("Account"),$_SERVER["PHP_SELF"],"ba.label","",$param,"",$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("NbOfCheques"),$_SERVER["PHP_SELF"],"bc.nbcheque","",$param,'align="right"',$sortfield,$sortorder);
@@ -212,7 +213,6 @@ if ($resql)
     }
     else
     {
-   		$var=!$var;
    		print "<tr ".$bc[$var].">";
    		print '<td colspan="7">'.$langs->trans("None")."</td>";
    		print '</tr>';

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

@@ -151,7 +151,7 @@ if ($id > 0)
 
 	if (GETPOST('error','alpha')!='')
 	{
-		print '<div class="error">'.$bon->ReadError(GETPOST('error','alpha')).'</div>';
+		print '<div class="error">'.$bon->getErrorString(GETPOST('error','alpha')).'</div>';
 	}
 
 	/*if ($action == 'credite')

+ 7 - 5
htdocs/compta/prelevement/class/bonprelevement.class.php

@@ -245,16 +245,18 @@ class BonPrelevement extends CommonObject
     }
 
     /**
-     *	Read errors
+     *	Return error string
      *
-     *  @param	int		$error 		id of error
-     *	@return	array 				Array of errors
+     *  @param	int		$error 		 Id of error
+     *	@return	string               Error string
      */
-    function ReadError($error)
+    function getErrorString($error)
     {
+        global $langs;
+        
         $errors = array();
 
-        $errors[1027] = "Date invalide";
+        $errors[1027] = $langs->trans("DateInvalid");
 
         return $errors[abs($error)];
     }

+ 1 - 1
htdocs/compta/resultat/clientfourn.php

@@ -978,7 +978,7 @@ $parameters["date_end"] = $date_end;
 $parameters["bc"] = $bc;
 // Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
 $hookmanager->initHooks(array('externalbalance'));
-$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+$reshook=$hookmanager->executeHooks('addBalanceLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 print $hookmanager->resPrint;
 
 if ($mysoc->tva_assuj != 'franchise')	// Assujeti

+ 1 - 1
htdocs/compta/resultat/index.php

@@ -472,7 +472,7 @@ $object = array(&$encaiss, &$encaiss_ttc, &$decaiss, &$decaiss_ttc);
 $parameters["mode"] = $modecompta;
 // Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
 $hookmanager->initHooks(array('externalbalance'));
-$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+$reshook=$hookmanager->executeHooks('addReportInfo',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 
 /*
  * Salaries

+ 1 - 1
htdocs/compta/salaries/document.php

@@ -72,7 +72,7 @@ $modulepart='salaries';
  * Actions
  */
 
-include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

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

@@ -73,7 +73,7 @@ $modulepart='tax';
  * Actions
  */
 
-include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

+ 53 - 39
htdocs/compta/tva/card.php

@@ -42,7 +42,7 @@ $socid = isset($_GET["socid"])?$_GET["socid"]:'';
 if ($user->societe_id) $socid=$user->societe_id;
 $result = restrictedArea($user, 'tax', '', '', 'charges');
 
-$tva = new Tva($db);
+$object = new Tva($db);
 
 // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
 $hookmanager->initHooks(array('taxvatcard','globalcard'));
@@ -52,12 +52,22 @@ $hookmanager->initHooks(array('taxvatcard','globalcard'));
  * Actions
  */
 
-if ($_POST["cancel"] == $langs->trans("Cancel"))
+if ($_POST["cancel"] == $langs->trans("Cancel") && ! $id)
 {
 	header("Location: reglement.php");
 	exit;
 }
 
+if ($action == 'setdatev' && $user->rights->tax->charges->creer)
+{
+    $object->fetch($id);
+    $object->datev=dol_mktime(12,0,0,$_POST['datevmonth'],$_POST['datevday'],$_POST['datevyear']);
+    $result=$object->update($user);
+    if ($result < 0) dol_print_error($db,$object->error);
+    
+    $action='';
+}
+
 if ($action == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
 {
     $error=0;
@@ -65,36 +75,36 @@ if ($action == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
 	$datev=dol_mktime(12,0,0, $_POST["datevmonth"], $_POST["datevday"], $_POST["datevyear"]);
     $datep=dol_mktime(12,0,0, $_POST["datepmonth"], $_POST["datepday"], $_POST["datepyear"]);
 
-    $tva->accountid=GETPOST("accountid");
-    $tva->type_payment=GETPOST("type_payment");
-	$tva->num_payment=GETPOST("num_payment");
-    $tva->datev=$datev;
-    $tva->datep=$datep;
+    $object->accountid=GETPOST("accountid");
+    $object->type_payment=GETPOST("type_payment");
+	$object->num_payment=GETPOST("num_payment");
+    $object->datev=$datev;
+    $object->datep=$datep;
 	
 	$amount = price2num(GETPOST("amount"));
 	if ($refund == 1) {
 		$amount= -$amount;
 	}
-    $tva->amount= $amount;
-	$tva->label=GETPOST("label");
-	$tva->note=GETPOST("note");
+    $object->amount= $amount;
+	$object->label=GETPOST("label");
+	$object->note=GETPOST("note");
 	
-	if (empty($tva->datev))
+	if (empty($object->datev))
 	{
 		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateValue")), null, 'errors');
 		$error++;
 	}
-	if (empty($tva->datep))
+	if (empty($object->datep))
 	{
 		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DatePayment")), null, 'errors');
 		$error++;
 	}
-	if (empty($tva->type_payment) || $tva->type_payment < 0)
+	if (empty($object->type_payment) || $object->type_payment < 0)
 	{
 		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PaymentMode")), null, 'errors');
 		$error++;
 	}
-	if (empty($tva->amount))
+	if (empty($object->amount))
 	{
 		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount")), null, 'errors');
 		$error++;
@@ -104,7 +114,7 @@ if ($action == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
 	{
 		$db->begin();
 
-    	$ret=$tva->addPayment($user);
+    	$ret=$object->addPayment($user);
 		if ($ret > 0)
 		{
 			$db->commit();
@@ -114,7 +124,7 @@ if ($action == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
 		else
 		{
 			$db->rollback();
-			setEventMessages($tva->error, $tva->errors, 'errors');
+			setEventMessages($object->error, $object->errors, 'errors');
 			$action="create";
 		}
 	}
@@ -124,19 +134,19 @@ if ($action == 'add' && $_POST["cancel"] <> $langs->trans("Cancel"))
 
 if ($action == 'delete')
 {
-    $result=$tva->fetch($id);
+    $result=$object->fetch($id);
 
-	if ($tva->rappro == 0)
+	if ($object->rappro == 0)
 	{
 	    $db->begin();
 
-	    $ret=$tva->delete($user);
+	    $ret=$object->delete($user);
 	    if ($ret > 0)
 	    {
-			if ($tva->fk_bank)
+			if ($object->fk_bank)
 			{
 				$accountline=new AccountLine($db);
-				$result=$accountline->fetch($tva->fk_bank);
+				$result=$accountline->fetch($object->fk_bank);
 				if ($result > 0) $result=$accountline->delete($user);	// $result may be 0 if not found (when bank entry was deleted manually and fk_bank point to nothing)
 			}
 
@@ -148,15 +158,15 @@ if ($action == 'delete')
 			}
 			else
 			{
-				$tva->error=$accountline->error;
+				$object->error=$accountline->error;
 				$db->rollback();
-				setEventMessages($tva->error, $tva->errors, 'errors');
+				setEventMessages($object->error, $object->errors, 'errors');
 			}
 	    }
 	    else
 	    {
 	        $db->rollback();
-	        setEventMessages($tva->error, $tva->errors, 'errors');
+	        setEventMessages($object->error, $object->errors, 'errors');
 	    }
 	}
 	else
@@ -176,8 +186,7 @@ $form = new Form($db);
 
 if ($id)
 {
-    $vatpayment = new Tva($db);
-	$result = $vatpayment->fetch($id);
+	$result = $object->fetch($id);
 	if ($result <= 0)
 	{
 		dol_print_error($db);
@@ -297,7 +306,7 @@ if ($action == 'create')
 if ($id)
 {
 	$h = 0;
-	$head[$h][0] = DOL_URL_ROOT.'/compta/tva/card.php?id='.$vatpayment->id;
+	$head[$h][0] = DOL_URL_ROOT.'/compta/tva/card.php?id='.$object->id;
 	$head[$h][1] = $langs->trans('Card');
 	$head[$h][2] = 'card';
 	$h++;
@@ -309,29 +318,33 @@ if ($id)
 
 	print "<tr>";
 	print '<td width="25%">'.$langs->trans("Ref").'</td><td colspan="3">';
-	print $vatpayment->ref;
+	print $object->ref;
 	print '</td></tr>';
 
 	// Label
-	print '<tr><td>'.$langs->trans("Label").'</td><td>'.$vatpayment->label.'</td></tr>';
+	print '<tr><td>'.$langs->trans("Label").'</td><td>'.$object->label.'</td></tr>';
 
 	print "<tr>";
 	print '<td>'.$langs->trans("DatePayment").'</td><td colspan="3">';
-	print dol_print_date($vatpayment->datep,'day');
+	print dol_print_date($object->datep,'day');
 	print '</td></tr>';
 
-	print '<tr><td>'.$langs->trans("DateValue").'</td><td colspan="3">';
-	print dol_print_date($vatpayment->datev,'day');
+
+	print '<tr><td>';
+	print $form->editfieldkey("DateValue", 'datev', $object->datev, $object, $user->rights->tax->charges->creer, 'day');
+	print '</td><td colspan="3">';
+	print $form->editfieldval("DateValue", 'datev', $object->datev, $object, $user->rights->tax->charges->creer, 'day');
+	//print dol_print_date($object->datev,'day');
 	print '</td></tr>';
 
-	print '<tr><td>'.$langs->trans("Amount").'</td><td colspan="3">'.price($vatpayment->amount).'</td></tr>';
+	print '<tr><td>'.$langs->trans("Amount").'</td><td colspan="3">'.price($object->amount).'</td></tr>';
 
 	if (! empty($conf->banque->enabled))
 	{
-		if ($vatpayment->fk_account > 0)
+		if ($object->fk_account > 0)
 		{
  		   	$bankline=new AccountLine($db);
-    		$bankline->fetch($vatpayment->fk_bank);
+    		$bankline->fetch($object->fk_bank);
 
 	    	print '<tr>';
 	    	print '<td>'.$langs->trans('BankTransactionLine').'</td>';
@@ -344,21 +357,22 @@ if ($id)
 
         // Other attributes
         $parameters=array('colspan' => ' colspan="3"');
-        $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$vatpayment,$action);    // Note that $action and $object may have been modified by hook
+        $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action);    // Note that $action and $object may have been modified by hook
 
 	print '</table>';
 
-	print '</div>';
+	dol_fiche_end();
 
+	
 	/*
 	* Boutons d'actions
 	*/
 	print "<div class=\"tabsAction\">\n";
-	if ($vatpayment->rappro == 0)
+	if ($object->rappro == 0)
 	{
 		if (! empty($user->rights->tax->charges->supprimer))
 		{
-			print '<a class="butActionDelete" href="card.php?id='.$vatpayment->id.'&action=delete">'.$langs->trans("Delete").'</a>';
+			print '<a class="butActionDelete" href="card.php?id='.$object->id.'&action=delete">'.$langs->trans("Delete").'</a>';
 		}
 		else
 		{

+ 4 - 2
htdocs/compta/tva/clients.php

@@ -250,9 +250,11 @@ $parameters["mode"] = $modetax;
 $parameters["start"] = $date_start;
 $parameters["end"] = $date_end;
 $parameters["direction"] = 'sell';
+$parameters["type"] = 'vat';
+
 // Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
 $hookmanager->initHooks(array('externalbalance'));
-$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+$reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 
 if (is_array($coll_list)) {
 	$var=true;
@@ -333,7 +335,7 @@ $company_static=new Societe($db);
 $coll_list = vat_by_thirdparty($db,0,$date_start,$date_end,$modetax,'buy');
 
 $parameters["direction"] = 'buy';
-$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+$reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 if (is_array($coll_list)) {
 	$var=true;
 	$total = 0;  $totalamount = 0;

+ 4 - 2
htdocs/compta/tva/index.php

@@ -56,7 +56,7 @@ if (isset($_GET["modetax"])) $modetax=$_GET["modetax"];
 
 
 /**
- * pt
+ * print function
  *
  * @param 	DoliDB	$db		Database handler
  * @param 	string	$sql	SQL Request
@@ -161,9 +161,11 @@ for ($m = 1 ; $m < 13 ; $m++ )
     $parameters["mode"] = $modetax;
     $parameters["year"] = $y;
     $parameters["month"] = $m;
+    $parameters["type"] = 'vat';
+    
     // Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
     $hookmanager->initHooks(array('externalbalance'));
-    $reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+    $reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 
     if (! is_array($coll_listbuy) && $coll_listbuy == -1)
     {

+ 3 - 1
htdocs/compta/tva/quadri_detail.php

@@ -325,10 +325,12 @@ else
 	$parameters["mode"] = $modetax;
 	$parameters["start"] = $date_start;
 	$parameters["end"] = $date_end;
+	$parameters["type"] = 'vat';
+	
 	$object = array(&$x_coll, &$x_paye, &$x_both);
 	// Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
 	$hookmanager->initHooks(array('externalbalance'));
-	$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+	$reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 	
 	foreach(array_keys($x_coll) as $rate)
 	{

+ 3 - 1
htdocs/compta/tva/quarter_report.php

@@ -378,10 +378,12 @@ if (!is_array($x_coll) || !is_array($x_paye)) {
 	$parameters["mode"] = $modetax;
 	$parameters["start"] = $date_start;
 	$parameters["end"] = $date_end;
+	$parameters["type"] = 'vat';
+	
 	$object = array(&$x_coll, &$x_paye, &$x_both);
 	// Initialize technical object to manage hooks of expenses. Note that conf->hooks_modules contains array array
 	$hookmanager->initHooks(array('externalbalance'));
-	$reshook=$hookmanager->executeHooks('addStatisticLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+	$reshook=$hookmanager->executeHooks('addVatLine',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
 	
 	foreach (array_keys($x_coll) as $rate) {
 		$subtot_coll_total_ht = 0;

+ 8 - 5
htdocs/compta/tva/reglement.php

@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2001-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
- * Copyright (C) 2004-2015 Laurent Destailleur  <eldy@users.sourceforge.net>
+ * Copyright (C) 2004-2016 Laurent Destailleur  <eldy@users.sourceforge.net>
  * Copyright (C) 2005-2009 Regis Houssin        <regis.houssin@capnetworks.com>
  * Copyright (C) 2011-2014 Alexandre Spangaro   <aspangaro.dolibarr@gmail.com>
  *
@@ -91,7 +91,7 @@ $form = new Form($db);
 $formother=new FormOther($db);
 $tva_static = new Tva($db);
 
-$sql = "SELECT t.rowid, t.amount, t.label, t.datev as dm, t.fk_typepayment as type, t.num_payment, pst.code as payment_code";
+$sql = "SELECT t.rowid, t.amount, t.label, t.datev as dv, t.datep as dp, t.fk_typepayment as type, t.num_payment, pst.code as payment_code";
 $sql.= " FROM ".MAIN_DB_PREFIX."tva as t";
 $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as pst ON t.fk_typepayment = pst.id";
 $sql.= " WHERE t.entity = ".$conf->entity;
@@ -151,7 +151,8 @@ if ($result)
     print '<tr class="liste_titre">';
 	print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"t.rowid","",$param,"",$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("Label"),$_SERVER["PHP_SELF"],"t.label","",$param,'align="left"',$sortfield,$sortorder);
-	print_liste_field_titre($langs->trans("DatePayment"),$_SERVER["PHP_SELF"],"dm","",$param,'align="center"',$sortfield,$sortorder);
+	print_liste_field_titre($langs->trans("DateValue"),$_SERVER["PHP_SELF"],"dv","",$param,'align="center"',$sortfield,$sortorder);
+	print_liste_field_titre($langs->trans("DatePayment"),$_SERVER["PHP_SELF"],"dp","",$param,'align="center"',$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("Type"),$_SERVER["PHP_SELF"],"type","",$param,'align="left"',$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("PayedByThisPayment"),$_SERVER["PHP_SELF"],"t.amount","",$param,'align="right"',$sortfield,$sortorder);
 	print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'','','',$sortfield,$sortorder,'maxwidthsearch ');
@@ -160,6 +161,7 @@ if ($result)
 	print '<tr class="liste_titre">';
 	print '<td class="liste_titre"><input type="text" class="flat" size="4" name="search_ref" value="'.$search_ref.'"></td>';
 	print '<td class="liste_titre"><input type="text" class="flat" size="10" name="search_label" value="'.$search_label.'"></td>';
+	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre" colspan="1" align="center">';
 	print '<input class="flat" type="text" size="1" maxlength="2" name="month" value="'.$month.'">';
 	$syear = $year;
@@ -197,8 +199,9 @@ if ($result)
 		$tva_static->ref=$obj->rowid;
 		print "<td>".$tva_static->getNomUrl(1)."</td>\n";
         print "<td>".dol_trunc($obj->label,40)."</td>\n";
-        print '<td align="center">'.dol_print_date($db->jdate($obj->dm),'day')."</td>\n";
-		// Type
+        print '<td align="center">'.dol_print_date($db->jdate($obj->dv),'day')."</td>\n";
+        print '<td align="center">'.dol_print_date($db->jdate($obj->dp),'day')."</td>\n";
+        // Type
 		print $type;
 		// Amount
         $total = $total + $obj->amount;

+ 3 - 7
htdocs/contact/card.php

@@ -314,13 +314,9 @@ if (empty($reshook))
                         else
                         {
                             $object->photo = dol_sanitizeFileName($_FILES['photo']['name']);
-                            // Create small thumbs for company (Ratio is near 16/9)
-                            // Used on logon for example
-                            $imgThumbSmall = vignette($newfile, $maxwidthsmall, $maxheightsmall, '_small', $quality);
 
-                            // Create mini thumbs for company (Ratio is near 16/9)
-                            // Used on menu or for setup page for example
-                            $imgThumbMini = vignette($newfile, $maxwidthmini, $maxheightmini, '_mini', $quality);
+    					    // Create thumbs
+    					    $object->addThumbs($newfile);					    
                         }
                     }
                 }
@@ -797,7 +793,7 @@ else
             {
                 print '<tr><td><label for="socid">'.$langs->trans("ThirdParty").'</label></td>';
                 print '<td colspan="3" class="maxwidthonsmartphone">';
-                print $form->select_company(GETPOST('socid','int')?GETPOST('socid','int'):($object->socid?$object->socid:-1),'socid','',1);
+                print $form->select_company(GETPOST('socid','int')?GETPOST('socid','int'):($object->socid?$object->socid:-1), 'socid', '', $langs->trans("SelectThirdParty"));
                 print '</td>';
                 print '</tr>';
             }

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

@@ -443,6 +443,7 @@ class Contact extends CommonObject
 		// Mis a jour contact
 		$sql = "UPDATE ".MAIN_DB_PREFIX."socpeople SET";
 		$sql.= " birthday=".($this->birthday ? "'".$this->db->idate($this->birthday)."'" : "null");
+		$sql.= ", photo = ".($this->photo? "'".$this->photo."'" : "null");
 		if ($user) $sql .= ", fk_user_modif=".$user->id;
 		$sql.= " WHERE rowid=".$this->db->escape($id);
 

+ 1 - 1
htdocs/contact/document.php

@@ -65,7 +65,7 @@ $modulepart='contact';
  * Actions
  */
 
-include DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php';
+include DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
 
 
 /*

+ 1 - 1
htdocs/contact/list.php

@@ -321,7 +321,7 @@ foreach ($search_array_options as $key => $val)
     $tmpkey=preg_replace('/search_options_/','',$key);
     $typ=$extrafields->attribute_type[$tmpkey];
     $mode=0;
-    if (in_array($typ, array('int'))) $mode=1;    // Search on a numeric
+    if (in_array($typ, array('int','double'))) $mode=1;    // Search on a numeric
     if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) 
     {
         $sql .= natural_search('ef.'.$tmpkey, $crit, $mode);

+ 69 - 0
htdocs/contact/perso.php

@@ -50,11 +50,66 @@ if ($action == 'update' && ! $_POST["cancel"] && $user->rights->societe->contact
 	$object->birthday = dol_mktime(0,0,0,$_POST["birthdaymonth"],$_POST["birthdayday"],$_POST["birthdayyear"]);
 	$object->birthday_alert = $_POST["birthday_alert"];
 
+	if (GETPOST('deletephoto')) $object->photo='';
+	elseif (! empty($_FILES['photo']['name'])) $object->photo  = dol_sanitizeFileName($_FILES['photo']['name']);
+
 	$result = $object->update_perso($id, $user);
 	if ($result > 0)
 	{
 		$object->old_name='';
 		$object->old_firstname='';
+		// Logo/Photo save
+		$dir= $conf->societe->dir_output.'/contact/' . get_exdir($object->id,0,0,1,$object,'contact').'/photos';
+		
+		$file_OK = is_uploaded_file($_FILES['photo']['tmp_name']);
+		if ($file_OK)
+		{
+			require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+			if (GETPOST('deletephoto'))
+			{
+				require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
+				$fileimg=$conf->societe->dir_output.'/contact/'.get_exdir($object->id,0,0,1,$object,'contact').'/photos/'.$object->photo;
+				$dirthumbs=$conf->societe->dir_output.'/contact/'.get_exdir($object->id,0,0,1,$object,'contact').'/photos/thumbs';
+				dol_delete_file($fileimg);
+				dol_delete_dir_recursive($dirthumbs);
+			}
+
+			if (image_format_supported($_FILES['photo']['name']) > 0)
+			{
+				dol_mkdir($dir);
+
+				if (@is_dir($dir))
+				{
+					$newfile=$dir.'/'.dol_sanitizeFileName($_FILES['photo']['name']);
+					if (! dol_move_uploaded_file($_FILES['photo']['tmp_name'],$newfile,1,0,$_FILES['photo']['error']) > 0)
+					{
+						setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors');
+					}
+					else
+					{
+					    // Create thumbs
+					    $object->addThumbs($newfile);					    
+					}
+				}
+			}
+			else
+			{
+				setEventMessages("ErrorBadImageFormat", null, 'errors');
+			}
+		}
+		else
+		{
+			switch($_FILES['photo']['error'])
+			{
+				case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
+				case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
+					$errors[] = "ErrorFileSizeTooLarge";
+					break;
+				case 3: //uploaded file was only partially uploaded
+					$errors[] = "ErrorFilePartiallyUploaded";
+					break;
+			}
+		}
 	}
 	else
 	{
@@ -98,6 +153,20 @@ if ($action == 'edit')
     // Ref
     print '<tr><td width="20%">'.$langs->trans("Ref").'</td><td colspan="3">';
     print $object->id;
+    print '</td>';
+    
+    // Photo
+    print '<td align="center" class="hideonsmartphone" valign="middle" width="25%" rowspan="5">';
+    print $form->showphoto('contact',$object)."\n";
+    if ($object->photo) print "<br>\n";
+    
+    print '<table class="nobordernopadding">';
+    
+    if ($object->photo) print '<tr><td align="center"><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> '.$langs->trans("Delete").'<br><br></td></tr>';
+    print '<tr><td>'.$langs->trans("PhotoFile").'</td></tr>';
+    print '<tr><td><input type="file" class="flat" name="photo" id="photoinput"></td></tr>';
+    print '</table>';
+    
     print '</td></tr>';
 
     // Name

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است