浏览代码

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

# Conflicts:
#	htdocs/imports/import.php
Maxime Kohlhaas 8 年之前
父节点
当前提交
04ed2df827
共有 100 个文件被更改,包括 3837 次插入1368 次删除
  1. 127 8
      ChangeLog
  2. 13 4
      build/composer/README
  3. 4 3
      build/debian/README.howto
  4. 8 3
      build/debian/source/lintian-overrides
  5. 7 0
      build/makepack-dolibarr.pl
  6. 2 0
      build/makepack-howto.txt
  7. 1 1
      composer.json
  8. 1393 13
      composer.lock
  9. 1 1
      dev/skeletons/modMyModule.class.php
  10. 14 4
      dev/skeletons/skeleton_card.php
  11. 12 5
      dev/skeletons/skeleton_list.php
  12. 13 13
      htdocs/accountancy/admin/account.php
  13. 2 2
      htdocs/accountancy/admin/accountmodel.php
  14. 1 1
      htdocs/accountancy/admin/fiscalyear.php
  15. 1 1
      htdocs/accountancy/admin/productaccount.php
  16. 155 157
      htdocs/accountancy/bookkeeping/balance.php
  17. 15 10
      htdocs/accountancy/bookkeeping/list.php
  18. 14 17
      htdocs/accountancy/bookkeeping/listbyaccount.php
  19. 1 1
      htdocs/accountancy/bookkeeping/listbyyear.php
  20. 1 1
      htdocs/accountancy/class/accountancyexport.class.php
  21. 4 4
      htdocs/accountancy/class/accountingaccount.class.php
  22. 37 67
      htdocs/accountancy/class/bookkeeping.class.php
  23. 75 67
      htdocs/accountancy/class/html.formventilation.class.php
  24. 83 12
      htdocs/accountancy/customer/index.php
  25. 53 38
      htdocs/accountancy/customer/lines.php
  26. 83 46
      htdocs/accountancy/customer/list.php
  27. 102 26
      htdocs/accountancy/expensereport/index.php
  28. 36 23
      htdocs/accountancy/expensereport/lines.php
  29. 83 47
      htdocs/accountancy/expensereport/list.php
  30. 35 24
      htdocs/accountancy/journal/bankjournal.php
  31. 4 4
      htdocs/accountancy/journal/expensereportsjournal.php
  32. 4 4
      htdocs/accountancy/journal/purchasesjournal.php
  33. 4 4
      htdocs/accountancy/journal/sellsjournal.php
  34. 8 3
      htdocs/accountancy/report/result.php
  35. 91 12
      htdocs/accountancy/supplier/index.php
  36. 60 43
      htdocs/accountancy/supplier/lines.php
  37. 113 71
      htdocs/accountancy/supplier/list.php
  38. 9 4
      htdocs/adherents/class/adherent.class.php
  39. 1 1
      htdocs/adherents/class/adherent_type.class.php
  40. 2 4
      htdocs/adherents/class/api_members.class.php
  41. 2 1
      htdocs/adherents/class/api_subscriptions.class.php
  42. 19 17
      htdocs/adherents/list.php
  43. 7 3
      htdocs/adherents/subscription/list.php
  44. 24 15
      htdocs/adherents/type.php
  45. 64 62
      htdocs/admin/company.php
  46. 33 7
      htdocs/admin/dict.php
  47. 2 2
      htdocs/admin/facture.php
  48. 4 4
      htdocs/admin/fckeditor.php
  49. 1 0
      htdocs/admin/ihm.php
  50. 47 52
      htdocs/admin/modules.php
  51. 13 1
      htdocs/admin/multicurrency.php
  52. 14 22
      htdocs/admin/stock.php
  53. 1 1
      htdocs/admin/tools/export.php
  54. 1 1
      htdocs/admin/tools/listevents.php
  55. 27 4
      htdocs/api/class/api.class.php
  56. 1 1
      htdocs/api/class/api_dictionnarycountries.class.php
  57. 1 1
      htdocs/api/class/api_dictionnarytowns.class.php
  58. 5 2
      htdocs/api/class/api_login.class.php
  59. 23 6
      htdocs/api/index.php
  60. 7 2
      htdocs/bookmarks/list.php
  61. 2 2
      htdocs/cache.manifest
  62. 1 1
      htdocs/categories/card.php
  63. 25 7
      htdocs/categories/class/api_categories.class.php
  64. 9 8
      htdocs/categories/class/api_deprecated_category.class.php
  65. 1 1
      htdocs/categories/edit.php
  66. 2 2
      htdocs/categories/traduction.php
  67. 1 1
      htdocs/categories/viewcat.php
  68. 2 2
      htdocs/comm/action/card.php
  69. 3 3
      htdocs/comm/action/class/actioncomm.class.php
  70. 13 6
      htdocs/comm/action/class/api_agendaevents.class.php
  71. 10 11
      htdocs/comm/action/listactions.php
  72. 2 1
      htdocs/comm/action/peruser.php
  73. 8 4
      htdocs/comm/action/rapport/index.php
  74. 1 1
      htdocs/comm/card.php
  75. 1 1
      htdocs/comm/index.php
  76. 13 10
      htdocs/comm/mailing/advtargetemailing.php
  77. 1 1
      htdocs/comm/mailing/card.php
  78. 67 36
      htdocs/comm/mailing/cibles.php
  79. 117 15
      htdocs/comm/mailing/class/advtargetemailing.class.php
  80. 15 3
      htdocs/comm/mailing/list.php
  81. 46 32
      htdocs/comm/propal/card.php
  82. 7 4
      htdocs/comm/propal/class/api_proposals.class.php
  83. 60 30
      htdocs/comm/propal/class/propal.class.php
  84. 1 0
      htdocs/comm/propal/contact.php
  85. 11 3
      htdocs/comm/propal/info.php
  86. 5 3
      htdocs/comm/propal/list.php
  87. 59 20
      htdocs/commande/card.php
  88. 5 3
      htdocs/commande/class/api_deprecated_commande.class.php
  89. 8 3
      htdocs/commande/class/api_orders.class.php
  90. 91 64
      htdocs/commande/class/commande.class.php
  91. 2 1
      htdocs/commande/class/commandestats.class.php
  92. 54 61
      htdocs/commande/contact.php
  93. 63 14
      htdocs/commande/document.php
  94. 71 7
      htdocs/commande/info.php
  95. 5 5
      htdocs/commande/list.php
  96. 59 30
      htdocs/commande/note.php
  97. 13 10
      htdocs/compta/bank/bankentries.php
  98. 5 5
      htdocs/compta/bank/card.php
  99. 8 3
      htdocs/compta/bank/class/account.class.php
  100. 2 1
      htdocs/compta/bank/class/api_bankaccounts.class.php

+ 127 - 8
ChangeLog

@@ -15,7 +15,126 @@ make a Dolibarr upgrade.
 
 ***** ChangeLog for 5.0.0 compared to 4.0.* *****
 For users:
-...
+NEW: Add module mulicurrency.
+NEW: Add module accoutancy expert (double party accountancy). 
+NEW: Better responsive design, above all on smartphone.
+NEW: #5801 More complete change to allow to disable supplier invoice document generation.
+NEW: #5830 Can choose a generic email or use remail in the mail from field.
+NEW: #5896 More complete data on event sent by email (name in title, emails list in details)
+NEW: Add a better icon to show when "run" in cron jobs is disabled.
+NEW: Add account statement into fields of bank account transaction list.
+NEW: Add a direct debit mandate PDF template.
+NEW: add clone contract feature.
+NEW: Add color regarding stock even on ajax autocompleter product selector.
+NEW: Add date into list of print jobs for Google Print.
+NEW: add field and filters on turnover by third party report.
+NEW: Add last activation date as info in module list.
+NEW: add option to limit stock product by warehouse.
+NEW: Add missing unique key on table llx_links.
+NEW: Add option "Hide images in Top menu".
+NEW: Add option PROJECT_LINES_PERWEEK_SHOW_THIRDPARTY to show thirdparty on page to submit time.
+NEW: Add option "Stock can be negative". Off by default.
+NEW: Add option SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED.
+NEW: Add hidden option to include parent products too in stats of orders (not supported in rest of app yet).
+NEW: Add Panama datas.
+NEW: Add ressource extrafields.
+NEW: add restrictions on standard exports (agenda, order, deplacement, facture, fournisseur, societe, propal, expedition)
+NEW: Add substitution keys __SHIPPINGTRACKNUM__, __SHIPPINGTRACKNUMURL__ into shipping email template.
+NEW: Add status Done on interventions.
+NEW: Add system tool "Files integrity checker" to detect modified files for packaged versions.
+NEW: Add tooltip in payment term edition in dictionnary.
+NEW: Add type "url" as possible extrafield.
+NEW: Add workflow to calculated supplier order status on stock dispatch.
+NEW: Add workflow to classifed propal bill on invoice validation.
+NEW: allow to save a parent warehouse.
+NEW: Better filtering of automatic/manually inserted events.
+NEW: Bill orders from order list.
+NEW: Can add event from the card listing events.
+NEW: Can change thirdparty when cloning a project.
+NEW: Can create expense report for someone else (advanced permission). 
+NEW: Can clone an expense report.
+NEW: Can edit a label for each price segment when using several segment prices for products.
+NEW: Can filter on fields on admin translation page.
+NEW: Can filter on project/task ref/label on the "new time consumed" page.
+NEW: Can filter on status on objects on the "statistics" pages.
+NEW: Can filter on type of leave requests in list.
+NEW: Can generate SEPA mandate for each bank account of your customers.
+NEW: Can see/make bank conciliation from bank transaction list.
+NEW: Can edit RUM number of a customer bank account.
+NEW: Can link template invoice to other objects. Generated invoices will be linked to same objects (example: contracts).
+NEW: Can renamed attached files on some documents tabs (like products and expense reports).
+NEW: Can see/edit the customer ref of a shipment.
+NEW: Can select fields/extrafields on contract list + Mass delete action.
+NEW: Can select fields on expense report list. Can make mass delete.
+NEW: Can select fields to show on list of bank transaction.
+NEW: Can set to paid automatically social or fiscal taxes after a payment was recorded.
+NEW: Can sort on status of recurring invoice in list of template invoices.
+NEW: Can use native php and dolibarr object on pages of module website.
+NEW: Checkbox 'close order to "Everything received" automatically if all products are received' is visible on supplier orders.
+NEW: conf to allow payments on different thirdparties bills but same parent company.
+NEW: Consumption view on thirdparty total line and total HT by element.
+NEW: Display bookkeeping by accounting account - Bookkeeping ordered by accounting account - Link with customers and suppliers invoices - Sub Total by accounting account - Ability to display more than 25 lines and filter by customer/supplier, invoice and accounting account
+NEW: Each user can select its landing page (on tab "user display setup").
+NEW: Editing translation GUI become easier with tool to search existing translation.
+NEW: Error code of each email sent is visible in list of email targets
+NEW: Export thirdparty with payment terms and mode.
+NEW: filter actiontype on thirdparty tab.
+NEW: filter by supplier and fk_warehouse on replenishment page.
+NEW: Filters can accept generic search key like __DAY__, __MONTH__, __YEAR__ replaced with current day, month year before making the search.
+NEW: Function "crop" images available on project, product and holiday attachment tab.
+NEW: function to display full path to current warehouse.
+NEW: Generation of document is available on member card.
+NEW: Introduce mass action "delete" on sales orders.
+NEW: Introduce option MAIN_DEFAULT_PAYMENT_TERM_ID to set default payment term on company level.
+NEW: introduce option PROJECT_DISABLE_PRIVATE_PROJECT and PROJECT_DISABLE_PUBLIC_PROJECT.
+NEW: Link between objects can be done on both side and on all objects.
+NEW: More filter on bank transaction list.
+NEW: Mutualize mass action. So "Send by email" is also available on orders.
+NEW: New set of icon for status easier to understand.
+NEW: option "Current/Next" for limit payment date (in payment term dictionary setup) to use a specific day of current month or jump to same day of next month.
+NEW: Option DOC_SHOW_FIRST_SALES_REP shows name of "user buyer or saler" on PDF.
+NEW: Option MAIN_INFO_SOCIETE_MAIL_ALIASES to be able to use several identities into the "email from".
+NEW: Pagination available on list of users.
+NEW: Phone formatting for Canada. Add dol_print_phone into phpunit tests.
+NEW: Reduce nb of picto visible after reference of an object into lists, merging preview and download.
+NEW: Reduce space lost on EDM module.
+NEW: Reopen a paid bill is a user advanced permission.
+NEW: can set a default bank account on thirdparty card.
+NEW: Show photo of contacts on thirdparty card.
+NEW: Show subtotal into list of linked elements.
+NEW: Show total line (planned workload and time spent) on list of tasks.
+NEW: Start to introduce search filters on dictionnaries for vat list.
+NEW: Support extrafields for expense reports.
+NEW: Support extrafields on product lot.
+NEW: Support free bottom text and watermark on expense report template.
+NEW: Support mass actions for proposals
+NEW: Table with list of lots/serial can be viewed (module product batch).
+NEW: The autofill zip/town table option is on by default.
+NEW: the count of linked files on card includes external links.
+NEW: Usage of vat code seems ok everywhere.
+NEW: User date of employment added.
+NEW: Use small photo of user on all user links.
+NEW: Use new archi to select fields into list of time spent.
+NEW: Available substitution key (__INVOICE_MONTH__, __INVOICE_PREVIOUS_MONTH__, ...) to use into note text of recurring invoices.
+
+For developers:
+NEW: Add ORDER_MODIFY trigger on each order modification.
+NEW: Trigger on delete stock
+NEW: The getURLContent return more information on success and error.
+NEW: Uniformize code and correct deal with triggers
+NEW: REST API explorer. Can create invoice and orders with lines.
+NEW: Add a lot of API REST: expense reports, orders, commercial proposals, projects, agenda events, users, invoices, ...
+NEW: Default collation for mysql is now utf8_unicode_ci
+NEW: Can use any filter on all REST API to list.
+NEW: ckeditor accept a parameter to disable all html filtering.
+NEW: Complete table llx_ecm_files with field generated_or_uploaded
+NEW: Enhance function setValueFrom so we can use it for "edit in form" feature.
+NEW: getNomUrl displays full path to warehouse
+NEW: Hook formObjectOptions
+NEW: hook in element overview
+NEW: Hook on stock product card
+NEW: param socid find_min_price_product_fournisseur() function
+NEW: More phpunit tests
 
 WARNING: 
 
@@ -39,7 +158,7 @@ Dolibarr better:
 - Trigger name SUPPLIER_PROPOSAL_CREATE has been renamed into PROPOSAL_SUPPLIER_CREATE.
 - A new paramater sqlfilters was introduced to allow filter on any fields int the REST API. Few old parameters,
   no more required, were also removed. Use this new one if you were using one of them.
-
+- The trigger that activate or close a contract line is run on a contract line, not on contract.
 
 
 ***** ChangeLog for 4.0.2 compared to 4.0.1 *****
@@ -139,12 +258,12 @@ NEW: Add the admin info on combo of type of contact
 NEW: Add the event BILL_PAYED to the list of supported events for module notification.
 NEW: Add total weight and volume on PDF. 
 NEW: Add hidden option to hide column qty ordered on shipments.
-NEW: Add view of virtual stock into product list (when appropriate).
-NEW: Add warning on tasks when they are late (add also the warning tolerance parameter).
-NEW: Add weight/volume for one product into shipment export.
-NEW: Add width and height on product card
-NEW: allow a document to be linked to project of another customer by config setup.
-NEW: allow project to be shared across entities (for multicompany module).
+NEW: Add view of virtual stock into product list (when appropriate)
+NEW: Add warning on tasks when they are late (add also the warning tolerance parameter)
+NEW: Add weight/volume for one product into shipment export
+NEW: Add width and height on product table
+NEW: allow a document to be linked to project from another customer on config
+NEW: allow project to be shared across entities (for multicompany module)
 NEW: All variant of ckeditor config can be tested into the setup page of module.
 NEW: Can change dynamically number of records visible into lists.
 NEW: Can change type of extrafields (for some combinations only).

+ 13 - 4
build/composer/README

@@ -1,10 +1,19 @@
 
-To test upgrade of a lib with composer:
+* To list packages 
 
-composer update --no-dev --no-autoloader --dry-run ccampbell/chromephp
+composer show -i
 
-To upgrade a lib with composer:
+* To test upgrade of a lib with composer:
+
+Remove entry in composer.lock
+Edit composer.json to change version to "x.y.z"
+composer -v update --root-reqs --no-dev --no-autoloader --dry-run ccampbell/chromephp
+
+* To upgrade a lib with composer:
+
+Remove entry in composer.lock
+Edit composer.json to change version to "x.y.z"
+composer -v update --root-reqs --no-dev --no-autoloader ccampbell/chromephp
 
-composer update --no-dev --no-autoloader ccampbell/chromephp
 
 

+ 4 - 3
build/debian/README.howto

@@ -73,7 +73,8 @@ Ex: https://alioth.debian.org/users/eldy-guest
 # msgfmt -v -c -o /dev/null XX.po		 		To have status of translation for language XX
  
 # To check package integrity
-# lintian --pedantic -E -I package.deb   To test a package   
+# lintian --pedantic -E -I package.deb   To test a binary package   
+# lintian --pedantic -E -I package.dsc   To test a source package   
 
 # To manipulate packages
 # dpkg -l                                List all packages
@@ -181,8 +182,8 @@ To test a package
 > cp ../build-area/* /srv/chroot/unstable/tmp
 > sudo schroot -c name_of_chroot
 > cd /tmp
-> lintian --pedantic -E -I dolibarr*.deb
-> lintian --pedantic -E -I dolibarr*.dsc
+> lintian --no-tag-display-limit --pedantic -E -I dolibarr*.deb
+> lintian --no-tag-display-limit --pedantic -E -I dolibarr*.dsc
 > dpkg -i dolibarr*.deb  ou   pour avoir des traces: dpkg -D77777 -i dolibarr*.deb
 > apt-get install -f
 

+ 8 - 3
build/debian/source/lintian-overrides

@@ -1,5 +1,10 @@
 # Remove warning, we want to keep both standard and minified sources.
-dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jsgantt/*
 dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jquery/*
-# This is a textual data file
-source-is-missing htdocs/includes/mobiledetect/mobiledetectlib/Mobile_Detect.json
+dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jsgantt/*
+dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jstz/*
+# Those are false positives, the files are their own sources since
+# they are not minified
+source-is-missing htdocs/includes/jsgantt/jsgantt.js *
+source-is-missing htdocs/includes/jquery/plugins/colorpicker/jquery.colorpicker.js *
+source-is-missing htdocs/includes/jquery/plugins/select2/select2.js *
+source-is-missing htdocs/includes/jquery/plugins/select2/select2_locale_ar.js *

+ 7 - 0
build/makepack-dolibarr.pl

@@ -1145,6 +1145,9 @@ if ($nboftargetok) {
 			"$DESTI/package_rpm_generic/$FILENAMERPM"=>'Dolibarr installer for Fedora-Redhat-Mandriva-Opensuse (DoliRpm)',
 			"$DESTI/package_rpm_generic/$FILENAMERPMSRC"=>'none',						# none means it won't be published on SF
 			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}_all.deb"=>'Dolibarr installer for Debian-Ubuntu (DoliDeb)',
+			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}_amd64.changes"=>'none',		# none means it won't be published on SF
+			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.dsc"=>'none',					# none means it won't be published on SF
+			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.debian.tar.gz"=>'none',		# none means it won't be published on SF
 			"$DESTI/package_debian-ubuntu/${FILENAMEDEBSHORT}.orig.tar.gz"=>'none',		# none means it won't be published on SF
 			"$DESTI/package_windows/$FILENAMEEXEDOLIWAMP.exe"=>'Dolibarr installer for Windows (DoliWamp)',
 			"$DESTI/standard/$FILENAMETGZ.tgz"=>'Dolibarr ERP-CRM',
@@ -1155,6 +1158,10 @@ if ($nboftargetok) {
 			"$DESTI/package_rpm_generic/$FILENAMERPM"=>'package_rpm_generic',
 			"$DESTI/package_rpm_generic/$FILENAMERPMSRC"=>'package_rpm_generic',
 			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}_all.deb"=>'package_debian-ubuntu',
+			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}_amd64.changes"=>'package_debian-ubuntu',
+			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.dsc"=>'package_debian-ubuntu',
+			"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.debian.tar.gz"=>'package_debian-ubuntu',
+			"$DESTI/package_debian-ubuntu/${FILENAMEDEBSHORT}.orig.tar.gz"=>'package_debian-ubuntu',
 			"$DESTI/package_debian-ubuntu/${FILENAMEDEBSHORT}.orig.tar.gz"=>'package_debian-ubuntu',
 			"$DESTI/package_windows/$FILENAMEEXEDOLIWAMP.exe"=>'package_windows',
 			"$DESTI/standard/$FILENAMETGZ.tgz"=>'standard',

+ 2 - 0
build/makepack-howto.txt

@@ -12,6 +12,7 @@ beta version of Dolibarr, step by step.
 To generate a changelog of a major new version x.y.0 (from develop repo), you can do "cd ~/git/dolibarr; git log `diff -u <(git rev-list --first-parent x.(y-1).0)  <(git rev-list --first-parent develop) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
 To generate a changelog of a major new version x.y.0 (from x.y repo), you can do "cd ~/git/dolibarr_x.y; git log `diff -u <(git rev-list --first-parent x.(y-1).0)  <(git rev-list --first-parent x.y.0) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
 To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log x.y.z-1.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
+- To know number of lines changes: git diff --shortstat A B
 - Update version number with x.y.z-w in htdocs/filefunc.inc.php
 - Commit all changes.
 
@@ -35,6 +36,7 @@ complete release of Dolibarr, step by step.
 To generate a changelog of a major new version x.y.0 (from develop repo), you can do "cd ~/git/dolibarr; git log `diff -u <(git rev-list --first-parent x.(y-1).0)  <(git rev-list --first-parent develop) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
 To generate a changelog of a major new version x.y.0 (from x.y repo), you can do "cd ~/git/dolibarr_x.y; git log `diff -u <(git rev-list --first-parent x.(y-1).0)  <(git rev-list --first-parent x.y.0) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
 To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log x.y.z-1.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
+- To know number of lines changes: git diff --shortstat A B
 - Update version number with x.y.z in htdocs/filefunc.inc.php
 - Commit all changes.
 

+ 1 - 1
composer.json

@@ -27,7 +27,7 @@
         "php": ">=5.3.0",
         "ext-curl": "*",
         "ccampbell/chromephp": "4.1.0",
-        "ckeditor/ckeditor": "dev-full/stable",
+        "ckeditor/ckeditor": "4.5.9",
         "mike42/escpos-php": "1.2.1",
         "mobiledetect/mobiledetectlib": "2.8.17",
         "phpoffice/phpexcel": "1.8.1",

+ 1393 - 13
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": "f666a32d1a59518b8ecc55899e829e79",
-    "content-hash": "8d110e7d8fca6eca1aa814ee35d0032b",
+    "hash": "c586663818e933f26657871d86d01dc6",
+    "content-hash": "09e891bb978d35a48902a5f57760aee9",
     "packages": [
         {
             "name": "ccampbell/chromephp",
@@ -52,16 +52,16 @@
         },
         {
             "name": "ckeditor/ckeditor",
-            "version": "dev-full/stable",
+            "version": "4.5.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/ckeditor/ckeditor-releases.git",
-                "reference": "4a7a6d717f9a408fa8f9ea53ef2dba4d64b83e91"
+                "reference": "48155a1e1c7e84736b5a166ad3f33acea2a51255"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/4a7a6d717f9a408fa8f9ea53ef2dba4d64b83e91",
-                "reference": "4a7a6d717f9a408fa8f9ea53ef2dba4d64b83e91",
+                "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/48155a1e1c7e84736b5a166ad3f33acea2a51255",
+                "reference": "48155a1e1c7e84736b5a166ad3f33acea2a51255",
                 "shasum": ""
             },
             "type": "library",
@@ -89,7 +89,7 @@
                 "text",
                 "wysiwyg"
             ],
-            "time": "2016-05-12 15:36:04"
+            "time": "2016-09-07 13:32:39"
         },
         {
             "name": "mike42/escpos-php",
@@ -273,12 +273,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/Luracast/Restler-Framework.git",
-                "reference": "bfe1139b233852b745c6a0ec14d7244ceb3b3fc6"
+                "reference": "3388d76e73a81f871ce5baa906271071b12cd17f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Luracast/Restler-Framework/zipball/bfe1139b233852b745c6a0ec14d7244ceb3b3fc6",
-                "reference": "bfe1139b233852b745c6a0ec14d7244ceb3b3fc6",
+                "url": "https://api.github.com/repos/Luracast/Restler-Framework/zipball/3388d76e73a81f871ce5baa906271071b12cd17f",
+                "reference": "3388d76e73a81f871ce5baa906271071b12cd17f",
                 "shasum": ""
             },
             "require": {
@@ -325,7 +325,7 @@
                 "rest",
                 "server"
             ],
-            "time": "2016-02-28 15:57:37"
+            "time": "2016-06-21 12:42:18"
         },
         {
             "name": "tecnickcom/tcpdf",
@@ -391,11 +391,1391 @@
             "time": "2015-09-12 10:08:34"
         }
     ],
-    "packages-dev": [],
+    "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": "jakub-onderka/php-console-color",
+            "version": "0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/JakubOnderka/PHP-Console-Color.git",
+                "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1",
+                "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "jakub-onderka/php-code-style": "1.0",
+                "jakub-onderka/php-parallel-lint": "0.*",
+                "jakub-onderka/php-var-dump-check": "0.*",
+                "phpunit/phpunit": "3.7.*",
+                "squizlabs/php_codesniffer": "1.*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "JakubOnderka\\PhpConsoleColor": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jakub Onderka",
+                    "email": "jakub.onderka@gmail.com",
+                    "homepage": "http://www.acci.cz"
+                }
+            ],
+            "time": "2014-04-08 15:00:19"
+        },
+        {
+            "name": "jakub-onderka/php-console-highlighter",
+            "version": "v0.3.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git",
+                "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5",
+                "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5",
+                "shasum": ""
+            },
+            "require": {
+                "jakub-onderka/php-console-color": "~0.1",
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "jakub-onderka/php-code-style": "~1.0",
+                "jakub-onderka/php-parallel-lint": "~0.5",
+                "jakub-onderka/php-var-dump-check": "~0.1",
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "~1.5"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "JakubOnderka\\PhpConsoleHighlighter": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jakub Onderka",
+                    "email": "acci@acci.cz",
+                    "homepage": "http://www.acci.cz/"
+                }
+            ],
+            "time": "2015-04-20 18:58:01"
+        },
+        {
+            "name": "jakub-onderka/php-parallel-lint",
+            "version": "v0.9.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git",
+                "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+                "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "jakub-onderka/php-console-highlighter": "~0.3",
+                "nette/tester": "~1.3"
+            },
+            "suggest": {
+                "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet"
+            },
+            "bin": [
+                "parallel-lint"
+            ],
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "./"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jakub Onderka",
+                    "email": "jakub.onderka@gmail.com"
+                }
+            ],
+            "description": "This tool check syntax of PHP files about 20x faster than serial check.",
+            "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint",
+            "time": "2015-12-15 10:42:16"
+        },
+        {
+            "name": "phpdocumentor/reflection-common",
+            "version": "1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+                "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
+                "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": [
+                        "src"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jaap van Otterdijk",
+                    "email": "opensource@ijaap.nl"
+                }
+            ],
+            "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+            "homepage": "http://www.phpdoc.org",
+            "keywords": [
+                "FQSEN",
+                "phpDocumentor",
+                "phpdoc",
+                "reflection",
+                "static analysis"
+            ],
+            "time": "2015-12-27 11:43:31"
+        },
+        {
+            "name": "phpdocumentor/reflection-docblock",
+            "version": "3.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+                "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
+                "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5",
+                "phpdocumentor/reflection-common": "^1.0@dev",
+                "phpdocumentor/type-resolver": "^0.2.0",
+                "webmozart/assert": "^1.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^0.9.4",
+                "phpunit/phpunit": "^4.4"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": [
+                        "src/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "me@mikevanriel.com"
+                }
+            ],
+            "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+            "time": "2016-09-30 07:12:33"
+        },
+        {
+            "name": "phpdocumentor/type-resolver",
+            "version": "0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/TypeResolver.git",
+                "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443",
+                "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5",
+                "phpdocumentor/reflection-common": "^1.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^0.9.4",
+                "phpunit/phpunit": "^5.2||^4.8.24"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": [
+                        "src/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "me@mikevanriel.com"
+                }
+            ],
+            "time": "2016-06-10 07:14:17"
+        },
+        {
+            "name": "phpspec/prophecy",
+            "version": "v1.6.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpspec/prophecy.git",
+                "reference": "58a8137754bc24b25740d4281399a4a3596058e0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
+                "reference": "58a8137754bc24b25740d4281399a4a3596058e0",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.0.2",
+                "php": "^5.3|^7.0",
+                "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
+                "sebastian/comparator": "^1.1",
+                "sebastian/recursion-context": "^1.0"
+            },
+            "require-dev": {
+                "phpspec/phpspec": "^2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.6.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": "2016-06-07 08:13:47"
+        },
+        {
+            "name": "phpunit/php-code-coverage",
+            "version": "2.2.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+                "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
+                "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "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": "~4"
+            },
+            "suggest": {
+                "ext-dom": "*",
+                "ext-xdebug": ">=2.2.1",
+                "ext-xmlwriter": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.2.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-10-06 15:47:00"
+        },
+        {
+            "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.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-timer.git",
+                "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
+                "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4|~5"
+            },
+            "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": "2016-05-12 18:03:57"
+        },
+        {
+            "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": "4.8.27",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpunit.git",
+                "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90",
+                "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-json": "*",
+                "ext-pcre": "*",
+                "ext-reflection": "*",
+                "ext-spl": "*",
+                "php": ">=5.3.3",
+                "phpspec/prophecy": "^1.3.1",
+                "phpunit/php-code-coverage": "~2.1",
+                "phpunit/php-file-iterator": "~1.4",
+                "phpunit/php-text-template": "~1.2",
+                "phpunit/php-timer": "^1.0.6",
+                "phpunit/phpunit-mock-objects": "~2.3",
+                "sebastian/comparator": "~1.1",
+                "sebastian/diff": "~1.2",
+                "sebastian/environment": "~1.3",
+                "sebastian/exporter": "~1.2",
+                "sebastian/global-state": "~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": "4.8.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": "2016-07-21 06:48:14"
+        },
+        {
+            "name": "phpunit/phpunit-mock-objects",
+            "version": "2.3.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
+                "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
+                "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.0.2",
+                "php": ">=5.3.3",
+                "phpunit/php-text-template": "~1.2",
+                "sebastian/exporter": "~1.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.4"
+            },
+            "suggest": {
+                "ext-soap": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.3.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-10-02 06:51:40"
+        },
+        {
+            "name": "phpunit/phpunit-selenium",
+            "version": "2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/giorgiosironi/phpunit-selenium.git",
+                "reference": "2bad798ec0daf20d2854400e3bc5329ee0a7b2d1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/giorgiosironi/phpunit-selenium/zipball/2bad798ec0daf20d2854400e3bc5329ee0a7b2d1",
+                "reference": "2bad798ec0daf20d2854400e3bc5329ee0a7b2d1",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "ext-dom": "*",
+                "php": ">=5.3.3",
+                "phpunit/phpunit": "~4.8",
+                "sebastian/comparator": "~1.0"
+            },
+            "require-dev": {
+                "phing/phing": "2.*"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "PHPUnit/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                ""
+            ],
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Giorgio Sironi",
+                    "email": "info@giorgiosironi.com",
+                    "role": "developer"
+                },
+                {
+                    "name": "Ivan Kurnosov",
+                    "email": "zerkms@zerkms.com",
+                    "role": "developer"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "original developer"
+                }
+            ],
+            "description": "Selenium Server integration for PHPUnit",
+            "homepage": "http://www.phpunit.de/",
+            "keywords": [
+                "phpunit",
+                "selenium",
+                "testing",
+                "xunit"
+            ],
+            "time": "2016-03-01 10:33:56"
+        },
+        {
+            "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.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/environment.git",
+                "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
+                "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8 || ^5.0"
+            },
+            "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": "2016-08-18 05:49:44"
+        },
+        {
+            "name": "sebastian/exporter",
+            "version": "1.2.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/exporter.git",
+                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
+                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "sebastian/recursion-context": "~1.0"
+            },
+            "require-dev": {
+                "ext-mbstring": "*",
+                "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": "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": "2016-06-17 09:04:28"
+        },
+        {
+            "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/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.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
+                "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
+                "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
+                "shasum": ""
+            },
+            "require": {
+                "ext-simplexml": "*",
+                "ext-tokenizer": "*",
+                "ext-xmlwriter": "*",
+                "php": ">=5.1.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "bin": [
+                "scripts/phpcs",
+                "scripts/phpcbf"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.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": "2016-09-01 23:53:02"
+        },
+        {
+            "name": "symfony/yaml",
+            "version": "v3.1.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/yaml.git",
+                "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27",
+                "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-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": "2016-10-24 18:41:13"
+        },
+        {
+            "name": "webmozart/assert",
+            "version": "1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/webmozart/assert.git",
+                "reference": "bb2d123231c095735130cc8f6d31385a44c7b308"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308",
+                "reference": "bb2d123231c095735130cc8f6d31385a44c7b308",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3|^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.6",
+                "sebastian/version": "^1.0.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Webmozart\\Assert\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@gmail.com"
+                }
+            ],
+            "description": "Assertions to validate method input/output with nice error messages.",
+            "keywords": [
+                "assert",
+                "check",
+                "validate"
+            ],
+            "time": "2016-08-09 15:02:57"
+        }
+    ],
     "aliases": [],
     "minimum-stability": "stable",
     "stability-flags": {
-        "ckeditor/ckeditor": 20,
         "restler/framework": 5
     },
     "prefer-stable": false,

+ 1 - 1
dev/skeletons/modMyModule.class.php

@@ -64,7 +64,7 @@ class modMyModule extends DolibarrModules
 		$this->description = "Description of module MyModule";
 		$this->descriptionlong = "A very long description. Can be a full HTML content";
 		$this->editor_name = 'Editor name';
-		$this->editor_url = 'http://www.dolibarr.org';
+		$this->editor_url = 'https://www.dolibarr.org';
 		
 		// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z'
 		$this->version = '1.0';

+ 14 - 4
dev/skeletons/skeleton_card.php

@@ -53,6 +53,7 @@ $langs->load("other");
 // Get parameters
 $id			= GETPOST('id','int');
 $action		= GETPOST('action','alpha');
+$cancel     = GETPOST('cancel');
 $backtopage = GETPOST('backtopage');
 $myparam	= GETPOST('myparam','alpha');
 
@@ -95,6 +96,18 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e
 
 if (empty($reshook))
 {
+	if ($cancel) 
+	{
+		if ($action != 'addlink')
+		{
+			$urltogo=$backtopage?$backtopage:dol_buildpath('/mymodule/list.php',1);
+			header("Location: ".$urltogo);
+			exit;
+		}		
+		if ($id > 0 || ! empty($ref)) $ret = $object->fetch($id,$ref);
+		$action='';
+	}
+	
 	// Action to add record
 	if ($action == 'add')
 	{
@@ -140,11 +153,8 @@ if (empty($reshook))
 		}
 	}
 
-	// Cancel
-	if ($action == 'update' && GETPOST('cancel')) $action='view';
-
 	// Action to update record
-	if ($action == 'update' && ! GETPOST('cancel'))
+	if ($action == 'update')
 	{
 		$error=0;
 

+ 12 - 5
dev/skeletons/skeleton_list.php

@@ -1,6 +1,7 @@
 <?php
 /* Copyright (C) 2007-2016 Laurent Destailleur  <eldy@users.sourceforge.net>
- * Copyright (C) 2014-2016  Juanjo Menent       <jmenent@2byte.es>
+ * Copyright (C) 2014-2016 Juanjo Menent        <jmenent@2byte.es>
+ * Copyright (C) 2016      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
@@ -52,9 +53,13 @@ dol_include_once('/mymodule/class/skeleton_class.class.php');
 $langs->load("mymodule");
 $langs->load("other");
 
-// Get parameters
+$action=GETPOST('action','alpha');
+$massaction=GETPOST('massaction','alpha');
+$show_files=GETPOST('show_files','int');
+$confirm=GETPOST('confirm','alpha');
+$toselect = GETPOST('toselect', 'array');
+
 $id			= GETPOST('id','int');
-$action		= GETPOST('action','alpha');
 $backtopage = GETPOST('backtopage');
 $myparam	= GETPOST('myparam','alpha');
 
@@ -212,7 +217,7 @@ $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."mytable as t";
-if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."mytable_extrafields as ef on (u.rowid = ef.fk_object)";
+if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."mytable_extrafields as ef on (t.rowid = ef.fk_object)";
 $sql.= " WHERE 1 = 1";
 //$sql.= " WHERE u.entity IN (".getEntity('mytable',1).")";
 if ($search_field1) $sql.= natural_search("field1",$search_field1);
@@ -239,7 +244,7 @@ $sql.=$db->order($sortfield,$sortorder);
 //$sql.= $db->plimit($conf->liste_limit+1, $offset);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
 	$result = $db->query($sql);
@@ -329,6 +334,7 @@ if (! empty($moreforfilter))
 $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
 $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
 
+print '<div class="div-table-responsive">';
 print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 
 // Fields title
@@ -531,6 +537,7 @@ $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters);    // N
 print $hookmanager->resPrint;
 
 print '</table>'."\n";
+print '</div>'."\n";
 
 print '</form>'."\n";
 

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

@@ -155,24 +155,24 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as a2 ON aa.account_par
 $sql .= " WHERE asy.rowid = " . $pcgver;
 
 if (strlen(trim($search_account))) {
-	$sql .= " AND aa.account_number like '%" . $search_account . "%'";
+	$sql .= natural_search("aa.account_number", $search_account);
 }
 if (strlen(trim($search_label))) {
-	$sql .= " AND aa.label like '%" . $search_label . "%'";
+	$sql .= natural_search("aa.label", $search_label);
 }
 if (strlen(trim($search_accountparent))) {
-	$sql .= " AND aa.account_parent like '%" . $search_accountparent . "%'";
+	$sql .= natural_search("aa.account_parent", $search_accountparent);
 }
 if (strlen(trim($search_pcgtype))) {
-	$sql .= " AND aa.pcg_type like '%" . $search_pcgtype . "%'";
+	$sql .= natural_search("aa.pcg_type", $search_pcgtype);
 }
 if (strlen(trim($search_pcgsubtype))) {
-	$sql .= " AND aa.pcg_subtype like '%" . $search_pcgsubtype . "%'";
+	$sql .= natural_search("aa.pcg_subtype", $search_pcgsubtype);
 }
 $sql .= $db->order($sortfield, $sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
 	$resql = $db->query($sql);
@@ -198,11 +198,9 @@ if ($resql) {
 	
 	print_barre_liste($langs->trans('ListAccounts'), $page, $_SERVER["PHP_SELF"], $params, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy');
 	
-	$i = 0;
-	
 	print '<form method="GET" action="' . $_SERVER["PHP_SELF"] . '">';
 	
-	// Box to select active chart of accoun
+	// Box to select active chart of account
     $var = ! $var;
     print $langs->trans("Selectchartofaccounts") . " : ";
     print '<select class="flat" name="chartofaccounts" id="chartofaccounts">';
@@ -235,7 +233,7 @@ if ($resql) {
 	print '<a class="butAction" href="./categories.php">' . $langs->trans("ApplyMassCategories") . '</a>';
 	// print '<a class="butAction" href="./importaccounts.php">' . $langs->trans("ImportAccount") . '</a>';
 	// print '<a class="butAction" href="./productaccount.php">' . $langs->trans("CheckProductAccountancyCode") . '</a>';
-	print '<br/><br/>';
+	print '<br><br>';
 	
 	print '<table class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
@@ -266,9 +264,11 @@ if ($resql) {
 	$accountstatic = new AccountingAccount($db);
 	$accountparent = new AccountingAccount($db);
 	
-	while ( $i < min($num, $limit) ) {
+	$i = 0;
+	while ( $i < min($num, $limit) ) 
+	{
 		$obj = $db->fetch_object($resql);
-		
+
 		$accountstatic->id = $obj->rowid;
 		$accountstatic->label = $obj->label;
 		$accountstatic->account_number = $obj->account_number;
@@ -318,7 +318,7 @@ if ($resql) {
 		
 		print "</tr>\n";
 		$var = ! $var;
-		$i ++;
+		$i++;
 	}
 	
 	print "</table>";

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

@@ -1262,8 +1262,8 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='')
 
 	$formadmin = new FormAdmin($db);
 	$formcompany = new FormCompany($db);
-	if (! empty($conf->accounting->enabled)) $formaccountancy = new FormVentilation($db);
-
+	$formaccountancy = new FormVentilation($db);
+	
 	foreach ($fieldlist as $field => $value)
 	{
 		if ($fieldlist[$field] == 'country')

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

@@ -90,7 +90,7 @@ $sql .= " WHERE f.entity = " . $conf->entity;
 $sql.=$db->order($sortfield,$sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
 	$result = $db->query($sql);

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

@@ -248,7 +248,7 @@ if (strlen(trim($search_desc))) {
 }
 $sql .= $db->order($sortfield, $sortorder);
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);

+ 155 - 157
htdocs/accountancy/bookkeeping/balance.php

@@ -65,14 +65,6 @@ $formventilation = new FormVentilation($db);
 $formother = new FormOther($db);
 $form = new Form($db);
 
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
-{
-	$search_accountancy_code_start = '';
-	$search_accountancy_code_end = '';
-	$search_date_start = '';
-	$search_date_end = '';
-}
-
 if (empty($search_date_start)) {
 	$search_date_start = dol_mktime(0, 0, 0, 1, 1, dol_print_date(dol_now(), '%Y'));
 	$search_date_end = dol_mktime(0, 0, 0, 12, 31, dol_print_date(dol_now(), '%Y'));
@@ -106,6 +98,19 @@ if (! empty($search_accountancy_code_end)) {
  * Action
  */
 
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
+{
+    $search_accountancy_code_start = '';
+    $search_accountancy_code_end = '';
+    $search_date_start = '';
+    $search_date_end = '';
+}
+
+
+/*
+ * View
+ */
+
 if ($action == 'export_csv') {
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
 	$journal = 'bookkepping';
@@ -132,155 +137,148 @@ if ($action == 'export_csv') {
 }
 
 else {
-
-	$title_page = $langs->trans("AccountBalance") . ' ' . dol_print_date($search_date_start) . '-' . dol_print_date($search_date_end);
-
-	llxHeader('', $title_page);
-
-	/*
-	 * List
-	 */
-	$nbtotalofrecords = 0;
-	if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
-		$nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
-		if ($nbtotalofrecords < 0) {
-			setEventMessages($object->error, $object->errors, 'errors');
-		}
-	}
-
-	$result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter);
-	if ($result < 0) {
-		setEventMessages($object->error, $object->errors, 'errors');
-	}
-
-	print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result, 0, 'title_accountancy');
-
-	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>';
-
-	$moreforfilter='';
-
-	$moreforfilter.='<div class="divsearchfield">';
-	$moreforfilter.=$langs->trans('DateStart') . ': ';
-	$moreforfilter.=$form->select_date($search_date_start, 'date_start', 0, 0, 1, '', 1, 0, 1);
-	$moreforfilter.=$langs->trans('DateEnd') . ': ';
-	$moreforfilter.=$form->select_date($search_date_end, 'date_end', 0, 0, 1, '', 1, 0, 1);
-	$moreforfilter.='</div>';
-
-	if (! empty($moreforfilter))
-	{
-		print '<div class="liste_titre liste_titre_bydiv centpercent">';
-		print $moreforfilter;
-    	$parameters=array();
-    	$reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters);    // Note that $action and $object may have been modified by hook
-	    print $hookmanager->resPrint;
-	    print '</div>';
-	}
-
-	print '<table class="liste '.($moreforfilter?"listwithfilterbefore":"").'">';
-	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("AccountAccounting"), $_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, "", 'align="right"', $sortfield, $sortorder);
-	print_liste_field_titre('', $_SERVER["PHP_SELF"], "", $options, "", 'width="60" align="center"', $sortfield, $sortorder);
-	print "</tr>\n";
-
-	print '<tr class="liste_titre">';
-	print '<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 $formventilation->select_account($search_accountancy_code_end, 'search_accountancy_code_end', 1, array (), 1, 1, '');
-	print '</td>';
-
-	print '<td>&nbsp;</td>';
-	print '<td>&nbsp;</td>';
-	print '<td>&nbsp;</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")) . '">';
-	print '&nbsp;';
-	print '<input type="image" class="liste_titre" src="' . img_picto($langs->trans("Search"), 'searchclear.png', '', '', 1) . '" name="button_removefilter" value="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '" title="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '">';
-	print '</td>';
-
-	print '</tr>';
-
-	$var = True;
-
-	$total_debit = 0;
-	$total_credit = 0;
-  $sous_total_debit = 0;
-  $sous_total_credit = 0;
-  $displayed_account = "";
-
-	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
-    $root_account_description = $object->get_compte_racine($line->numero_compte);
-		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].'>';
-
-
-    // Permet d'afficher le compte comptable
-    if ($root_account_description != $displayed_account) {
-
-      // Affiche un Sous-Total par compte comptable
-      if ($displayed_account != "") {
-        print '<tr class="liste_total"><td align="right" colspan="2">'.$langs->trans("SubTotal") . ':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td><td class="nowrap" align="right">'.price($sous_total_credit-$sous_total_debit).'</td>';
-        print "<td>&nbsp;</td>\n";
-        print '</tr>';
-      }
-
-      // Affiche le compte comptable en d�but de ligne
-      print "<tr>";
-    	print '<td colspan="6" style="font-weight:bold; border-bottom: 1pt solid black;">'. $root_account_description .'</td>';
-    	print '</tr>';
-
-      $displayed_account = $root_account_description;
-      $sous_total_debit = 0;
-      $sous_total_credit = 0;
+    $title_page = $langs->trans("AccountBalance") . ' ' . dol_print_date($search_date_start) . '-' . dol_print_date($search_date_end);
+    
+    llxHeader('', $title_page);
+    
+    // List
+
+    $nbtotalofrecords = -1;
+    if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
+        $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
+        if ($nbtotalofrecords < 0) {
+            setEventMessages($object->error, $object->errors, 'errors');
+        }
     }
-
-    // $object->get_compte_racine($line->numero_compte);
-
-
-		print '<td>' . length_accountg($line->numero_compte) . '</td>';
-		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";
-
-    // Comptabilise le sous-total
-    $sous_total_debit += $line->debit;
-    $sous_total_credit += $line->credit;
-
-	}
-
-  print '<tr class="liste_total"><td align="right" colspan="2">'.$langs->trans("SubTotal") . ':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td><td class="nowrap" align="right">'.price($sous_total_credit-$sous_total_debit).'</td>';
-  print "<td>&nbsp;</td>\n";
-  print '</tr>';
-
-  print '<tr class="liste_total"><td align="right" colspan="2">'.$langs->trans("AccountBalance") . ':</td><td class="nowrap" align="right">'.price($total_debit).'</td><td class="nowrap" align="right">'.price($total_credit).'</td><td class="nowrap" align="right">'.price($total_credit-$total_debit).'</td>';
-  print "<td>&nbsp;</td>\n";
-  print '</tr>';
-
-
-	print "</table>";
-	print '</form>';
-
-	llxFooter();
+    
+    $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter);
+    if ($result < 0) {
+        setEventMessages($object->error, $object->errors, 'errors');
+    }
+    
+    
+    print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
+    
+    $button = '<input type="submit" name="button_export_csv" class="butAction" value="' . $langs->trans("Export") . '" />';
+    print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result, 0, 'title_accountancy', 0, $button);
+    
+    
+    $moreforfilter = '';
+    
+    $moreforfilter .= '<div class="divsearchfield">';
+    $moreforfilter .= $langs->trans('DateStart') . ': ';
+    $moreforfilter .= $form->select_date($search_date_start, 'date_start', 0, 0, 1, '', 1, 0, 1);
+    $moreforfilter .= $langs->trans('DateEnd') . ': ';
+    $moreforfilter .= $form->select_date($search_date_end, 'date_end', 0, 0, 1, '', 1, 0, 1);
+    $moreforfilter .= '</div>';
+    
+    if (! empty($moreforfilter)) {
+        print '<div class="liste_titre liste_titre_bydiv centpercent">';
+        print $moreforfilter;
+        $parameters = array();
+        $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
+        print $hookmanager->resPrint;
+        print '</div>';
+    }
+    
+    print '<table class="liste ' . ($moreforfilter ? "listwithfilterbefore" : "") . '">';
+    print '<tr class="liste_titre">';
+    print_liste_field_titre($langs->trans("AccountAccounting"), $_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, "", 'align="right"', $sortfield, $sortorder);
+    print_liste_field_titre('', $_SERVER["PHP_SELF"], "", $options, "", 'width="60" align="center"', $sortfield, $sortorder);
+    print "</tr>\n";
+    
+    print '<tr class="liste_titre">';
+    print '<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 $formventilation->select_account($search_accountancy_code_end, 'search_accountancy_code_end', 1, array(), 1, 1, '');
+    print '</td>';
+    
+    print '<td>&nbsp;</td>';
+    print '<td>&nbsp;</td>';
+    print '<td>&nbsp;</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")) . '">';
+    print '&nbsp;';
+    print '<input type="image" class="liste_titre" src="' . img_picto($langs->trans("Search"), 'searchclear.png', '', '', 1) . '" name="button_removefilter" value="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '" title="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '">';
+    print '</td>';
+    
+    print '</tr>';
+    
+    $var = True;
+    
+    $total_debit = 0;
+    $total_credit = 0;
+    $sous_total_debit = 0;
+    $sous_total_credit = 0;
+    $displayed_account = "";
+    
+    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
+        $root_account_description = $object->get_compte_racine($line->numero_compte);
+        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] . '>';
+        
+        // Permet d'afficher le compte comptable
+        if ($root_account_description != $displayed_account) {
+            
+            // Affiche un Sous-Total par compte comptable
+            if ($displayed_account != "") {
+                print '<tr class="liste_total"><td align="right" colspan="2">' . $langs->trans("SubTotal") . ':</td><td class="nowrap" align="right">' . price($sous_total_debit) . '</td><td class="nowrap" align="right">' . price($sous_total_credit) . '</td><td class="nowrap" align="right">' . price($sous_total_credit - $sous_total_debit) . '</td>';
+                print "<td>&nbsp;</td>\n";
+                print '</tr>';
+            }
+            
+            // Affiche le compte comptable en d�but de ligne
+            print "<tr>";
+            print '<td colspan="6" style="font-weight:bold; border-bottom: 1pt solid black;">' . $root_account_description . '</td>';
+            print '</tr>';
+            
+            $displayed_account = $root_account_description;
+            $sous_total_debit = 0;
+            $sous_total_credit = 0;
+        }
+        
+        // $object->get_compte_racine($line->numero_compte);
+        
+        print '<td>' . length_accountg($line->numero_compte) . '</td>';
+        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";
+        
+        // Comptabilise le sous-total
+        $sous_total_debit += $line->debit;
+        $sous_total_credit += $line->credit;
+    }
+    
+    print '<tr class="liste_total"><td align="right" colspan="2">' . $langs->trans("SubTotal") . ':</td><td class="nowrap" align="right">' . price($sous_total_debit) . '</td><td class="nowrap" align="right">' . price($sous_total_credit) . '</td><td class="nowrap" align="right">' . price($sous_total_credit - $sous_total_debit) . '</td>';
+    print "<td>&nbsp;</td>\n";
+    print '</tr>';
+    
+    print '<tr class="liste_total"><td align="right" colspan="2">' . $langs->trans("AccountBalance") . ':</td><td class="nowrap" align="right">' . price($total_debit) . '</td><td class="nowrap" align="right">' . price($total_credit) . '</td><td class="nowrap" align="right">' . price($total_credit - $total_debit) . '</td>';
+    print "<td>&nbsp;</td>\n";
+    print '</tr>';
+    
+    print "</table>";
+    print '</form>';
+    
+    llxFooter();
 }
 $db->close();

+ 15 - 10
htdocs/accountancy/bookkeeping/list.php

@@ -288,12 +288,12 @@ if ($action == 'export_csv') {
 }
 
 $title_page = $langs->trans("Bookkeeping");
-if ($search_date_start || $search_date_end) $title_page .= ' ' . dol_print_date($search_date_start, 'day') . ' - ' . dol_print_date($search_date_end, 'day');
+
 llxHeader('', $title_page);
 
 // List
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
 	$nbtotalofrecords = $object->fetchAll($sortorder, $sortfield, 0, 0, $filter);
 	if ($nbtotalofrecords < 0) {
@@ -307,6 +307,8 @@ if ($result < 0) {
 	setEventMessages($object->error, $object->errors, 'errors');
 }
 
+$num=count($object->lines);
+
 if ($action == 'delmouv') {
 	$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?mvt_num=' . GETPOST('mvt_num'), $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1);
 	print $formconfirm;
@@ -354,20 +356,21 @@ print '<input type="hidden" name="formfilteraction" id="formfilteraction" value=
 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
 
-print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit);
+$button = '<a class="butAction" name="button_export_csv" href="'.$_SERVER["PHP_SELF"].'?action=export_csv'.($param?'&'.$param:'').'">';
+if (count($filter)) $button.= $langs->trans("ExportFilteredList");
+else $button.= $langs->trans("ExportList");
+$button.= '</a>';
+
+$groupby = ' <a href="./listbyaccount.php">' . $langs->trans("GroupByAccountAccounting") . '</a>';
+
+print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $button, $result, $nbtotalofrecords, 'title_accountancy', 0, $groupby, '', $limit);
 
 print '<div class="tabsAction">' . "\n";
 print '<div class="inline-block divButAction"><a class="butAction" href="./card.php?action=create">' . $langs->trans("NewAccountingMvt") . '</a></div>';
-print '<div class="inline-block divButAction"><a class="butAction" name="button_export_csv" href="'.$_SERVER["PHP_SELF"].'?action=export_csv'.($param?'&'.$param:'').'">';
-if (count($filter)) print $langs->trans("ExportFilteredList");
-else print $langs->trans("ExportList");
-print '</a></div>';
 print '<div class="inline-block divButAction"><a class="butActionDelete" name="button_delmvt" href="'.$_SERVER["PHP_SELF"].'?action=delbookkeepingyear'.($param?'&'.$param:'').'">' . $langs->trans("DelBookKeeping") . '</a></div>';
 
 print '</div>';
 
-print ' <a href="./listbyaccount.php">' . $langs->trans("GroupByAccountAccounting") . '</a><br><br>';
-
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
 print_liste_field_titre($langs->trans("TransactionNumShort"), $_SERVER['PHP_SELF'], "t.piece_num", "", $param, "", $sortfield, $sortorder);
@@ -448,7 +451,9 @@ foreach ($object->lines as $line ) {
 }
 
 print '<tr class="liste_total">';
-print '<td colspan="6"></td>';
+if ($num < $limit) print '<td align="left" colspan="6">'.$langs->trans("Total").'</td>';
+else print '<td align="left" colspan="6">'.$langs->trans("Totalforthispage").'</td>';
+print '</td>';
 print '<td  align="right">';
 print price($total_debit);
 print '</td>';

+ 14 - 17
htdocs/accountancy/bookkeeping/listbyaccount.php

@@ -1,7 +1,6 @@
 <?php
 /*
- * Copyright (C) 2016 Neil Orley	<neil.orley@oeris.fr>
- * largely based on the great work of :
+ * Copyright (C) 2016 Neil Orley	<neil.orley@oeris.fr> largely based on the great work of :
  *  - Copyright (C) 2013-2016 Olivier Geffroy		<jeff@jeffinfo.com>
  *  - Copyright (C) 2013-2016 Florian Henry		<florian.henry@open-concept.pro>
  *  - Copyright (C) 2013-2016 Alexandre Spangaro	<aspangaro.dolibarr@gmail.com>
@@ -18,7 +17,6 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
  */
 
 /**
@@ -72,11 +70,8 @@ $pagenext = $page + 1;
 if ($sortorder == "") $sortorder = "ASC";
 if ($sortfield == "") $sortfield = "t.rowid";
 
-if (empty($search_date_start)) {
-	$search_date_start = dol_mktime(0, 0, 0, 1, 1, dol_print_date(dol_now(), '%Y'));
-	$search_date_end = dol_mktime(0, 0, 0, 12, 31, dol_print_date(dol_now(), '%Y'));
-}
-
+if (empty($search_date_start)) $search_date_start = dol_mktime(0, 0, 0, 1, 1, dol_print_date(dol_now(), '%Y'));
+if (empty($search_date_end)) $search_date_end = dol_mktime(0, 0, 0, 12, 31, dol_print_date(dol_now(), '%Y'));
 
 $object = new BookKeeping($db);
 
@@ -126,16 +121,17 @@ if (!GETPOST("button_removefilter_x") && !GETPOST("button_removefilter")) // Bot
   }
 }
 
+
 /*
  * Action
  */
 
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 {
 	$search_doc_date = '';
 	$search_accountancy_code = '';
 	$search_accountancy_code_start = '';
-  $search_label_account = '';
+    $search_label_account = '';
 	$search_mvt_label = '';
 	$search_direction = '';
 	$search_ledger_code = '';
@@ -160,13 +156,13 @@ if ($action == 'delmouvconfirm') {
  * View
  */
 
-$title_page = $langs->trans("Bookkeeping") . ' ' . strtolower($langs->trans("By")) . ' ' . $langs->trans("AccountAccounting") . ' ' . dol_print_date($search_date_start) . '-' . dol_print_date($search_date_end);
+$title_page = $langs->trans("Bookkeeping") . ' ' . strtolower($langs->trans("By")) . ' ' . $langs->trans("AccountAccounting");
 
 llxHeader('', $title_page);
 
 // List
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
 	$nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter);
 	if ($nbtotalofrecords < 0) {
@@ -211,7 +207,9 @@ if ($action == 'delbookkeepingyear') {
 
 print '<form method="GET" id="searchFormList" action="' . $_SERVER["PHP_SELF"] . '">';
 
-print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result, $nbtotalofrecords,'title_accountancy',0,'','',$limit);
+$viewflat = ' <a href="./list.php">' . $langs->trans("ViewFlatList") . '</a>';
+
+print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $options, $sortfield, $sortorder, '', $result, $nbtotalofrecords,'title_accountancy',0,$viewflat,'',$limit);
 
 // Reverse sort order
 if ( preg_match('/^asc/i', $sortorder) )
@@ -223,8 +221,6 @@ print '<div class="tabsAction">' . "\n";
 print '<div class="inline-block divButAction"><a class="butAction" href="./card.php?action=create">' . $langs->trans("NewAccountingMvt") . '</a></div>';
 print '</div>';
 
-print ' <a href="./list.php">' . $langs->trans("ViewFlatList") . '</a><br><br>';
-
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
 print '<td>' . $langs->trans("AccountAccounting") . '</td>';
@@ -335,14 +331,15 @@ foreach ( $object->lines as $line ) {
 }
 
 // Affiche un Sous-Total du dernier compte comptable affiché
-print '<tr class="liste_total"><td align="right" colspan="4">'.$langs->trans("SubTotal").':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td>';
+print '<tr class="liste_total">';
+print '<td align="right" colspan="5">'.$langs->trans("SubTotal").':</td><td class="nowrap" align="right">'.price($sous_total_debit).'</td><td class="nowrap" align="right">'.price($sous_total_credit).'</td>';
 print "<td>&nbsp;</td>\n";
 print '</tr>';
 
 
 // Affiche le Total
 print '<tr class="liste_total">';
-print '<td align="right" colspan="4">'.$langs->trans("Total").':</td>';
+print '<td align="right" colspan="5">'.$langs->trans("Total").':</td>';
 print '<td  align="right">';
 print price($total_debit);
 print '</td>';

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

@@ -158,7 +158,7 @@ if (! empty($search_code_journal)) {
  * Mode List
  */
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
 	$nbtotalofrecords = $object->fetchAll($sortorder, $sortfield, 0, 0);
 	if ($nbtotalofrecords < 0) {

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

@@ -402,7 +402,7 @@ class AccountancyExport
 			print length_accountg($line->numero_compte) . $this->separator;
 			print substr(length_accountg($line->numero_compte),0,2) . $this->separator;
 			print '"'.dol_trunc($line->label_compte,40,'right','UTF-8',1).'"' . $this->separator;
-			print '"'.dol_trunc($line->piece_num,15,'right','UTF-8',1)."'".$this->separator;
+			print '"'.dol_trunc($line->piece_num,15,'right','UTF-8',1).'"'.$this->separator;
 			print price2num($line->montant).$this->separator;
 			print $line->sens.$this->separator;
 			print $date . $this->separator;

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

@@ -60,10 +60,10 @@ class AccountingAccount extends CommonObject
 	/**
 	 * Load record in memory
 	 *
-	 * @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
+	 * @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, Id of record if OK and found
 	 */
 	function fetch($rowid = null, $account_number = null, $limittocurrentchart = 0) {
 		global $conf;

+ 37 - 67
htdocs/accountancy/class/bookkeeping.class.php

@@ -73,7 +73,7 @@ class BookKeeping extends CommonObject
 	public $id;
 	/**
 	 */
-	public $doc_date = '';
+	public $doc_date;
 	public $doc_type;
 	public $doc_ref;
 	public $fk_doc;
@@ -184,25 +184,21 @@ class BookKeeping extends CommonObject
 		$sql .= " WHERE doc_type = '" . $this->doc_type . "'";
 		$sql .= " AND fk_docdet = " . $this->fk_docdet;
 		$sql .= " AND numero_compte = '" . $this->numero_compte . "'";
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		$resql = $this->db->query($sql);
 		
 		if ($resql) {
 			$row = $this->db->fetch_object($resql);
-			if ($row->nb == 0) {
-				
+			if ($row->nb == 0) 
+			{
 				// Determine piece_num
 				$sqlnum = "SELECT piece_num";
 				$sqlnum .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
-				$sqlnum .= " WHERE doc_type = '" . $this->doc_type . "'";
-				$sqlnum .= " AND fk_docdet = '" . $this->fk_docdet . "'";
-				$sqlnum .= " AND doc_ref = '" . $this->doc_ref . "'";
-				if (! empty($conf->multicompany->enabled)) {
-				    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-				}
+				$sqlnum .= " WHERE doc_type = '" . $this->doc_type . "'";		// For example doc_type = 'bank' 
+				$sqlnum .= " AND fk_docdet = '" . $this->fk_docdet . "'";		// fk_docdet is rowid into llx_bank or llx_facturedet or llx_facturefourndet, or ...
+				$sqlnum .= " AND doc_ref = '" . $this->doc_ref . "'";			// ref of source object
+			    $sqlnum .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 				
 				dol_syslog(get_class($this) . ":: create sqlnum=" . $sqlnum, LOG_DEBUG);
 				$resqlnum = $this->db->query($sqlnum);
@@ -214,9 +210,7 @@ class BookKeeping extends CommonObject
 				if (empty($this->piece_num)) {
 					$sqlnum = "SELECT MAX(piece_num)+1 as maxpiecenum";
 					$sqlnum .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
-					if (! empty($conf->multicompany->enabled)) {
-					    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
-					}
+				    $sqlnum .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
 						
 					dol_syslog(get_class($this) . ":: create sqlnum=" . $sqlnum, LOG_DEBUG);
 					$resqlnum = $this->db->query($sqlnum);
@@ -282,13 +276,13 @@ class BookKeeping extends CommonObject
 						$this->id = $id;
 						$result = 0;
 					} else {
-						$result = - 2;
+						$result = -2;
 						$error ++;
 						$this->errors[] = 'Error Create Error ' . $result . ' lecture ID';
 						dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
 					}
 				} else {
-					$result = - 1;
+					$result = -1;
 					$error ++;
 					$this->errors[] = 'Error ' . $this->db->lasterror();
 					dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
@@ -296,11 +290,11 @@ class BookKeeping extends CommonObject
 			} else {     // Already exists
 				$result = -3;
 				$error++;
-				$this->errors[] = 'Error Transaction for ('.$this->doc_type.', '.$this->doc_ref.', '.$this->fk_docdet.') were already recorded';
-				dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_WARNING);
+				$this->error='BookkeepingRecordAlreadyExists';
+				dol_syslog(__METHOD__ . ' ' . $this->error, LOG_WARNING);
 			}
 		} else {
-			$result = - 5;
+			$result = -5;
 			$error ++;
 			$this->errors[] = 'Error ' . $this->db->lasterror();
 			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
@@ -322,11 +316,9 @@ class BookKeeping extends CommonObject
 		// Commit or rollback
 		if ($error) {
 			$this->db->rollback();
-			
-			return - 1 * $error;
+			return -1 * $error;
 		} else {
 			$this->db->commit();
-			
 			return $result;
 		}
 	}
@@ -503,9 +495,7 @@ class BookKeeping extends CommonObject
 		$sql .= " t.piece_num";
 		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
 		$sql .= ' WHERE 1 = 1';
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		if (null !== $ref) {
 			$sql .= ' AND t.ref = ' . '\'' . $ref . '\'';
 		} else {
@@ -608,10 +598,9 @@ class BookKeeping extends CommonObject
 				}
 			}
 		}
-		$sql.= ' WHERE 1 = 1';
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
+		$sql .= ' WHERE 1 = 1';
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		if (count($sqlwhere) > 0) {
 			$sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere);
 		}
@@ -721,9 +710,7 @@ class BookKeeping extends CommonObject
 			}
 		}
 		$sql.= ' WHERE 1 = 1';
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		if (count($sqlwhere) > 0) {
 			$sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere);
 		}
@@ -817,9 +804,7 @@ class BookKeeping extends CommonObject
 			}
 		}
 		$sql.= ' WHERE 1 = 1';
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		if (count($sqlwhere) > 0) {
 			$sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere);
 		}
@@ -1073,9 +1058,7 @@ class BookKeeping extends CommonObject
 		$sql.= " WHERE 1 = 1";
 		if (! empty($delyear)) $sql.= " AND YEAR(doc_date) = " . $delyear;         // FIXME Must use between
 		if (! empty($journal)) $sql.= " AND code_journal = '".$journal."'";
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		$resql = $this->db->query($sql);
 		
 		if (! $resql) {
@@ -1107,9 +1090,7 @@ class BookKeeping extends CommonObject
 		$sql = "DELETE";
 		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
 		$sql .= " WHERE piece_num = " . $piecenum;
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		$resql = $this->db->query($sql);
 		
@@ -1180,9 +1161,12 @@ class BookKeeping extends CommonObject
 	 * @return void
 	 */
 	public function initAsSpecimen() {
-		$this->id = 0;
+		global $user;
+		
+		$now=dol_now();
 		
-		$this->doc_date = '';
+		$this->id = 0;
+		$this->doc_date = $now;
 		$this->doc_type = '';
 		$this->doc_ref = '';
 		$this->fk_doc = '';
@@ -1190,11 +1174,11 @@ class BookKeeping extends CommonObject
 		$this->code_tiers = '';
 		$this->numero_compte = '';
 		$this->label_compte = '';
-		$this->debit = '';
+		$this->debit = 99.9;
 		$this->credit = '';
 		$this->montant = '';
 		$this->sens = '';
-		$this->fk_user_author = '';
+		$this->fk_user_author = $user->id;
 		$this->import_key = '';
 		$this->code_journal = '';
 		$this->piece_num = '';
@@ -1212,9 +1196,7 @@ class BookKeeping extends CommonObject
 	    $sql = "SELECT piece_num,doc_date,code_journal,doc_ref,doc_type";
 		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
 		$sql .= " WHERE piece_num = " . $piecenum;
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG);
 		$result = $this->db->query($sql);
@@ -1245,9 +1227,7 @@ class BookKeeping extends CommonObject
 	    global $conf;
 	    
 		$sql = "SELECT MAX(piece_num)+1 as max FROM " . MAIN_DB_PREFIX . $this->table_element;
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		dol_syslog(get_class($this) . "getNextNumMvt sql=" . $sql, LOG_DEBUG);
 		$result = $this->db->query($sql);
@@ -1279,9 +1259,7 @@ class BookKeeping extends CommonObject
 		$sql .= " montant, sens, fk_user_author, import_key, code_journal, piece_num";
 		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
 		$sql .= " WHERE piece_num = " . $piecenum;
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG);
 		$result = $this->db->query($sql);
@@ -1333,9 +1311,7 @@ class BookKeeping extends CommonObject
 		$sql .= " numero_compte, label_compte, debit, credit,";
 		$sql .= " montant, sens, fk_user_author, import_key, code_journal, piece_num";
 		$sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		dol_syslog(get_class($this) . "::export_bookkeping", LOG_DEBUG);
 		
@@ -1404,9 +1380,7 @@ class BookKeeping extends CommonObject
         $sql .= " AND aa.active = 1";
         $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
         $sql .= " AND asy.rowid = " . $pcgver;
-    	if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " AND ab.entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " AND ab.entity IN (" . getEntity("accountancy", 1) . ")";
         $sql .= " ORDER BY account_number ASC";
         
         dol_syslog(get_class($this) . "::select_account", LOG_DEBUG);
@@ -1472,9 +1446,7 @@ class BookKeeping extends CommonObject
         $sql .= " WHERE aa.account_number = '" . $account . "'";  
         $sql .= " AND parent.active = 1";
         $sql .= " AND root.active = 1";
-        if (! empty($conf->multicompany->enabled)) {
-            $sql .= " AND aa.entity IN (" . getEntity("accountancy", 1) . ")";
-        }
+        $sql .= " AND aa.entity IN (" . getEntity("accountancy", 1) . ")";
         
 		dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG);
 		$resql = $this->db->query($sql);
@@ -1513,9 +1485,7 @@ class BookKeeping extends CommonObject
 		$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";
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE aa.entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " WHERE aa.entity IN (" . getEntity("accountancy", 1) . ")";
 		
 		dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG);
 		$resql = $this->db->query($sql);

+ 75 - 67
htdocs/accountancy/class/html.formventilation.class.php

@@ -30,6 +30,10 @@
  */
 class FormVentilation extends Form
 {
+
+    private $options_cache = array();
+
+
 	/**
 	 * Return select filter with date of transaction
 	 *
@@ -41,9 +45,7 @@ class FormVentilation extends Form
 		$options = array();
 
 		$sql = 'SELECT DISTINCT import_key from ' . MAIN_DB_PREFIX . 'accounting_bookkeeping';
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
 		$sql .= ' ORDER BY import_key DESC';
 
 		dol_syslog(get_class($this) . "::select_bookkeeping_importkey", LOG_DEBUG);
@@ -69,67 +71,81 @@ class FormVentilation extends Form
 	 * @param string   $htmlname           Name of field in html form
 	 * @param int      $showempty          Add an empty field
 	 * @param array    $event              Event options
-	 * @param int      $select_in          selectid value is a aa.rowid (0 default) or aa.account_number (1)
-	 * @param int      $select_out         set value returned by select 0=rowid (default), 1=account_number
+	 * @param int      $select_in          0=selectid value is a aa.rowid (default) or 1=selectid is aa.account_number
+	 * @param int      $select_out         Set value returned by select. 0=rowid (default), 1=account_number
 	 * @param string   $morecss            More css non HTML object
-	 * @return string String with HTML select
+	 * @param string   $usecache           Key to use to store result into a cache. Next call with same key will reuse the cache.
+	 * @return string                      String with HTML select
 	 */
-	function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $morecss='maxwidth300 maxwidthonsmartphone') {
+	function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $morecss='maxwidth300 maxwidthonsmartphone', $usecache='')
+	{
 		global $conf;
 
 		require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
 
-		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT') ? $conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT : 50;
-
-		$sql = "SELECT DISTINCT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version";
-		$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 asy.rowid = " . $conf->global->CHARTOFACCOUNTS;
-		$sql .= " AND aa.active = 1";
-		$sql .= " ORDER BY aa.account_number";
-
-		dol_syslog(get_class($this) . "::select_account", LOG_DEBUG);
-		$resql = $this->db->query($sql);
-
-		if (!$resql) {
-			$this->error = "Error " . $this->db->lasterror();
-			dol_syslog(get_class($this) . "::select_account " . $this->error, LOG_ERR);
-			return -1;
+    	$options = array();
+		if ($usecache && ! empty($this->options_cache[$usecache]))
+		{
+		    $options = $this->options_cache[$usecache];
+		    $selected=$selectid;
 		}
-
-		$out = ajax_combobox($htmlname, $event);
-
-		// TODO Add $options in cache so next call will not execute the request
-		$selected = 0;
-		$options = array();
-		while ($obj = $this->db->fetch_object($resql)) 
+		else
 		{
-			$label = length_accountg($obj->account_number) . ' - ' . $obj->label;
-			$label = dol_trunc($label, $trunclength);
-
-			$select_value_in = $obj->rowid;
-			$select_value_out = $obj->rowid;
-
-			// Try to guess if we have found default value
-			if ($select_in == 1) {
-				$select_value_in = $obj->account_number;
-			}
-			if ($select_out == 1) {
-				$select_value_out = $obj->account_number;
-			}
-			// Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number
-			// Because same account_number can be share between different accounting_system and do have the same meaning
-			if ($selectid != '' && $selectid == $select_value_in) {
-			    //var_dump("Found ".$selectid." ".$select_value_in);
-				$selected = $select_value_out;
-			}
-
-			$options[$select_value_out] = $label;
+    		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT') ? $conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT : 50;
+
+    		$sql = "SELECT DISTINCT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version";
+    		$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 asy.rowid = " . $conf->global->CHARTOFACCOUNTS;
+    		$sql .= " AND aa.active = 1";
+    		$sql .= " ORDER BY aa.account_number";
+
+    		dol_syslog(get_class($this) . "::select_account", LOG_DEBUG);
+    		$resql = $this->db->query($sql);
+
+    		if (!$resql) {
+    			$this->error = "Error " . $this->db->lasterror();
+    			dol_syslog(get_class($this) . "::select_account " . $this->error, LOG_ERR);
+    			return -1;
+    		}
+
+    		$out = ajax_combobox($htmlname, $event);
+
+    		$selected = 0;
+    		while ($obj = $this->db->fetch_object($resql))
+    		{
+    			$label = length_accountg($obj->account_number) . ' - ' . $obj->label;
+    			$label = dol_trunc($label, $trunclength);
+
+    			$select_value_in = $obj->rowid;
+    			$select_value_out = $obj->rowid;
+
+    			// Try to guess if we have found default value
+    			if ($select_in == 1) {
+    				$select_value_in = $obj->account_number;
+    			}
+    			if ($select_out == 1) {
+    				$select_value_out = $obj->account_number;
+    			}
+    			// Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number
+    			// Because same account_number can be share between different accounting_system and do have the same meaning
+    			if ($selectid != '' && $selectid == $select_value_in) {
+    			    //var_dump("Found ".$selectid." ".$select_value_in);
+    				$selected = $select_value_out;
+    			}
+
+    			$options[$select_value_out] = $label;
+    		}
+    		$this->db->free($resql);
+
+    		if ($usecache)
+    		{
+                $this->options_cache[$usecache] = $options;
+    		}
 		}
 
 		$out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1);
-		$this->db->free($resql);
-		
+
 		return $out;
 	}
 
@@ -232,9 +248,7 @@ class FormVentilation extends Form
 		// Auxiliary customer account
 		$sql = "SELECT DISTINCT code_compta, nom ";
 		$sql .= " FROM ".MAIN_DB_PREFIX."societe";
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")";
-		}
+	    $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")";
 		$sql .= " ORDER BY code_compta";
 		dol_syslog(get_class($this)."::select_auxaccount", LOG_DEBUG);
 		$resql = $this->db->query($sql);
@@ -254,9 +268,7 @@ class FormVentilation extends Form
 		// Auxiliary supplier account
 		$sql = "SELECT DISTINCT code_compta_fournisseur, nom ";
 		$sql .= " FROM ".MAIN_DB_PREFIX."societe";
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")";
-		}
+	    $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")";
 		$sql .= " ORDER BY code_compta_fournisseur";
 		dol_syslog(get_class($this)."::select_auxaccount", LOG_DEBUG);
 		$resql = $this->db->query($sql);
@@ -292,14 +304,12 @@ class FormVentilation extends Form
 	function selectyear_accountancy_bookkepping($selected = '', $htmlname = 'yearid', $useempty = 0, $output_format = 'html')
 	{
 	    global $conf;
-	    
+
 		$out_array = array();
 
 		$sql = "SELECT DISTINCT date_format(doc_date,'%Y') as dtyear";
 		$sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
 		$sql .= " ORDER BY date_format(doc_date,'%Y')";
 		dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG);
 		$resql = $this->db->query($sql);
@@ -333,14 +343,12 @@ class FormVentilation extends Form
 	function selectjournal_accountancy_bookkepping($selected = '', $htmlname = 'journalid', $useempty = 0, $output_format = 'html')
 	{
 	    global $conf,$langs;
-	    
+
 		$out_array = array();
 
 		$sql = "SELECT DISTINCT code_journal";
 		$sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping";
-		if (! empty($conf->multicompany->enabled)) {
-		    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
-		}
+	    $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")";
 		$sql .= " ORDER BY code_journal";
 		dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG);
 		$resql = $this->db->query($sql);

+ 83 - 12
htdocs/accountancy/customer/index.php

@@ -80,7 +80,7 @@ if ($action == 'validatehistory') {
 	$sqlclean .= '	ON accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=' . $conf->global->CHARTOFACCOUNTS . ')';
 	$resql = $db->query($sqlclean);
 
-	// Now make the binding
+	// Now make the binding. Bind automatically only for product with a dedicated account that exists into chart of account, others need a manual bind
 	if ($db->type == 'pgsql') {
 		$sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet";
 		$sql1 .= " SET fk_code_ventilation = accnt.rowid";
@@ -136,11 +136,13 @@ if ($action == 'validatehistory') {
 	
 	// Now clean
 	$sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet as fd";
-	$sql1 .= " SET fd.fk_code_ventilation = 0";
-	$sql1 .= " WHERE fd.fk_facture IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture as f";
-	$sql1 .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'";
-	$sql1 .= " AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "')";
-
+	$sql1.= " SET fd.fk_code_ventilation = 0";
+	$sql1.= " WHERE fd.fk_facture IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture as f";
+	$sql1.= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'";
+	$sql1.= " AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "'";
+	$sql1.= " AND f.entity IN (" . getEntity("accountancy", 1) . ")";
+	$sql1.=")";
+	
 	dol_syslog("htdocs/accountancy/customer/index.php fixaccountancycode", LOG_DEBUG);
 
 	$resql1 = $db->query($sql1);
@@ -169,12 +171,10 @@ print load_fiche_titre($langs->trans("CustomersVentilation") . " " . $textprevye
 print $langs->trans("DescVentilCustomer") . '<br>';
 print $langs->trans("DescVentilMore", $langs->transnoentitiesnoconv("ValidateHistory"), $langs->transnoentitiesnoconv("ToBind")) . '<br>';
 print '<br>';
-print '<div class="inline-block divButAction">';
-print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=validatehistory">' . $langs->trans("ValidateHistory") . '</a>';
-print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=cleanaccountancycode">' . $langs->trans("CleanHistory", $year_current) . '</a>';
+//print '<div class="inline-block divButAction">';
 // TODO Remove this. Should be done into the repair.php script
-if ($conf->global->MAIN_FEATURES_LEVEL > 0) print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=fixaccountancycode">' . $langs->trans("CleanFixHistory", $year_current) . '</a>';
-print '</div>';
+if ($conf->global->MAIN_FEATURES_LEVEL > 1) print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=fixaccountancycode">' . $langs->trans("CleanFixHistory", $year_current) . '</a>';
+//print '</div>';
 
 $sql = "SELECT count(*) FROM " . MAIN_DB_PREFIX . "facturedet as fd";
 $sql .= " , " . MAIN_DB_PREFIX . "facture as f";
@@ -191,8 +191,16 @@ if ($result) {
 
 $y = $year_current;
 
+$buttonbind = '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=validatehistory">' . $langs->trans("ValidateHistory") . '</a>';
+$buttonreset = '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=cleanaccountancycode">' . $langs->trans("CleanHistory", $year_current) . '</a>';
+
+
+
+
 $var = true;
 
+print_fiche_titre($langs->trans("OverviewOfAmountOfLinesNotBound"), $buttonbind, '');
+
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre"><td width="200">' . $langs->trans("Account") . '</td>';
 print '<td width="200" align="left">' . $langs->trans("Label") . '</td>';
@@ -213,7 +221,7 @@ $sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid
 $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
 $sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
 $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";   // We don't share object for accountancy
-
+$sql .= " AND aa.account_number IS NULL";
 $sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label";
 
 dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG);
@@ -239,6 +247,69 @@ if ($resql) {
 }
 print "</table>\n";
 
+
+print '<br>';
+
+
+print_fiche_titre($langs->trans("OverviewOfAmountOfLinesBound"), $buttonreset, '');
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre"><td width="200">' . $langs->trans("Account") . '</td>';
+print '<td width="200" align="left">' . $langs->trans("Label") . '</td>';
+for($i = 1; $i <= 12; $i ++) {
+    print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+}
+print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
+
+$sql = "SELECT " . $db->ifsql('aa.account_number IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.account_number') . " AS codecomptable,";
+$sql .= "  " . $db->ifsql('aa.label IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.label') . " AS intitule,";
+for($i = 1; $i <= 12; $i ++) {
+    $sql .= "  SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, 'fd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+}
+$sql .= "  SUM(fd.total_ht) as total";
+$sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd";
+$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture";
+$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid = fd.fk_code_ventilation";
+$sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
+$sql .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
+$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";   // We don't share object for accountancy
+$sql .= " AND aa.account_number IS NOT NULL";
+$sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label";
+
+dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG);
+$resql = $db->query($sql);
+if ($resql) {
+    $num = $db->num_rows($resql);
+
+    while ( $row = $db->fetch_row($resql)) {
+
+        $var = ! $var;
+        print '<tr ' . $bc[$var] . '><td>' . length_accountg($row[0]) . '</td>';
+        print '<td align="left">' . $row[1] . '</td>';
+        for($i = 2; $i <= 12; $i ++) {
+            print '<td align="right">' . price($row[$i]) . '</td>';
+        }
+        print '<td align="right">' . price($row[13]) . '</td>';
+        print '<td align="right"><b>' . price($row[14]) . '</b></td>';
+        print '</tr>';
+    }
+    $db->free($resql);
+} else {
+    print $db->lasterror(); // Show last sql error
+}
+print "</table>\n";
+
+
+
+
+
+print '<br>';
+print '<br>';
+
+
+print_fiche_titre($langs->trans("OtherInfo"), '', '');
+
+
 print "<br>\n";
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("TotalVente") . '</td>';

+ 53 - 38
htdocs/accountancy/customer/lines.php

@@ -38,6 +38,7 @@ $langs->load("bills");
 $langs->load("compta");
 $langs->load("main");
 $langs->load("accountancy");
+$langs->load("productbatch");
 
 $account_parent = GETPOST('account_parent');
 $changeaccount = GETPOST('changeaccount');
@@ -122,6 +123,7 @@ if (is_array($changeaccount) && count($changeaccount) > 0) {
 	$account_parent = '';   // Protection to avoid to mass apply it a second time
 }
 
+
 /*
  * View
  */
@@ -148,7 +150,7 @@ print '<script type="text/javascript">
 /*
  * Customer Invoice lines
  */
-$sql = "SELECT f.rowid, f.facnumber, f.type, f.datef as df, f.ref_client,";
+$sql = "SELECT f.rowid, f.facnumber, f.type, f.datef, f.ref_client,";
 $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.tva_tx, fd.total_ttc,";
 $sql .= " s.rowid as socid, s.nom as name, s.code_compta, s.code_client,";
 $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.accountancy_code_sell, aa.rowid as fk_compte, aa.account_number, aa.label as label_compte,";
@@ -198,7 +200,7 @@ $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";    // We don't sha
 $sql .= $db->order($sortfield, $sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -251,17 +253,19 @@ if ($result) {
 
 	$moreforfilter = '';
 	
+    print '<div class="div-table-responsive">';
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "fd.rowid", "", $param, 'align="right"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "fd.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Invoice"), $_SERVER["PHP_SELF"], "f.facnumber", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Label"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Date"), $_SERVER["PHP_SELF"], "f.datef, f.facnumber, fd.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("ProductRef"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
+	//print_liste_field_titre($langs->trans("ProductLabel"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Description"), $_SERVER["PHP_SELF"], "fd.description", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Amount"), $_SERVER["PHP_SELF"], "fd.total_ht", "", $param, 'align="right"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("VATRate"), $_SERVER["PHP_SELF"], "fd.tva_tx", "", $param, 'align="center"', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Account"), $_SERVER["PHP_SELF"], "aa.account_number", "", $param, 'align="center"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Account"), $_SERVER["PHP_SELF"], "aa.account_number", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Country"), $_SERVER["PHP_SELF"], "co.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("VATIntra"), $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre('', '', '', '', '', 'align="center"');
@@ -269,15 +273,16 @@ if ($result) {
 
 	print '<tr class="liste_titre">';
 	print '<td class="liste_titre"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" name="search_invoice" size="6" value="' . $search_invoice . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_ref" value="' . $search_ref . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_label" value="' . $search_label . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_desc" value="' . $search_desc . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="6" name="search_amount" value="' . $search_amount . '"></td>';
-	print '<td class="liste_titre" align="center"><input type="text" class="flat" size="3" name="search_vat" value="' . $search_vat . '"></td>';
-	print '<td class="liste_titre" align="center"><input type="text" class="flat" size="6" name="search_account" value="' . $search_account . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" name="search_country" size="5" value="' . $search_country . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" name="search_tavintra" size="5" value="' . $search_tavintra . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
+	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
+	//print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_label" value="' . dol_escape_htmltag($search_label) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_desc" value="' . dol_escape_htmltag($search_desc) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_amount" value="' . dol_escape_htmltag($search_amount) . '"></td>';
+	print '<td class="liste_titre" align="center"><input type="text" class="flat maxwidth50" name="search_vat" size="1" value="' . dol_escape_htmltag($search_vat) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_account" value="' . dol_escape_htmltag($search_account) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_country" value="' . dol_escape_htmltag($search_country) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_tavintra" value="' . dol_escape_htmltag($search_tavintra) . '"></td>';
 	print '<td class="liste_titre" align="right">';
 	$searchpitco=$form->showFilterAndCheckAddButtons(1);
 	print $searchpitco;
@@ -291,34 +296,43 @@ if ($result) {
 		$var = ! $var;
 		$codecompta = length_accountg($objp->account_number) . ' - ' . $objp->label_compte;
 
+		$facture_static->ref = $objp->facnumber;
+		$facture_static->id = $objp->rowid;
+		
+		$product_static->ref = $objp->product_ref;
+		$product_static->id = $objp->product_id;
+		$product_static->type = $objp->product_type;
+		$product_static->label = $objp->product_label;
+		
 		print '<tr '. $bc[$var].'>';
 
-		print '<td align="right">' . $objp->rowid . '</td>';
+		print '<td>' . $objp->rowid . '</td>';
 		
 		// Ref Invoice
-		$facture_static->ref = $objp->facnumber;
-		$facture_static->id = $objp->rowid;
 		print '<td>' . $facture_static->getNomUrl(1) . '</td>';
 
+		print '<td align="center">' . dol_print_date($db->jdate($objp->datef), 'day') . '</td>';
+		
 		// Ref Product
-		$product_static->ref = $objp->product_ref;
-		$product_static->id = $objp->product_id;
-		$product_static->type = $objp->product_type;
-		$product_static->label = $objp->product_label;
 		print '<td>';
 		if ($product_static->id)
 			print $product_static->getNomUrl(1);
-		else
-			print '&nbsp;';
+		if ($objp->product_label) print '<br>'.$objp->product_label;
 		print '</td>';
-
-		print '<td>' . dol_trunc($objp->product_label, 24) . '</td>';
-		print '<td>' . nl2br(dol_trunc($objp->description, 32)) . '</td>';
+		
+		print '<td>';
+		$text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->description));
+		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION') ? ACCOUNTING_LENGTH_DESCRIPTION : 32;
+		print $form->textwithtooltip(dol_trunc($text,$trunclength), $objp->description);
+		print '</td>';
+		
 		print '<td align="right">' . price($objp->total_ht) . '</td>';
 		print '<td align="center">' . price($objp->tva_tx) . '</td>';
-		print '<td>' . $codecompta . '<a href="./card.php?id=' . $objp->fdid . '">';
+		print '<td>';
+		print $codecompta . ' <a href="./card.php?id=' . $objp->fdid . '">';
 		print img_edit();
-		print '</a></td>';
+		print '</a>';
+		print '</td>';
 		print '<td>' . $objp->country .'</td>';
 		print '<td>' . $objp->tva_intra . '</td>';
 		print '<td align="right"><input type="checkbox" class="checkforaction" name="changeaccount[]" value="' . $objp->fdid . '"/></td>';
@@ -326,18 +340,19 @@ if ($result) {
 		print "</tr>";
 		$i ++;
 	}
+	
+	print "</table>";
+	print "</div>";
+	
+    if ($nbtotalofrecords > $limit) {
+        print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, '', 0, '', '', $limit, 1);
+    }
+    
+    print '</form>';
 } else {
-	print $db->error();
+	print $db->lasterror();
 }
 
-print "</table>";
-
-if ($nbtotalofrecords > $limit) {
-    print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, '', 0, '', '', $limit, 1);
-}
-
-print '</form>';
-
 
 llxFooter();
 $db->close();

+ 83 - 46
htdocs/accountancy/customer/list.php

@@ -40,11 +40,16 @@ $langs->load("bills");
 $langs->load("other");
 $langs->load("main");
 $langs->load("accountancy");
+$langs->load("productbatch");
 
-$action = GETPOST('action');
+$action=GETPOST('action','alpha');
+$massaction=GETPOST('massaction','alpha');
+$show_files=GETPOST('show_files','int');
+$confirm=GETPOST('confirm','alpha');
+$toselect = GETPOST('toselect', 'array');
 
 // Select Box
-$mesCasesCochees = GETPOST('mesCasesCochees', 'array');
+$mesCasesCochees = GETPOST('toselect', 'array');
 
 // Search Getpost
 $search_invoice = GETPOST('search_invoice', 'alpha');
@@ -89,6 +94,9 @@ $aarowid_p = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOU
  * Action
  */
 
+if (GETPOST('cancel')) { $action='list'; $massaction=''; }
+if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; }
+
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 {
@@ -101,11 +109,19 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
 	$search_vat = '';
 }
 
-if ($action == 'ventil' && ! empty($btn_ventil)) {
+// Mass actions
+$objectclass='Skeleton';
+$objectlabel='Skeleton';
+$permtoread = $user->rights->accounting->read;
+$permtodelete = $user->rights->accounting->delete;
+$uploaddir = $conf->accounting->dir_output;
+include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
+
+if ($massaction == 'ventil') {
     $msg='';
     //print '<div><font color="red">' . $langs->trans("Processing") . '...</font></div>';
     if (! empty($mesCasesCochees)) {
-        $msg = '<div>' . $langs->trans("SelectedLines") . ': '.count($_POST["mesCasesCochees"]).'</div>';
+        $msg = '<div>' . $langs->trans("SelectedLines") . ': '.count($mesCasesCochees).'</div>';
         $msg.='<div class="detail">';
         $cpt = 0;
         $ok=0;
@@ -143,10 +159,10 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
             $cpt++;
         }
         $msg.='</div>';
-    } else {
-        setEventMessages($langs->trans("NoRecordSelected"), null, 'warnings');
+        $msg.= '<div>' . $langs->trans("EndProcessing") . '</div>';
+    //} else {
+    //    setEventMessages($langs->trans("NoRecordSelected"), null, 'warnings');
     }
-    $msg.= '<div>' . $langs->trans("EndProcessing") . '</div>';
 }
 
 
@@ -155,6 +171,8 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
  * View
  */
 
+$form = new Form($db);
+
 llxHeader('', $langs->trans("Ventilation"));
 
 // Customer Invoice lines
@@ -172,32 +190,32 @@ $sql .= " AND product_type <= 2";
 $sql .= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_sell IS NULL OR p.accountancy_code_sell ='')";
 // Add search filter like
 if (strlen(trim($search_invoice))) {
-	$sql .= " AND (f.facnumber like '%" . $search_invoice . "%')";
+    $sql .= natural_search("f.facnumber",$search_invoice);
 }
 if (strlen(trim($search_ref))) {
-	$sql .= " AND (p.ref like '%" . $search_ref . "%')";
+    $sql .= natural_search("p.ref",$search_ref);
 }
 if (strlen(trim($search_label))) {
-	$sql .= " AND (p.label like '%" . $search_label . "%')";
+    $sql .= natural_search("p.label",$search_label);
 }
 if (strlen(trim($search_desc))) {
-	$sql .= " AND (l.description like '%" . $search_desc . "%')";
+    $sql .= natural_search("l.description",$search_desc);
 }
 if (strlen(trim($search_amount))) {
-	$sql .= " AND l.total_ht like '" . $search_amount . "%'";
+    $sql .= natural_search("l.total_ht",$search_amount,1);
 }
 if (strlen(trim($search_account))) {
-	$sql .= " AND aa.account_number like '%" . $search_account . "%'";
+    $sql .= natural_search("aa.account_number",$search_account);
 }
 if (strlen(trim($search_vat))) {
-	$sql .= " AND (l.tva_tx like '" . $search_vat . "%')";
+    $sql .= natural_search("l.tva_tx",$search_vat,1);
 }
 $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")";    // We don't share object for accountancy
 
 $sql .= $db->order($sortfield, $sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -218,6 +236,16 @@ if ($result) {
 	if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage;
 	if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit;
 
+	$arrayofmassactions =  array(
+	    'ventil'=>$langs->trans("Ventilate")
+	    //'presend'=>$langs->trans("SendByMail"),
+	    //'builddoc'=>$langs->trans("PDFMerge"),
+	);
+	//if ($user->rights->mymodule->supprimer) $arrayofmassactions['delete']=$langs->trans("Delete");
+	//if ($massaction == 'presend') $arrayofmassactions=array();
+	$massactionbutton=$form->selectMassAction('ventil', $arrayofmassactions, 1);
+	
+	
 	print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">' . "\n";
 	print '<input type="hidden" name="action" value="ventil">';
 	if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
@@ -226,9 +254,9 @@ if ($result) {
 	print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 	print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
 	
-	$center='<div align="center"><input type="submit" class="butAction" value="' . $langs->trans("Ventilate") . '" name="ventil"></div>';
+	//$center='<div align="center"><input type="submit" class="butAction" value="' . $langs->trans("Ventilate") . '" name="ventil"></div>';
 	
-	print_barre_liste($langs->trans("InvoiceLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $center, $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit);
+	print_barre_liste($langs->trans("InvoiceLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit);
 
 	print $langs->trans("DescVentilTodoCustomer") . '</br><br>';
 
@@ -236,33 +264,36 @@ if ($result) {
 	
 	$moreforfilter = '';
 	
+    print '<div class="div-table-responsive">';
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "l.rowid", "", $param, 'align="right"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "l.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Invoice"), $_SERVER["PHP_SELF"], "f.facnumber", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Label"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Date"), $_SERVER["PHP_SELF"], "f.datef, f.facnumber, l.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("ProductRef"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
+	//print_liste_field_titre($langs->trans("ProductLabel"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Description"), $_SERVER["PHP_SELF"], "l.description", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Amount"), $_SERVER["PHP_SELF"], "l.total_ht", "", $param, 'align="right"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("VATRate"), $_SERVER["PHP_SELF"], "l.tva_tx", "", $param, 'align="right"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("AccountAccountingSuggest"), '', '', '', '', 'align="center"');
 	print_liste_field_titre($langs->trans("IntoAccount"), '', '', '', '', 'align="center"');
 	print_liste_field_titre('', '', '', '', '', 'align="center"');
-	print '</tr>';
+	print "</tr>\n";
 
 	// We add search filter
 	print '<tr class="liste_titre">';
 	print '<td class="liste_titre"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_invoice" value="' . $search_invoice . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_ref" value="' . $search_ref . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_label" value="' . $search_label . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_desc" value="' . $search_desc . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="6" name="search_amount" value="' . $search_amount . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="3" name="search_vat" value="' . $search_vat . '">%</td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
+	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
+	//print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_label" value="' . dol_escape_htmltag($search_label) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidthonsmartphone" name="search_desc" value="' . dol_escape_htmltag($search_desc) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_amount" value="' . dol_escape_htmltag($search_amount) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_vat" size="1" value="' . dol_escape_htmltag($search_vat) . '">%</td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td align="right" class="liste_titre">';
-	$searchpitco=$form->showFilterAndCheckAddButtons(1);
+	$searchpitco=$form->showFilterAndCheckAddButtons($massactionbutton?1:0, 'checkforselect', 1);
 	print $searchpitco;
 	print '</td>';
 	print '</tr>';
@@ -280,6 +311,15 @@ if ($result) {
 		$objp->code_sell_p = '';
 		$objp->aarowid_suggest = '';
 
+		$product_static->ref = $objp->product_ref;
+		$product_static->id = $objp->product_id;
+		$product_static->type = $objp->type;
+		$product_static->label = $objp->product_label;
+
+		$facture_static->ref = $objp->facnumber;
+		$facture_static->id = $objp->facid;
+		$facture_static->type = $objp->ftype;
+		
 		$code_sell_p_notset = '';
 		$objp->aarowid_suggest = $objp->aarowid;
 
@@ -309,30 +349,25 @@ if ($result) {
 		print '<tr '. $bc[$var].'>';
 
 		// Line id
-		print '<td align="center">' . $objp->rowid . '</td>';
+		print '<td>' . $objp->rowid . '</td>';
 		
 		// Ref Invoice
-		$facture_static->ref = $objp->facnumber;
-		$facture_static->id = $objp->facid;
-		$facture_static->type = $objp->ftype;
 		print '<td>' . $facture_static->getNomUrl(1) . '</td>';
 
+		print '<td align="center">' . dol_print_date($db->jdate($objp->datef), 'day') . '</td>';
+		
 		// Ref Product
-		$product_static->ref = $objp->product_ref;
-		$product_static->id = $objp->product_id;
-		$product_static->type = $objp->type;
 		print '<td>';
-
 		if ($product_static->id)
 			print $product_static->getNomUrl(1);
-		else
-			print '&nbsp;';
-
+		if ($objp->product_label) print '<br>'.$objp->product_label;
 		print '</td>';
-
-		print '<td>' . dol_trunc($objp->product_label, 24) . '</td>';
+		
+		print '<td class="tdoverflowonsmartphone">';
+		$text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->description));
 		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION') ? ACCOUNTING_LENGTH_DESCRIPTION : 32;
-		print '<td>' . nl2br(dol_trunc($objp->description, $trunclength)) . '</td>';
+		print $form->textwithtooltip(dol_trunc($text,$trunclength), $objp->description);
+		print '</td>';
 		
 		print '<td align="right">';
 		print price($objp->total_ht);
@@ -345,7 +380,7 @@ if ($result) {
 		print price($objp->tva_tx_line);
 		print '</td>';
 		
-		// Suggested accounting account
+		// Current account
 		print '<td align="center" style="' . $code_sell_p_notset . '">';
 	    print (($objp->type_l == 1)?$langs->trans("DefaultForService"):$langs->trans("DefaultForProduct")) . ' = ' . ($objp->code_sell_l > 0 ? length_accountg($objp->code_sell_l) : $langs->trans("Unknown"));
 		if ($objp->product_id > 0)
@@ -355,18 +390,20 @@ if ($result) {
 		}
 		print '</td>';
 
+		// Suggested accounting account
 		print '<td align="center">';
-		print $formventilation->select_account($objp->aarowid_suggest, 'codeventil'.$objp->rowid, 1);
+		print $formventilation->select_account($objp->aarowid_suggest, 'codeventil'.$objp->rowid, 1, array(), 0, 0, 'maxwidth300 maxwidthonsmartphone', 'cachewithshowemptyone');
 		print '</td>';
 		
 		print '<td align="right">';
-		print '<input type="checkbox" class="checkforaction" name="mesCasesCochees[]" value="' . $objp->rowid . "_" . $i . '"' . ($objp->aarowid ? "checked" : "") . '/>';
+		print '<input type="checkbox" class="flat checkforselect" name="toselect[]"  value="' . $objp->rowid . "_" . $i . '"' . ($objp->aarowid ? "checked" : "") . '/>';
 		print '</td>';
 		print '</tr>';
 		$i ++;
 	}
-
 	print '</table>';
+	print "</div>";
+	
 	print '</form>';
 } else {
 	print $db->error();

+ 102 - 26
htdocs/accountancy/expensereport/index.php

@@ -130,11 +130,13 @@ if ($action == 'validatehistory') {
 	$db->begin();
 
 	$sql1 = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det as fd";
-	$sql1 .= " SET fd.fk_code_ventilation = 0";
-	$sql1 .= " WHERE fd.fk_facture_fourn IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
-	$sql1 .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'";
-	$sql1 .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "')";
-
+	$sql1.= " SET fd.fk_code_ventilation = 0";
+	$sql1.= " WHERE fd.fk_facture_fourn IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
+	$sql1.= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'";
+	$sql1.= " AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "'";
+	$sql1.= " AND f.entity IN (" . getEntity("accountancy", 1) . ")";
+	$sql1.=")";
+	
 	dol_syslog("htdocs/accountancy/customer/index.php fixaccountancycode", LOG_DEBUG);
 
 	$resql1 = $db->query($sql1);
@@ -163,29 +165,39 @@ print $langs->trans("DescVentilExpenseReport") . '<br>';
 print $langs->trans("DescVentilExpenseReportMore", $langs->transnoentitiesnoconv("ValidateHistory"), $langs->transnoentitiesnoconv("ToBind")) . '<br>';
 print '<br>';
 
-print '<div class="inline-block divButAction">';
-print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=validatehistory">' . $langs->trans("ValidateHistory") . '</a>';
-print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=cleanaccountancycode">' . $langs->trans("CleanHistory", $year_current) . '</a>';
+//print '<div class="inline-block divButAction">';
 // TODO Remove this. Should be done always.
 if ($conf->global->MAIN_FEATURES_LEVEL > 0) print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=fixaccountancycode">' . $langs->trans("CleanFixHistory", $year_current) . '</a>';
-print '</div>';
+//print '</div>';
+
+
+$buttonbind = '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=validatehistory">' . $langs->trans("ValidateHistory") . '</a>';
+$buttonreset = '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=cleanaccountancycode">' . $langs->trans("CleanHistory", $year_current) . '</a>';
+
+
 
 $y = $year_current;
 
 $var = true;
 
+
+print '<br>';
+
+print_fiche_titre($langs->trans("OverviewOfAmountOfLinesNotBound"), $buttonbind, '');
+
+
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre"><td width="200" align="left">' . $langs->trans("Account") . '</td>';
 print '<td width="200" align="left">' . $langs->trans("Label") . '</td>';
 for($i = 1; $i <= 12; $i ++) {
-	print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+    print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
 }
 print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
 
 $sql = "SELECT  ".$db->ifsql('aa.account_number IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.account_number') ." AS codecomptable,";
 $sql .= "  " . $db->ifsql('aa.label IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.label') . " AS intitule,";
 for($i = 1; $i <= 12; $i ++) {
-	$sql .= "  SUM(" . $db->ifsql('MONTH(er.date_create)=' . $i, 'erd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+    $sql .= "  SUM(" . $db->ifsql('MONTH(er.date_create)=' . $i, 'erd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
 }
 $sql .= " ROUND(SUM(erd.total_ht),2) as total";
 $sql .= " FROM " . MAIN_DB_PREFIX . "expensereport_det as erd";
@@ -195,32 +207,96 @@ $sql .= " WHERE er.date_create >= '" . $db->idate(dol_get_first_day($y, 1, false
 $sql .= " AND er.date_create <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
 $sql .= " AND er.fk_statut > 0 ";
 $sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")";     // We don't share object for accountancy
-
 $sql .= " GROUP BY erd.fk_code_ventilation,aa.account_number,aa.label";
 
 dol_syslog('/accountancy/expensereport/index.php:: sql=' . $sql);
 $resql = $db->query($sql);
 if ($resql) {
-	$num = $db->num_rows($resql);
+    $num = $db->num_rows($resql);
+
+    while ( $row = $db->fetch_row($resql)) {
+
+        $var = ! $var;
+        print '<tr ' . $bc[$var] . '><td>' . length_accountg($row[0]) . '</td>';
+        print '<td align="left">' . $row[1] . '</td>';
+        for($i = 2; $i <= 12; $i ++) {
+            print '<td align="right">' . price($row[$i]) . '</td>';
+        }
+        print '<td align="right">' . price($row[13]) . '</td>';
+        print '<td align="right"><b>' . price($row[14]) . '</b></td>';
+        print '</tr>';
+    }
+    $db->free($resql);
+} else {
+    print $db->lasterror(); // Show last sql error
+}
+print "</table>\n";
 
-	while ( $row = $db->fetch_row($resql)) {
 
-		$var = ! $var;
-		print '<tr ' . $bc[$var] . '><td>' . length_accountg($row[0]) . '</td>';
-		print '<td align="left">' . $row[1] . '</td>';
-		for($i = 2; $i <= 12; $i ++) {
-			print '<td align="right">' . price($row[$i]) . '</td>';
-		}
-		print '<td align="right">' . price($row[13]) . '</td>';
-		print '<td align="right"><b>' . price($row[14]) . '</b></td>';
-		print '</tr>';
-	}
-	$db->free($resql);
+
+print '<br>';
+
+print_fiche_titre($langs->trans("OverviewOfAmountOfLinesBound"), $buttonreset, '');
+
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre"><td width="200" align="left">' . $langs->trans("Account") . '</td>';
+print '<td width="200" align="left">' . $langs->trans("Label") . '</td>';
+for($i = 1; $i <= 12; $i ++) {
+    print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+}
+print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
+
+$sql = "SELECT  ".$db->ifsql('aa.account_number IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.account_number') ." AS codecomptable,";
+$sql .= "  " . $db->ifsql('aa.label IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.label') . " AS intitule,";
+for($i = 1; $i <= 12; $i ++) {
+    $sql .= "  SUM(" . $db->ifsql('MONTH(er.date_create)=' . $i, 'erd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+}
+$sql .= " ROUND(SUM(erd.total_ht),2) as total";
+$sql .= " FROM " . MAIN_DB_PREFIX . "expensereport_det as erd";
+$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expensereport as er ON er.rowid = erd.fk_expensereport";
+$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid = erd.fk_code_ventilation";
+$sql .= " WHERE er.date_create >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
+$sql .= " AND er.date_create <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
+$sql .= " AND er.fk_statut > 0 ";
+$sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")";     // We don't share object for accountancy
+$sql .= " AND aa.account_number IS NULL";
+$sql .= " GROUP BY erd.fk_code_ventilation,aa.account_number,aa.label";
+
+dol_syslog('/accountancy/expensereport/index.php:: sql=' . $sql);
+$resql = $db->query($sql);
+if ($resql) {
+    $num = $db->num_rows($resql);
+
+    while ( $row = $db->fetch_row($resql)) {
+
+        $var = ! $var;
+        print '<tr ' . $bc[$var] . '><td>' . length_accountg($row[0]) . '</td>';
+        print '<td align="left">' . $row[1] . '</td>';
+        for($i = 2; $i <= 12; $i ++) {
+            print '<td align="right">' . price($row[$i]) . '</td>';
+        }
+        print '<td align="right">' . price($row[13]) . '</td>';
+        print '<td align="right"><b>' . price($row[14]) . '</b></td>';
+        print '</tr>';
+    }
+    $db->free($resql);
 } else {
-	print $db->lasterror(); // Show last sql error
+    print $db->lasterror(); // Show last sql error
 }
 print "</table>\n";
 
+
+
+
+print '<br>';
+print '<br>';
+
+
+print_fiche_titre($langs->trans("OtherInfo"), '', '');
+
+
+
 print "<br>\n";
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("Total") . '</td>';

+ 36 - 23
htdocs/accountancy/expensereport/lines.php

@@ -39,6 +39,7 @@ $langs->load("other");
 $langs->load("main");
 $langs->load("accountancy");
 $langs->load("trips");
+$langs->load("productbatch");
 
 $account_parent = GETPOST('account_parent');
 $changeaccount = GETPOST('changeaccount');
@@ -60,7 +61,7 @@ $offset = $conf->liste_limit * $page;
 $pageprev = $page - 1;
 $pagenext = $page + 1;
 if (! $sortfield)
-	$sortfield = "er.date_create, er.ref, erd.rowid";
+	$sortfield = "erd.date, erd.rowid";
 if (! $sortorder) {
 	if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE > 0) {
 		$sortorder = "DESC";
@@ -144,7 +145,9 @@ print '<script type="text/javascript">
 /*
  * Expense reports lines
  */
-$sql = "SELECT er.ref, er.rowid as erid, erd.rowid, erd.fk_c_type_fees, erd.comments, erd.total_ht, erd.fk_code_ventilation, erd.tva_tx, aa.label, aa.account_number, ";
+$sql = "SELECT er.ref, er.rowid as erid,";
+$sql .= " erd.rowid, erd.fk_c_type_fees, erd.comments, erd.total_ht, erd.fk_code_ventilation, erd.tva_tx, erd.date,";
+$sql .= " aa.label, aa.account_number,";
 $sql .= " f.id as fees_id, f.label as fees_label";
 $sql .= " FROM " . MAIN_DB_PREFIX . "expensereport as er";
 $sql .= " , " . MAIN_DB_PREFIX . "accounting_account as aa";
@@ -175,7 +178,7 @@ $sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")";  // We don'
 $sql .= $db->order($sortfield, $sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -227,11 +230,13 @@ if ($result) {
 
 	$moreforfilter = '';
 
+    print '<div class="div-table-responsive">';
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "erd.rowid", "", $param, 'align="right"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "erd.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("ExpenseReport"), $_SERVER["PHP_SELF"], "er.ref", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Date"), $_SERVER["PHP_SELF"], "erd.date, erd.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("TypeFees"), $_SERVER["PHP_SELF"], "f.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Description"), $_SERVER["PHP_SELF"], "erd.comments", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Amount"), $_SERVER["PHP_SELF"], "erd.total_ht", "", $param, 'align="right"', $sortfield, $sortorder);
@@ -242,13 +247,14 @@ if ($result) {
 	print "</tr>\n";
 
 	print '<tr class="liste_titre">';
+	print '<td class="liste_titre"></td>';
+	print '<td><input type="text" class="flat maxwidth50" name="search_expensereport" value="' . dol_escape_htmltag($search_expensereport) . '"></td>';
 	print '<td class="liste_titre" align="right"></td>';
-	print '<td><input type="text" class="flat" name="search_expensereport" size="6" value="' . $search_expensereport . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_label" value="' . $search_label . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_desc" value="' . $search_desc . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="6" name="search_amount" value="' . $search_amount . '"></td>';
-	print '<td class="liste_titre" align="center"><input type="text" class="flat" size="3" name="search_vat" value="' . $search_vat . '"></td>';
-	print '<td class="liste_titre" align="center"><input type="text" class="flat" size="6" name="search_account" value="' . $search_account . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_label" value="' . dol_escape_htmltag($search_label) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_desc" value="' . dol_escape_htmltag($search_desc) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_amount" value="' . dol_escape_htmltag($search_amount) . '"></td>';
+	print '<td class="liste_titre" align="center"><input type="text" class="flat maxwidth50" name="search_vat" size="1" value="' . dol_escape_htmltag($search_vat) . '"></td>';
+	print '<td class="liste_titre" align="center"><input type="text" class="flat maxwidth50" name="search_account" value="' . dol_escape_htmltag($search_account) . '"></td>';
     print '<td class="liste_titre" align="right"></td>';
     print '<td class="liste_titre" align="right">';
     $searchpicto=$form->showFilterAndCheckAddButtons(1);
@@ -264,19 +270,25 @@ if ($result) {
 		$var = ! $var;
 		$codeCompta = length_accountg($objp->account_number) . ' - ' . $objp->label;
 
+		$expensereport_static->ref = $objp->ref;
+		$expensereport_static->id = $objp->erid;
+		
 		print '<tr '. $bc[$var].'>';
 
-		print '<td align="right">' . $objp->rowid . '</td>';
+		print '<td>' . $objp->rowid . '</td>';
 
 		// Ref Invoice
-		$expensereport_static->ref = $objp->ref;
-		$expensereport_static->id = $objp->erid;
 		print '<td>' . $expensereport_static->getNomUrl(1) . '</td>';
 
-		print '<td>' . dol_trunc($objp->fees_label, 24) . '</td>';
+		print '<td align="center">' . dol_print_date($db->jdate($objp->date), 'day') . '</td>';
+		
+		print '<td class="tdoverflow">' . $objp->fees_label . '</td>';
 
+		print '<td>';
+		$text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->comments));
 		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION') ? ACCOUNTING_LENGTH_DESCRIPTION : 32;
-		print '<td>' . nl2br(dol_trunc($objp->comments, $trunclength)) . '</td>';
+		print $form->textwithtooltip(dol_trunc($text,$trunclength), $objp->comments);
+		print '</td>';
 
 		print '<td align="right">' . price($objp->total_ht) . '</td>';
 
@@ -293,18 +305,19 @@ if ($result) {
 		print "</tr>";
 		$i ++;
 	}
+	
+	print "</table>";
+	print "</div>";
+	
+	if ($nbtotalofrecords > $limit) {
+	    print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, '', 0, '', '', $limit, 1);
+	}
+	
+	print '</form>';
 } else {
 	print $db->error();
 }
 
-print "</table>";
-
-if ($nbtotalofrecords > $limit) {
-    print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, '', 0, '', '', $limit, 1);
-}
-
-print '</form>';
-
 
 llxFooter();
 $db->close();

+ 83 - 47
htdocs/accountancy/expensereport/list.php

@@ -40,11 +40,16 @@ $langs->load("other");
 $langs->load("trips");
 $langs->load("main");
 $langs->load("accountancy");
+$langs->load("productbatch");
 
-$action = GETPOST('action');
+$action=GETPOST('action','alpha');
+$massaction=GETPOST('massaction','alpha');
+$show_files=GETPOST('show_files','int');
+$confirm=GETPOST('confirm','alpha');
+$toselect = GETPOST('toselect', 'array');
 
 // Select Box
-$mesCasesCochees = GETPOST('mesCasesCochees', 'array');
+$mesCasesCochees = GETPOST('toselect', 'array');
 
 // Search Getpost
 $search_expensereport = GETPOST('search_expensereport', 'alpha');
@@ -65,7 +70,7 @@ $offset = $limit * $page;
 $pageprev = $page - 1;
 $pagenext = $page + 1;
 if (! $sortfield)
-	$sortfield = "er.date_create, er.ref, erd.rowid";
+	$sortfield = "erd.date, erd.rowid";
 if (! $sortorder) {
 	if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO > 0) {
 		$sortorder = "DESC";
@@ -79,16 +84,16 @@ if (! $user->rights->accounting->bind->write)
 	accessforbidden();
 
 $formventilation = new FormVentilation($db);
-
-// Defaut AccountingAccount RowId Product / Service
-// at this time ACCOUNTING_SERVICE_SOLD_ACCOUNT & ACCOUNTING_PRODUCT_SOLD_ACCOUNT are account number not accountingacount rowid
-// so we need to get those default value rowid first
 $accounting = new AccountingAccount($db);
 
+
 /*
  * Action
  */
 
+if (GETPOST('cancel')) { $action='list'; $massaction=''; }
+if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; }
+
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 {
@@ -100,11 +105,19 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
     $search_vat = '';
 }
 
-if ($action == 'ventil' && ! empty($btn_ventil)) {
-    $msg='';
+// Mass actions
+$objectclass='Skeleton';
+$objectlabel='Skeleton';
+$permtoread = $user->rights->accounting->read;
+$permtodelete = $user->rights->accounting->delete;
+$uploaddir = $conf->accounting->dir_output;
+include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
+
+if ($massaction == 'ventil') {
+	$msg='';
     //print '<div><font color="red">' . $langs->trans("Processing") . '...</font></div>';
     if (! empty($mesCasesCochees)) {
-        $msg = '<div>' . $langs->trans("SelectedLines") . ': '.count($_POST["mesCasesCochees"]).'</div>';
+        $msg = '<div>' . $langs->trans("SelectedLines") . ': '.count($mesCasesCochees).'</div>';
         $msg.='<div class="detail">';
         $mesCodesVentilChoisis = $codeventil;
         $cpt = 0;
@@ -112,7 +125,6 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
         $ko=0;
 
         foreach ( $mesCasesCochees as $maLigneCochee ) {
-            // print '<div><font color="red">id selectionnee : '.$monChoix."</font></div>";
             $maLigneCourante = explode("_", $maLigneCochee);
             $monId = $maLigneCourante[0];
             $monCompte = GETPOST('codeventil'.$monId);
@@ -133,21 +145,21 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
     
                 dol_syslog('accountancy/expensereport/list.php:: sql=' . $sql, LOG_DEBUG);
                 if ($db->query($sql)) {
-                    $ok++;
                     $msg.= '<div><font color="green">' . $langs->trans("LineOfExpenseReport") . ' ' . $monId . ' - ' . $langs->trans("VentilatedinAccount") . ' : ' . length_accountg($accountventilated->account_number) . '</font></div>';
+                    $ok++;
                 } else {
-                    $ko++;
                     $msg.= '<div><font color="red">' . $langs->trans("ErrorDB") . ' : ' . $langs->trans("Lineofinvoice") . ' ' . $monId . ' - ' . $langs->trans("NotVentilatedinAccount") . ' : ' . length_accountg($accountventilated->account_number) . '<br/> <pre>' . $sql . '</pre></font></div>';
+                    $ko++;
                 }
             }
             
             $cpt++;
         }
         $msg.='</div>';
-    } else {
-        setEventMessages($langs->trans("NoRecordSelected"), null, 'warnings');
+        $msg.= '<div>' . $langs->trans("EndProcessing") . '</div>';
+    //} else {
+    //    setEventMessages($langs->trans("NoRecordSelected"), null, 'warnings');
     }
-    $msg.= '<div>' . $langs->trans("EndProcessing") . '</div>';
 }
 
 
@@ -155,10 +167,14 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
 /*
  * View
  */
+
+$form = new Form($db);
+
 llxHeader('', $langs->trans("ExpenseReportsVentilation"));
 
 // Expense report lines
-$sql = "SELECT er.ref, er.rowid as erid, er.date_debut, erd.rowid, erd.fk_c_type_fees, erd.comments, erd.total_ht as price, erd.fk_code_ventilation, erd.tva_tx as tva_tx_line, ";
+$sql = "SELECT er.ref, er.rowid as erid, er.date_debut,";
+$sql .= " erd.rowid, erd.fk_c_type_fees, erd.comments, erd.total_ht as price, erd.fk_code_ventilation, erd.tva_tx as tva_tx_line, erd.date,";
 $sql .= " f.id as fees_id, f.label as fees_label, f.accountancy_code as code_buy,";
 $sql .= " aa.rowid as aarowid";
 $sql .= " FROM " . MAIN_DB_PREFIX . "expensereport as er";
@@ -170,29 +186,29 @@ $sql .= " WHERE er.fk_statut > 4 AND erd.fk_code_ventilation <= 0";
 $sql .= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR f.accountancy_code IS NULL OR f.accountancy_code ='')";
 // Add search filter like
 if (strlen(trim($search_expensereport))) {
-	$sql .= " AND (er.ref like '%" . $search_expensereport . "%')";
+    $sql .= natural_search("er.ref",$search_expensereport);
 }
 if (strlen(trim($search_label))) {
-	$sql .= " AND (f.label like '%" . $search_label . "%')";
+    $sql .= natural_search("f.label",$search_label);
 }
 if (strlen(trim($search_desc))) {
-	$sql .= " AND (erd.comments like '%" . $search_desc . "%')";
+    $sql .= natural_search("erd.comments",$search_desc);
 }
 if (strlen(trim($search_amount))) {
-	$sql .= " AND erd.total_ht like '" . $search_amount . "%'";
+    $sql .= natural_search("erd.total_ht",$search_amount,1);
 }
 if (strlen(trim($search_account))) {
-	$sql .= " AND aa.account_number like '%" . $search_account . "%'";
+    $sql .= natural_search("aa.account_number",$search_account);
 }
 if (strlen(trim($search_vat))) {
-	$sql .= " AND (erd.tva_tx like '" . $search_vat . "%')";
+    $sql .= natural_search("erd.tva_tx",$search_vat,1);
 }
 $sql .= " AND er.entity IN (" . getEntity("expensereport", 0) . ")";  // We don't share object for accountancy
 
 $sql .= $db->order($sortfield, $sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -213,6 +229,16 @@ if ($result) {
 	if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage;
 	if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit;
 
+	$arrayofmassactions =  array(
+	    'ventil'=>$langs->trans("Ventilate")
+	    //'presend'=>$langs->trans("SendByMail"),
+	    //'builddoc'=>$langs->trans("PDFMerge"),
+	);
+	//if ($user->rights->mymodule->supprimer) $arrayofmassactions['delete']=$langs->trans("Delete");
+	//if ($massaction == 'presend') $arrayofmassactions=array();
+	$massactionbutton=$form->selectMassAction('ventil', $arrayofmassactions, 1);
+	
+	
 	print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">' . "\n";
 	print '<input type="hidden" name="action" value="ventil">';
 	if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
@@ -221,20 +247,22 @@ if ($result) {
 	print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 	print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
 
-	$center='<div class="center"><input type="submit" class="butAction" value="' . $langs->trans("Ventilate") . '" name="ventil"></div>';
+	//$center='<div class="center"><input type="submit" class="butAction" value="' . $langs->trans("Ventilate") . '" name="ventil"></div>';
 
-	print_barre_liste($langs->trans("ExpenseReportLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $center, $num_lines, 0, 'title_accountancy', 0, '', '', $limit);
-
-	if ($msg) print $msg.'<br>';
+	print_barre_liste($langs->trans("ExpenseReportLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit);
 
 	print $langs->trans("DescVentilTodoExpenseReport") . '</br><br>';
 
+	if ($msg) print $msg.'<br>';
+
 	$moreforfilter = '';
 
+    print '<div class="div-table-responsive">';
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "erd.rowid", "", $param, 'align="right"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "erd.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("ExpenseReport"), $_SERVER["PHP_SELF"], "er.ref", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Date"), $_SERVER["PHP_SELF"], "erd.date, erd.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("TypeFees"), $_SERVER["PHP_SELF"], "f.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Description"), $_SERVER["PHP_SELF"], "erd.comments", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Amount"), $_SERVER["PHP_SELF"], "erd.total_ht", "", $param, 'align="right"', $sortfield, $sortorder);
@@ -244,17 +272,19 @@ if ($result) {
 	print_liste_field_titre('', '', '', '', '', 'align="center"');
 	print "</tr>\n";
 
+	// We add search filter
 	print '<tr class="liste_titre">';
 	print '<td class="liste_titre"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_expensereport" value="' . $search_expensereport . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_label" value="' . $search_label . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_desc" value="' . $search_desc . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="6" name="search_amount" value="' . $search_amount . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="5" name="search_vat" value="' . $search_vat . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_expensereport" value="' . dol_escape_htmltag($search_expensereport) . '"></td>';
+	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_label" value="' . dol_escape_htmltag($search_label) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidthonsmartphone" name="search_desc" value="' . dol_escape_htmltag($search_desc) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_amount" value="' . dol_escape_htmltag($search_amount) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_vat" size="1" value="' . dol_escape_htmltag($search_vat) . '"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td align="right" class="liste_titre">';
-	$searchpicto=$form->showFilterAndCheckAddButtons(1);
+	$searchpicto=$form->showFilterAndCheckAddButtons($massactionbutton?1:0, 'checkforselect', 1);
 	print $searchpicto;
 	print '</td>';
 	print '</tr>';
@@ -262,7 +292,7 @@ if ($result) {
 	$expensereport_static = new ExpenseReport($db);
 	$form = new Form($db);
 
-	$var = True;
+	$var = true;
 	while ( $i < min($num_lines, $limit) ) {
 		$objp = $db->fetch_object($result);
 		$var = ! $var;
@@ -270,25 +300,30 @@ if ($result) {
 		$objp->aarowid_suggest = '';
 		$objp->aarowid_suggest = $objp->aarowid;
 
+		$expensereport_static->ref = $objp->ref;
+		$expensereport_static->id = $objp->erid;
+		
 		print '<tr '. $bc[$var].'>';
 
 		// Line id
-		print '<td align="center">' . $objp->rowid . '</td>';
+		print '<td>' . $objp->rowid . '</td>';
 
+		print '<td align="center">' . dol_print_date($db->jdate($objp->date), 'day') . '</td>';
+		
 		// Ref Expense report
-		$expensereport_static->ref = $objp->ref;
-		$expensereport_static->id = $objp->erid;
 		print '<td>' . $expensereport_static->getNomUrl(1) . '</td>';
 
 		// Fees label
 		print '<td>';
-		print dol_trunc($objp->fees_label, 24);
+		print $objp->fees_label;
 		print '</td>';
 
 		// Fees description -- Can be null
-		// TODO: we should set a user defined value to adjust user square / wide screen size
+		print '<td>';
+		$text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->comments));
 		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION') ? ACCOUNTING_LENGTH_DESCRIPTION : 32;
-		print '<td>' . nl2br(dol_trunc($objp->comments, $trunclength)) . '</td>';
+		print $form->textwithtooltip(dol_trunc($text,$trunclength), $objp->comments);
+		print '</td>';
 
 		print '<td align="right">';
 		print price($objp->price);
@@ -299,19 +334,18 @@ if ($result) {
 		print price($objp->tva_tx_line);
 		print '</td>';
 
-		// Accounting account suggested
+		// Current account
 		print '<td align="center">';
 		print length_accountg(html_entity_decode($objp->code_buy));
 		print '</td>';
 
-		// Colonne choix du compte
+		// Suggested accounting account
 		print '<td align="center">';
-		print $formventilation->select_account($objp->aarowid_suggest, 'codeventil'.$objp->rowid, 1);
+		print $formventilation->select_account($objp->aarowid_suggest, 'codeventil'.$objp->rowid, 1, array(), 0, 0, 'maxwidth300 maxwidthonsmartphone', 'cachewithshowemptyone');
 		print '</td>';
 
-		// Colonne choix ligne a ventiler
 		print '<td align="right">';
-		print '<input type="checkbox" class="checkforaction" name="mesCasesCochees[]" value="' . $objp->rowid . "_" . $i . '"' . ($objp->aarowid ? "checked" : "") . '/>';
+		print '<input type="checkbox" class="flat checkforselect" name="toselect[]" value="' . $objp->rowid . "_" . $i . '"' . ($objp->aarowid ? "checked" : "") . '/>';
 		print '</td>';
 
 		print "</tr>";
@@ -319,6 +353,8 @@ if ($result) {
 	}
 
 	print '</table>';
+	print "</div>";
+	
 	print '</form>';
 } else {
 	print $db->error();

+ 35 - 24
htdocs/accountancy/journal/bankjournal.php

@@ -109,7 +109,7 @@ $sql .= " JOIN " . MAIN_DB_PREFIX . "bank_account as ba on b.fk_account=ba.rowid
 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url as bu1 ON bu1.fk_bank = b.rowid AND bu1.type='company'";
 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as soc on bu1.url_id=soc.rowid";
 $sql .= " WHERE ba.rowid=" . $id_bank_account;
-$sql .= ' AND ba.entity IN ('.getEntity('banque', 0).')';        // We don't share object for accountancy
+$sql .= ' AND ba.entity IN ('.getEntity('bank_account', 0).')';        // We don't share object for accountancy
 if ($date_start && $date_end)
 	$sql .= " AND b.dateo >= '" . $db->idate($date_start) . "' AND b.dateo <= '" . $db->idate($date_end) . "'";
 $sql .= " ORDER BY b.datev";
@@ -153,7 +153,8 @@ if ($result) {
 	// one line for bank jounral = tabbq
 	// one line for thirdparty journal = tabtp
 	$i = 0;
-	while ( $i < $num ) {
+	while ( $i < $num ) 
+	{
 		$obj = $db->fetch_object($result);
 
 		// Set accountancy code (for bank and thirdparty)
@@ -314,7 +315,8 @@ if (! $error && $action == 'writebookkeeping') {
 		if (! $errorforline)
 		{
 		    // Line into bank account
-    		foreach ( $tabbq[$key] as $k => $mt ) {
+    		foreach ( $tabbq[$key] as $k => $mt ) 
+    		{
     			$bookkeeping = new BookKeeping($db);
     			$bookkeeping->doc_date = $val["date"];
     			$bookkeeping->doc_ref = $val["ref"];
@@ -363,9 +365,18 @@ if (! $error && $action == 'writebookkeeping') {
     
     			$result = $bookkeeping->create($user);
     			if ($result < 0) {
-    				$error++;
-    				$errorforline++;
-    				setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+    				if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists')	// Already exists
+    				{
+    					$error++;
+    					$errorforline++;
+    					//setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->doc_ref.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
+    				}
+    				else
+    				{
+	    				$error++;
+	    				$errorforline++;
+	    				setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
+    				}
     			}
     		}
 		}
@@ -463,16 +474,6 @@ if (! $error && $action == 'writebookkeeping') {
 	$action = '';
 }
 
-
-
-
-/*
- * View
- */
-
-$form = new Form($db);
-
-
 // Export
 if ($action == 'export_csv') {
 	$sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
@@ -633,6 +634,15 @@ if ($action == 'export_csv') {
 	}
 }
 
+
+
+
+/*
+ * View
+ */
+
+$form = new Form($db);
+
 if (empty($action) || $action == 'view') {
 	$invoicestatic = new Facture($db);
 	$invoicesupplierstatic = new FactureFournisseur($db);
@@ -689,7 +699,8 @@ if (empty($action) || $action == 'view') {
 	print "<td>" . $langs->trans("AccountAccounting") . "</td>";
 	print "<td>" . $langs->trans("Type") . "</td>";
 	print "<td>" . $langs->trans("PaymentMode") . "</td>";
-	print "<td align='right'>" . $langs->trans("Debit") . "</td><td align='right'>" . $langs->trans("Credit") . "</td>";
+	print "<td align='right'>" . $langs->trans("Debit") . "</td>";
+	print "<td align='right'>" . $langs->trans("Credit") . "</td>";
 	print "</tr>\n";
 
 	$var = true;
@@ -697,7 +708,7 @@ if (empty($action) || $action == 'view') {
 
 	foreach ( $tabpay as $key => $val ) {      // $key is rowid in llx_bank
 		$date = dol_print_date($db->jdate($val["date"]), 'day');
-		
+
 		$reflabel = $val["ref"];
 		if ($reflabel == '(SupplierInvoicePayment)') {
 			$reflabel = $langs->trans('Supplier');
@@ -721,7 +732,7 @@ if (empty($action) || $action == 'view') {
 		    $sqlmid = 'SELECT payfac.fk_facture as id';
 		    $sqlmid .= " FROM ".MAIN_DB_PREFIX."paiement_facture as payfac";
 		    $sqlmid .= " WHERE payfac.fk_paiement=" . $val["paymentid"];
-		    dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+		    dol_syslog("accountancy/journal/bankjournal.php::sqlmid=" . $sqlmid, LOG_DEBUG);
 		    $resultmid = $db->query($sqlmid);
 		    if ($resultmid) {
 		        $objmid = $db->fetch_object($resultmid);
@@ -735,7 +746,7 @@ if (empty($action) || $action == 'view') {
 		    $sqlmid = 'SELECT payfac.fk_facturefourn as id';
 		    $sqlmid .= " FROM " . MAIN_DB_PREFIX . "paiementfourn_facturefourn as payfac";
 		    $sqlmid .= " WHERE payfac.fk_paiementfourn=" . $val["paymentsupplierid"];
-		    dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+		    dol_syslog("accountancy/journal/bankjournal.php::sqlmid=" . $sqlmid, LOG_DEBUG);
 		    $resultmid = $db->query($sqlmid);
 		    if ($resultmid) {
 		        $objmid = $db->fetch_object($resultmid);
@@ -744,14 +755,14 @@ if (empty($action) || $action == 'view') {
 		    }
 		    else dol_print_error($db);
 		}
-		
+
 
 		/*$invoicestatic->id = $key;
 		$invoicestatic->ref = $val["ref"];
 		$invoicestatic->type = $val["type"];*/
 		// Bank
-		foreach ( $tabbq[$key] as $k => $mt ) {
-
+		foreach ( $tabbq[$key] as $k => $mt ) 
+		{
 		    print "<tr " . $bc[$var] . ">";
 		    print "<td><!-- Bank bank.rowid=".$key."--></td>";
 		    print "<td>" . $date . "</td>";
@@ -809,7 +820,7 @@ if (empty($action) || $action == 'view') {
         		{
         		    print '<span class="error">'.$langs->trans("WaitAccountNotDefined").'</span>';
         		}
-				else print length_accountg($conf->global->ACCOUNTING_ACCOUNT_SUSPENSE) . 
+				else print length_accountg($conf->global->ACCOUNTING_ACCOUNT_SUSPENSE); 
 				print "</td>";
 				print "<td>" . $reflabel . "</td>";
 				print "<td>&nbsp;</td>";

+ 4 - 4
htdocs/accountancy/journal/expensereportsjournal.php

@@ -187,11 +187,11 @@ if ($action == 'writebookkeeping') {
 		// Fees
 		foreach ( $tabht[$key] as $k => $mt ) {
 			$accountingaccount = new AccountingAccount($db);
-			$accountingaccount->fetch(null, $k);
+			$accountingaccount->fetch(null, $k, true);
 			if ($mt) {
 				// get compte id and label
 				$accountingaccount = new AccountingAccount($db);
-				if ($accountingaccount->fetch(null, $k)) {
+				if ($accountingaccount->fetch(null, $k, true)) {
 					$bookkeeping = new BookKeeping($db);
 					$bookkeeping->doc_date = $val["date"];
 					$bookkeeping->doc_ref = $val["ref"];
@@ -355,7 +355,7 @@ if ($action == 'export_csv') {
 			// Fees
 			foreach ( $tabht[$key] as $k => $mt ) {
 				$accountingaccount = new AccountingAccount($db);
-				$accountingaccount->fetch(null, $k);
+				$accountingaccount->fetch(null, $k, true);
 				if ($mt) {
 					print '"' . $date . '"' . $sep;
 					print '"' . $val["ref"] . '"' . $sep;
@@ -464,7 +464,7 @@ if (empty($action) || $action == 'view') {
 		// Fees
 		foreach ( $tabht[$key] as $k => $mt ) {
 			$accountingaccount = new AccountingAccount($db);
-			$accountingaccount->fetch(null, $k);
+			$accountingaccount->fetch(null, $k, true);
 
 			if ($mt) {
 				print "<tr " . $bc[$var] . " >";

+ 4 - 4
htdocs/accountancy/journal/purchasesjournal.php

@@ -219,11 +219,11 @@ if ($action == 'writebookkeeping') {
 		// Product / Service
 		foreach ( $tabht[$key] as $k => $mt ) {
 			$accountingaccount = new AccountingAccount($db);
-			$accountingaccount->fetch(null, $k);
+			$accountingaccount->fetch(null, $k, true);
 			if ($mt) {
 				// get compte id and label
 				$accountingaccount = new AccountingAccount($db);
-				if ($accountingaccount->fetch(null, $k)) {
+				if ($accountingaccount->fetch(null, $k, true)) {
 					$bookkeeping = new BookKeeping($db);
 					$bookkeeping->doc_date = $val["date"];
 					$bookkeeping->doc_ref = $val["ref"];
@@ -398,7 +398,7 @@ if ($action == 'export_csv') {
 			// Product / Service
 			foreach ( $tabht[$key] as $k => $mt ) {
 				$accountingaccount = new AccountingAccount($db);
-				$accountingaccount->fetch(null, $k);
+				$accountingaccount->fetch(null, $k, true);
 				if ($mt) {
 					print '"' . $date . '"' . $sep;
 					print '"' . $val["ref"] . '"' . $sep;
@@ -518,7 +518,7 @@ if (empty($action) || $action == 'view') {
 		// Product / Service
 		foreach ( $tabht[$key] as $k => $mt ) {
 			$accountingaccount = new AccountingAccount($db);
-			$accountingaccount->fetch(null, $k);
+			$accountingaccount->fetch(null, $k, true);
 
 			if ($mt) {
 				print "<tr " . $bc[$var] . " >";

+ 4 - 4
htdocs/accountancy/journal/sellsjournal.php

@@ -243,7 +243,7 @@ if ($action == 'writebookkeeping') {
             if ($mt) {
                 // get compte id and label
                 $accountingaccount = new AccountingAccount($db);
-                if ($accountingaccount->fetch(null, $k)) {
+                if ($accountingaccount->fetch(null, $k, true)) {
                     $bookkeeping = new BookKeeping($db);
                     $bookkeeping->doc_date = $val["date"];
                     $bookkeeping->doc_ref = $val["ref"];
@@ -375,7 +375,7 @@ if ($action == 'export_csv') {
             // Product / Service
             foreach ( $tabht[$key] as $k => $mt ) {
                 $accountingaccount_static = new AccountingAccount($db);
-                if ($accountingaccount_static->fetch(null, $k)) {
+                if ($accountingaccount_static->fetch(null, $k, true)) {
                     print $date . $sep;
                     print $sell_journal . $sep;
                     print length_accountg(html_entity_decode($k)) . $sep;
@@ -429,7 +429,7 @@ if ($action == 'export_csv') {
             // Product / Service
             foreach ( $tabht[$key] as $k => $mt ) {
                 $accountingaccount = new AccountingAccount($db);
-                $accountingaccount->fetch(null, $k);
+                $accountingaccount->fetch(null, $k, true);
 
                 if ($mt) {
                     print '"' . $date . '"' . $sep;
@@ -559,7 +559,7 @@ if (empty($action) || $action == 'view') {
 		// Product / Service
 		foreach ( $tabht[$key] as $k => $mt ) {
 			$accountingaccount = new AccountingAccount($db);
-			$accountingaccount->fetch(null, $k);
+			$accountingaccount->fetch(null, $k, true);
 
 			if ($mt) {
 				print "<tr " . $bc[$var] . ">";

+ 8 - 3
htdocs/accountancy/report/result.php

@@ -75,9 +75,12 @@ $form = new Form($db);
 $textprevyear = '<a href="' . $_SERVER["PHP_SELF"] . '?year=' . ($year_current - 1) . '">' . img_previous() . '</a>';
 $textnextyear = '&nbsp;<a href="' . $_SERVER["PHP_SELF"] . '?year=' . ($year_current + 1) . '">' . img_next() . '</a>';
 
-print load_fiche_titre($langs->trans('ReportInOut') . " " . $textprevyear . " " . $langs->trans("Year") . " " . $year_start . " " . $textnextyear, '', 'title_accountancy');
+print load_fiche_titre($langs->trans('ReportInOut'), $textprevyear . " " . $langs->trans("Year") . " " . $year_start . " " . $textnextyear, 'title_accountancy');
 
-print '<table class="border" width="100%">';
+$moreforfilter='';
+
+print '<div class="div-table-responsive">';
+print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 
 $months = array( $langs->trans("JanuaryMin"),
 				$langs->trans("FebruaryMin"),
@@ -93,7 +96,8 @@ $months = array( $langs->trans("JanuaryMin"),
 				$langs->trans("DecemberMin"),
 			);
 
-print '<tr class="liste_titre"><th class="liste_titre">'.$langs->trans("Account").'</th>';
+print '<tr class="liste_titre">';
+print '<th class="liste_titre">'.$langs->trans("Account").'</th>';
 print '<th class="liste_titre">'.$langs->trans("Description").'</th>';
 print '<th class="liste_titre" align="center">N-1</th>';
 print '<th class="liste_titre" align="center">'.$langs->trans("NReal").'</th>';
@@ -257,6 +261,7 @@ if (!empty($cats))
 }
 
 print "</table>";
+print '</div>';
 
 llxFooter();
 $db->close();

+ 91 - 12
htdocs/accountancy/supplier/index.php

@@ -77,7 +77,7 @@ if ($action == 'validatehistory') {
 	$sqlclean .= '	ON accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=' . $conf->global->CHARTOFACCOUNTS . ')';
 	$resql = $db->query($sqlclean);
 	
-	// Now make the binding
+	// Now make the binding. Bind automatically only for product with a dedicated account that exists into chart of account, others need a manual bind
 	if ($db->type == 'pgsql') {
 		$sql1 = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det";
 		$sql1 .= " SET fk_code_ventilation = accnt.rowid";
@@ -130,11 +130,13 @@ if ($action == 'validatehistory') {
 	$db->begin();
 
 	$sql1 = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det as fd";
-	$sql1 .= " SET fd.fk_code_ventilation = 0";
-	$sql1 .= " WHERE fd.fk_facture_fourn IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
-	$sql1 .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'";
-	$sql1 .= "  AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "')";
-
+	$sql1.= " SET fd.fk_code_ventilation = 0";
+	$sql1.= " WHERE fd.fk_facture_fourn IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
+	$sql1.= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'";
+	$sql1.= " AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "'";
+	$sql1.= " AND f.entity IN (" . getEntity("accountancy", 1) . ")";
+	$sql1.= ")";
+	
 	dol_syslog("htdocs/accountancy/customer/index.php fixaccountancycode", LOG_DEBUG);
 
 	$resql1 = $db->query($sql1);
@@ -163,17 +165,25 @@ print $langs->trans("DescVentilSupplier") . '<br>';
 print $langs->trans("DescVentilMore", $langs->transnoentitiesnoconv("ValidateHistory"), $langs->transnoentitiesnoconv("ToBind")) . '<br>';
 print '<br>';
 
-print '<div class="inline-block divButAction">';
-print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=validatehistory">' . $langs->trans("ValidateHistory") . '</a>';
-print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=cleanaccountancycode">' . $langs->trans("CleanHistory", $year_current) . '</a>';
+//print '<div class="inline-block divButAction">';
 // TODO Remove this. Should be done always.
-if ($conf->global->MAIN_FEATURES_LEVEL > 0) print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=fixaccountancycode">' . $langs->trans("CleanFixHistory", $year_current) . '</a>';
-print '</div>';
+if ($conf->global->MAIN_FEATURES_LEVEL > 1) print '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=fixaccountancycode">' . $langs->trans("CleanFixHistory", $year_current) . '</a>';
+//print '</div>';
+
+$buttonbind = '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=validatehistory">' . $langs->trans("ValidateHistory") . '</a>';
+$buttonreset = '<a class="butActionDelete" href="' . $_SERVER['PHP_SELF'] . '?year=' . $year_current . '&action=cleanaccountancycode">' . $langs->trans("CleanHistory", $year_current) . '</a>';
+
+
 
 $y = $year_current;
 
 $var = true;
 
+
+print '<br>';
+
+print_fiche_titre($langs->trans("OverviewOfAmountOfLinesNotBound"), $buttonbind, '');
+
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre"><td width="200" align="left">' . $langs->trans("Account") . '</td>';
 print '<td width="200" align="left">' . $langs->trans("Label") . '</td>';
@@ -195,7 +205,7 @@ $sql .= " WHERE ff.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "
 $sql .= "  AND ff.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
 $sql .= "  AND ff.fk_statut > 0 ";
 $sql .= " AND ff.entity IN (" . getEntity("facture_fourn", 0) . ")";     // We don't share object for accountancy
-
+$sql .= " AND aa.account_number IS NULL";
 $sql .= " GROUP BY ffd.fk_code_ventilation,aa.account_number,aa.label";
 
 dol_syslog('/accountancy/supplier/index.php:: sql=' . $sql);
@@ -221,6 +231,75 @@ if ($resql) {
 }
 print "</table>\n";
 
+
+
+
+print '<br>';
+
+
+print_fiche_titre($langs->trans("OverviewOfAmountOfLinesBound"), $buttonreset, '');
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre"><td width="200" align="left">' . $langs->trans("Account") . '</td>';
+print '<td width="200" align="left">' . $langs->trans("Label") . '</td>';
+for($i = 1; $i <= 12; $i ++) {
+    print '<td width="60" align="right">' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '</td>';
+}
+print '<td width="60" align="right"><b>' . $langs->trans("Total") . '</b></td></tr>';
+
+$sql = "SELECT  ".$db->ifsql('aa.account_number IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.account_number') ." AS codecomptable,";
+$sql .= "  " . $db->ifsql('aa.label IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.label') . " AS intitule,";
+for($i = 1; $i <= 12; $i ++) {
+    $sql .= "  SUM(" . $db->ifsql('MONTH(ff.datef)=' . $i, 'ffd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ",";
+}
+$sql .= "  ROUND(SUM(ffd.total_ht),2) as total";
+$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn_det as ffd";
+$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "facture_fourn as ff ON ff.rowid = ffd.fk_facture_fourn";
+$sql .= "  LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid = ffd.fk_code_ventilation";
+$sql .= " WHERE ff.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'";
+$sql .= "  AND ff.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'";
+$sql .= "  AND ff.fk_statut > 0 ";
+$sql .= " AND ff.entity IN (" . getEntity("facture_fourn", 0) . ")";     // We don't share object for accountancy
+$sql .= " AND aa.account_number IS NOT NULL";
+$sql .= " GROUP BY ffd.fk_code_ventilation,aa.account_number,aa.label";
+
+dol_syslog('/accountancy/supplier/index.php:: sql=' . $sql);
+$resql = $db->query($sql);
+if ($resql) {
+    $num = $db->num_rows($resql);
+
+    while ( $row = $db->fetch_row($resql)) {
+
+        $var = ! $var;
+        print '<tr ' . $bc[$var] . '><td>' . length_accountg($row[0]) . '</td>';
+        print '<td align="left">' . $row[1] . '</td>';
+        for($i = 2; $i <= 12; $i ++) {
+            print '<td align="right">' . price($row[$i]) . '</td>';
+        }
+        print '<td align="right">' . price($row[13]) . '</td>';
+        print '<td align="right"><b>' . price($row[14]) . '</b></td>';
+        print '</tr>';
+    }
+    $db->free($resql);
+} else {
+    print $db->lasterror(); // Show last sql error
+}
+print "</table>\n";
+
+
+
+
+
+print '<br>';
+print '<br>';
+
+
+print_fiche_titre($langs->trans("OtherInfo"), '', '');
+
+
+
+
+
 print "<br>\n";
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre"><td width="400" align="left">' . $langs->trans("Total") . '</td>';

+ 60 - 43
htdocs/accountancy/supplier/lines.php

@@ -39,6 +39,7 @@ $langs->load("bills");
 $langs->load("other");
 $langs->load("main");
 $langs->load("accountancy");
+$langs->load("productbatch");
 
 $account_parent = GETPOST('account_parent');
 $changeaccount = GETPOST('changeaccount');
@@ -146,14 +147,15 @@ print '<script type="text/javascript">
 /*
  * Supplier Invoice lines
  */
-$sql = "SELECT f.ref as facnumber, f.rowid as facid, l.fk_product, l.description, l.total_ht , l.qty, l.rowid, l.tva_tx, aa.label, aa.account_number, ";
-$sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type";
-$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
-$sql .= " , " . MAIN_DB_PREFIX . "accounting_account as aa";
-$sql .= " , " . MAIN_DB_PREFIX . "facture_fourn_det as l";
-$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product";
-$sql .= " WHERE f.rowid = l.fk_facture_fourn and f.fk_statut >= 1 AND l.fk_code_ventilation <> 0 ";
-$sql .= " AND aa.rowid = l.fk_code_ventilation";
+$sql = "SELECT f.rowid as facid, f.ref as facnumber, f.ref_supplier, f.libelle as invoice_label, f.datef,";
+$sql.= " l.fk_product, l.description, l.total_ht , l.qty, l.rowid, l.tva_tx, aa.label, aa.account_number, ";
+$sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type";
+$sql.= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
+$sql.= " , " . MAIN_DB_PREFIX . "accounting_account as aa";
+$sql.= " , " . MAIN_DB_PREFIX . "facture_fourn_det as l";
+$sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product";
+$sql.= " WHERE f.rowid = l.fk_facture_fourn and f.fk_statut >= 1 AND l.fk_code_ventilation <> 0 ";
+$sql.= " AND aa.rowid = l.fk_code_ventilation";
 if (strlen(trim($search_invoice))) {
 	$sql .= " AND f.ref like '%" . $search_invoice . "%'";
 }
@@ -180,7 +182,7 @@ $sql .= " AND f.entity IN (" . getEntity("facture_fourn", 0) . ")";  // We don't
 $sql .= $db->order($sortfield, $sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -234,31 +236,34 @@ if ($result) {
 	
 	$moreforfilter = '';
 	
+    print '<div class="div-table-responsive">';
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "l.rowid", "", $param, 'align="right"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "l.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Invoice"), $_SERVER["PHP_SELF"], "f.ref", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Label"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("InvoiceLabel"), $_SERVER["PHP_SELF"], "f.libelle", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Date"), $_SERVER["PHP_SELF"], "f.datef, f.ref, l.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("ProductRef"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
+	//print_liste_field_titre($langs->trans("ProductLabel"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Description"), $_SERVER["PHP_SELF"], "l.description", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Amount"), $_SERVER["PHP_SELF"], "l.total_ht", "", $param, 'align="right"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("VATRate"), $_SERVER["PHP_SELF"], "l.tva_tx", "", $param, 'align="center"', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Account"), $_SERVER["PHP_SELF"], "aa.account_number", "", $param, 'align="center"', $sortfield, $sortorder);
-	print_liste_field_titre('');
+	print_liste_field_titre($langs->trans("Account"), $_SERVER["PHP_SELF"], "aa.account_number", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre('', '', '', '', '', 'align="center"');
 	print "</tr>\n";
 	
 	print '<tr class="liste_titre">';
     print '<td class="liste_titre"></td>';
-	print '<td><input type="text" class="flat" name="search_invoice" size="6" value="' . $search_invoice . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_ref" value="' . $search_ref . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_label" value="' . $search_label . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_desc" value="' . $search_desc . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="6" name="search_amount" value="' . $search_amount . '"></td>';
-	print '<td class="liste_titre" align="center"><input type="text" class="flat" size="3" name="search_vat" value="' . $search_vat . '"></td>';
-	print '<td class="liste_titre" align="center"><input type="text" class="flat" size="6" name="search_account" value="' . $search_account . '"></td>';
-	print '<td class="liste_titre" align="right"></td>';
+	print '<td><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
+	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
+	//print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_label" value="' . dol_escape_htmltag($search_label) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_desc" value="' . dol_escape_htmltag($search_desc) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_amount" value="' . dol_escape_htmltag($search_amount) . '"></td>';
+	print '<td class="liste_titre" align="center"><input type="text" class="flat maxwidth50" name="search_vat" size="1" value="' . dol_escape_htmltag($search_vat) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_account" value="' . dol_escape_htmltag($search_account) . '"></td>';
     print '<td class="liste_titre" align="right">';
     $searchpitco=$form->showFilterAndCheckAddButtons(1);
     print $searchpitco;
@@ -272,35 +277,46 @@ if ($result) {
 	while ( $i < min($num_lines, $limit) ) {
 		$objp = $db->fetch_object($result);
 		$var = ! $var;
-		$codeCompta = length_accountg($objp->account_number) . ' - ' . $objp->label;
+		$codecompta = length_accountg($objp->account_number) . ' - ' . $objp->label;
 		
-		print '<tr '. $bc[$var].'>';
-		
-		print '<td align="right">' . $objp->rowid . '</td>';
-		
-		// Ref Invoice
 		$facturefournisseur_static->ref = $objp->facnumber;
 		$facturefournisseur_static->id = $objp->facid;
-		print '<td>' . $facturefournisseur_static->getNomUrl(1) . '</td>';
 		
-		// Ref Product
 		$product_static->ref = $objp->product_ref;
 		$product_static->id = $objp->product_id;
 		$product_static->type = $objp->type;
 		$product_static->label = $objp->product_label;
+		
+		print '<tr '. $bc[$var].'>';
+		
+		print '<td>' . $objp->rowid . '</td>';
+		
+		// Ref Invoice
+		print '<td>' . $facturefournisseur_static->getNomUrl(1) . '</td>';
+		
+		print '<td>';
+		print $objp->invoice_label;
+		print '</td>';
+		
+		print '<td align="center">' . dol_print_date($db->jdate($objp->datef), 'day') . '</td>';
+		
+		// Ref Product
 		print '<td>';
 		if ($product_static->id)
 			print $product_static->getNomUrl(1);
-		else
-			print '&nbsp;';
+	    if ($objp->product_label) print '<br>'.$objp->product_label;
+		print '</td>';
+		
+		print '<td>';
+		$text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->description));
+		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION') ? ACCOUNTING_LENGTH_DESCRIPTION : 32;
+		print $form->textwithtooltip(dol_trunc($text,$trunclength), $objp->description);
 		print '</td>';
 		
-		print '<td>' . dol_trunc($objp->product_label, 24) . '</td>';
-		print '<td>' . nl2br(dol_trunc($objp->description, 32)) . '</td>';
 		print '<td align="right">' . price($objp->total_ht) . '</td>';
 		print '<td align="center">' . price($objp->tva_tx) . '</td>';
-		print '<td>' . $codeCompta . '</td>';
-		print '<td align="left"><a href="./card.php?id=' . $objp->rowid . '">';
+		print '<td align="left">';
+		print $codecompta . ' <a href="./card.php?id=' . $objp->rowid . '">';
 		print img_edit();
 		print '</a></td>';
 		
@@ -309,17 +325,18 @@ if ($result) {
 		print "</tr>";
 		$i ++;
 	}
+    print "</table>";
+    print "</div>";
+    
+    if ($nbtotalofrecords > $limit) {
+        print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, '', 0, '', '', $limit, 1);
+    }
+    
+    print '</form>';
 } else {
 	print $db->error();
 }
 
-print "</table>";
-
-if ($nbtotalofrecords > $limit) {
-    print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, '', 0, '', '', $limit, 1);
-}
-
-print '</form>';
 
 
 llxFooter();

+ 113 - 71
htdocs/accountancy/supplier/list.php

@@ -40,11 +40,16 @@ $langs->load("bills");
 $langs->load("other");
 $langs->load("main");
 $langs->load("accountancy");
+$langs->load("productbatch");
 
-$action = GETPOST('action');
+$action=GETPOST('action','alpha');
+$massaction=GETPOST('massaction','alpha');
+$show_files=GETPOST('show_files','int');
+$confirm=GETPOST('confirm','alpha');
+$toselect = GETPOST('toselect', 'array');
 
 // Select Box
-$mesCasesCochees = GETPOST('mesCasesCochees', 'array');
+$mesCasesCochees = GETPOST('toselect', 'array');
 
 // Search Getpost
 $search_invoice = GETPOST('search_invoice', 'alpha');
@@ -80,12 +85,7 @@ if (! $user->rights->accounting->bind->write)
 	accessforbidden();
 
 $formventilation = new FormVentilation($db);
-
-// Defaut AccountingAccount RowId Product / Service
-// at this time ACCOUNTING_SERVICE_SOLD_ACCOUNT & ACCOUNTING_PRODUCT_SOLD_ACCOUNT are account number not accountingacount rowid
-// so we need to get those default value rowid first
 $accounting = new AccountingAccount($db);
-
 // TODO: we should need to check if result is a really exist accountaccount rowid.....
 $aarowid_s = $accounting->fetch('', $conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT, 1);
 $aarowid_p = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT, 1);
@@ -95,10 +95,14 @@ $aarowid_p = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUN
  * Action
  */
 
+if (GETPOST('cancel')) { $action='list'; $massaction=''; }
+if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; }
+
 // Purge search criteria
 if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
 {
     $search_ref = '';
+    $search_invoice = '';    
     $search_label = '';
     $search_desc = '';
     $search_amount = '';
@@ -106,11 +110,19 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
     $search_vat = '';
 }
 
-if ($action == 'ventil' && ! empty($btn_ventil)) {
+// Mass actions
+$objectclass='Skeleton';
+$objectlabel='Skeleton';
+$permtoread = $user->rights->accounting->read;
+$permtodelete = $user->rights->accounting->delete;
+$uploaddir = $conf->accounting->dir_output;
+include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
+
+if ($massaction == 'ventil') {
     $msg='';
     //print '<div><font color="red">' . $langs->trans("Processing") . '...</font></div>';
     if (! empty($mesCasesCochees)) {
-        $msg = '<div>' . $langs->trans("SelectedLines") . ': '.count($_POST["mesCasesCochees"]).'</div>';
+        $msg = '<div>' . $langs->trans("SelectedLines") . ': '.count($mesCasesCochees).'</div>';
         $msg.='<div class="detail">';
         $mesCodesVentilChoisis = $codeventil;
         $cpt = 0;
@@ -118,7 +130,6 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
         $ko=0;
 
         foreach ( $mesCasesCochees as $maLigneCochee ) {
-            // print '<div><font color="red">id selectionnee : '.$monChoix."</font></div>";
             $maLigneCourante = explode("_", $maLigneCochee);
             $monId = $maLigneCourante[0];
             $monCompte = GETPOST('codeventil'.$monId);
@@ -139,21 +150,21 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
     
                 dol_syslog('accountancy/supplier/list.php:: sql=' . $sql, LOG_DEBUG);
                 if ($db->query($sql)) {
-                    $ok++;
                     $msg.= '<div><font color="green">' . $langs->trans("Lineofinvoice") . ' ' . $monId . ' - ' . $langs->trans("VentilatedinAccount") . ' : ' . length_accountg($accountventilated->account_number) . '</font></div>';
+                    $ok++;
                 } else {
-                    $ko++;
                     $msg.= '<div><font color="red">' . $langs->trans("ErrorDB") . ' : ' . $langs->trans("Lineofinvoice") . ' ' . $monId . ' - ' . $langs->trans("NotVentilatedinAccount") . ' : ' . length_accountg($accountventilated->account_number) . '<br/> <pre>' . $sql . '</pre></font></div>';
+                    $ko++;
                 }
             }
             
             $cpt++;
         }
         $msg.='</div>';
-    } else {
-        setEventMessages($langs->trans("NoRecordSelected"), null, 'warnings');
+        $msg.= '<div>' . $langs->trans("EndProcessing") . '</div>';
+    //} else {
+    //    setEventMessages($langs->trans("NoRecordSelected"), null, 'warnings');
     }
-    $msg.= '<div>' . $langs->trans("EndProcessing") . '</div>';
 }
 
 
@@ -161,49 +172,52 @@ if ($action == 'ventil' && ! empty($btn_ventil)) {
 /*
  * View
  */
+
+$form = new Form($db);
+
 llxHeader('', $langs->trans("SuppliersVentilation"));
 
 // Supplier Invoice Lines
-$sql = "SELECT f.ref, f.rowid as facid, f.ref_supplier, f.datef,";
-$sql .= " l.fk_product, l.description, l.total_ht as price, l.rowid, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, ";
-$sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_buy as code_buy, p.tva_tx as tva_tx_prod,";
-$sql .= " aa.rowid as aarowid";
-$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
-$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "facture_fourn_det as l ON f.rowid = l.fk_facture_fourn";
-$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product";
-$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON p.accountancy_code_buy = aa.account_number";
-$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_system as accsys ON accsys.pcg_version = aa.fk_pcg_version";
-$sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0";
-$sql .= " AND product_type <= 2";
-$sql .= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_buy IS NULL OR p.accountancy_code_buy ='')";
+$sql = "SELECT f.rowid as facid, f.ref, f.ref_supplier, f.libelle as invoice_label, f.datef,";
+$sql.= " l.fk_product, l.description, l.total_ht as price, l.rowid, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, ";
+$sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_buy as code_buy, p.tva_tx as tva_tx_prod,";
+$sql.= " aa.rowid as aarowid";
+$sql.= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
+$sql.= " INNER JOIN " . MAIN_DB_PREFIX . "facture_fourn_det as l ON f.rowid = l.fk_facture_fourn";
+$sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product";
+$sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON p.accountancy_code_buy = aa.account_number";
+$sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_system as accsys ON accsys.pcg_version = aa.fk_pcg_version";
+$sql.= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0";
+$sql.= " AND product_type <= 2";
+$sql.= " AND (accsys.rowid='" . $conf->global->CHARTOFACCOUNTS . "' OR p.accountancy_code_buy IS NULL OR p.accountancy_code_buy ='')";
 // Add search filter like
 if (strlen(trim($search_invoice))) {
-	$sql .= " AND (f.ref like '%" . $search_invoice . "%')";
+    $sql .= natural_search("f.ref",$search_invoice);
 }
 if (strlen(trim($search_ref))) {
-	$sql .= " AND (p.ref like '%" . $search_ref . "%')";
+    $sql .= natural_search("p.ref",$search_ref);
 }
 if (strlen(trim($search_label))) {
-	$sql .= " AND (p.label like '%" . $search_label . "%')";
+    $sql .= natural_search("p.label",$search_label);
 }
 if (strlen(trim($search_desc))) {
-	$sql .= " AND (l.description like '%" . $search_desc . "%')";
+    $sql .= natural_search("l.description",$search_desc);
 }
 if (strlen(trim($search_amount))) {
-	$sql .= " AND l.total_ht like '" . $search_amount . "%'";
+    $sql .= natural_search("l.total_ht",$search_amount,1);
 }
 if (strlen(trim($search_account))) {
-	$sql .= " AND aa.account_number like '%" . $search_account . "%'";
+    $sql .= natural_search("aa.account_number",$search_account);
 }
 if (strlen(trim($search_vat))) {
-	$sql .= " AND (l.tva_tx like '" . $search_vat . "%')";
+    $sql .= natural_search("l.tva_tx",$search_vat,1);
 }
 $sql .= " AND f.entity IN (" . getEntity("facture_fourn", 0) . ")";  // We don't share object for accountancy
 
 $sql .= $db->order($sortfield, $sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -224,6 +238,16 @@ if ($result) {
 	if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage;
 	if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit;
 	
+	$arrayofmassactions =  array(
+	    'ventil'=>$langs->trans("Ventilate")
+	    //'presend'=>$langs->trans("SendByMail"),
+	    //'builddoc'=>$langs->trans("PDFMerge"),
+	);
+	//if ($user->rights->mymodule->supprimer) $arrayofmassactions['delete']=$langs->trans("Delete");
+	//if ($massaction == 'presend') $arrayofmassactions=array();
+	$massactionbutton=$form->selectMassAction('ventil', $arrayofmassactions, 1);
+	
+	
 	print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">' . "\n";
 	print '<input type="hidden" name="action" value="ventil">';
 	if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
@@ -232,22 +256,25 @@ if ($result) {
 	print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 	print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
 	
-	$center='<div align="center"><input type="submit" class="butAction" value="' . $langs->trans("Ventilate") . '" name="ventil"></div>';
+	//$center='<div align="center"><input type="submit" class="butAction" value="' . $langs->trans("Ventilate") . '" name="ventil"></div>';
 	
-	print_barre_liste($langs->trans("InvoiceLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $center, $num_lines, 0, 'title_accountancy', 0, '', '', $limit);
+	print_barre_liste($langs->trans("InvoiceLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit);
 
-	if ($msg) print $msg.'<br>';
-	
 	print $langs->trans("DescVentilTodoCustomer") . '</br><br>';
 
-    $moreforfilter = '';
+	if ($msg) print $msg.'<br>';
 	
-    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+	$moreforfilter = '';
+	
+    print '<div class="div-table-responsive">';
+	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	print '<tr class="liste_titre">';
-	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "l.rowid", "", $param, 'align="right"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("LineId"), $_SERVER["PHP_SELF"], "l.rowid", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Invoice"), $_SERVER["PHP_SELF"], "f.ref", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre($langs->trans("Label"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("InvoiceLabel"), $_SERVER["PHP_SELF"], "f.libelle", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("Date"), $_SERVER["PHP_SELF"], "f.datef, f.ref, l.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
+	print_liste_field_titre($langs->trans("ProductRef"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
+	//print_liste_field_titre($langs->trans("ProductLabel"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Description"), $_SERVER["PHP_SELF"], "l.description", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("Amount"), $_SERVER["PHP_SELF"], "l.total_ht", "", $param, 'align="right"', $sortfield, $sortorder);
 	print_liste_field_titre($langs->trans("VATRate"), $_SERVER["PHP_SELF"], "l.tva_tx", "", $param, 'align="right"', $sortfield, $sortorder);
@@ -256,18 +283,21 @@ if ($result) {
 	print_liste_field_titre('', '', '', '', '', 'align="center"');
 	print "</tr>\n";
 
+	// We add search filter
 	print '<tr class="liste_titre">';
 	print '<td class="liste_titre"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_invoice" value="' . $search_invoice . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_ref" value="' . $search_ref . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_label" value="' . $search_label . '"></td>';
-	print '<td class="liste_titre"><input type="text" class="flat" size="6" name="search_desc" value="' . $search_desc . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="6" name="search_amount" value="' . $search_amount . '"></td>';
-	print '<td class="liste_titre" align="right"><input type="text" class="flat" size="5" name="search_vat" value="' . $search_vat . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_invoice" value="' . dol_escape_htmltag($search_invoice) . '"></td>';
+	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_ref" value="' . dol_escape_htmltag($search_ref) . '"></td>';
+	//print '<td class="liste_titre"><input type="text" class="flat maxwidth50" name="search_label" value="' . dol_escape_htmltag($search_label) . '"></td>';
+	print '<td class="liste_titre"><input type="text" class="flat maxwidthonsmartphone" name="search_desc" value="' . dol_escape_htmltag($search_desc) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_amount" value="' . dol_escape_htmltag($search_amount) . '"></td>';
+	print '<td class="liste_titre" align="right"><input type="text" class="flat maxwidth50" name="search_vat" size="1" value="' . dol_escape_htmltag($search_vat) . '"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td align="right" class="liste_titre">';
-	$searchpitco=$form->showFilterAndCheckAddButtons(1);
+	$searchpitco=$form->showFilterAndCheckAddButtons($massactionbutton?1:0, 'checkforselect', 1);
 	print $searchpitco;
 	print '</td>';
 	print '</tr>';
@@ -276,7 +306,7 @@ if ($result) {
 	$productfourn_static = new ProductFournisseur($db);
 	$form = new Form($db);
 
-	$var = True;
+	$var = true;
 	while ( $i < min($num_lines, $limit) ) {
 		$objp = $db->fetch_object($result);
 		$var = ! $var;
@@ -288,6 +318,15 @@ if ($result) {
 		$objp->code_buy_p = '';
 		$objp->aarowid_suggest = '';
 
+		$productfourn_static->ref = $objp->product_ref;
+		$productfourn_static->id = $objp->product_id;
+		$productfourn_static->type = $objp->type;
+		$productfourn_static->label = $objp->product_label;
+		
+		$facturefourn_static->ref = $objp->ref;
+		$facturefourn_static->id = $objp->facid;
+		$facturefourn_static->type = $objp->type;
+		
 		$code_buy_p_notset = '';
 		$objp->aarowid_suggest = $objp->aarowid;
 
@@ -303,7 +342,7 @@ if ($result) {
 		if ($objp->code_buy_l == -1) $objp->code_buy_l='';
 		
 		if (! empty($objp->code_buy)) {
-			$objp->code_buy_p = $objp->code_buy;
+			$objp->code_buy_p = $objp->code_buy;       // Code on product
 		} else {
 			$code_buy_p_notset = 'color:orange';
 		}
@@ -315,29 +354,30 @@ if ($result) {
 		print '<tr '. $bc[$var].'>';
 
 		// Line id
-		print '<td align="center">' . $objp->rowid . '</td>';
+		print '<td>' . $objp->rowid . '</td>';
 		
 		// Ref Invoice
-		$facturefourn_static->ref = $objp->ref;
-		$facturefourn_static->id = $objp->facid;
 		print '<td>' . $facturefourn_static->getNomUrl(1) . '</td>';
 
-		// Ref Supplier Invoice
-		$productfourn_static->ref = $objp->product_ref;
-		$productfourn_static->id = $objp->product_id;
-		$productfourn_static->type = $objp->type;
+		print '<td class="tdoverflowonsmartphone">';
+		print $objp->invoice_label;
+		print '</td>';
+		
+		print '<td align="center">' . dol_print_date($db->jdate($objp->datef), 'day') . '</td>';
+		
+		// Ref product
 		print '<td>';
 		if ($productfourn_static->id)
 			print $productfourn_static->getNomUrl(1);
-		else
-			print '&nbsp;';
-		print '</td>';
-
-		print '<td>' . dol_trunc($objp->product_label, 24) . '</td>';
-
-		// TODO: we should set a user defined value to adjust user square / wide screen size
+		if ($objp->product_label) print '<br>'.$objp->product_label;
+        print '</td>';
+        
+        // Description
+		print '<td>';
+		$text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->description));
 		$trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION') ? ACCOUNTING_LENGTH_DESCRIPTION : 32;
-		print '<td>' . nl2br(dol_trunc($objp->description, $trunclength)) . '</td>';
+		print $form->textwithtooltip(dol_trunc($text,$trunclength), $objp->description);
+		print '</td>';
 
 		print '<td align="right">';
 		print price($objp->price);
@@ -350,7 +390,7 @@ if ($result) {
 		print price($objp->tva_tx_line);
 		print '</td>';
 
-		// Accounting account suggested
+		// Current account
 		print '<td align="center" style="' . $code_buy_p_notset . '">';
 		print (($objp->type_l == 1)?$langs->trans("DefaultForService"):$langs->trans("DefaultForProduct")) . ' = ' . ($objp->code_buy_l > 0 ? length_accountg($objp->code_buy_l) : $langs->trans("Unknown"));
 		if ($objp->product_id > 0)
@@ -362,12 +402,12 @@ if ($result) {
 
 		// Suggested accounting account
 		print '<td align="center">';
-		print $formventilation->select_account($objp->aarowid_suggest, 'codeventil'.$objp->rowid, 1);
+		print $formventilation->select_account($objp->aarowid_suggest, 'codeventil'.$objp->rowid, 1, array(), 0, 0, 'maxwidth300 maxwidthonsmartphone', 'cachewithshowemptyone');
 		print '</td>';
 		
 		// Colonne choix ligne a ventiler
 		print '<td align="right">';
-		print '<input type="checkbox" class="checkforaction" name="mesCasesCochees[]" value="' . $objp->rowid . "_" . $i . '"' . ($objp->aarowid ? "checked" : "") . '/>';
+		print '<input type="checkbox" class="flat checkforselect" name="toselect[]" value="' . $objp->rowid . "_" . $i . '"' . ($objp->aarowid ? "checked" : "") . '/>';
 		print '</td>';
 
 		print "</tr>";
@@ -375,6 +415,8 @@ if ($result) {
 	}
 
 	print '</table>';
+	print "</div>";
+	
 	print '</form>';
 } else {
 	print $db->error();

+ 9 - 4
htdocs/adherents/class/adherent.class.php

@@ -83,6 +83,9 @@ class Adherent extends CommonObject
     var $datevalid;
     var $birth;
 
+    var $note_public;
+    var $note_private;
+
     var $typeid;			// Id type adherent
     var $type;				// Libelle type adherent
     var $need_subscription;
@@ -410,7 +413,9 @@ class Adherent extends CommonObject
 		$this->country_id=($this->country_id > 0?$this->country_id:$this->country_id);
 		$this->state_id=($this->state_id > 0?$this->state_id:$this->state_id);
 		if (! empty($conf->global->MAIN_FIRST_TO_UPPER)) $this->lastname=ucwords(trim($this->lastname));
-        if (! empty($conf->global->MAIN_FIRST_TO_UPPER)) $this->firstname=ucwords(trim($this->firstname));
+		if (! empty($conf->global->MAIN_FIRST_TO_UPPER)) $this->firstname=ucwords(trim($this->firstname));
+		$this->note_public=($this->note_public?$this->note_public:$this->note_public);
+		$this->note_private=($this->note_private?$this->note_private:$this->note_private);
 
         // Check parameters
         if (! empty($conf->global->ADHERENT_MAIL_REQUIRED) && ! isValidEMail($this->email))
@@ -440,7 +445,7 @@ class Adherent extends CommonObject
         $sql.= ", phone_perso=" .($this->phone_perso?"'".$this->db->escape($this->phone_perso)."'":"null");
         $sql.= ", phone_mobile=" .($this->phone_mobile?"'".$this->db->escape($this->phone_mobile)."'":"null");
         $sql.= ", note_private=" .($this->note_private?"'".$this->db->escape($this->note_private)."'":"null");
-        $sql.= ", note_public=" .($this->note_private?"'".$this->db->escape($this->note_public)."'":"null");
+        $sql.= ", note_public=" .($this->note_public?"'".$this->db->escape($this->note_public)."'":"null");
         $sql.= ", photo="   .($this->photo?"'".$this->photo."'":"null");
         $sql.= ", public='".$this->public."'";
         $sql.= ", statut="  .$this->statut;
@@ -1146,11 +1151,11 @@ class Adherent extends CommonObject
                 $this->birth			= $this->db->jdate($obj->birthday);
 
                 $this->note_private		= $obj->note_private;
-                $this->note_public      	= $obj->note_public;
+                $this->note_public		= $obj->note_public;
                 $this->morphy			= $obj->morphy;
 
                 $this->typeid			= $obj->fk_adherent_type;
-                $this->type			= $obj->type;
+                $this->type				= $obj->type;
                 $this->need_subscription 	= $obj->subscription;
 
                 $this->user_id			= $obj->user_id;

+ 1 - 1
htdocs/adherents/class/adherent_type.class.php

@@ -45,7 +45,7 @@ class AdherentType extends CommonObject
 	 */
 	public $cotisation;
 	/**
-	 * @var bool Subsription required
+	 * @var int Subsription required (0 or 1)
 	 * @since 5.0
 	 */
 	public $subscription;

+ 2 - 4
htdocs/adherents/class/api_members.class.php

@@ -143,7 +143,7 @@ class Members extends DolibarrApi
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve member list : '.$member->error);
+            throw new RestException(503, 'Error when retrieve member list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No member found');
@@ -200,6 +200,7 @@ class Members extends DolibarrApi
         }
 
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             // Process the status separately because it must be updated using
             // the validate() and resiliate() methods of the class Adherent.
             if ($field == 'statut') {
@@ -288,9 +289,6 @@ class Members extends DolibarrApi
      *
      * @param   object  $object    Object to clean
      * @return    array    Array of cleaned object properties
-     *
-     * @todo use an array for properties to clean
-     *
      */
     function _cleanObjectDatas($object) {
 

+ 2 - 1
htdocs/adherents/class/api_subscriptions.class.php

@@ -135,7 +135,7 @@ class Subscriptions extends DolibarrApi
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve subscription list : '.$subscription->error);
+            throw new RestException(503, 'Error when retrieve subscription list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No Subscription found');
@@ -188,6 +188,7 @@ class Subscriptions extends DolibarrApi
         }
 
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $subscription->$field = $value;
         }
 

+ 19 - 17
htdocs/adherents/list.php

@@ -250,7 +250,7 @@ $sql.=$hookmanager->resPrint;
 $sql.= $db->order($sortfield,$sortorder);
 
 // Count total nb of records with no order and no limits
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
 	$resql = $db->query($sql);
@@ -375,6 +375,7 @@ if (! empty($moreforfilter))
 $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
 $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
 
+print '<div class="div-table-responsive">';
 print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 print '<tr class="liste_titre">';
 if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
@@ -394,8 +395,8 @@ if (! empty($arrayfields['d.town']['checked']))           print_liste_field_titr
 if (! empty($arrayfields['state.nom']['checked']))        print_liste_field_titre($langs->trans("StateShort"),$_SERVER["PHP_SELF"],"state.nom","",$param,'',$sortfield,$sortorder);
 if (! empty($arrayfields['country.code_iso']['checked'])) print_liste_field_titre($langs->trans("Country"),$_SERVER["PHP_SELF"],"country.code_iso","",$param,'align="center"',$sortfield,$sortorder);
 if (! empty($arrayfields['d.phone']['checked']))          print_liste_field_titre($arrayfields['d.phone']['label'],$_SERVER["PHP_SELF"],'d.phone','',$param,'',$sortfield,$sortorder);
-if (! empty($arrayfields['d.phone_perso']['checked']))          print_liste_field_titre($arrayfields['d.phone_perso']['label'],$_SERVER["PHP_SELF"],'d.phone_perso','',$param,'',$sortfield,$sortorder);
-if (! empty($arrayfields['d.phone_mobile']['checked']))          print_liste_field_titre($arrayfields['d.phone_mobile']['label'],$_SERVER["PHP_SELF"],'d.phone_mobile','',$param,'',$sortfield,$sortorder);
+if (! empty($arrayfields['d.phone_perso']['checked']))    print_liste_field_titre($arrayfields['d.phone_perso']['label'],$_SERVER["PHP_SELF"],'d.phone_perso','',$param,'',$sortfield,$sortorder);
+if (! empty($arrayfields['d.phone_mobile']['checked']))   print_liste_field_titre($arrayfields['d.phone_mobile']['label'],$_SERVER["PHP_SELF"],'d.phone_mobile','',$param,'',$sortfield,$sortorder);
 if (! empty($arrayfields['d.email']['checked']))          print_liste_field_titre($arrayfields['d.email']['label'],$_SERVER["PHP_SELF"],'d.email','',$param,'',$sortfield,$sortorder);
 if (! empty($arrayfields['d.datefin']['checked']))        print_liste_field_titre($arrayfields['d.datefin']['label'],$_SERVER["PHP_SELF"],'d.datefin','',$param,'align="center"',$sortfield,$sortorder);
 // Extra fields
@@ -433,32 +434,32 @@ if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
 if (! empty($arrayfields['d.ref']['checked'])) 
 {
     print '<td class="liste_titre">';
-	print '<input class="flat" size="6" type="text" name="search_ref" value="'.$search_ref.'">';
+	print '<input class="flat maxwidth50" type="text" name="search_ref" value="'.dol_escape_htmltag($search_ref).'">';
     print '</td>';
 }
 
 if (! empty($arrayfields['d.firstname']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_firstname" value="'.$search_firstname.'" size="6"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_firstname" value="'.dol_escape_htmltag($search_firstname).'"></td>';
 }
 
 if (! empty($arrayfields['d.lastname']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_lastname" value="'.$search_lastname.'" size="6"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_lastname" value="'.dol_escape_htmltag($search_lastname).'"></td>';
 }
 
 if (! empty($arrayfields['d.company']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_company" value="'.$search_company.'" size="6"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_company" value="'.dol_escape_htmltag($search_company).'"></td>';
 }
 
 if (! empty($arrayfields['d.login']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_login" value="'.$search_login.'" size="6"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_login" value="'.dol_escape_htmltag($search_login).'"></td>';
 }
 
 if (! empty($arrayfields['d.morphy']['checked']))
@@ -478,24 +479,24 @@ if (! empty($arrayfields['t.libelle']['checked']))
 if (! empty($arrayfields['d.address']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_address" value="'.$search_address.'" size="5"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_address" value="'.$search_address.'"></td>';
 }
 
 if (! empty($arrayfields['d.zip']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_zip" value="'.$search_zip.'" size="5"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_zip" value="'.$search_zip.'"></td>';
 }
 if (! empty($arrayfields['d.town']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_town" value="'.$search_town.'" size="5"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_town" value="'.$search_town.'"></td>';
 }
 // State
 if (! empty($arrayfields['state.nom']['checked']))
 {
     print '<td class="liste_titre">';
-    print '<input class="flat searchstring" size="4" type="text" name="search_state" value="'.dol_escape_htmltag($search_state).'">';
+    print '<input class="flat searchstring maxwidth50" type="text" name="search_state" value="'.dol_escape_htmltag($search_state).'">';
     print '</td>';
 }
 // Country
@@ -509,25 +510,25 @@ if (! empty($arrayfields['country.code_iso']['checked']))
 if (! empty($arrayfields['d.phone']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_phone" value="'.$search_phone.'" size="5"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_phone" value="'.$search_phone.'"></td>';
 }
 // Phone perso
 if (! empty($arrayfields['d.phone_perso']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_phone_perso" value="'.$search_phone_perso.'" size="5"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_phone_perso" value="'.$search_phone_perso.'"></td>';
 }
 // Phone mobile
 if (! empty($arrayfields['d.phone_mobile']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_phone_mobile" value="'.$search_phone_mobile.'" size="5"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_phone_mobile" value="'.$search_phone_mobile.'"></td>';
 }
 // Email
 if (! empty($arrayfields['d.email']['checked'])) 
 {
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_email" value="'.$search_email.'" size="5"></td>';
+	print '<input class="flat maxwidth50" type="text" name="search_email" value="'.$search_email.'"></td>';
 }
 
 if (! empty($arrayfields['d.datefin']['checked'])) 
@@ -596,7 +597,7 @@ print "</tr>\n";
 
 $var=True;
 $i = 0;
-while ($i < $num && $i < $conf->liste_limit)
+while ($i < min($num, $limit))
 {
 	$obj = $db->fetch_object($resql);
 
@@ -842,6 +843,7 @@ $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters);    // N
 print $hookmanager->resPrint;
 
 print "</table>\n";
+print "</div>";
 print '</form>';
 
 if ($num > $limit || $page) print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_generic.png', 0, '', '', $limit, 1);

+ 7 - 3
htdocs/adherents/subscription/list.php

@@ -61,7 +61,7 @@ $result=restrictedArea($user,'adherent','','','cotisation');
  *	Actions
  */
 
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
 {
     $search="";
 	$search_ref="";
@@ -110,7 +110,7 @@ if ($search_account > 0) $sql.= " AND b.fk_account = ".$search_account;
 if ($search_amount) $sql.= natural_search('c.subscription', $search_amount, 1);
 $sql.= $db->order($sortfield,$sortorder);
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -154,7 +154,10 @@ if ($result)
 		print $langs->trans("Filter")." (".$langs->trans("Ref").", ".$langs->trans("Lastname").", ".$langs->trans("Firstname").", ".$langs->trans("EMail").", ".$langs->trans("Address")." ".$langs->trans("or")." ".$langs->trans("Town")."): ".$sall;
 	}
 
-    print '<table class="noborder" width="100%">';
+    $moreforfilter = '';
+    
+    print '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 
     print '<tr class="liste_titre">';
     print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"c.rowid",$param,"","",$sortfield,$sortorder);
@@ -301,6 +304,7 @@ if ($result)
     print "</tr>\n";
 
     print "</table>";
+    print '</div>';
 	print '</form>';
 }
 else

+ 24 - 15
htdocs/adherents/type.php

@@ -68,7 +68,7 @@ $extrafields = new ExtraFields($db);
 // fetch optionals attributes and labels
 $extralabels=$extrafields->fetch_name_optionals_label('adherent_type');
 
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 {
     $search_lastname="";
     $search_login="";
@@ -181,8 +181,11 @@ if (! $rowid && $action != 'create' && $action != 'edit')
 		$num = $db->num_rows($result);
 		$i = 0;
 
-		print '<table class="noborder" width="100%">';
-
+		$moreforfilter = '';
+		
+		print '<div class="div-table-responsive">';
+		print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+		
 		print '<tr class="liste_titre">';
 		print '<td>'.$langs->trans("Ref").'</td>';
 		print '<td>'.$langs->trans("Label").'</td>';
@@ -209,6 +212,7 @@ if (! $rowid && $action != 'create' && $action != 'edit')
 			$i++;
 		}
 		print "</table>";
+		print '</div>';
 	}
 	else
 	{
@@ -252,7 +256,7 @@ if ($action == 'create')
 
 	print '<tr><td valign="top">'.$langs->trans("WelcomeEMail").'</td><td>';
 	require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-	$doleditor=new DolEditor('mail_valid',$object->mail_valid,'',280,'dolibarr_notes','',false,true,$conf->fckeditor->enabled,15,90);
+	$doleditor=new DolEditor('mail_valid',$object->mail_valid,'',280,'dolibarr_notes','',false,true,$conf->fckeditor->enabled,15,'90%');
 	$doleditor->Create();
 	print '</td></tr>';
 
@@ -299,13 +303,13 @@ if ($rowid > 0)
 		$linkback = '<a href="'.DOL_URL_ROOT.'/adherents/type.php">'.$langs->trans("BackToList").'</a>';
 
 		// Ref
-		print '<tr><td width="15%">'.$langs->trans("Ref").'</td>';
+		print '<tr><td class="titlefield">'.$langs->trans("Ref").'</td>';
 		print '<td>';
 		print $form->showrefnav($object, 'rowid', $linkback);
 		print '</td></tr>';
 
 		// Label
-		print '<tr><td width="15%">'.$langs->trans("Label").'</td><td>'.dol_escape_htmltag($object->libelle).'</td></tr>';
+		print '<tr><td>'.$langs->trans("Label").'</td><td>'.dol_escape_htmltag($object->libelle).'</td></tr>';
 
 		print '<tr><td>'.$langs->trans("SubscriptionRequired").'</td><td>';
 		print yn($object->subscription);
@@ -410,7 +414,7 @@ if ($rowid > 0)
 		    $sql.=" AND datefin < '".$db->idate($now)."'";
 		}
 		// Count total nb of records
-		$nbtotalofrecords = 0;
+		$nbtotalofrecords = -1;
 		if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 		{
 			$resql = $db->query($sql);
@@ -462,9 +466,16 @@ if ($rowid > 0)
 		        print $langs->trans("Filter")." (".$langs->trans("Lastname").", ".$langs->trans("Firstname").", ".$langs->trans("EMail").", ".$langs->trans("Address")." ".$langs->trans("or")." ".$langs->trans("Town")."): ".$sall;
 		    }
 
-		    print '<br>';
+			print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
+			print '<input class="flat" type="hidden" name="rowid" value="'.$rowid.'" size="12"></td>';
+				
+			print '<br>';
             print_barre_liste('',$page,$_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,'',$num,$nbtotalofrecords);
-		    print '<table class="noborder" width="100%">';
+		    
+            $moreforfilter = '';
+            
+            print '<div class="div-table-responsive">';
+            print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 
 		    print '<tr class="liste_titre">';
 		    print_liste_field_titre($langs->trans("Name")." / ".$langs->trans("Company"),$_SERVER["PHP_SELF"],"d.lastname",$param,"","",$sortfield,$sortorder);
@@ -477,9 +488,6 @@ if ($rowid > 0)
 		    print "</tr>\n";
 
 			// Lignes des champs de filtre
-			print '<form method="GET" action="'.$_SERVER["PHP_SELF"].'">';
-			print '<input class="flat" type="hidden" name="rowid" value="'.$rowid.'" size="12"></td>';
-
 			print '<tr class="liste_titre">';
 
 			print '<td class="liste_titre" align="left">';
@@ -502,7 +510,6 @@ if ($rowid > 0)
 			print '</td>';
 
 			print "</tr>\n";
-			print '</form>';
 
 		    $var=True;
 		    while ($i < $num && $i < $conf->liste_limit)
@@ -596,7 +603,9 @@ if ($rowid > 0)
 		    }
 
 		    print "</table>\n";
-
+            print '</div>';
+            print '</form>';
+            
 			if ($num > $conf->liste_limit)
 			{
 			    print_barre_liste('',$page,$_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,'',$num,$nbtotalofrecords,'');
@@ -650,7 +659,7 @@ if ($rowid > 0)
 
 		print '<tr><td valign="top">'.$langs->trans("WelcomeEMail").'</td><td>';
 		require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-		$doleditor=new DolEditor('mail_valid',$object->mail_valid,'',280,'dolibarr_notes','',false,true,$conf->fckeditor->enabled,15,90);
+		$doleditor=new DolEditor('mail_valid',$object->mail_valid,'',280,'dolibarr_notes','',false,true,$conf->fckeditor->enabled,15,'90%');
 		$doleditor->Create();
 		print "</td></tr>";
 

+ 64 - 62
htdocs/admin/company.php

@@ -306,12 +306,12 @@ if ($action == 'edit' || $action == 'updateedit')
 	$var=true;
 
 	print '<table class="noborder" width="100%">';
-	print '<tr class="liste_titre"><th width="35%">'.$langs->trans("CompanyInfo").'</th><th>'.$langs->trans("Value").'</th></tr>'."\n";
+	print '<tr class="liste_titre"><th class="titlefield">'.$langs->trans("CompanyInfo").'</th><th>'.$langs->trans("Value").'</th></tr>'."\n";
 
 	// Name
 	$var=!$var;
 	print '<tr '.$bc[$var].'><td class="fieldrequired"><label for="name">'.$langs->trans("CompanyName").'</label></td><td>';
-	print '<input name="nom" id="name" size="30" value="'. ($conf->global->MAIN_INFO_SOCIETE_NOM?$conf->global->MAIN_INFO_SOCIETE_NOM:$_POST["nom"]) . '" autofocus="autofocus"></td></tr>'."\n";
+	print '<input name="nom" id="name" class="minwidth200" value="'. ($conf->global->MAIN_INFO_SOCIETE_NOM?$conf->global->MAIN_INFO_SOCIETE_NOM:$_POST["nom"]) . '" autofocus="autofocus"></td></tr>'."\n";
 
 	// Addresse
 	$var=!$var;
@@ -320,11 +320,11 @@ if ($action == 'edit' || $action == 'updateedit')
 
 	$var=!$var;
 	print '<tr '.$bc[$var].'><td><label for="zipcode">'.$langs->trans("CompanyZip").'</label></td><td>';
-	print '<input name="zipcode" id="zipcode" value="'. ($conf->global->MAIN_INFO_SOCIETE_ZIP?$conf->global->MAIN_INFO_SOCIETE_ZIP:$_POST["zipcode"]) . '" size="10"></td></tr>'."\n";
+	print '<input class="minwidth100" name="zipcode" id="zipcode" value="'. ($conf->global->MAIN_INFO_SOCIETE_ZIP?$conf->global->MAIN_INFO_SOCIETE_ZIP:$_POST["zipcode"]) . '"></td></tr>'."\n";
 
 	$var=!$var;
 	print '<tr '.$bc[$var].'><td><label for="town">'.$langs->trans("CompanyTown").'</label></td><td>';
-	print '<input name="town" id="town" size="30" value="'. ($conf->global->MAIN_INFO_SOCIETE_TOWN?$conf->global->MAIN_INFO_SOCIETE_TOWN:$_POST["town"]) . '"></td></tr>'."\n";
+	print '<input name="town" class="minwidth100" id="town" value="'. ($conf->global->MAIN_INFO_SOCIETE_TOWN?$conf->global->MAIN_INFO_SOCIETE_TOWN:$_POST["town"]) . '"></td></tr>'."\n";
 
 	// Country
 	$var=!$var;
@@ -356,20 +356,20 @@ if ($action == 'edit' || $action == 'updateedit')
 
 	$var=!$var;
 	print '<tr '.$bc[$var].'><td><label for="email">'.$langs->trans("EMail").'</label></td><td>';
-	print '<input name="mail" id="email" size="60" value="'. $conf->global->MAIN_INFO_SOCIETE_MAIL . '"></td></tr>';
+	print '<input name="mail" id="email" class="minwidth200" value="'. $conf->global->MAIN_INFO_SOCIETE_MAIL . '"></td></tr>';
 	print '</td></tr>'."\n";
 
 	// Web
 	$var=!$var;
 	print '<tr '.$bc[$var].'><td><label for="web">'.$langs->trans("Web").'</label></td><td>';
-	print '<input name="web" id="web" size="60" value="'. $conf->global->MAIN_INFO_SOCIETE_WEB . '"></td></tr>';
+	print '<input name="web" id="web" class="minwidth300" value="'. $conf->global->MAIN_INFO_SOCIETE_WEB . '"></td></tr>';
 	print '</td></tr>'."\n";
 
 	// Barcode
 	if (! empty($conf->barcode->enabled)) {
 		$var=!$var;
 		print '<tr '.$bc[$var].'><td><label for="barcode">'.$langs->trans("Gencod").'</label></td><td>';
-		print '<input name="barcode" id="barcode" size="40" value="'. $conf->global->MAIN_INFO_SOCIETE_GENCOD . '"></td></tr>';
+		print '<input name="barcode" id="barcode" class="minwidth150" value="'. $conf->global->MAIN_INFO_SOCIETE_GENCOD . '"></td></tr>';
 		print '</td></tr>';
 	}
 
@@ -377,7 +377,7 @@ if ($action == 'edit' || $action == 'updateedit')
 	$var=!$var;
 	print '<tr'.dol_bc($var,'hideonsmartphone').'><td><label for="logo">'.$langs->trans("Logo").' (png,jpg)</label></td><td>';
 	print '<table width="100%" class="nobordernopadding"><tr class="nocellnopadd"><td valign="middle" class="nocellnopadd">';
-	print '<input type="file" class="flat" name="logo" id="logo" size="50">';
+	print '<input type="file" class="flat class=minwidth200" name="logo" id="logo">';
 	print '</td><td class="nocellnopadd" valign="middle" align="right">';
 	if (! empty($mysoc->logo_mini)) {
 		print '<a href="'.$_SERVER["PHP_SELF"].'?action=removelogo">'.img_delete($langs->trans("Delete")).'</a>';
@@ -393,7 +393,7 @@ if ($action == 'edit' || $action == 'updateedit')
 
 	// Note
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td valign="top"><label for="note">'.$langs->trans("Note").'</label></td><td>';
+	print '<tr '.$bc[$var].'><td class="tdtop"><label for="note">'.$langs->trans("Note").'</label></td><td>';
 	print '<textarea class="flat quatrevingtpercent" name="note" id="note" rows="'.ROWS_5.'">'.(! empty($conf->global->MAIN_INFO_SOCIETE_NOTE) ? $conf->global->MAIN_INFO_SOCIETE_NOTE : '').'</textarea></td></tr>';
 	print '</td></tr>';
 
@@ -410,13 +410,13 @@ if ($action == 'edit' || $action == 'updateedit')
 
 	// Managing Director(s)
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%"><label for="director">'.$langs->trans("ManagingDirectors").'</label></td><td>';
-	print '<input name="MAIN_INFO_SOCIETE_MANAGERS" id="director" size="80" value="' . $conf->global->MAIN_INFO_SOCIETE_MANAGERS . '"></td></tr>';
+	print '<tr '.$bc[$var].'><td><label for="director">'.$langs->trans("ManagingDirectors").'</label></td><td>';
+	print '<input name="MAIN_INFO_SOCIETE_MANAGERS" id="director" class="minwidth200" value="' . $conf->global->MAIN_INFO_SOCIETE_MANAGERS . '"></td></tr>';
 
 	// Capital
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%"><label for="capital">'.$langs->trans("Capital").'</label></td><td>';
-	print '<input name="capital" id="capital" size="20" value="' . $conf->global->MAIN_INFO_CAPITAL . '"></td></tr>';
+	print '<tr '.$bc[$var].'><td><label for="capital">'.$langs->trans("Capital").'</label></td><td>';
+	print '<input name="capital" id="capital" class="minwidth100" value="' . $conf->global->MAIN_INFO_CAPITAL . '"></td></tr>';
 
 	// Juridical Status
 	$var=!$var;
@@ -432,10 +432,10 @@ if ($action == 'edit' || $action == 'updateedit')
 	if ($langs->transcountry("ProfId1",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%"><label for="profid1">'.$langs->transcountry("ProfId1",$mysoc->country_code).'</label></td><td>';
+		print '<tr '.$bc[$var].'><td><label for="profid1">'.$langs->transcountry("ProfId1",$mysoc->country_code).'</label></td><td>';
 		if (! empty($mysoc->country_code))
 		{
-			print '<input name="siren" id="profid1" size="20" value="' . (! empty($conf->global->MAIN_INFO_SIREN) ? $conf->global->MAIN_INFO_SIREN : '') . '">';
+			print '<input name="siren" id="profid1" class="minwidth200" value="' . (! empty($conf->global->MAIN_INFO_SIREN) ? $conf->global->MAIN_INFO_SIREN : '') . '">';
 		}
 		else
 		{
@@ -448,10 +448,10 @@ if ($action == 'edit' || $action == 'updateedit')
 	if ($langs->transcountry("ProfId2",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%"><label for="profid2">'.$langs->transcountry("ProfId2",$mysoc->country_code).'</label></td><td>';
+		print '<tr '.$bc[$var].'><td><label for="profid2">'.$langs->transcountry("ProfId2",$mysoc->country_code).'</label></td><td>';
 		if (! empty($mysoc->country_code))
 		{
-			print '<input name="siret" id="profid2" size="20" value="' . (! empty($conf->global->MAIN_INFO_SIRET) ? $conf->global->MAIN_INFO_SIRET : '' ) . '">';
+			print '<input name="siret" id="profid2" class="minwidth200" value="' . (! empty($conf->global->MAIN_INFO_SIRET) ? $conf->global->MAIN_INFO_SIRET : '' ) . '">';
 		}
 		else
 		{
@@ -464,10 +464,10 @@ if ($action == 'edit' || $action == 'updateedit')
 	if ($langs->transcountry("ProfId3",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%"><label for="profid3">'.$langs->transcountry("ProfId3",$mysoc->country_code).'</label></td><td>';
+		print '<tr '.$bc[$var].'><td><label for="profid3">'.$langs->transcountry("ProfId3",$mysoc->country_code).'</label></td><td>';
 		if (! empty($mysoc->country_code))
 		{
-			print '<input name="ape" id="profid3" size="20" value="' . (! empty($conf->global->MAIN_INFO_APE) ? $conf->global->MAIN_INFO_APE : '') . '">';
+			print '<input name="ape" id="profid3" class="minwidth200" value="' . (! empty($conf->global->MAIN_INFO_APE) ? $conf->global->MAIN_INFO_APE : '') . '">';
 		}
 		else
 		{
@@ -480,10 +480,10 @@ if ($action == 'edit' || $action == 'updateedit')
 	if ($langs->transcountry("ProfId4",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%"><label for="profid4">'.$langs->transcountry("ProfId4",$mysoc->country_code).'</label></td><td>';
+		print '<tr '.$bc[$var].'><td><label for="profid4">'.$langs->transcountry("ProfId4",$mysoc->country_code).'</label></td><td>';
 		if (! empty($mysoc->country_code))
 		{
-			print '<input name="rcs" id="profid4" size="20" value="' . (! empty($conf->global->MAIN_INFO_RCS) ? $conf->global->MAIN_INFO_RCS : '') . '">';
+			print '<input name="rcs" id="profid4" class="minwidth200" value="' . (! empty($conf->global->MAIN_INFO_RCS) ? $conf->global->MAIN_INFO_RCS : '') . '">';
 		}
 		else
 		{
@@ -496,10 +496,10 @@ if ($action == 'edit' || $action == 'updateedit')
 	if ($langs->transcountry("ProfId5",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%"><label for="profid5">'.$langs->transcountry("ProfId5",$mysoc->country_code).'</label></td><td>';
+		print '<tr '.$bc[$var].'><td><label for="profid5">'.$langs->transcountry("ProfId5",$mysoc->country_code).'</label></td><td>';
 		if (! empty($mysoc->country_code))
 		{
-			print '<input name="MAIN_INFO_PROFID5" id="profid5" size="20" value="' . (! empty($conf->global->MAIN_INFO_PROFID5) ? $conf->global->MAIN_INFO_PROFID5 : '') . '">';
+			print '<input name="MAIN_INFO_PROFID5" id="profid5" class="minwidth200" value="' . (! empty($conf->global->MAIN_INFO_PROFID5) ? $conf->global->MAIN_INFO_PROFID5 : '') . '">';
 		}
 		else
 		{
@@ -512,10 +512,10 @@ if ($action == 'edit' || $action == 'updateedit')
 	if ($langs->transcountry("ProfId6",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%"><label for="profid6">'.$langs->transcountry("ProfId6",$mysoc->country_code).'</label></td><td>';
+		print '<tr '.$bc[$var].'><td><label for="profid6">'.$langs->transcountry("ProfId6",$mysoc->country_code).'</label></td><td>';
 		if (! empty($mysoc->country_code))
 		{
-			print '<input name="MAIN_INFO_PROFID6" id="profid6" size="20" value="' . (! empty($conf->global->MAIN_INFO_PROFID6) ? $conf->global->MAIN_INFO_PROFID6 : '') . '">';
+			print '<input name="MAIN_INFO_PROFID6" id="profid6" class="minwidth200" value="' . (! empty($conf->global->MAIN_INFO_PROFID6) ? $conf->global->MAIN_INFO_PROFID6 : '') . '">';
 		}
 		else
 		{
@@ -526,13 +526,13 @@ if ($action == 'edit' || $action == 'updateedit')
 
 	// TVA Intra
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%"><label for="intra_vat">'.$langs->trans("VATIntra").'</label></td><td>';
-	print '<input name="tva" id="intra_vat" size="20" value="' . (! empty($conf->global->MAIN_INFO_TVAINTRA) ? $conf->global->MAIN_INFO_TVAINTRA : '') . '">';
+	print '<tr '.$bc[$var].'><td><label for="intra_vat">'.$langs->trans("VATIntra").'</label></td><td>';
+	print '<input name="tva" id="intra_vat" class="minwidth200" value="' . (! empty($conf->global->MAIN_INFO_TVAINTRA) ? $conf->global->MAIN_INFO_TVAINTRA : '') . '">';
 	print '</td></tr>';
 	
 	// Object of the company
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%"><label for="object">'.$langs->trans("CompanyObject").'</label></td><td>';
+	print '<tr '.$bc[$var].'><td><label for="object">'.$langs->trans("CompanyObject").'</label></td><td>';
 	print '<textarea class="flat quatrevingtpercent" name="object" id="object" rows="'.ROWS_5.'">'.(! empty($conf->global->MAIN_INFO_SOCIETE_OBJECT) ? $conf->global->MAIN_INFO_SOCIETE_OBJECT : '').'</textarea></td></tr>';
 	print '</td></tr>';
 
@@ -543,12 +543,12 @@ if ($action == 'edit' || $action == 'updateedit')
 	print '<br>';
 	print '<table class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
-	print '<td>'.$langs->trans("FiscalYearInformation").'</td><td>'.$langs->trans("Value").'</td>';
+	print '<td class="titlefield">'.$langs->trans("FiscalYearInformation").'</td><td>'.$langs->trans("Value").'</td>';
 	print "</tr>\n";
 	$var=true;
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%"><label for="fiscalmonthstart">'.$langs->trans("FiscalMonthStart").'</label></td><td>';
+	print '<tr '.$bc[$var].'><td><label for="fiscalmonthstart">'.$langs->trans("FiscalMonthStart").'</label></td><td>';
 	print $formother->select_month($conf->global->SOCIETE_FISCAL_MONTH_START,'fiscalmonthstart',0,1) . '</td></tr>';
 
 	print "</table>";
@@ -558,7 +558,7 @@ if ($action == 'edit' || $action == 'updateedit')
 	print '<br>';
 	print '<table class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
-	print '<td>'.$langs->trans("VATManagement").'</td><td>'.$langs->trans("Description").'</td>';
+	print '<td class="titlefield">'.$langs->trans("VATManagement").'</td><td>'.$langs->trans("Description").'</td>';
 	print '<td align="right">&nbsp;</td>';
 	print "</tr>\n";
 	$var=true;
@@ -699,19 +699,19 @@ else
 	$var=true;
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("CompanyName").'</td><td>';
+	print '<tr '.$bc[$var].'><td class="titlefield">'.$langs->trans("CompanyName").'</td><td>';
 	if (! empty($conf->global->MAIN_INFO_SOCIETE_NOM)) print $conf->global->MAIN_INFO_SOCIETE_NOM;
 	else print img_warning().' <font class="error">'.$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("CompanyName")).'</font>';
 	print '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("CompanyAddress").'</td><td>' . nl2br(empty($conf->global->MAIN_INFO_SOCIETE_ADDRESS)?'':$conf->global->MAIN_INFO_SOCIETE_ADDRESS) . '</td></tr>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("CompanyAddress").'</td><td>' . nl2br(empty($conf->global->MAIN_INFO_SOCIETE_ADDRESS)?'':$conf->global->MAIN_INFO_SOCIETE_ADDRESS) . '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("CompanyZip").'</td><td>' . (empty($conf->global->MAIN_INFO_SOCIETE_ZIP)?'':$conf->global->MAIN_INFO_SOCIETE_ZIP) . '</td></tr>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("CompanyZip").'</td><td>' . (empty($conf->global->MAIN_INFO_SOCIETE_ZIP)?'':$conf->global->MAIN_INFO_SOCIETE_ZIP) . '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("CompanyTown").'</td><td>' . (empty($conf->global->MAIN_INFO_SOCIETE_TOWN)?'':$conf->global->MAIN_INFO_SOCIETE_TOWN) . '</td></tr>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("CompanyTown").'</td><td>' . (empty($conf->global->MAIN_INFO_SOCIETE_TOWN)?'':$conf->global->MAIN_INFO_SOCIETE_TOWN) . '</td></tr>';
 
 	$var=!$var;
 	print '<tr '.$bc[$var].'><td>'.$langs->trans("CompanyCountry").'</td><td>';
@@ -731,7 +731,7 @@ else
 	print '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("CompanyCurrency").'</td><td>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("CompanyCurrency").'</td><td>';
 	print currency_name($conf->currency,1);
 	print ' ('.$conf->currency;
 	print ($conf->currency != $langs->getCurrencySymbol($conf->currency) ? ' - '.$langs->getCurrencySymbol($conf->currency) : '');
@@ -739,52 +739,54 @@ else
 	print '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("Phone").'</td><td>' . dol_print_phone($conf->global->MAIN_INFO_SOCIETE_TEL,$mysoc->country_code) . '</td></tr>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("Phone").'</td><td>' . dol_print_phone($conf->global->MAIN_INFO_SOCIETE_TEL,$mysoc->country_code) . '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("Fax").'</td><td>' . dol_print_phone($conf->global->MAIN_INFO_SOCIETE_FAX,$mysoc->country_code) . '</td></tr>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("Fax").'</td><td>' . dol_print_phone($conf->global->MAIN_INFO_SOCIETE_FAX,$mysoc->country_code) . '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("Mail").'</td><td>' . dol_print_email($conf->global->MAIN_INFO_SOCIETE_MAIL,0,0,0,80) . '</td></tr>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("Mail").'</td><td>' . dol_print_email($conf->global->MAIN_INFO_SOCIETE_MAIL,0,0,0,80) . '</td></tr>';
 
 	// Web
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("Web").'</td><td>' . dol_print_url($conf->global->MAIN_INFO_SOCIETE_WEB,'_blank',80) . '</td></tr>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("Web").'</td><td>' . dol_print_url($conf->global->MAIN_INFO_SOCIETE_WEB,'_blank',80) . '</td></tr>';
 
 	// Barcode
 	if (! empty($conf->barcode->enabled))
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("Gencod").'</td><td>' . $conf->global->MAIN_INFO_SOCIETE_GENCOD . '</td></tr>';
+		print '<tr '.$bc[$var].'><td>'.$langs->trans("Gencod").'</td><td>' . $conf->global->MAIN_INFO_SOCIETE_GENCOD . '</td></tr>';
 	}
 
 	// Logo
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("Logo").'</td><td>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("Logo").'</td><td>';
 
-	print '<table width="100%" class="nobordernopadding"><tr class="nocellnopadd"><td valign="middle" class="nocellnopadd">';
+	$tagtd='tagtd ';
+	if ($conf->browser->layout == 'phone') $tagtd='';
+	print '<div class="tagtable centpercent"><div class="tagtr inline-block centpercent valignmiddle"><div class="'.$tagtd.'inline-block valignmiddle left">';
 	print $mysoc->logo;
-	print '</td><td class="nocellnopadd" valign="center" align="right">';
+	print '</div><div class="'.$tagtd.'inline-block valignmiddle left">';
 
 	// It offers the generation of the thumbnail if it does not exist
 	if (!is_file($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_mini) && preg_match('/(\.jpg|\.jpeg|\.png)$/i',$mysoc->logo))
 	{
-		print '<a href="'.$_SERVER["PHP_SELF"].'?action=addthumb&amp;file='.urlencode($mysoc->logo).'">'.img_picto($langs->trans('GenerateThumb'),'refresh').'</a>&nbsp;&nbsp;';
+		print '<a class="img_logo" href="'.$_SERVER["PHP_SELF"].'?action=addthumb&amp;file='.urlencode($mysoc->logo).'">'.img_picto($langs->trans('GenerateThumb'),'refresh').'</a>&nbsp;&nbsp;';
 	}
 	else if ($mysoc->logo_mini && is_file($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_mini))
 	{
-		print '<img src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=companylogo&amp;file='.urlencode('/thumbs/'.$mysoc->logo_mini).'">';
+		print '<img class="img_logo" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=companylogo&amp;file='.urlencode('/thumbs/'.$mysoc->logo_mini).'">';
 	}
 	else
 	{
-		print '<img height="30" src="'.DOL_URL_ROOT.'/public/theme/common/nophoto.png">';
+		print '<img class="img_logo" src="'.DOL_URL_ROOT.'/public/theme/common/nophoto.png">';
 	}
-	print '</td></tr></table>';
+	print '</div></div></div>';
 
 	print '</td></tr>';
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%" valign="top">'.$langs->trans("Note").'</td><td>' . (! empty($conf->global->MAIN_INFO_SOCIETE_NOTE) ? nl2br($conf->global->MAIN_INFO_SOCIETE_NOTE) : '') . '</td></tr>';
+	print '<tr '.$bc[$var].'><td valign="top">'.$langs->trans("Note").'</td><td>' . (! empty($conf->global->MAIN_INFO_SOCIETE_NOTE) ? nl2br($conf->global->MAIN_INFO_SOCIETE_NOTE) : '') . '</td></tr>';
 
 	print '</table>';
 
@@ -796,22 +798,22 @@ else
 	print '<form name="formsoc" method="post">';
 	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 	print '<table class="noborder" width="100%">';
-	print '<tr class="liste_titre"><td>'.$langs->trans("CompanyIds").'</td><td>'.$langs->trans("Value").'</td></tr>';
+	print '<tr class="liste_titre"><td class="titlefield">'.$langs->trans("CompanyIds").'</td><td>'.$langs->trans("Value").'</td></tr>';
 	$var=true;
 
 	// Managing Director(s)
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("ManagingDirectors").'</td><td>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("ManagingDirectors").'</td><td>';
 	print $conf->global->MAIN_INFO_SOCIETE_MANAGERS . '</td></tr>';
 
 	// Capital
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("Capital").'</td><td>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("Capital").'</td><td>';
 	print $conf->global->MAIN_INFO_CAPITAL . '</td></tr>';
 
 	// Juridical Status
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("JuridicalStatus").'</td><td>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("JuridicalStatus").'</td><td>';
 	print getFormeJuridiqueLabel($conf->global->MAIN_INFO_SOCIETE_FORME_JURIDIQUE);
 	print '</td></tr>';
 
@@ -819,7 +821,7 @@ else
 	if ($langs->transcountry("ProfId1",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%">'.$langs->transcountry("ProfId1",$mysoc->country_code).'</td><td>';
+		print '<tr '.$bc[$var].'><td>'.$langs->transcountry("ProfId1",$mysoc->country_code).'</td><td>';
 		if (! empty($conf->global->MAIN_INFO_SIREN))
 		{
 			print $conf->global->MAIN_INFO_SIREN;
@@ -835,7 +837,7 @@ else
 	if ($langs->transcountry("ProfId2",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%">'.$langs->transcountry("ProfId2",$mysoc->country_code).'</td><td>';
+		print '<tr '.$bc[$var].'><td>'.$langs->transcountry("ProfId2",$mysoc->country_code).'</td><td>';
 		if (! empty($conf->global->MAIN_INFO_SIRET))
 		{
 			print $conf->global->MAIN_INFO_SIRET;
@@ -851,7 +853,7 @@ else
 	if ($langs->transcountry("ProfId3",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%">'.$langs->transcountry("ProfId3",$mysoc->country_code).'</td><td>';
+		print '<tr '.$bc[$var].'><td>'.$langs->transcountry("ProfId3",$mysoc->country_code).'</td><td>';
 		if (! empty($conf->global->MAIN_INFO_APE))
 		{
 			print $conf->global->MAIN_INFO_APE;
@@ -867,7 +869,7 @@ else
 	if ($langs->transcountry("ProfId4",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%">'.$langs->transcountry("ProfId4",$mysoc->country_code).'</td><td>';
+		print '<tr '.$bc[$var].'><td>'.$langs->transcountry("ProfId4",$mysoc->country_code).'</td><td>';
 		if (! empty($conf->global->MAIN_INFO_RCS))
 		{
 			print $conf->global->MAIN_INFO_RCS;
@@ -883,7 +885,7 @@ else
 	if ($langs->transcountry("ProfId5",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%">'.$langs->transcountry("ProfId5",$mysoc->country_code).'</td><td>';
+		print '<tr '.$bc[$var].'><td>'.$langs->transcountry("ProfId5",$mysoc->country_code).'</td><td>';
 		if (! empty($conf->global->MAIN_INFO_PROFID5))
 		{
 			print $conf->global->MAIN_INFO_PROFID5;
@@ -899,7 +901,7 @@ else
 	if ($langs->transcountry("ProfId6",$mysoc->country_code) != '-')
 	{
 		$var=!$var;
-		print '<tr '.$bc[$var].'><td width="35%">'.$langs->transcountry("ProfId6",$mysoc->country_code).'</td><td>';
+		print '<tr '.$bc[$var].'><td>'.$langs->transcountry("ProfId6",$mysoc->country_code).'</td><td>';
 		if (! empty($conf->global->MAIN_INFO_PROFID6))
 		{
 			print $conf->global->MAIN_INFO_PROFID6;
@@ -950,7 +952,7 @@ else
 	print '</tr>';
 	
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%" valign="top">'.$langs->trans("CompanyObject").'</td><td>' . (! empty($conf->global->MAIN_INFO_SOCIETE_OBJECT) ? nl2br($conf->global->MAIN_INFO_SOCIETE_OBJECT) : '') . '</td></tr>';
+	print '<tr '.$bc[$var].'><td valign="top">'.$langs->trans("CompanyObject").'</td><td>' . (! empty($conf->global->MAIN_INFO_SOCIETE_OBJECT) ? nl2br($conf->global->MAIN_INFO_SOCIETE_OBJECT) : '') . '</td></tr>';
 
 	print '</table>';
 	print '</form>';
@@ -961,12 +963,12 @@ else
 	print '<br>';
 	print '<table class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
-	print '<td>'.$langs->trans("FiscalYearInformation").'</td><td>'.$langs->trans("Value").'</td>';
+	print '<td class="titlefield">'.$langs->trans("FiscalYearInformation").'</td><td>'.$langs->trans("Value").'</td>';
 	print "</tr>\n";
 	$var=true;
 
 	$var=!$var;
-	print '<tr '.$bc[$var].'><td width="35%">'.$langs->trans("FiscalMonthStart").'</td><td>';
+	print '<tr '.$bc[$var].'><td>'.$langs->trans("FiscalMonthStart").'</td><td>';
 	$monthstart=(! empty($conf->global->SOCIETE_FISCAL_MONTH_START)) ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1;
 	print dol_print_date(dol_mktime(12,0,0,$monthstart,1,2000,1),'%B','gm') . '</td></tr>';
 

+ 33 - 7
htdocs/admin/dict.php

@@ -86,7 +86,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,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);
+$taborder=array(9,0,4,3,2,0,1,8,19,16,27,0,5,11,0,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,32,0);
 
 // Name of SQL tables of dictionaries
 $tabname=array();
@@ -1034,9 +1034,9 @@ if ($id)
             if ($fieldlist[$field]=='nbjour')          { $valuetoshow=$langs->trans("NbOfDays"); }
             if ($fieldlist[$field]=='type_cdr')        { $valuetoshow=$langs->trans("AtEndOfMonth"); $align="center"; }
             if ($fieldlist[$field]=='decalage')        { $valuetoshow=$langs->trans("Offset"); }
-            if ($fieldlist[$field]=='width')           { $valuetoshow=$langs->trans("Width"); }
-            if ($fieldlist[$field]=='height')          { $valuetoshow=$langs->trans("Height"); }
-            if ($fieldlist[$field]=='unit')            { $valuetoshow=$langs->trans("MeasuringUnit"); }
+            if ($fieldlist[$field]=='width' || $fieldlist[$field]=='nx') { $valuetoshow=$langs->trans("Width"); }
+            if ($fieldlist[$field]=='height' || $fieldlist[$field]=='ny') { $valuetoshow=$langs->trans("Height"); }
+            if ($fieldlist[$field]=='unit' || $fieldlist[$field]=='metric') { $valuetoshow=$langs->trans("MeasuringUnit"); }
             if ($fieldlist[$field]=='region_id' || $fieldlist[$field]=='country_id') { $valuetoshow=''; }
             if ($fieldlist[$field]=='accountancy_code'){ $valuetoshow=$langs->trans("AccountancyCode"); }
             if ($fieldlist[$field]=='accountancy_code_sell'){ $valuetoshow=$langs->trans("AccountancyCodeSell"); }
@@ -1052,6 +1052,18 @@ if ($id)
 			if ($fieldlist[$field]=='sens')            { $valuetoshow=$langs->trans("Sens"); }
 			if ($fieldlist[$field]=='category_type')   { $valuetoshow=$langs->trans("Calculated"); }
 			if ($fieldlist[$field]=='formula')         { $valuetoshow=$langs->trans("Formula"); }
+			if ($fieldlist[$field]=='paper_size')      { $valuetoshow=$langs->trans("PaperSize"); }
+			if ($fieldlist[$field]=='orientation')     { $valuetoshow=$langs->trans("Orientation"); }
+			if ($fieldlist[$field]=='leftmargin')      { $valuetoshow=$langs->trans("LeftMargin"); }
+			if ($fieldlist[$field]=='topmargin')       { $valuetoshow=$langs->trans("TopMargin"); }
+			if ($fieldlist[$field]=='spacex')          { $valuetoshow=$langs->trans("SpaceX"); }
+			if ($fieldlist[$field]=='spacey')          { $valuetoshow=$langs->trans("SpaceY"); }
+			if ($fieldlist[$field]=='font_size')       { $valuetoshow=$langs->trans("FontSize"); }
+			if ($fieldlist[$field]=='custom_x')        { $valuetoshow=$langs->trans("CustomX"); }
+			if ($fieldlist[$field]=='custom_y')        { $valuetoshow=$langs->trans("CustomY"); }
+			if ($fieldlist[$field]=='content')         { $valuetoshow=$langs->trans("Content"); }
+			if ($fieldlist[$field]=='percent')         { $valuetoshow=$langs->trans("Percentage"); }
+			if ($fieldlist[$field]=='affect')          { $valuetoshow=$langs->trans("Info"); }
 
             if ($id == 2)	// Special cas for state page
             {
@@ -1211,9 +1223,9 @@ if ($id)
             if ($fieldlist[$field]=='nbjour')          { $valuetoshow=$langs->trans("NbOfDays"); }
             if ($fieldlist[$field]=='type_cdr')        { $valuetoshow=$langs->trans("AtEndOfMonth"); $align="center"; }
             if ($fieldlist[$field]=='decalage')        { $valuetoshow=$langs->trans("Offset"); }
-            if ($fieldlist[$field]=='width')           { $valuetoshow=$langs->trans("Width"); }
-            if ($fieldlist[$field]=='height')          { $valuetoshow=$langs->trans("Height"); }
-            if ($fieldlist[$field]=='unit')            { $valuetoshow=$langs->trans("MeasuringUnit"); }
+            if ($fieldlist[$field]=='width' || $fieldlist[$field]=='nx') { $valuetoshow=$langs->trans("Width"); }
+            if ($fieldlist[$field]=='height' || $fieldlist[$field]=='ny') { $valuetoshow=$langs->trans("Height"); }
+            if ($fieldlist[$field]=='unit' || $fieldlist[$field]=='metric') { $valuetoshow=$langs->trans("MeasuringUnit"); }
             if ($fieldlist[$field]=='region_id' || $fieldlist[$field]=='country_id') { $showfield=0; }
             if ($fieldlist[$field]=='accountancy_code'){ $valuetoshow=$langs->trans("AccountancyCode"); }
             if ($fieldlist[$field]=='accountancy_code_sell'){ $valuetoshow=$langs->trans("AccountancyCodeSell"); $sortable=0; }
@@ -1229,6 +1241,20 @@ if ($id)
 			if ($fieldlist[$field]=='sens')            { $valuetoshow=$langs->trans("Sens"); }
 			if ($fieldlist[$field]=='category_type')   { $valuetoshow=$langs->trans("Calculated"); }
 			if ($fieldlist[$field]=='formula')         { $valuetoshow=$langs->trans("Formula"); }
+			if ($fieldlist[$field]=='paper_size')      { $valuetoshow=$langs->trans("PaperSize"); }
+			if ($fieldlist[$field]=='orientation')     { $valuetoshow=$langs->trans("Orientation"); }
+			if ($fieldlist[$field]=='leftmargin')      { $valuetoshow=$langs->trans("LeftMargin"); }
+			if ($fieldlist[$field]=='topmargin')       { $valuetoshow=$langs->trans("TopMargin"); }
+			if ($fieldlist[$field]=='spacex')          { $valuetoshow=$langs->trans("SpaceX"); }
+			if ($fieldlist[$field]=='spacey')          { $valuetoshow=$langs->trans("SpaceY"); }
+			if ($fieldlist[$field]=='font_size')       { $valuetoshow=$langs->trans("FontSize"); }
+			if ($fieldlist[$field]=='custom_x')        { $valuetoshow=$langs->trans("CustomX"); }
+			if ($fieldlist[$field]=='custom_y')        { $valuetoshow=$langs->trans("CustomY"); }
+			if ($fieldlist[$field]=='content')         { $valuetoshow=$langs->trans("Content"); }
+			if ($fieldlist[$field]=='percent')         { $valuetoshow=$langs->trans("Percentage"); }
+			if ($fieldlist[$field]=='affect')          { $valuetoshow=$langs->trans("Info"); }
+			if ($fieldlist[$field]=='delay')           { $valuetoshow=$langs->trans("NoticePeriod"); }
+			if ($fieldlist[$field]=='newbymonth')      { $valuetoshow=$langs->trans("NewByMonth"); }
 
             // Affiche nom du champ
             if ($showfield)

+ 2 - 2
htdocs/admin/facture.php

@@ -638,7 +638,7 @@ if (! empty($conf->banque->enabled))
     $sql.= " FROM ".MAIN_DB_PREFIX."bank_account";
     $sql.= " WHERE clos = 0";
     $sql.= " AND courant = 1";
-    $sql.= " AND entity IN (".getEntity('bank_account', 1).")";
+    $sql.= " AND entity IN (".getEntity('bank', 1).")";
     $resql=$db->query($sql);
     if ($resql)
     {
@@ -683,7 +683,7 @@ $sql = "SELECT rowid, label";
 $sql.= " FROM ".MAIN_DB_PREFIX."bank_account";
 $sql.= " WHERE clos = 0";
 $sql.= " AND courant = 1";
-$sql.= " AND entity IN (".getEntity('bank_account', 1).")";
+$sql.= " AND entity IN (".getEntity('bank', 1).")";
 $var=True;
 $resql=$db->query($sql);
 if ($resql)

+ 4 - 4
htdocs/admin/fckeditor.php

@@ -46,27 +46,27 @@ if (!$user->admin) accessforbidden();
 $modules = array(
 'SOCIETE' => 'FCKeditorForCompany',
 'PRODUCTDESC' => 'FCKeditorForProduct',
-'MAILING' => 'FCKeditorForMailing',
 'DETAILS' => 'FCKeditorForProductDetails',
 'USERSIGN' => 'FCKeditorForUserSignature',
+'MAILING' => 'FCKeditorForMailing',
 'MAIL' => 'FCKeditorForMail'
 );
 // Conditions pour que l'option soit proposee
 $conditions = array(
 'SOCIETE' => 1,
 'PRODUCTDESC' => (! empty($conf->product->enabled) || ! empty($conf->service->enabled)),
-'MAILING' => ! empty($conf->mailing->enabled),
 'DETAILS' => (! empty($conf->facture->enabled) || ! empty($conf->propal->enabled) || ! empty($conf->commande->enabled) || ! empty($conf->supplier_proposal->enabled) || ! empty($conf->fournisseur->enabled)),
 'USERSIGN' => 1,
+'MAILING' => ! empty($conf->mailing->enabled),
 'MAIL' => (! empty($conf->facture->enabled) || ! empty($conf->propal->enabled) || ! empty($conf->commande->enabled))
 );
 // Picto
 $picto = array(
 'SOCIETE' => 'generic',
 'PRODUCTDESC' => 'product',
-'MAILING' => 'email',
-'DETAILS' => 'generic',
+'DETAILS' => 'product',
 'USERSIGN' => 'user',
+'MAILING' => 'email',
 'MAIL' => 'email'
 );
 

+ 1 - 0
htdocs/admin/ihm.php

@@ -39,6 +39,7 @@ $langs->load("products");
 $langs->load("members");
 $langs->load("projects");
 $langs->load("hrm");
+$langs->load("agenda");
 
 if (! $user->admin) accessforbidden();
 

+ 47 - 52
htdocs/admin/modules.php

@@ -286,23 +286,10 @@ if ($mode==='expdev')      print $langs->trans("ModuleFamilyExperimental")."<br>
 $h = 0;
 
 $categidx='common';    // Main
-//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';
-if (! empty($categ[$categidx]))
-{
-	$categidx='expdev';
-    $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
-    $head[$h][1] = $form->textwithpicto($langs->trans("ModuleFamilyExperimental"), $langs->trans('DoNotUseInProduction'), 1, 'warning', '', 0, 3);
-    $head[$h][2] = 'expdev';
-    $h++;
-}*/
+$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
+$head[$h][1] = $langs->trans("AvailableModules");
+$head[$h][2] = 'common';
+$h++;
 
 $categidx='marketplace';
 $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
@@ -314,17 +301,18 @@ $h++;
 print "<br>\n";
 
 
-dol_fiche_head($head, $mode, '');
-
 $var=true;
 
 if ($mode != 'marketplace')
 {
+    
     print '<form method="GET" id="searchFormList" 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="sortfield" value="'.$sortfield.'">';
     print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
+
+    dol_fiche_head($head, $mode, '');
     
     $moreforfilter = '';
     $moreforfilter.='<div class="divsearchfield">';
@@ -352,7 +340,7 @@ if ($mode != 'marketplace')
     $moreforfilter.=' ';
     $moreforfilter.='<input type="submit" name="buttonreset" class="button" value="'.dol_escape_htmltag($langs->trans("Reset")).'">';
     $moreforfilter.= '</div>';
-    
+
     if (! empty($moreforfilter))
     {
         //print '<div class="liste_titre liste_titre_bydiv centpercent">';
@@ -361,14 +349,18 @@ if ($mode != 'marketplace')
         $reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters);    // Note that $action and $object may have been modified by hook
         print $hookmanager->resPrint;
         //print '</div>';
-    }    
+    }
     
-    print '<br><br><br><br>';
+    //dol_fiche_end();
     
+    print '<div class="clearboth"></div><br>';
+    //print '<br><br><br><br>';
+
+    $moreforfilter='';
     
     // Show list of modules
-
-    print '<table summary="list_of_modules" id="list_of_modules" class="liste" width="100%">'."\n";
+    print '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'" summary="list_of_modules" id="list_of_modules" >'."\n";
 
     $oldfamily='';
 
@@ -380,7 +372,7 @@ if ($mode != 'marketplace')
         $modName = $filename[$key];
     	$objMod  = $modules[$key];
     	$dirofmodule = $dirmod[$key];
-    	 
+
     	$special = $objMod->special;
 
     	//print $objMod->name." - ".$key." - ".$objMod->special.' - '.$objMod->version."<br>";
@@ -393,9 +385,9 @@ if ($mode != 'marketplace')
         	dol_syslog("Error for module ".$key." - Property name of module looks empty", LOG_WARNING);
       		continue;
         }
-        
+
         $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
-        
+
         // Check filters
         $modulename=$objMod->getName();
         $moduledesc=$objMod->getDesc();
@@ -506,10 +498,12 @@ if ($mode != 'marketplace')
         $text='';
         if ($objMod->getDescLong()) $text.='<div class="titre">'.$objMod->getDesc().'</div><br>'.$objMod->getDescLong().'<br>';
         else $text.='<div class="titre">'.$objMod->getDesc().'</div><br>';
-        
+
         $textexternal='';
+	$imginfo="info";
         if ($objMod->isCoreOrExternalModule() == 'external')
         {
+ 	    $imginfo="info_black";
             $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;
@@ -524,7 +518,7 @@ if ($mode != 'marketplace')
         if (! empty($conf->global->$const_name)) $text.=dol_print_date($objMod->getLastActivationDate(), 'dayhour');
         else $text.=$langs->trans("Disabled");
         $text.='<br>';
-        
+
         $text.='<br><strong>'.$langs->trans("AddRemoveTabs").':</strong> ';
         if (isset($objMod->tabs) && is_array($objMod->tabs) && count($objMod->tabs))
         {
@@ -537,7 +531,7 @@ if ($mode != 'marketplace')
             }
         }
         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']))
         {
@@ -549,7 +543,7 @@ if ($mode != 'marketplace')
             }
         }
         else $text.=$langs->trans("No");
-        
+
         $text.='<br><strong>'.$langs->trans("AddBoxes").':</strong> ';
         if (isset($objMod->boxes) && is_array($objMod->boxes) && count($objMod->boxes))
         {
@@ -568,14 +562,14 @@ if ($mode != 'marketplace')
             $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))
         {
@@ -587,14 +581,14 @@ if ($mode != 'marketplace')
             }
         }
         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']))
         {
@@ -618,14 +612,14 @@ if ($mode != 'marketplace')
             }
         }
         else $text.=$langs->trans("No");
-        
+
         $text.='<br><strong>'.$langs->trans("AddMenus").':</strong> ';
         if (isset($objMod->menu) && ! empty($objMod->menu)) // objMod can be an array or just an int 1
         {
             $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))
         {
@@ -637,7 +631,7 @@ if ($mode != 'marketplace')
             }
         }
         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))
         {
@@ -649,29 +643,27 @@ if ($mode != 'marketplace')
             }
         }
         else $text.=$langs->trans("No");
-        
+
         $text.='<br><strong>'.$langs->trans("AddOtherPagesOrServices").':</strong> ';
         $text.=$langs->trans("DetectionNotPossible");
-        
-        print $form->textwithpicto('', $text, 1, 'help', 'minheight20');
+
+        print $form->textwithpicto('', $text, 1, $imginfo, 'minheight20');
 
         print '</td>';
-        
+
         // Version
         print '<td align="center" valign="top" class="nowrap">';
-        
+
         // Picto warning
         $version=$objMod->getVersion(0);
         $versiontrans=$objMod->getVersion(1);
         if (preg_match('/development/i', $version))  print img_warning($langs->trans("Development"), 'style="float: left"');
         if (preg_match('/experimental/i', $version)) print img_warning($langs->trans("Experimental"), 'style="float: left"');
         if (preg_match('/deprecated/i', $version))   print img_warning($langs->trans("Deprecated"), 'style="float: left"');
-        
-        // Picto external
-        if ($textexternal) print img_picto($langs->trans("ExternalModule",$dirofmodule), 'external', 'style="float: left"');
-        
+
+
         print $versiontrans;
-        
+
         print "</td>\n";
 
         // Activate/Disable and Setup (2 columns)
@@ -767,9 +759,12 @@ if ($mode != 'marketplace')
 
     }
     print "</table>\n";
+    print '</div>';
 }
 else
 {
+    dol_fiche_head($head, $mode, '');
+    
     // Marketplace
     print "<table summary=\"list_of_modules\" class=\"noborder\" width=\"100%\">\n";
     print "<tr class=\"liste_titre\">\n";
@@ -781,7 +776,7 @@ else
     $var=!$var;
     print "<tr ".$bc[$var].">\n";
     $url='https://www.dolistore.com';
-    print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" width="180" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.png"></a></td>';
+    print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.png"></a></td>';
     print '<td>'.$langs->trans("DoliStoreDesc").'</td>';
     print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>';
     print '</tr>';
@@ -789,18 +784,18 @@ else
     $var=!$var;
     print "<tr ".$bc[$var].">\n";
     $url='https://partners.dolibarr.org';
-    print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" width="180" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner_int.png"></a></td>';
+    print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner_int.png"></a></td>';
     print '<td>'.$langs->trans("DoliPartnersDesc").'</td>';
     print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>';
     print '</tr>';
 
     print "</table>\n";
-}
 
+    //dol_fiche_end();
+}
 
 dol_fiche_end();
 
-
 // Show warning about external users
 if ($mode != 'marketplace') print info_admin(showModulesExludedForExternal($modules))."\n";
 

+ 13 - 1
htdocs/admin/multicurrency.php

@@ -33,6 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
 
 
 // Translations
+$langs->load("admin");
 $langs->load("multicurrency");
 
 // Access control
@@ -323,8 +324,17 @@ print '<input type="text" name="rate" value="" size="13" placeholder="'.$langs->
 print '<input type="submit" class="button" value="'.$langs->trans("Add").'">';
 print '</td></form></tr>';
 
+$var=!$var;
+print '<tr '.$bc[$var].'>';
+print '<td>'.$conf->currency.$form->textwithpicto(' ', $langs->trans("BaseCurrency")).'</td>';
+print '<td align="center" width="20">&nbsp;</td>';
+print '<td align="right" width="300">1';
+print '</td></form></tr>';
+
 foreach ($TCurrency as &$currency)
 {
+	if($currency->code == $conf->currency) continue;
+	
 	$var=!$var;
 	print '<tr '.$bc[$var].'>';
 	print '<td>'.$currency->code.' - '.$currency->name.'</td>';
@@ -334,10 +344,12 @@ foreach ($TCurrency as &$currency)
 	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 	print '<input type="hidden" name="action" value="update_currency">';
 	print '<input type="hidden" name="fk_multicurrency" value="'.$currency->id.'">';
-	print '<input type="text" name="rate" value="'.($currency->rate->rate ? $currency->rate->rate : '').'" size="13" />&nbsp;';
+	print '1 '.$conf->currency.' = ';
+	print '<input type="text" name="rate" value="'.($currency->rate->rate ? $currency->rate->rate : '').'" size="13" />&nbsp;'.$currency->code.'&nbsp;';
 	print '<input type="submit" name="submit" class="button" value="'.$langs->trans("Modify").'">&nbsp;';
 	print '<input type="submit" name="submit" class="button" value="'.$langs->trans("Delete").'">';
 	print '</form>';
+
 	print '</td></tr>';
 }
 

+ 14 - 22
htdocs/admin/stock.php

@@ -324,27 +324,6 @@ else
     print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name"));
 }
 print "</td>\n</tr>\n";
-
-if (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) {
-	$var=!$var;
-	print "<tr ".$bc[$var].">";
-	print '<td width="60%">'.$langs->trans("UseDispatchStatus").'</td>';
-	print '<td width="160" align="right">';
-	if (! empty($conf->fournisseur->enabled))
-	{
-		print "<form method=\"post\" action=\"stock.php\">";
-		print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-		print "<input type=\"hidden\" name=\"action\" value=\"SUPPLIER_ORDER_USE_DISPATCH_STATUS\">";
-		print $form->selectyesno("SUPPLIER_ORDER_USE_DISPATCH_STATUS",$conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS,1,$disabled);
-		print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-		print "</form>\n";
-	}
-	else
-	{
-		print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name"));
-	}
-	print "</td>\n</tr>\n";
-}
 $found++;
 
 /*if (! $found)
@@ -461,11 +440,24 @@ print "  <td>".$langs->trans("Other")."</td>\n";
 print "  <td align=\"right\" width=\"160\">&nbsp;</td>\n";
 print '</tr>'."\n";
 
+if (! empty($conf->fournisseur->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) {
+    $var=!$var;
+    print "<tr ".$bc[$var].">";
+    print '<td width="60%">'.$langs->trans("UseDispatchStatus").'</td>';
+    print '<td width="160" align="right">';
+    print "<form method=\"post\" action=\"stock.php\">";
+    print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+    print "<input type=\"hidden\" name=\"action\" value=\"SUPPLIER_ORDER_USE_DISPATCH_STATUS\">";
+    print $form->selectyesno("SUPPLIER_ORDER_USE_DISPATCH_STATUS",$conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS,1);
+    print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
+    print "</form>\n";
+    print "</td>\n</tr>\n";
+}
+
 $var=!$var;
 
 print "<tr ".$bc[$var].">";
 print '<td width="60%">'.$langs->trans("UserWarehouseAutoCreate").'</td>';
-
 print '<td width="160" align="right">';
 print "<form method=\"post\" action=\"stock.php\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';

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

@@ -289,7 +289,7 @@ function backup_tables($outputfile, $tables='*')
 
     // Print headers and global mysql config vars
     $sqlhead = '';
-    $sqlhead .= "-- ".$db::LABEL." dump via php
+    $sqlhead .= "-- ".$db::LABEL." dump via php with Dolibarr ".DOL_VERSION."
 --
 -- Host: ".$db->db->host_info."    Database: ".$db->database_name."
 -- ------------------------------------------------------

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

@@ -165,7 +165,7 @@ $sql.= " e.fk_user, e.description,";
 $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.= " WHERE e.entity IN (".getEntity('event', 1).")";
 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); }

+ 27 - 4
htdocs/api/class/api.class.php

@@ -81,9 +81,6 @@ class DolibarrApi
      *
      * @param   object  $object	Object to clean
      * @return	array	Array of cleaned object properties
-     *
-     * @todo use an array for properties to clean
-     *
      */
     function _cleanObjectDatas($object) {
 
@@ -93,13 +90,39 @@ class DolibarrApi
         // Remove linkedObjects. We should already have linkedObjectIds that avoid huge responses
         unset($object->linkedObjects);
         
-        unset($object->lignes); // should be lines
+        unset($object->lignes); // should be ->lines
+        unset($object->oldline);
+        
+        unset($object->error);
+        unset($object->errors);
+        
+        unset($object->ref_previous);
+        unset($object->ref_next);
+        unset($object->ref_int);
+        
+        unset($object->projet);     // Should be fk_project
+        unset($object->project);    // Should be fk_project
+        unset($object->author);     // Should be fk_user_author
+        unset($object->timespent_old_duration);
+        unset($object->timespent_id);
+        unset($object->timespent_duration);
+        unset($object->timespent_date);
+        unset($object->timespent_datehour);
+        unset($object->timespent_withhour);
+        unset($object->timespent_fk_user);
+        unset($object->timespent_note);
         
         unset($object->statuts);
         unset($object->statuts_short);
         unset($object->statuts_logo);
         unset($object->statuts_long);
         
+        unset($object->element);
+        unset($object->fk_element);
+        unset($object->table_element);
+        unset($object->table_element_line);
+        unset($object->picto);
+        
         // Remove the $oldcopy property because it is not supported by the JSON
         // encoder. The following error is generated when trying to serialize
         // it: "Error encoding/decoding JSON: Type is not supported"

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

@@ -54,7 +54,7 @@ class DictionnaryCountries extends DolibarrApi
      * @param int       $page       Page number (starting from zero)
      * @param string    $filter     To filter the countries by name
      * @param string    $lang       Code of the language the label of the countries must be translated to
-     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
+     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
      * @return List of countries
      *            
      * @throws RestException

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

@@ -47,7 +47,7 @@ class DictionnaryTowns extends DolibarrApi
      * @param int       $page       Page number (starting from zero)
      * @param string    $zipcode    To filter on zipcode
      * @param string    $town       To filter on city name
-     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
+     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
      * @return List of towns
      *            
      * @throws RestException

+ 5 - 2
htdocs/api/class/api_login.class.php

@@ -38,11 +38,14 @@ class Login
 	 *
 	 * @param   string  $login			Username
 	 * @param   string  $password		User password
-	 * @param   int     $entity			User entity
-	 * @param   int     $reset          Reset token
+	 * @param   int     $entity			Entity (when multicompany module is used). Empty means 1=first company.
+	 * @param   int     $reset          Reset token (0=get current token, 1=ask a new token, meaning that all future access using current token will failed)
      * @return  array                   Response status and user token
      *
 	 * @throws RestException
+	 * 
+	 * @url GET /
+	 * @url POST /
 	 */
 	public function index($login, $password, $entity=0, $reset=0) {
 

+ 23 - 6
htdocs/api/index.php

@@ -109,6 +109,16 @@ foreach ($modulesdir as $dir)
                 elseif ($module == 'project') {
                     $moduledirforclass = 'projet';
                 }
+                elseif ($module == 'task') {
+                    $moduledirforclass = 'projet';
+                }
+                elseif ($module == 'stock') {
+                    $moduledirforclass = 'product/stock';
+                }
+                elseif ($module == 'fournisseur') {
+                    $moduledirforclass = 'fourn';
+                }
+                //dol_syslog("Found module file ".$file." - module=".$module." - moduledirforclass=".$moduledirforclass);
                 
                 // Defined if module is enabled
                 $enabled=true;
@@ -131,6 +141,8 @@ foreach ($modulesdir as $dir)
                     {
                         while (($file_searched = readdir($handle_part))!==false)
                         {
+                            if ($file_searched == 'api_access.class.php') continue;
+                            
                             // Support of the deprecated API.
                             if (is_readable($dir_part.$file_searched) && preg_match("/^api_deprecated_(.*)\.class\.php$/i",$file_searched,$reg))
                             {
@@ -138,19 +150,28 @@ foreach ($modulesdir as $dir)
                                 require_once $dir_part.$file_searched;
                                 if (class_exists($classname))
                                 {
-                                    dol_syslog("Found deprecated API by index.php classname=".$classname." into ".$dir);
+                                    //dol_syslog("Found deprecated API by index.php: classname=".$classname." for module ".$dir." into ".$dir_part.$file_searched);
                                     $api->r->addAPIClass($classname, '/');
                                 }
+                                else
+                                {
+                                    dol_syslog("We found an api_xxx file (".$file_searched.") but class ".$classname." does not exists after loading file", LOG_WARNING);
+                                }
                             }
                             elseif (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i",$file_searched,$reg))
                             {
                                 $classname = ucwords($reg[1]);
+                                $classname = str_replace('_', '', $classname);
                                 require_once $dir_part.$file_searched;
                                 if (class_exists($classname))
                                 {
-                                    dol_syslog("Found API by index.php classname=".$classname." into ".$dir);
+                                    //dol_syslog("Found API by index.php: classname=".$classname." for module ".$dir." into ".$dir_part.$file_searched);
                                     $listofapis[] = $classname;
                                 }
+                                else
+                                {
+                                    dol_syslog("We found an api_xxx file (".$file_searched.") but class ".$classname." does not exists after loading file", LOG_WARNING);
+                                }
                             }
                         }
                     }
@@ -175,7 +196,3 @@ foreach ($listofapis as $classname)
 
 // Call API (we suppose we found it)
 $api->r->handle();
-
-
-
-

+ 7 - 2
htdocs/bookmarks/list.php

@@ -92,8 +92,11 @@ if ($resql)
     $param = "";
     if ($optioncss != '') $param ='&optioncss='.$optioncss;
 
-    print "<table class=\"noborder\" width=\"100%\">";
-
+    $moreforfilter='';
+    
+    print '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+    
     print "<tr class=\"liste_titre\">";
     //print "<td>&nbsp;</td>";
     print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"bid","", $param,'align="left"',$sortfield,$sortorder);
@@ -200,6 +203,8 @@ if ($resql)
         $i++;
     }
     print "</table>";
+    print '</div>';
+    
     $db->free($resql);
 }
 else

+ 2 - 2
htdocs/cache.manifest

@@ -33,5 +33,5 @@ NETWORK:
 # If the browser is unable to retrieve the original content, the fallback resource will be used.
 # In the example above, we display a static image in case the dynamic one is unavailable.
 FALLBACK: 
-#/ public/offline.php
-#theme/amarok/img/* theme/eldy/img/
+#/ public/notice.php
+#theme/eldy/img/* theme/md/img/*

+ 1 - 1
htdocs/categories/card.php

@@ -252,7 +252,7 @@ if ($user->rights->categorie->creer)
 		// Description
 		print '<tr><td valign="top">'.$langs->trans("Description").'</td><td>';
 		require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-		$doleditor=new DolEditor('description',$description,'',200,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_PRODUCTDESC,ROWS_6,50);
+		$doleditor=new DolEditor('description',$description,'',200,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_PRODUCTDESC,ROWS_6,'90%');
 		$doleditor->Create();
 		print '</td></tr>';
 

+ 25 - 7
htdocs/categories/class/api_categories.class.php

@@ -114,7 +114,7 @@ class Categories extends DolibarrApi
         
         $sql = "SELECT t.rowid";
         $sql.= " FROM ".MAIN_DB_PREFIX."categorie as t";
-        $sql.= ' WHERE t.entity IN ('.getEntity('categorie', 1).')';
+        $sql.= ' WHERE t.entity IN ('.getEntity('category', 1).')';
         if (!empty($type))
         {
             $sql.= ' AND t.type='.array_search($type,Categories::$TYPES);
@@ -151,13 +151,13 @@ class Categories extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $category_static = new Categorie($db);
                 if($category_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($category_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($category_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve category list : '.$category_static->error);
+            throw new RestException(503, 'Error when retrieve category list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No category found');
@@ -204,12 +204,12 @@ class Categories extends DolibarrApi
         $sql = "SELECT s.rowid";
         $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s";
         $sql.= " , ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub ";
-        $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')';
+        $sql.= ' WHERE s.entity IN ('.getEntity('category', 1).')';
         $sql.= ' AND s.type='.array_search($type,Categories::$TYPES);
         $sql.= ' AND s.rowid = sub.fk_categorie';
         $sql.= ' AND sub.'.$subcol_name.' = '.$item;
 
-        $nbtotalofrecords = 0;
+        $nbtotalofrecords = -1;
         if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
         {
             $result = $db->query($sql);
@@ -237,13 +237,13 @@ class Categories extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $category_static = new Categorie($db);
                 if($category_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($category_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($category_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve category list : '.$category_static->error);
+            throw new RestException(503, 'Error when retrieve category list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No category found');
@@ -298,6 +298,7 @@ class Categories extends DolibarrApi
 		}
 
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $this->category->$field = $value;
         }
         
@@ -339,6 +340,23 @@ class Categories extends DolibarrApi
         );
     }
     
+    
+    /**
+     * Clean sensible object datas
+     *
+     * @param   Categorie  $object    Object to clean
+     * @return    array    Array of cleaned object properties
+     */
+    function _cleanObjectDatas($object) {
+    
+        $object = parent::_cleanObjectDatas($object);
+    
+        // Remove the subscriptions because they are handled as a subresource.
+        //unset($object->subscriptions);
+    
+        return $object;
+    }
+    
     /**
      * Validate fields before create or update object
      * 

+ 9 - 8
htdocs/categories/class/api_deprecated_category.class.php

@@ -121,10 +121,10 @@ class CategoryApi extends DolibarrApi
         
         $sql = "SELECT s.rowid";
         $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s";
-        $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')';
+        $sql.= ' WHERE s.entity IN ('.getEntity('category', 1).')';
         $sql.= ' AND s.type='.array_search($type,CategoryApi::$TYPES);
 
-        $nbtotalofrecords = 0;
+        $nbtotalofrecords = -1;
         if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
         {
             $result = $db->query($sql);
@@ -152,13 +152,13 @@ class CategoryApi extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $category_static = new Categorie($db);
                 if($category_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($category_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($category_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve category list : '.$category_static->error);
+            throw new RestException(503, 'Error when retrieve category list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No category found');
@@ -200,12 +200,12 @@ class CategoryApi extends DolibarrApi
         $sql = "SELECT s.rowid";
         $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s";
         $sql.= " , ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub ";
-        $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')';
+        $sql.= ' WHERE s.entity IN ('.getEntity('category', 1).')';
         $sql.= ' AND s.type='.array_search($type,CategoryApi::$TYPES);
         $sql.= ' AND s.rowid = sub.fk_categorie';
         $sql.= ' AND sub.'.$subcol_name.' = '.$item;
 
-        $nbtotalofrecords = 0;
+        $nbtotalofrecords = -1;
         if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
         {
             $result = $db->query($sql);
@@ -233,13 +233,13 @@ class CategoryApi extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $category_static = new Categorie($db);
                 if($category_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($category_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($category_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve category list : '.$category_static->error);
+            throw new RestException(503, 'Error when retrieve category list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No category found');
@@ -425,6 +425,7 @@ class CategoryApi extends DolibarrApi
 		}
 
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $this->category->$field = $value;
         }
         

+ 1 - 1
htdocs/categories/edit.php

@@ -157,7 +157,7 @@ print '<tr>';
 print '<td>'.$langs->trans("Description").'</td>';
 print '<td >';
 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-$doleditor=new DolEditor('description',$object->description,'',200,'dolibarr_notes','',false,true,$conf->fckeditor->enabled,ROWS_6,50);
+$doleditor=new DolEditor('description',$object->description,'',200,'dolibarr_notes','',false,true,$conf->fckeditor->enabled,ROWS_6,'90%');
 $doleditor->Create();
 print '</td></tr>';
 

+ 2 - 2
htdocs/categories/traduction.php

@@ -205,7 +205,7 @@ if ($action == 'edit')
 			print '<table class="border" width="100%">';
 			print '<tr><td class="fieldtitlecreate fieldrequired">'.$langs->trans('Label').'</td><td><input name="libelle-'.$key.'" size="40" value="'.$object->multilangs[$key]["label"].'"></td></tr>';
 			print '<tr><td class="tdtop">'.$langs->trans('Description').'</td><td>';
-			$doleditor = new DolEditor("desc-$key", $object->multilangs[$key]["description"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80);
+			$doleditor = new DolEditor("desc-$key", $object->multilangs[$key]["description"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_3,'90%');
 			$doleditor->Create();
 			print '</td></tr>';
 
@@ -285,7 +285,7 @@ if ($action == 'add' && ($user->rights->produit->creer || $user->rights->service
 	print '</td></tr>';
 	print '<tr><td class="fieldrequired">'.$langs->trans('Label').'</td><td><input name="libelle" size="40"></td></tr>';
 	print '<tr><td class="tdtop">'.$langs->trans('Description').'</td><td>';
-	$doleditor = new DolEditor('desc', '', '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80);
+	$doleditor = new DolEditor('desc', '', '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_3,'90%');
 	$doleditor->Create();
 	print '</td></tr>';
 

+ 1 - 1
htdocs/categories/viewcat.php

@@ -199,7 +199,7 @@ dol_fiche_head($head, 'card', $title, 0, 'category');
 
 if ($action == 'delete')
 {
-	print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;type='.$type,$langs->trans('DeleteCategory'),$langs->trans('ConfirmDeleteCategory'),'confirm_delete');
+	print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;type='.$type, $langs->trans('DeleteCategory'), $langs->trans('ConfirmDeleteCategory'), 'confirm_delete', '', '', 1);
 }
 
 print '<table width="100%" class="border">';

+ 2 - 2
htdocs/comm/action/card.php

@@ -819,7 +819,7 @@ if ($action == 'create')
     // Description
     print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td>';
     require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-    $doleditor=new DolEditor('note',(GETPOST('note')?GETPOST('note'):$object->note),'',180,'dolibarr_notes','In',true,true,$conf->fckeditor->enabled,ROWS_6,90);
+    $doleditor=new DolEditor('note',(GETPOST('note')?GETPOST('note'):$object->note),'',180,'dolibarr_notes','In',true,true,$conf->fckeditor->enabled,ROWS_5,'90%');
     $doleditor->Create();
     print '</td></tr>';
 
@@ -1151,7 +1151,7 @@ if ($id > 0)
         print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td>';
         // Editeur wysiwyg
         require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-        $doleditor=new DolEditor('note',$object->note,'',200,'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>';
 

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

@@ -870,7 +870,7 @@ class ActionComm extends CommonObject
 
         $sql = "SELECT a.id";
         $sql.= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
-        $sql.= " WHERE a.entity IN (".getEntity('actioncomm', 1).")";
+        $sql.= " WHERE a.entity IN (".getEntity('agenda', 1).")";
         if (! empty($socid)) $sql.= " AND a.fk_soc = ".$socid;
         if (! empty($elementtype))
         {
@@ -921,7 +921,7 @@ class ActionComm extends CommonObject
         if (! $user->rights->societe->client->voir && ! $user->societe_id) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON a.fk_soc = sc.fk_soc";
         $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON a.fk_soc = s.rowid";
         $sql.= " WHERE a.percent >= 0 AND a.percent < 100";
-        $sql.= " AND a.entity IN (".getEntity('actioncomm', 1).")";
+        $sql.= " AND a.entity IN (".getEntity('agenda', 1).")";
         if (! $user->rights->societe->client->voir && ! $user->societe_id) $sql.= " AND (a.fk_soc IS NULL OR sc.fk_user = " .$user->id . ")";
         if ($user->societe_id) $sql.=" AND a.fk_soc = ".$user->societe_id;
         if (! $user->rights->agenda->allactions->read) $sql.= " AND (a.fk_user_author = ".$user->id . " OR a.fk_user_action = ".$user->id . " OR a.fk_user_done = ".$user->id . ")";
@@ -1281,7 +1281,7 @@ class ActionComm extends CommonObject
 			// We must filter on assignement table
 			if ($filters['logint'] || $filters['login']) $sql.=", ".MAIN_DB_PREFIX."actioncomm_resources as ar";
 			$sql.= " WHERE a.fk_action=c.id";
-            $sql.= " AND a.entity IN (".getEntity('actioncomm', 1).")";
+            $sql.= " AND a.entity IN (".getEntity('agenda', 1).")";
             foreach ($filters as $key => $value)
             {
                 if ($key == 'notolderthan' && $value != '') $sql.=" AND a.datep >= '".$this->db->idate($now-($value*24*60*60))."'";

+ 13 - 6
htdocs/comm/action/class/api_agendaevents.class.php

@@ -102,13 +102,19 @@ class AgendaEvents extends DolibarrApi
         
         $obj_ret = array();
 
-        // case of external user, $societe param is ignored and replaced by user's socid
-        //$socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $societe;
-            
+        // case of external user
+        $socid = 0;
+        if (! empty(DolibarrApiAccess::$user->societe_id)) $socid = DolibarrApiAccess::$user->societe_id;
+        
+        // If the internal user must only see his customers, force searching by him
+        $search_sale = 0;
+        if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id;
+        
         $sql = "SELECT t.id as rowid";
         $sql.= " FROM ".MAIN_DB_PREFIX."actioncomm as t";
-        $sql.= ' WHERE t.entity IN ('.getEntity('actioncomm', 1).')';
+        $sql.= ' WHERE t.entity IN ('.getEntity('agenda', 1).')';
         if ($user_ids) $sql.=" AND t.fk_user_action IN (".$user_ids.")";
+        if ($socid > 0) $sql.= " AND t.fk_soc = ".$socid;
         // Insert sale filter
         if ($search_sale > 0)
         {
@@ -146,13 +152,13 @@ class AgendaEvents extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $actioncomm_static = new ActionComm($db);
                 if($actioncomm_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($actioncomm_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($actioncomm_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve Agenda Event list');
+            throw new RestException(503, 'Error when retrieve Agenda Event list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No Agenda Event found');
@@ -223,6 +229,7 @@ class AgendaEvents extends DolibarrApi
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $this->expensereport->$field = $value;
         }
         

+ 10 - 11
htdocs/comm/action/listactions.php

@@ -132,7 +132,7 @@ $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action);
 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
 
 // Purge search criteria
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 {
     $actioncode='';
     $search_title='';
@@ -245,7 +245,7 @@ if ($datestart > 0) $sql.= " AND a.datep BETWEEN '".$db->idate($datestart)."' AN
 if ($dateend > 0) $sql.= " AND a.datep2 BETWEEN '".$db->idate($dateend)."' AND '".$db->idate($dateend+3600*24-1)."'";
 $sql.= $db->order($sortfield,$sortorder);
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -335,9 +335,13 @@ if ($resql)
     
     print_barre_liste($s, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $link, $num, -1 * $nbtotalofrecords, '', 0, $nav, '', $limit);
 
+    $moreforfilter='';
+    
     $i = 0;
-	print '<table class="liste" width="100%">';
-	print '<tr class="liste_titre">';
+    print '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+
+    print '<tr class="liste_titre">';
 	print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"a.id",$param,"","",$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("Title"),$_SERVER["PHP_SELF"],"a.label",$param,"","",$sortfield,$sortorder);
 	//if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) 
@@ -354,11 +358,7 @@ if ($resql)
 	print '<tr class="liste_titre">';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"><input type="text" name="search_title" value="'.$search_title.'"></td>';
-	//if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) 
-	//{
-	    print '<td class="liste_titre"></td>';
-	    //print '<td class="liste_titre"><input type="text" name="search_type" value="'.$search_type.'"></td>';
-	//}
+    print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre" align="center">';
 	print $form->select_date($datestart, 'datestart', 0, 0, 1, '', 1, 0, 1);
 	print '</td>';
@@ -367,7 +367,6 @@ if ($resql)
 	print '</td>';
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
-	//print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
     print '<td></td>';
 	// Action column
@@ -499,7 +498,7 @@ if ($resql)
 		$i++;
 	}
 	print "</table>";
-
+    print '</div>';
 	print '</form>';
 
 	$db->free($resql);

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

@@ -590,6 +590,7 @@ echo '</form>';
 //print "begin_d=".$begin_d." end_d=".$end_d;
 
 
+echo '<div class="div-table-responsive">';
 echo '<table width="100%" class="noborder nocellnopadd cal_month">';
 
 echo '<tr class="liste_titre">';
@@ -766,7 +767,7 @@ foreach ($usernames as $username)
 }
 
 echo "</table>\n";
-
+echo '</div>';
 
 if (! empty($conf->global->AGENDA_USE_EVENT_TYPE))
 {

+ 8 - 4
htdocs/comm/action/rapport/index.php

@@ -85,7 +85,7 @@ $sql.= ' AND a.entity IN ('.getEntity('agenda', 1).')';
 $sql.= " GROUP BY year, month, df";
 $sql.= " ORDER BY year DESC, month DESC, df DESC";
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -114,9 +114,13 @@ if ($resql)
 	
 	print_barre_liste($langs->trans("Actions"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_agenda', 0, '', '', $limit);
 
+	$moreforfilter='';
+	
 	$i = 0;
-	print '<table class="noborder" width="100%">';
-	print '<tr class="liste_titre">';
+    print '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+
+    print '<tr class="liste_titre">';
 	print '<td>'.$langs->trans("Date").'</td>';
 	print '<td align="center">'.$langs->trans("EventsNb").'</td>';
 	print '<td align="center">'.$langs->trans("Action").'</td>';
@@ -162,7 +166,7 @@ if ($resql)
 		$i++;
 	}
 	print "</table>";
-	
+	print '</div>';
 	print '</form>';
 	
 	$db->free($resql);

+ 1 - 1
htdocs/comm/card.php

@@ -592,7 +592,7 @@ if ($id > 0)
                 $propal_static->total_tva = $objp->total_tva;
                 $propal_static->total_ttc = $objp->total_ttc;
                 print $propal_static->getNomUrl(1);
-                if ( ($db->jdate($objp->dp) < ($now - $conf->propal->cloture->warning_delay)) && $objp->fk_statut == 1 ) {
+                if ( ($db->jdate($objp->datelimite) < ($now - $conf->propal->cloture->warning_delay)) && $objp->fk_statut == 1 ) {
                     print " ".img_warning();
                 }
 				print '</td><td align="right" width="80px">'.dol_print_date($db->jdate($objp->dp),'day')."</td>\n";

+ 1 - 1
htdocs/comm/index.php

@@ -611,7 +611,7 @@ if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire && 0) // TO
 	$sql.= ", ".MAIN_DB_PREFIX."product as p";
 	if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
 	$sql.= " WHERE c.fk_soc = s.rowid";
-	$sql.= " AND c.entity IN (".getEntity('contrat', 1).")";
+	$sql.= " AND c.entity IN (".getEntity('contract', 1).")";
 	$sql.= " AND c.fk_product = p.rowid";
 	if (! $user->rights->societe->client->voir && ! $socid)	$sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
 	if ($socid) $sql.= " AND s.rowid = ".$socid;

+ 13 - 10
htdocs/comm/mailing/advtargetemailing.php

@@ -189,6 +189,10 @@ if ($action == 'add') {
 			}
 		}
 
+		if ($array_query['type_of_target'] == 2 || $array_query['type_of_target'] == 4) {
+			$user_contact_query = true;
+		}
+
 		if (preg_match("/^type_of_target/", $key)) {
 			$array_query[$key] = GETPOST($key);
 		}
@@ -203,8 +207,8 @@ if ($action == 'add') {
 		$advTarget->thirdparty_lines = array ();
 	}*/
 
-	if ($user_contact_query && ($array_query['type_of_target'] == 1 || $array_query['type_of_target'] == 2)) {
-		$result = $advTarget->query_contact($array_query);
+	if ($user_contact_query && ($array_query['type_of_target'] == 1 || $array_query['type_of_target'] == 2 || $array_query['type_of_target'] == 4)) {
+		$result = $advTarget->query_contact($array_query, 1);
 		if ($result < 0) {
 			setEventMessage($advTarget->error, 'errors');
 		}
@@ -889,6 +893,11 @@ if ($object->fetch($id) >= 0) {
 			dol_include_once('/core/class/extrafields.class.php');
 			$extrafields = new ExtraFields($db);
 			$extralabels = $extrafields->fetch_name_optionals_label('socpeople');
+            foreach($extrafields->attribute_type as $key=>&$value) {
+                if($value == 'radio')$value = 'select';
+            }
+
+
 			foreach ( $extralabels as $key => $val ) {
 
 				print '<tr><td>' . $extrafields->attribute_label[$key];
@@ -900,8 +909,8 @@ if ($object->fetch($id) >= 0) {
 					print '<input type="text" name="options_' . $key . '_cnct"/></td><td>' . "\n";
 					print $form->textwithpicto('', $langs->trans("AdvTgtSearchTextHelp"), 1, 'help');
 				} elseif (($extrafields->attribute_type[$key] == 'int') || ($extrafields->attribute_type[$key] == 'double')) {
-					print $langs->trans("AdvTgtMinVal") . '<input type="text" name="options' . $key . '_min_cnct"/>';
-					print $langs->trans("AdvTgtMaxVal") . '<input type="text" name="options' . $key . '_max_cnct"/>';
+					print $langs->trans("AdvTgtMinVal") . '<input type="text" name="options_' . $key . '_min_cnct"/>';
+					print $langs->trans("AdvTgtMaxVal") . '<input type="text" name="options_' . $key . '_max_cnct"/>';
 					print '</td><td>' . "\n";
 					print $form->textwithpicto('', $langs->trans("AdvTgtSearchIntHelp"), 1, 'help');
 				} elseif (($extrafields->attribute_type[$key] == 'date') || ($extrafields->attribute_type[$key] == 'datetime')) {
@@ -967,12 +976,6 @@ if ($object->fetch($id) >= 0) {
 		print '</form>';
 		print '<br>';
 	}
-
-
-	if (empty($conf->mailchimp->enabled) || (! empty($conf->mailchimp->enabled) && $object->statut != 3))
-	{
-	    // List of recipients (TODO Move code of page cibles.php into a .tpl.php file and make an include here to avoid duplicate content)
-	}
 }
 
 llxFooter();

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

@@ -1196,7 +1196,7 @@ else
 			print '<div style="padding-top: 10px">';
 			// Editeur wysiwyg
 			require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-			$doleditor=new DolEditor('body',$object->body,'',320,'dolibarr_mailings','',true,true,$conf->global->FCKEDITOR_ENABLE_MAILING,20,120);
+			$doleditor=new DolEditor('body',$object->body,'',320,'dolibarr_mailings','',true,true,$conf->global->FCKEDITOR_ENABLE_MAILING,20,'90%');
 			$doleditor->Create();
 			print '</div>';
 

+ 67 - 36
htdocs/comm/mailing/cibles.php

@@ -238,14 +238,22 @@ if ($object->fetch($id) >= 0)
 	{
 		print load_fiche_titre($langs->trans("ToAddRecipientsChooseHere"), ($user->admin?info_admin($langs->trans("YouCanAddYourOwnPredefindedListHere"),1):''), 'title_generic');
 
-		print '<table class="noborder" width="100%">';
-		print '<tr class="liste_titre">';
-		print '<td class="liste_titre">'.$langs->trans("RecipientSelectionModules").'</td>';
-		print '<td class="liste_titre" align="center">'.$langs->trans("NbOfUniqueEMails").'</td>';
-		print '<td class="liste_titre" align="left">'.$langs->trans("Filter").'</td>';
-		print '<td class="liste_titre" align="center">&nbsp;</td>';
-		print "</tr>\n";
-
+		//print '<table class="noborder" width="100%">';
+		print '<div class="tagtable centpercent liste_titre_bydiv" id="tablelines">';
+		
+		//print '<tr class="liste_titre">';
+		print '<div class="tagtr liste_titre">';
+		//print '<td class="liste_titre">'.$langs->trans("RecipientSelectionModules").'</td>';
+		print '<div class="tagtd">'.$langs->trans("RecipientSelectionModules").'</div>';
+		//print '<td class="liste_titre" align="center">'.$langs->trans("NbOfUniqueEMails").'</td>';
+		print '<div class="tagtd" align="center">'.$langs->trans("NbOfUniqueEMails").'</div>';
+		//print '<td class="liste_titre" align="left">'.$langs->trans("Filter").'</td>';
+		print '<div class="tagtd" align="left">'.$langs->trans("Filter").'</div>';
+		//print '<td class="liste_titre" align="center">&nbsp;</td>';
+		print '<div class="tagtd">&nbsp;</div>';
+		//print "</tr>\n";
+		print '</div>';
+		
 		clearstatcache();
 
 		$var=true;
@@ -303,19 +311,28 @@ if ($object->fetch($id) >= 0)
 				if ($qualified)
 				{
 					$var = !$var;
-					print '<tr '.$bc[$var].'>';
+					//print '<tr '.$bc[$var].'>';
+//					print '<div '.$bctag[$var].'>';
 
 					if ($allowaddtarget)
 					{
-						print '<form name="'.$modulename.'" action="'.$_SERVER['PHP_SELF'].'?action=add&id='.$object->id.'&module='.$modulename.'" method="POST" enctype="multipart/form-data">';
+						print '<form '.$bctag[$var].' name="'.$modulename.'" action="'.$_SERVER['PHP_SELF'].'?action=add&id='.$object->id.'&module='.$modulename.'" method="POST" enctype="multipart/form-data">';
 						print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 					}
+					else
+					{
+					    print '<div '.$bctag[$var].'>';
+					}
 
-					print '<td>';
+					//print '<td>';
+					print '<div class="tagtd">';
 					if (empty($obj->picto)) $obj->picto='generic';
-					print img_object($langs->trans("Module").': '.get_class($obj),$obj->picto).' '.$obj->getDesc();
-					print '</td>';
-
+					print img_object($langs->trans("Module").': '.get_class($obj),$obj->picto);
+					print ' ';
+					print $obj->getDesc();
+					//print '</td>';
+					print '</div>';
+						
 					try {
 						$nbofrecipient=$obj->getNbOfRecipients('');
 					}
@@ -324,7 +341,8 @@ if ($object->fetch($id) >= 0)
 						dol_syslog($e->getMessage(), LOG_ERR);
 					}
 
-					print '<td align="center">';
+					//print '<td align="center">';
+					print '<div class="tagtd center">';
 					if ($nbofrecipient >= 0)
 					{
 						print $nbofrecipient;
@@ -333,41 +351,54 @@ if ($object->fetch($id) >= 0)
 					{
 						print $langs->trans("Error").' '.img_error($obj->error);
 					}
-					print '</td>';
-
-					print '<td align="left">';
-					try {
-						$filter=$obj->formFilter();
-					}
-					catch(Exception $e)
+					//print '</td>';
+					print '</div>';
+						
+					//print '<td align="left">';
+					print '<div class="tagtd" align="left">';
+					if ($allowaddtarget)
 					{
-						dol_syslog($e->getMessage(), LOG_ERR);
+    					try {
+    						$filter=$obj->formFilter();
+    					}
+    					catch(Exception $e)
+    					{
+    						dol_syslog($e->getMessage(), LOG_ERR);
+    					}
+    					if ($filter) print $filter;
+    					else print $langs->trans("None");
 					}
-					if ($filter) print $filter;
-					else print $langs->trans("None");
-					print '</td>';
-
-					print '<td align="right">';
+					//print '</td>';
+					print '</div>';
+						
+					//print '<td align="right">';
+					print '<div class="tagtd" align="right">';
 					if ($allowaddtarget)
 					{
-						print '<input type="submit" class="button" value="'.$langs->trans("Add").'">';
+						print '<input type="submit" class="button" name="button_'.$modulename.'" value="'.$langs->trans("Add").'">';
 					}
 					else
 					{
+					    print '<input type="submit" class="button disabled" disabled="disabled" name="button_'.$modulename.'" value="'.$langs->trans("Add").'">';
 						//print $langs->trans("MailNoChangePossible");
 						print "&nbsp;";
 					}
-					print '</td>';
-
+					//print '</td>';
+					print '</div>';
+						
 					if ($allowaddtarget) print '</form>';
-
-					print "</tr>\n";
+					else print '</div>';
+						
+					//print "</tr>\n";
+//					print '</div>'."\n";
 				}
 			}
 		}	// End foreach dir
 
-		print '</table>';
-		print '<br>';
+		//print '</table>';
+		print '</div>';
+		
+		print '<br><br>';
 	}
 
 	// List of selected targets
@@ -381,7 +412,7 @@ if ($object->fetch($id) >= 0)
 	$sql .= $db->order($sortfield,$sortorder);
 
 	// Count total nb of records
-	$nbtotalofrecords = 0;
+	$nbtotalofrecords = -1;
 	if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 	{
 	    $result = $db->query($sql);

+ 117 - 15
htdocs/comm/mailing/class/advtargetemailing.class.php

@@ -64,16 +64,19 @@ class AdvanceTargetingMailing extends CommonObject
 
 		$this->db = $db;
 
-		$this->select_target_type = array('2'=>$langs->trans('Contacts'),'1'=>$langs->trans('Contacts').'+'.$langs->trans('ThirdParty'),
-			'3'=>$langs->trans('ThirdParty'),
-			);
-		$this->type_statuscommprospect=array(
-			-1=>$langs->trans("StatusProspect-1"),
-			0=>$langs->trans("StatusProspect0"),
-			1=>$langs->trans("StatusProspect1"),
-			2=>$langs->trans("StatusProspect2"),
-			3=>$langs->trans("StatusProspect3"));
-
+		$this->select_target_type = array(
+				'2' => $langs->trans('Contacts'),
+				'1' => $langs->trans('Contacts') . '+' . $langs->trans('ThirdParty'),
+				'3' => $langs->trans('ThirdParty'),
+				'4' => $langs->trans('ContactsWithThirdpartyFilter')
+		);
+		$this->type_statuscommprospect = array(
+				- 1 => $langs->trans("StatusProspect-1"),
+				0 => $langs->trans("StatusProspect0"),
+				1 => $langs->trans("StatusProspect1"),
+				2 => $langs->trans("StatusProspect2"),
+				3 => $langs->trans("StatusProspect3")
+		);
 
 		return 1;
 	}
@@ -492,7 +495,7 @@ class AdvanceTargetingMailing extends CommonObject
 			}
 			if (!empty($arrayquery['cust_mothercompany'])) {
 				$str=$this->transformToSQL('nom',$arrayquery['cust_mothercompany']);
-				$sqlwhere[]= " (t.parent IN (SELECT rowid FROM " . MAIN_DB_PREFIX . "societe WHERE ('.$str.')))";
+				$sqlwhere[]= " (t.parent IN (SELECT rowid FROM " . MAIN_DB_PREFIX . "societe WHERE (".$str.")))";
 			}
 			if (!empty($arrayquery['cust_status']) && count($arrayquery['cust_status'])>0) {
 				$sqlwhere[]= " (t.status IN (".implode(',',$arrayquery['cust_status'])."))";
@@ -603,9 +606,10 @@ class AdvanceTargetingMailing extends CommonObject
 	 * Load object in memory from database
 	 *
 	 * 	@param		array		$arrayquery	All element to Query
+	 * 	@param		int			$withThirdpartyFilter	add contact with tridparty filter
 	 * 	@return		int			<0 if KO, >0 if OK
 	 */
-	function query_contact($arrayquery)
+	function query_contact($arrayquery, $withThirdpartyFilter = 0)
 	{
 		global $langs,$conf;
 
@@ -614,6 +618,11 @@ class AdvanceTargetingMailing extends CommonObject
 		$sql.= " FROM " . MAIN_DB_PREFIX . "socpeople as t";
 		$sql.= " LEFT OUTER JOIN " . MAIN_DB_PREFIX . "socpeople_extrafields as te ON te.fk_object=t.rowid ";
 
+		if (! empty($withThirdpartyFilter)) {
+			$sql .= " LEFT OUTER JOIN " . MAIN_DB_PREFIX . "societe as ts ON ts.rowid=t.fk_soc";
+			$sql .= " LEFT OUTER JOIN " . MAIN_DB_PREFIX . "societe_extrafields as tse ON tse.fk_object=ts.rowid ";
+		}
+
 		$sqlwhere=array();
 
 		$sqlwhere[]= 't.entity IN ('.getEntity('socpeople',1).')';
@@ -694,14 +703,107 @@ class AdvanceTargetingMailing extends CommonObject
 
 				}
 
+				if (! empty($withThirdpartyFilter)) {
+					if (array_key_exists('cust_saleman', $arrayquery)) {
+						$sql.= " LEFT OUTER JOIN " . MAIN_DB_PREFIX . "societe_commerciaux as saleman ON saleman.fk_soc=ts.rowid ";
+					}
+					if (array_key_exists('cust_categ', $arrayquery)) {
+						$sql.= " LEFT OUTER JOIN " . MAIN_DB_PREFIX . "categorie_societe as custcateg ON custcateg.fk_soc=ts.rowid ";
+					}
 
-			}
+					if (!empty($arrayquery['cust_name'])) {
 
-			if (count($sqlwhere)>0)	$sql.= " WHERE ".implode(" AND ",$sqlwhere);
+						$sqlwhere[]= $this->transformToSQL('ts.nom',$arrayquery['cust_name']);
+					}
+					if (!empty($arrayquery['cust_code'])) {
+						$sqlwhere[]= $this->transformToSQL('ts.code_client',$arrayquery['cust_code']);
+					}
+					if (!empty($arrayquery['cust_adress'])) {
+						$sqlwhere[]= $this->transformToSQL('ts.address',$arrayquery['cust_adress']);
+					}
+					if (!empty($arrayquery['cust_zip'])) {
+						$sqlwhere[]= $this->transformToSQL('ts.zip',$arrayquery['cust_zip']);
+					}
+					if (!empty($arrayquery['cust_city'])) {
+						$sqlwhere[]= $this->transformToSQL('ts.town',$arrayquery['cust_city']);
+					}
+					if (!empty($arrayquery['cust_mothercompany'])) {
+						$str=$this->transformToSQL('nom',$arrayquery['cust_mothercompany']);
+						$sqlwhere[]= " (ts.parent IN (SELECT rowid FROM " . MAIN_DB_PREFIX . "societe WHERE (".$str.")))";
+					}
+					if (!empty($arrayquery['cust_status']) && count($arrayquery['cust_status'])>0) {
+						$sqlwhere[]= " (ts.status IN (".implode(',',$arrayquery['cust_status'])."))";
+					}
+					if (!empty($arrayquery['cust_typecust']) && count($arrayquery['cust_typecust'])>0) {
+						$sqlwhere[]= " (ts.client IN (".implode(',',$arrayquery['cust_typecust'])."))";
+					}
+					if (!empty($arrayquery['cust_comm_status']) && count($arrayquery['cust_comm_status']>0)) {
+						$sqlwhere[]= " (ts.fk_stcomm IN (".implode(',',$arrayquery['cust_comm_status'])."))";
+					}
+					if (!empty($arrayquery['cust_prospect_status']) && count($arrayquery['cust_prospect_status'])>0) {
+						$sqlwhere[]= " (ts.fk_prospectlevel IN ('".implode("','",$arrayquery['cust_prospect_status'])."'))";
+					}
+					if (!empty($arrayquery['cust_typeent']) && count($arrayquery['cust_typeent'])>0) {
+						$sqlwhere[]= " (ts.fk_typent IN (".implode(',',$arrayquery['cust_typeent'])."))";
+					}
+					if (!empty($arrayquery['cust_saleman']) && count($arrayquery['cust_saleman'])>0) {
+						$sqlwhere[]= " (saleman.fk_user IN (".implode(',',$arrayquery['cust_saleman'])."))";
+					}
+					if (!empty($arrayquery['cust_country']) && count($arrayquery['cust_country'])>0) {
+						$sqlwhere[]= " (ts.fk_pays IN (".implode(',',$arrayquery['cust_country'])."))";
+					}
+					if (!empty($arrayquery['cust_effectif_id']) && count($arrayquery['cust_effectif_id'])>0) {
+						$sqlwhere[]= " (ts.fk_effectif IN (".implode(',',$arrayquery['cust_effectif_id'])."))";
+					}
+					if (!empty($arrayquery['cust_categ']) && count($arrayquery['cust_categ'])>0) {
+						$sqlwhere[]= " (custcateg.fk_categorie IN (".implode(',',$arrayquery['cust_categ'])."))";
+					}
+					if (!empty($arrayquery['cust_language']) && count($arrayquery['cust_language'])>0) {
+						$sqlwhere[]= " (ts.default_lang IN ('".implode("','",$arrayquery['cust_language'])."'))";
+					}
 
+					//Standard Extrafield feature
+					if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
+						// fetch optionals attributes and labels
+						dol_include_once('/core/class/extrafields.class.php');
+						$extrafields = new ExtraFields($this->db);
+						$extralabels=$extrafields->fetch_name_optionals_label('societe');
+
+						foreach($extralabels as $key=>$val) {
+
+							if (($extrafields->attribute_type[$key] == 'varchar') ||
+									($extrafields->attribute_type[$key] == 'text')) {
+										if (!empty($arrayquery['options_'.$key])) {
+											$sqlwhere[]= " (tse.".$key." LIKE '".$arrayquery['options_'.$key]."')";
+										}
+									} elseif (($extrafields->attribute_type[$key] == 'int') ||
+											($extrafields->attribute_type[$key] == 'double')) {
+												if (!empty($arrayquery['options_'.$key.'_max'])) {
+													$sqlwhere[]= " (tse.".$key." >= ".$arrayquery['options_'.$key.'_max']." AND tse.".$key." <= ".$arrayquery['options_'.$key.'_min'].")";
+												}
+									} else if (($extrafields->attribute_type[$key] == 'date') ||
+											($extrafields->attribute_type[$key] == 'datetime')) {
+												if (!empty($arrayquery['options_'.$key.'_end_dt'])){
+													$sqlwhere[]= " (tse.".$key." >= '".$this->db->idate($arrayquery['options_'.$key.'_st_dt'])."' AND tse.".$key." <= '".$this->db->idate($arrayquery['options_'.$key.'_end_dt'])."')";
+												}
+											}else if ($extrafields->attribute_type[$key] == 'boolean') {
+												if ($arrayquery['options_'.$key]!=''){
+													$sqlwhere[]= " (tse.".$key." = ".$arrayquery['options_'.$key].")";
+												}
+											}else{
+												if (is_array($arrayquery['options_'.$key])) {
+													$sqlwhere[]= " (tse.".$key." IN ('".implode("','",$arrayquery['options_'.$key])."'))";
+												} elseif (!empty($arrayquery['options_'.$key])) {
+													$sqlwhere[]= " (tse.".$key." LIKE '".$arrayquery['options_'.$key]."')";
+												}
+											}
+						}
+					}
+				}
+			}
+			if (count($sqlwhere)>0)	$sql.= " WHERE ".implode(" AND ",$sqlwhere);
 		}
 
-
 		dol_syslog(get_class($this) . "::query_contact sql=" . $sql, LOG_DEBUG);
 		$resql = $this->db->query($sql);
 		if ($resql) {

+ 15 - 3
htdocs/comm/mailing/list.php

@@ -111,8 +111,18 @@ if ($result)
 	if ($filteremail) $param.='&amp;filteremail='.urlencode($filteremail);
 	
 	print '<form method="GET" action="'.$_SERVER["PHP_SELF"].'">';
-	print '<table class="liste">';
-	print '<tr class="liste_titre">';
+	if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
+	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	print '<input type="hidden" name="action" value="list">';
+	print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
+	print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
+	
+    $moreforfilter = '';
+    
+    print '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+
+    print '<tr class="liste_titre">';
 	print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"m.rowid",$param,"","",$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("Title"),$_SERVER["PHP_SELF"],"m.titre",$param,"","",$sortfield,$sortorder);
 	print_liste_field_titre($langs->trans("DateCreation"),$_SERVER["PHP_SELF"],"m.date_creat",$param,"",'align="center"',$sortfield,$sortorder);
@@ -193,7 +203,9 @@ if ($result)
 		print "</tr>\n";
 		$i++;
 	}
-	print '</table></form>';
+	print '</table>';
+	print '</div>';
+	print '</form>';
 	$db->free($result);
 }
 else

+ 46 - 32
htdocs/comm/propal/card.php

@@ -681,6 +681,7 @@ if (empty($reshook))
 		$predef='';
 		$product_desc=(GETPOST('dp_desc')?GETPOST('dp_desc'):'');
 		$price_ht = GETPOST('price_ht');
+		$price_ht_devise = GETPOST('multicurrency_price_ht');
 		if (GETPOST('prod_entry_mode') == 'free')
 		{
 			$idprod=0;
@@ -712,7 +713,7 @@ if (empty($reshook))
 			$error ++;
 		}
 
-		if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && $price_ht == '') 	// Unit price can be 0 but not ''. Also price can be negative for proposal.
+		if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && $price_ht == '' && $price_ht_devise == '') 	// Unit price can be 0 but not ''. Also price can be negative for proposal.
 		{
 			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
 			$error ++;
@@ -858,6 +859,7 @@ if (empty($reshook))
 				$type = GETPOST('type');
 
 				$fk_unit = GETPOST('units', 'alpha');
+				$pu_ht_devise = price2num($price_ht_devise, 'MU');
 			}
 
 			// Margin
@@ -880,7 +882,7 @@ if (empty($reshook))
 				setEventMessages($mesg, null, 'errors');
 			} else {
 				// Insert line
-				$result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $pu_ttc, $info_bits, $type, - 1, 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $date_start, $date_end, $array_options, $fk_unit);
+				$result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $pu_ttc, $info_bits, $type, - 1, 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $date_start, $date_end, $array_options, $fk_unit, '', 0, $pu_ht_devise);
 
 				if ($result > 0) {
 					$db->commit();
@@ -959,6 +961,8 @@ if (empty($reshook))
 		// Add buying price
 		$fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
 		$buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : '');    // If buying_price is '0', we muste keep this value
+		
+		$pu_ht_devise = GETPOST('multicurrency_subprice');
 
 		$date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
 		$date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
@@ -1011,7 +1015,7 @@ if (empty($reshook))
 		if (! $error) {
 			$db->begin();
 
-			$result = $object->updateline(GETPOST('lineid'), $pu_ht, GETPOST('qty'), GETPOST('remise_percent'), $vat_rate, $localtax1_rate, $localtax2_rate, $description, 'HT', $info_bits, $special_code, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $type, $date_start, $date_end, $array_options, $_POST["units"]);
+			$result = $object->updateline(GETPOST('lineid'), $pu_ht, GETPOST('qty'), GETPOST('remise_percent'), $vat_rate, $localtax1_rate, $localtax2_rate, $description, 'HT', $info_bits, $special_code, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $type, $date_start, $date_end, $array_options, $_POST["units"], $pu_ht_devise);
 
 			if ($result >= 0) {
 				$db->commit();
@@ -1070,17 +1074,17 @@ if (empty($reshook))
 
 	// Set project
 	else if ($action == 'classin' && $user->rights->propal->creer) {
-		$object->setProject($_POST['projectid']);
+		$object->setProject(GETPOST('projectid','int'));
 	}
 
 	// Delai de livraison
 	else if ($action == 'setavailability' && $user->rights->propal->creer) {
-		$result = $object->availability($_POST['availability_id']);
+		$result = $object->set_availability($user, GETPOST('availability_id','int'));
 	}
 
 	// Origine de la propale
 	else if ($action == 'setdemandreason' && $user->rights->propal->creer) {
-		$result = $object->demand_reason($_POST['demand_reason_id']);
+		$result = $object->set_demand_reason($user, GETPOST('demand_reason_id','int'));
 	}
 
 	// Conditions de reglement
@@ -1701,10 +1705,10 @@ if ($action == 'create')
 
 
 	// Proposal card
-	
+
 	$linkback = '<a href="' . DOL_URL_ROOT . '/comm/propal/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
 
-	
+
 	$morehtmlref='<div class="refidno">';
 	// Ref customer
 	$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->propal->creer, 'string', '', 0, 1);
@@ -1744,17 +1748,17 @@ if ($action == 'create')
         }
     }
     $morehtmlref.='</div>';
-    
-    
+
+
 	dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
-	
-    
+
+
     print '<div class="fichecenter">';
     print '<div class="fichehalfleft">';
     print '<div class="underbanner clearboth"></div>';
-    
+
 	print '<table class="border" width="100%">';
-    
+
     // Ref
     /*
 	print '<tr><td>' . $langs->trans('Ref') . '</td><td colspan="5">';
@@ -1784,7 +1788,7 @@ if ($action == 'create')
 	print '</td>';
 	print '</tr>';
     */
-	
+
 	// Company
 	/*
 	print '<tr><td>' . $langs->trans('Company') . '</td><td colspan="5">' . $soc->getNomUrl(1) . '</td>';
@@ -2002,10 +2006,18 @@ if ($action == 'create')
 			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencyrate&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
 		print '</tr></table>';
 		print '</td><td>';
-		if ($action == 'editmulticurrencyrate') {
+		if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
+			if($action == 'actualizemulticurrencyrate') {
+				list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
+			}
 			$form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
 		} else {
 			$form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
+			if($object->statut == 0) {
+				print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
+				print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
+				print '</div>';
+			}
 		}
 		print '</td></tr>';
 	}
@@ -2107,42 +2119,42 @@ if ($action == 'create')
 	include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
 
 	print '</table>';
-	
+
 	print '</div>';
 	print '<div class="fichehalfright">';
 	print '<div class="ficheaddleft">';
 	print '<div class="underbanner clearboth"></div>';
-	
+
     print '<table class="border centpercent">';
-    
+
     if (!empty($conf->multicurrency->enabled) && ($object->multicurrency_code != $conf->currency))
     {
         // Multicurrency Amount HT
         print '<tr><td class="titlefieldmiddle">' . fieldLabel('MulticurrencyAmountHT','multicurrency_total_ht') . '</td>';
         print '<td class="nowrap">' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
         print '</tr>';
-    
+
         // Multicurrency Amount VAT
         print '<tr><td>' . fieldLabel('MulticurrencyAmountVAT','multicurrency_total_tva') . '</td>';
         print '<td class="nowrap">' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
         print '</tr>';
-    
+
         // Multicurrency Amount TTC
         print '<tr><td>' . fieldLabel('MulticurrencyAmountTTC','multicurrency_total_ttc') . '</td>';
         print '<td class="nowrap">' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
         print '</tr>';
     }
-        
+
 	// Amount HT
 	print '<tr><td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
 	print '<td class="nowrap">' . price($object->total_ht, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
 	print '</tr>';
-	
+
 	// Amount VAT
 	print '<tr><td>' . $langs->trans('AmountVAT') . '</td>';
 	print '<td class="nowrap">' . price($object->total_tva, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
 	print '</tr>';
-	
+
 	// Amount Local Taxes
 	if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) 	// Localtax1
 	{
@@ -2156,27 +2168,27 @@ if ($action == 'create')
 	    print '<td class="nowrap">' . price($object->total_localtax2, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
 	    print '</tr>';
 	}
-	
+
 	// Amount TTC
 	print '<tr><td>' . $langs->trans('AmountTTC') . '</td>';
 	print '<td class="nowrap">' . price($object->total_ttc, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
 	print '</tr>';
-	
+
 	// Statut
 	//print '<tr><td height="10">' . $langs->trans('Status') . '</td><td align="left" colspan="2">' . $object->getLibStatut(4) . '</td></tr>';
-	
+
 	print '</table>';
-	
+
 	// Margin Infos
 	if (! empty($conf->margin->enabled))
 	{
 	    $formmargin->displayMarginInfos($object);
 	}
-	
+
 	print '</div>';
 	print '</div>';
 	print '</div>';
-	
+
 	print '<div class="clearboth"></div><br>';
 
 	if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
@@ -2209,6 +2221,7 @@ if ($action == 'create')
 		include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
 	}
 
+    print '<div class="div-table-responsive">';
 	print '<table id="tablelines" class="noborder noshadow" width="100%">';
 
 	if (! empty($object->lines))
@@ -2230,6 +2243,7 @@ if ($action == 'create')
 	}
 
 	print '</table>';
+    print '</div>';
 
 	print "</form>\n";
 
@@ -2384,12 +2398,12 @@ if ($action == 'create')
 
 		$var = true;
 
-		print $formfile->showdocuments('propal', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', 0, '', $soc->default_lang);
+		print $formfile->showdocuments('propal', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', 0, '', $soc->default_lang, '', $object);
 
 		// Show links to link elements
 		$linktoelem = $form->showLinkToObjectBlock($object, null, array('propal'));
 		$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
-		
+
 
 		print '</div><div class="fichehalfright"><div class="ficheaddleft">';
 

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

@@ -90,17 +90,19 @@ class Proposals extends DolibarrApi
      * @param int		$limit		        Limit for list
      * @param int		$page		        Page number
      * @param string   	$thirdparty_ids	    Thirdparty ids to filter commercial proposal of. Example: '1' or '1,2,3'          {@pattern /^[0-9,]*$/i}
-     * @param string    $sqlfilters         Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
+     * @param string    $sqlfilters         Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.datec:<:'20160101')"
      * @return  array                       Array of order objects
      */
     function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $thirdparty_ids = '', $sqlfilters = '') {
         global $db, $conf;
         
         $obj_ret = array();
-        // case of external user, $thirdpartyid param is ignored and replaced by user's socid
+
+        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
         $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
             
         // If the internal user must only see his customers, force searching by him
+        $search_sale = 0;
         if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id;
 
         $sql = "SELECT t.rowid";
@@ -150,13 +152,13 @@ class Proposals extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $propal_static = new Propal($db);
                 if($propal_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($propal_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($propal_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve propal list');
+            throw new RestException(503, 'Error when retrieve propal list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No order found');
@@ -396,6 +398,7 @@ class Proposals extends DolibarrApi
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $this->propal->$field = $value;
         }
         

+ 60 - 30
htdocs/comm/propal/class/propal.class.php

@@ -50,7 +50,7 @@ class Propal extends CommonObject
     public $fk_element='fk_propal';
     protected $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
     public $picto='propal';
-    
+
     /**
      * {@inheritdoc}
      */
@@ -392,10 +392,10 @@ class Propal extends CommonObject
      *      @param		string		$origin				'order', ...
      *      @param		int			$origin_id			Id of origin object
      *    	@return    	int         	    			>0 if OK, <0 if KO
-     *
+     * 		@param		double		$pu_ht_devise		Unit price in currency
      *    	@see       	add_product
      */
-	function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $fk_product=0, $remise_percent=0.0, $price_base_type='HT', $pu_ttc=0.0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$date_start='', $date_end='',$array_options=0, $fk_unit=null, $origin='', $origin_id=0)
+	function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $fk_product=0, $remise_percent=0.0, $price_base_type='HT', $pu_ttc=0.0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$date_start='', $date_end='',$array_options=0, $fk_unit=null, $origin='', $origin_id=0, $pu_ht_devise = 0)
     {
     	global $mysoc, $conf, $langs;
 
@@ -463,18 +463,22 @@ class Propal extends CommonObject
                 $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
             }
 
-            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx);
+            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
 
             $total_ht  = $tabprice[0];
             $total_tva = $tabprice[1];
             $total_ttc = $tabprice[2];
             $total_localtax1 = $tabprice[9];
             $total_localtax2 = $tabprice[10];
+			$pu_ht  = $tabprice[3];
+			$pu_tva = $tabprice[4];
+			$pu_ttc = $tabprice[5];
 
 			// MultiCurrency
 			$multicurrency_total_ht  = $tabprice[16];
             $multicurrency_total_tva = $tabprice[17];
             $multicurrency_total_ttc = $tabprice[18];
+			$pu_ht_devise = $tabprice[19];
 
             // Rang to use
             $rangtouse = $rang;
@@ -503,7 +507,7 @@ class Propal extends CommonObject
             $this->line->label=$label;
             $this->line->desc=$desc;
             $this->line->qty=$qty;
-            
+
 			$this->line->vat_src_code=$vat_src_code;
             $this->line->tva_tx=$txtva;
             $this->line->localtax1_tx=$txlocaltax1;
@@ -537,7 +541,7 @@ class Propal extends CommonObject
 			// Multicurrency
 			$this->line->fk_multicurrency			= $this->fk_multicurrency;
 			$this->line->multicurrency_code			= $this->multicurrency_code;
-			$this->line->multicurrency_subprice		= price2num($pu_ht * $this->multicurrency_tx);
+			$this->line->multicurrency_subprice		= $pu_ht_devise;
 			$this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
             $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
             $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
@@ -607,9 +611,10 @@ class Propal extends CommonObject
      *	@param      int			$date_end         	End date of the line
 	 *  @param		array		$array_options		extrafields array
      * 	@param 		string		$fk_unit 			Code of the unit to use. Null to use the default one
+	 * 	@param		double		$pu_ht_devise		Unit price in currency
      *  @return     int     		        		0 if OK, <0 if KO
      */
-	function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $desc='', $price_base_type='HT', $info_bits=0, $special_code=0, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=0, $pa_ht=0, $label='', $type=0, $date_start='', $date_end='', $array_options=0, $fk_unit=null)
+	function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $desc='', $price_base_type='HT', $info_bits=0, $special_code=0, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=0, $pa_ht=0, $label='', $type=0, $date_start='', $date_end='', $array_options=0, $fk_unit=null, $pu_ht_devise = 0)
     {
         global $mysoc;
 
@@ -638,7 +643,7 @@ class Propal extends CommonObject
             // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
 
             $localtaxes_type=getLocalTaxesFromRate($txtva,0,$this->thirdparty,$mysoc);
-            
+
             // Clean vat code
             $vat_src_code='';
             if (preg_match('/\((.*)\)/', $txtva, $reg))
@@ -647,17 +652,21 @@ class Propal extends CommonObject
                 $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
             }
 
-            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx);
+            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
             $total_ht  = $tabprice[0];
             $total_tva = $tabprice[1];
             $total_ttc = $tabprice[2];
             $total_localtax1 = $tabprice[9];
             $total_localtax2 = $tabprice[10];
+			$pu_ht  = $tabprice[3];
+			$pu_tva = $tabprice[4];
+			$pu_ttc = $tabprice[5];
 
 			// MultiCurrency
 			$multicurrency_total_ht  = $tabprice[16];
             $multicurrency_total_tva = $tabprice[17];
             $multicurrency_total_ttc = $tabprice[18];
+			$pu_ht_devise = $tabprice[19];
 
             // Anciens indicateurs: $price, $remise (a ne plus utiliser)
             $price = $pu;
@@ -670,6 +679,7 @@ class Propal extends CommonObject
             //Fetch current line from the database and then clone the object and set it in $oldline property
             $line = new PropaleLigne($this->db);
             $line->fetch($rowid);
+			$line->fetch_optionals(); // Fetch extrafields for oldcopy
 
 			$staticline = clone $line;
 
@@ -695,7 +705,7 @@ class Propal extends CommonObject
 			$this->line->localtax1_type		= $localtaxes_type[0];
 			$this->line->localtax2_type		= $localtaxes_type[2];
             $this->line->remise_percent		= $remise_percent;
-            $this->line->subprice			= $pu;
+            $this->line->subprice			= $pu_ht;
             $this->line->info_bits			= $info_bits;
 
             $this->line->vat_src_code		= $vat_src_code;
@@ -724,7 +734,7 @@ class Propal extends CommonObject
             }
 
 			// Multicurrency
-			$this->line->multicurrency_subprice		= price2num($pu * $this->multicurrency_tx);
+			$this->line->multicurrency_subprice		= $pu_ht_devise;
 			$this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
             $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
             $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
@@ -1179,7 +1189,7 @@ class Propal extends CommonObject
         $clonedObj->ref = $modPropale->getNextValue($objsoc,$clonedObj);
 
         // Create clone
-        
+
         $result=$clonedObj->create($user);
         if ($result < 0) $error++;
         else
@@ -1540,7 +1550,7 @@ class Propal extends CommonObject
             dol_syslog(get_class($this)."::valid action abandonned: already validated", LOG_WARNING);
             return 0;
         }
-        
+
         if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->propal->creer))
        	|| (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->propal->propal_advance->validate))))
         {
@@ -1550,7 +1560,7 @@ class Propal extends CommonObject
         }
 
         $now=dol_now();
-            
+
         $this->db->begin();
 
         // Numbering module definition
@@ -1838,7 +1848,7 @@ class Propal extends CommonObject
      */
     function set_availability($user, $id, $notrigger=0)
     {
-        if (! empty($user->rights->propal->creer))
+        if (! empty($user->rights->propal->creer) && $this->statut >= self::STATUS_DRAFT)
         {
         	$error=0;
 
@@ -1848,7 +1858,7 @@ class Propal extends CommonObject
             $sql.= " SET fk_availability = '".$id."'";
             $sql.= " WHERE rowid = ".$this->id;
 
-            dol_syslog(__METHOD__, LOG_DEBUG);
+            dol_syslog(__METHOD__.' availability('.$availability_id.')', LOG_DEBUG);
             $resql=$this->db->query($sql);
             if (!$resql)
             {
@@ -1860,6 +1870,7 @@ class Propal extends CommonObject
             {
             	$this->oldcopy= clone $this;
             	$this->fk_availability = $id;
+            	$this->availability_id = $availability_id;
             }
 
             if (! $notrigger && empty($error))
@@ -1886,6 +1897,14 @@ class Propal extends CommonObject
             	return -1*$error;
             }
         }
+        else
+        {
+        	$error_str='Propal status do not meet requirement '.$this->statut;
+        	dol_syslog(__METHOD__.$error_str, LOG_ERR);
+        	$this->error=$error_str;
+        	$this->errors[]= $this->error;
+        	return -2;
+        }
     }
 
     /**
@@ -1898,14 +1917,14 @@ class Propal extends CommonObject
      */
     function set_demand_reason($user, $id, $notrigger=0)
     {
-        if (! empty($user->rights->propal->creer))
+        if (! empty($user->rights->propal->creer) && $this->statut >= self::STATUS_DRAFT)
         {
         	$error=0;
 
         	$this->db->begin();
 
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal ";
-            $sql.= " SET fk_input_reason = '".$id."'";
+            $sql.= " SET fk_input_reason = ".$id;
             $sql.= " WHERE rowid = ".$this->id;
 
             dol_syslog(__METHOD__, LOG_DEBUG);
@@ -1921,6 +1940,7 @@ class Propal extends CommonObject
             {
             	$this->oldcopy= clone $this;
             	$this->fk_input_reason = $id;
+            	$this->demand_reason_id = $id;
             }
 
 
@@ -1948,6 +1968,14 @@ class Propal extends CommonObject
             	return -1*$error;
             }
         }
+        else
+        {
+        	$error_str='Propal status do not meet requirement '.$this->statut;
+        	dol_syslog(__METHOD__.$error_str, LOG_ERR);
+        	$this->error=$error_str;
+        	$this->errors[]= $this->error;
+        	return -2;
+        }
     }
 
     /**
@@ -2405,7 +2433,7 @@ class Propal extends CommonObject
         	$this->statut = self::STATUS_DRAFT;
             $this->brouillon = 1;
         }
-        
+
         if (! $notrigger && empty($error))
         {
         	// Call trigger
@@ -2732,6 +2760,7 @@ class Propal extends CommonObject
      *  @param	int	$availability_id	Id of new delivery time
      * 	@param	int	$notrigger			1=Does not execute triggers, 0= execute triggers
      *  @return int                  	>0 if OK, <0 if KO
+     *  @deprecated  use set_availability
      */
     function availability($availability_id, $notrigger=0)
     {
@@ -2752,7 +2781,7 @@ class Propal extends CommonObject
             	$this->errors[]=$this->db->error();
             	$error++;
             }
-            
+
             if (! $error)
             {
             	$this->oldcopy= clone $this;
@@ -2799,6 +2828,7 @@ class Propal extends CommonObject
      *	@param	int $demand_reason_id 	Id of new source demand
      * 	@param	int	$notrigger			1=Does not execute triggers, 0= execute triggers
      *	@return int						>0 si ok, <0 si ko
+     *	@deprecated use set_demand_reason
      */
     function demand_reason($demand_reason_id, $notrigger=0)
     {
@@ -2819,7 +2849,7 @@ class Propal extends CommonObject
             	$this->errors[]=$this->db->error();
             	$error++;
             }
-            
+
             if (! $error)
             {
             	$this->oldcopy= clone $this;
@@ -3240,7 +3270,7 @@ class Propal extends CommonObject
         global $langs, $conf, $user;
 
         if (! empty($conf->dol_no_mouse_hover)) $notooltip=1;   // Force disable tooltips
-        
+
         $result='';
         $label='';
         $url='';
@@ -3271,7 +3301,7 @@ class Propal extends CommonObject
                 $url = DOL_URL_ROOT.'/comm/propal/document.php?id='.$this->id. $get_params;
             }
         }
-        
+
         $linkclose='';
         if (empty($notooltip) && $user->rights->propal->lire)
         {
@@ -3283,9 +3313,9 @@ class Propal extends CommonObject
             $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
             $linkclose.=' class="classfortooltip"';
         }
-        
+
         $linkstart = '<a href="'.$url.'"';
-        $linkstart.=$linkclose.'>';        
+        $linkstart.=$linkclose.'>';
         $linkend='</a>';
 
         if ($withpicto)
@@ -3310,8 +3340,7 @@ class Propal extends CommonObject
         $sql.= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code, pt.localtax1_tx, pt.localtax2_tx,';
         $sql.= ' pt.date_start, pt.date_end, pt.product_type, pt.rang, pt.fk_parent_line,';
 	    $sql.= ' pt.fk_unit,';
-        $sql.= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid,';
-        $sql.= ' p.description as product_desc,';
+        $sql.= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.description as product_desc, p.tobatch as product_tobatch,';
         $sql.= ' p.entity,';
 		$sql.= ' pt.fk_multicurrency, pt.multicurrency_code, pt.multicurrency_subprice, pt.multicurrency_total_ht, pt.multicurrency_total_tva, pt.multicurrency_total_ttc';
         $sql.= ' FROM '.MAIN_DB_PREFIX.'propaldet as pt';
@@ -3342,6 +3371,7 @@ class Propal extends CommonObject
                 $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]->product_tobatch   = $obj->product_tobatch;
                 $this->lines[$i]->fk_product_type	= $obj->fk_product_type;    // deprecated
                 $this->lines[$i]->product_type		= $obj->product_type;
                 $this->lines[$i]->qty				= $obj->qty;
@@ -3349,7 +3379,7 @@ class Propal extends CommonObject
                 $this->lines[$i]->fk_remise_except 	= $obj->fk_remise_except;
                 $this->lines[$i]->remise_percent	= $obj->remise_percent;
 
-                $this->lines[$i]->vat_src_code      = $obj->vat_src_code; 
+                $this->lines[$i]->vat_src_code      = $obj->vat_src_code;
                 $this->lines[$i]->tva_tx			= $obj->tva_tx;
                 $this->lines[$i]->info_bits			= $obj->info_bits;
                 $this->lines[$i]->total_ht			= $obj->total_ht;
@@ -3681,9 +3711,9 @@ class PropaleLigne  extends CommonObjectLine
         if (empty($this->pa_ht)) $this->pa_ht=0;
         if (empty($this->multicurrency_subprice))  $this->multicurrency_subprice=0;
         if (empty($this->multicurrency_total_ht))  $this->multicurrency_total_ht=0;
-        if (empty($this->multicurrency_total_vat)) $this->multicurrency_total_vat=0;
+        if (empty($this->multicurrency_total_tva)) $this->multicurrency_total_tva=0;
         if (empty($this->multicurrency_total_ttc)) $this->multicurrency_total_ttc=0;
-        
+
        // if buy price not defined, define buyprice as configured in margin admin
 		if ($this->pa_ht == 0 && $pa_ht_isemptystring)
 		{

+ 1 - 0
htdocs/comm/propal/contact.php

@@ -30,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/propal.lib.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.'/projet/class/project.class.php';
 
 $langs->load("facture");
 $langs->load("orders");

+ 11 - 3
htdocs/comm/propal/info.php

@@ -32,21 +32,30 @@ $langs->load('propal');
 $langs->load('compta');
 
 $id=GETPOST('id','int');
+$ref=GETPOST('ref','alpha');
 $socid=GETPOST('socid','int');
 
 // Security check
 if (! empty($user->societe_id)) $socid=$user->societe_id;
 $result = restrictedArea($user, 'propal', $id);
 
+$object = new Propal($db);
+if (! $object->fetch($id, $ref) > 0)
+{
+    dol_print_error($db);
+    exit;
+}
+
+
 
 /*
  *	View
  */
 
+$form = new Form($db);
+
 llxHeader('',$langs->trans('Proposal'),'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos');
 
-$object = new Propal($db);
-$object->fetch($id);
 $object->fetch_thirdparty();
 
 $head = propal_prepare_head($object);
@@ -110,7 +119,6 @@ print '<br>';
 
 dol_print_object_info($object);
 
-print '</div>';
 print '</div>';
 
 dol_fiche_end();

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

@@ -289,7 +289,7 @@ if ($sall) {
 }
 if ($search_product_category > 0) $sql.=" AND cp.fk_categorie = ".$search_product_category;
 if ($socid > 0) $sql.= ' AND s.rowid = '.$socid;
-if ($viewstatut <> '')
+if ($viewstatut != '' && $viewstatut != '-1')
 {
 	$sql.= ' AND p.fk_statut IN ('.$viewstatut.')';
 }
@@ -333,7 +333,7 @@ $sql.= $db->order($sortfield,$sortorder);
 $sql.=', p.ref DESC';
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
     $result = $db->query($sql);
@@ -538,7 +538,7 @@ if ($resql)
 		$moreforfilter.='<div class="divsearchfield">';
 		$moreforfilter.=$langs->trans('IncludingProductWithTag'). ': ';
 		$cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, null, 'parent', null, null, 1);
-		$moreforfilter.=$form->selectarray('search_product_category', $cate_arbo, $search_product_category, 1, 0, 0, '', 0, 0, 0, 0, '', 1);
+		$moreforfilter.=$form->selectarray('search_product_category', $cate_arbo, $search_product_category, 1, 0, 0, '', 0, 0, 0, 0, 'maxwidth300', 1);
 		$moreforfilter.='</div>';
 	}
 	$parameters=array();
@@ -556,6 +556,7 @@ if ($resql)
     $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
     $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
 	
+    print '<div class="div-table-responsive">';
 	print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	
 	// Fields title
@@ -1003,6 +1004,7 @@ if ($resql)
 	print $hookmanager->resPrint;
 				
 	print '</table>'."\n";
+    print '</div>'."\n";
 
 	print '</form>'."\n";
 	

+ 59 - 20
htdocs/commande/card.php

@@ -44,9 +44,9 @@ require_once DOL_DOCUMENT_ROOT . '/core/lib/order.lib.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
 require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
 if (! empty($conf->propal->enabled))
-	require DOL_DOCUMENT_ROOT . '/comm/propal/class/propal.class.php';
+	require_once DOL_DOCUMENT_ROOT . '/comm/propal/class/propal.class.php';
 if (! empty($conf->projet->enabled)) {
-	require DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
+	require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
 	require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
 }
 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
@@ -99,7 +99,6 @@ $permissiondellink = $user->rights->commande->creer; 	// Used by the include of
 $permissionedit = $user->rights->commande->creer; 		// Used by the include of actions_lineupdown.inc.php
 
 
-
 /*
  * Actions
  */
@@ -110,8 +109,21 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e
 
 if (empty($reshook))
 {
-	if ($cancel) $action='';
-
+	if ($cancel) 
+	{
+		if ($action != 'addlink' && $action != 'updateline')
+		{
+			$urltogo=$backtopage?$backtopage:dol_buildpath('/commande/list.php',1);
+			header("Location: ".$urltogo);
+			exit;
+		}
+		if ($id > 0 || ! empty($ref)) {
+		    $ret = $object->fetch($id,$ref);
+		    $object->fetch_thirdparty();
+        }
+		$action='';
+	}
+	
 	include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; 	// Must be include, not include_once
 
 	include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php';		// Must be include, not include_once
@@ -627,6 +639,7 @@ if (empty($reshook))
 		$predef='';
 		$product_desc=(GETPOST('dp_desc')?GETPOST('dp_desc'):'');
 		$price_ht = GETPOST('price_ht');
+		$price_ht_devise = GETPOST('multicurrency_price_ht');
 		if (GETPOST('prod_entry_mode') == 'free')
 		{
 			$idprod=0;
@@ -661,7 +674,7 @@ if (empty($reshook))
 			setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
 			$error++;
 		}
-		if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && (! ($price_ht >= 0) || $price_ht == '')) 	// Unit price can be 0 but not ''
+		if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && (! ($price_ht >= 0) || $price_ht == '') && (! ($price_ht_devise >= 0) || $price_ht_devise == '')) 	// Unit price can be 0 but not ''
 		{
 			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
 			$error++;
@@ -801,6 +814,7 @@ if (empty($reshook))
 				$desc = $product_desc;
 				$type = GETPOST('type');
 				$fk_unit=GETPOST('units', 'alpha');
+				$pu_ht_devise = price2num($price_ht_devise, 'MU');
 			}
 
 			// Margin
@@ -822,7 +836,7 @@ if (empty($reshook))
 				setEventMessages($mesg, null, 'errors');
 			} else {
 				// Insert line
-				$result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $info_bits, 0, $price_base_type, $pu_ttc, $date_start, $date_end, $type, - 1, 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $fk_unit);
+				$result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $info_bits, 0, $price_base_type, $pu_ttc, $date_start, $date_end, $type, - 1, 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $fk_unit, '', 0, $pu_ht_devise);
 
 				if ($result > 0) {
 					$ret = $object->fetch($object->id); // Reload to get new records
@@ -893,6 +907,7 @@ if (empty($reshook))
 		$description=dol_htmlcleanlastbr(GETPOST('product_desc'));
 		$pu_ht=GETPOST('price_ht');
 		$vat_rate=(GETPOST('tva_tx')?GETPOST('tva_tx'):0);
+		$pu_ht_devise = GETPOST('multicurrency_subprice');
 
 		// Define info_bits
 		$info_bits = 0;
@@ -953,7 +968,7 @@ if (empty($reshook))
 		}
 
 		if (! $error) {
-			$result = $object->updateline(GETPOST('lineid'), $description, $pu_ht, GETPOST('qty'), GETPOST('remise_percent'), $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $info_bits, $date_start, $date_end, $type, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOST('units'));
+			$result = $object->updateline(GETPOST('lineid'), $description, $pu_ht, GETPOST('qty'), GETPOST('remise_percent'), $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $info_bits, $date_start, $date_end, $type, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOST('units'),$pu_ht_devise);
 
 			if ($result >= 0) {
 				if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
@@ -1620,7 +1635,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 	}
 
 	// Template to use by default
-	print '<tr><td>' . $langs->trans('Model') . '</td>';
+	print '<tr><td>' . $langs->trans('DefaultModel') . '</td>';
 	print '<td colspan="2">';
 	include_once DOL_DOCUMENT_ROOT . '/core/modules/commande/modules_commande.php';
 	$liste = ModelePDFCommandes::liste_modeles($db);
@@ -1725,7 +1740,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 	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 '<input type="submit" class="button" name="cancel" value="' . $langs->trans("Cancel") . '">';
 	print '</div>';
 
 	print '</form>';
@@ -2184,10 +2199,18 @@ if ($action == 'create' && $user->rights->commande->creer)
 				print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencyrate&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
 			print '</tr></table>';
 			print '</td><td>';
-			if ($action == 'editmulticurrencyrate') {
+			if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
+    			if($action == 'actualizemulticurrencyrate') {
+    				list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
+    			}
 				$form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
 			} else {
 				$form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
+				if($object->statut == 0) {
+					print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
+					print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
+					print '</div>';
+				}
 			}
 			print '</td></tr>';
 		}
@@ -2208,7 +2231,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 		}
 		print '</td></tr>';
 
-		// Origin
+		// Source reason (why we have an ordrer)
 		print '<tr><td height="10">';
 		print '<table class="nobordernopadding" width="100%"><tr><td>';
 		print $langs->trans('Source');
@@ -2222,12 +2245,26 @@ if ($action == 'create' && $user->rights->commande->creer)
 		} else {
 			$form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'none');
 		}
-		// Removed because using dictionary is an admin feature, not a user feature. There is already the "star" to show info to admin users.
-		// This is to avoid too heavy screens and have an uniform look and feel for all screens.
-		// print '</td><td>';
-		// print '<a href="'.DOL_URL_ROOT.'/admin/dict.php?id=22&origin=order&originid='.$object->id.'">'.$langs->trans("DictionarySource").'</a>';
 		print '</td></tr>';
 
+		// TODO Order mode (how we receive order). Not yet implemented
+		/*
+		print '<tr><td height="10">';
+		print '<table class="nobordernopadding" width="100%"><tr><td>';
+		print $langs->trans('SourceMode');
+		print '</td>';
+		if ($action != 'editinputmode')
+			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editinputmode&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetInputMode'), 1) . '</a></td>';
+		print '</tr></table>';
+		print '</td><td>';
+		if ($action == 'editinputmode') {
+			$form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'input_mode_id', 1);
+		} else {
+			$form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'none');
+		}
+		print '</td></tr>';
+		*/
+		
 		$tmparray=$object->getTotalWeightVolume();
 		$totalWeight=$tmparray['weight'];
 		$totalVolume=$tmparray['volume'];
@@ -2386,6 +2423,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 			include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
 		}
 
+        print '<div class="div-table-responsive">';
 		print '<table id="tablelines" class="noborder noshadow" width="100%">';
 
 		// Show object lines
@@ -2411,7 +2449,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 			}
 		}
 		print '</table>';
-
+        print '</div>';
+        
 		print "</form>\n";
 
 		dol_fiche_end();
@@ -2484,13 +2523,13 @@ if ($action == 'create' && $user->rights->commande->creer)
 					if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfProductsLines() > 0) {
 						if (($conf->expedition_bon->enabled && $user->rights->expedition->creer) || ($conf->livraison_bon->enabled && $user->rights->expedition->livraison->creer)) {
 							if ($user->rights->expedition->creer) {
-								print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/expedition/shipment.php?id=' . $object->id . '">' . $langs->trans('ShipProduct') . '</a></div>';
+								print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/expedition/shipment.php?id=' . $object->id . '">' . $langs->trans('CreateShipment') . '</a></div>';
 							} else {
-								print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('ShipProduct') . '</a></div>';
+								print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('CreateShipment') . '</a></div>';
 							}
 						} else {
 							$langs->load("errors");
-							print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("ErrorModuleSetupNotComplete")) . '">' . $langs->trans('ShipProduct') . '</a></div>';
+							print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("ErrorModuleSetupNotComplete")) . '">' . $langs->trans('CreateShipment') . '</a></div>';
 						}
 					}
 				}

+ 5 - 3
htdocs/commande/class/api_deprecated_commande.class.php

@@ -115,6 +115,7 @@ class CommandeApi extends DolibarrApi
         $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $societe;
 
         // If the internal user must only see his customers, force searching by him
+        $search_sale = 0;
         if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id;
 
         $sql = "SELECT s.rowid";
@@ -138,7 +139,7 @@ class CommandeApi extends DolibarrApi
             $sql .= " AND sc.fk_user = ".$search_sale;
         }
 
-        $nbtotalofrecords = 0;
+        $nbtotalofrecords = -1;
         if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
         {
             $result = $db->query($sql);
@@ -167,13 +168,13 @@ class CommandeApi extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $commande_static = new Commande($db);
                 if($commande_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($commande_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($commande_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve commande list');
+            throw new RestException(503, 'Error when retrieve commande list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No commande found');
@@ -432,6 +433,7 @@ class CommandeApi extends DolibarrApi
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $this->commande->$field = $value;
         }
 

+ 8 - 3
htdocs/commande/class/api_orders.class.php

@@ -94,15 +94,19 @@ class Orders extends DolibarrApi
      * @param string   	       $thirdparty_ids	    Thirdparty ids to filter orders of. {@example '1' or '1,2,3'} {@pattern /^[0-9,]*$/i}
      * @param string           $sqlfilters          Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
      * @return  array                               Array of order objects
+     *
+	 * @throws RestException
      */
     function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '') {
         global $db, $conf;
 
         $obj_ret = array();
-        // case of external user, $thirdpartyid param is ignored and replaced by user's socid
+        
+        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
         $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
 
         // If the internal user must only see his customers, force searching by him
+        $search_sale = 0;
         if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id;
 
         $sql = "SELECT t.rowid";
@@ -153,13 +157,13 @@ class Orders extends DolibarrApi
                 $obj = $db->fetch_object($result);
                 $commande_static = new Commande($db);
                 if($commande_static->fetch($obj->rowid)) {
-                    $obj_ret[] = parent::_cleanObjectDatas($commande_static);
+                    $obj_ret[] = $this->_cleanObjectDatas($commande_static);
                 }
                 $i++;
             }
         }
         else {
-            throw new RestException(503, 'Error when retrieve commande list');
+            throw new RestException(503, 'Error when retrieve commande list : '.$db->lasterror());
         }
         if( ! count($obj_ret)) {
             throw new RestException(404, 'No order found');
@@ -399,6 +403,7 @@ class Orders extends DolibarrApi
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
         foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $this->commande->$field = $value;
         }
 

+ 91 - 64
htdocs/commande/class/commande.class.php

@@ -114,7 +114,7 @@ class Commande extends CommonOrder
      */
     public $availability;
 
-    public $demand_reason_id;
+    public $demand_reason_id;   // Source reason. Why we receive order (after a phone campaign, ...)
     public $demand_reason_code;
     public $address;
     public $date;				// Date commande
@@ -123,14 +123,14 @@ class Commande extends CommonOrder
 	 * @see date
 	 */
     public $date_commande;
-    public $date_livraison;	// Date livraison souhaitee
+    public $date_livraison;	    // Date expected of shipment (date starting shipment, not the reception that occurs some days after)
     public $fk_remise_except;
     public $remise_percent;
     public $remise_absolue;
     public $info_bits;
     public $rang;
     public $special_code;
-    public $source;			// Origin of order
+    public $source;			    // Order mode. How we received order (by phone, by email, ...)
     public $extraparams=array();
 
     public $linked_objects=array();
@@ -875,54 +875,70 @@ class Commande extends CommonOrder
                     	$this->ref = $initialref;
 
                         // Add object linked
-                        if (is_array($this->linked_objects) && ! empty($this->linked_objects))
+                        if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
                         {
-                        	foreach($this->linked_objects as $origin => $origin_id)
+                        	foreach($this->linked_objects as $origin => $tmp_origin_id)
                         	{
-                        		$ret = $this->add_object_linked($origin, $origin_id);
-                        		if (! $ret)
-                        		{
-                        			dol_print_error($this->db);
-                        			$error++;
-                        		}
-
-                        		if (! empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN))
-                        		{
-                        		    $originforcontact = $origin;
-                        		    $originidforcontact = $origin_id;
-                        		    if ($originforcontact == 'shipping')     // shipment and order share the same contacts. If creating from shipment we take data of order
-                        		    {
-                        		        require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
-                        		        $exp = new Expedition($db);
-                        		        $exp->fetch($origin_id);
-                        		        $exp->fetchObjectLinked();
-                        		        if (count($exp->linkedObjectsIds['commande']) > 0)
-                        		        {
-                        		            foreach ($exp->linkedObjectsIds['commande'] as $key => $value)
-                        		            {
-                        		                $originforcontact = 'commande';
-                        		                $originidforcontact = $value->id;
-                        		                break; // We take first one
-                        		            }
-                        		        }
-                        		    }
-
-                        		    $sqlcontact = "SELECT ctc.code, ctc.source, ec.fk_socpeople FROM ".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as ctc";
-                        		    $sqlcontact.= " WHERE element_id = ".$originidforcontact." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$originforcontact."'";
-
-                        		    $resqlcontact = $this->db->query($sqlcontact);
-                        		    if ($resqlcontact)
-                        		    {
-                        		        while($objcontact = $this->db->fetch_object($resqlcontact))
-                        		        {
-                					        //print $objcontact->code.'-'.$objcontact->source.'-'.$objcontact->fk_socpeople."\n";
-                        		            $this->add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);    // May failed because of duplicate key or because code of contact type does not exists for new object
-                        		        }
-                        		    }
-                        		    else dol_print_error($resqlcontact);
-                        		}
+                        	    if (is_array($tmp_origin_id))       // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
+                        	    {
+                        	        foreach($tmp_origin_id as $origin_id)
+                        	        {
+                        	            $ret = $this->add_object_linked($origin, $origin_id);
+                        	            if (! $ret)
+                        	            {
+                        	                dol_print_error($this->db);
+                        	                $error++;
+                        	            }
+                        	        }
+                        	    }
+                        	    else                                // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
+                        	    {
+                        	        $origin_id = $tmp_origin_id;
+                        	        $ret = $this->add_object_linked($origin, $origin_id);
+                        	        if (! $ret)
+                        	        {
+                        	            dol_print_error($this->db);
+                        	            $error++;
+                        	        }
+                          	    }
                         	}
                         }
+
+            			if (! $error && $this->id && ! empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN) && ! empty($this->origin) && ! empty($this->origin_id))   // Get contact from origin object
+            			{
+            				$originforcontact = $this->origin;
+            				$originidforcontact = $this->origin_id;
+                		    if ($originforcontact == 'shipping')     // shipment and order share the same contacts. If creating from shipment we take data of order
+                		    {
+                		        require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
+                		        $exp = new Expedition($db);
+                		        $exp->fetch($this->origin_id);
+                		        $exp->fetchObjectLinked();
+                		        if (count($exp->linkedObjectsIds['commande']) > 0)
+                		        {
+                		            foreach ($exp->linkedObjectsIds['commande'] as $key => $value)
+                		            {
+                		                $originforcontact = 'commande';
+                		                $originidforcontact = $value->id;
+                		                break; // We take first one
+                		            }
+                		        }
+                		    }
+
+                		    $sqlcontact = "SELECT ctc.code, ctc.source, ec.fk_socpeople FROM ".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as ctc";
+                		    $sqlcontact.= " WHERE element_id = ".$originidforcontact." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$originforcontact."'";
+
+                		    $resqlcontact = $this->db->query($sqlcontact);
+                		    if ($resqlcontact)
+                		    {
+                		        while($objcontact = $this->db->fetch_object($resqlcontact))
+                		        {
+        					        //print $objcontact->code.'-'.$objcontact->source.'-'.$objcontact->fk_socpeople."\n";
+                		            $this->add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);    // May failed because of duplicate key or because code of contact type does not exists for new object
+                		        }
+                		    }
+                		    else dol_print_error($resqlcontact);
+                		}
                     }
 
                     if (! $error)
@@ -1209,6 +1225,7 @@ class Commande extends CommonOrder
      * 	@param 		string			$fk_unit 			Code of the unit to use. Null to use the default one
      * 	@param		string		    $origin				'order', ...
      *  @param		int			    $origin_id			Id of origin object
+	 * 	@param		double			$pu_ht_devise		Unit price in currency
      *	@return     int             					>0 if OK, <0 if KO
      *
      *	@see        add_product
@@ -1218,7 +1235,7 @@ class Commande extends CommonOrder
      *	par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,produit)
      *	et le desc doit deja avoir la bonne valeur (a l'appelant de gerer le multilangue)
      */
-	function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $info_bits=0, $fk_remise_except=0, $price_base_type='HT', $pu_ttc=0, $date_start='', $date_end='', $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=null, $pa_ht=0, $label='',$array_options=0, $fk_unit=null, $origin='', $origin_id=0)
+	function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $info_bits=0, $fk_remise_except=0, $price_base_type='HT', $pu_ttc=0, $date_start='', $date_end='', $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=null, $pa_ht=0, $label='',$array_options=0, $fk_unit=null, $origin='', $origin_id=0, $pu_ht_devise = 0)
     {
     	global $mysoc, $conf, $langs, $user;
 
@@ -1294,18 +1311,20 @@ class Commande extends CommonOrder
     		    $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
     		}
 
-            $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx);
+            $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
 
             $total_ht  = $tabprice[0];
             $total_tva = $tabprice[1];
             $total_ttc = $tabprice[2];
             $total_localtax1 = $tabprice[9];
             $total_localtax2 = $tabprice[10];
+			$pu_ht = $tabprice[3];
 
 			// MultiCurrency
 			$multicurrency_total_ht  = $tabprice[16];
             $multicurrency_total_tva = $tabprice[17];
             $multicurrency_total_ttc = $tabprice[18];
+			$pu_ht_devise = $tabprice[19];
 
             // Rang to use
             $rangtouse = $rang;
@@ -1369,7 +1388,7 @@ class Commande extends CommonOrder
 			// Multicurrency
 			$this->line->fk_multicurrency			= $this->fk_multicurrency;
 			$this->line->multicurrency_code			= $this->multicurrency_code;
-			$this->line->multicurrency_subprice		= price2num($pu_ht * $this->multicurrency_tx);
+			$this->line->multicurrency_subprice		= $pu_ht_devise;
 			$this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
             $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
             $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
@@ -1741,7 +1760,7 @@ 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, p.tobatch as product_tobatch,';
         $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)';
@@ -1801,6 +1820,7 @@ class Commande extends CommonOrder
                 $line->libelle			= $objp->product_label;
                 $line->product_label	= $objp->product_label;
                 $line->product_desc     = $objp->product_desc;
+                $line->product_tobatch  = $objp->product_tobatch;
                 $line->fk_product_type  = $objp->fk_product_type;	// Produit ou service
 	            $line->fk_unit          = $objp->fk_unit;
 
@@ -2728,17 +2748,17 @@ class Commande extends CommonOrder
      *  Update a line in database
      *
      *  @param    	int				$rowid            	Id of line to update
-     *  @param    	string			$desc             	Description de la ligne
-     *  @param    	float			$pu               	Prix unitaire
+     *  @param    	string			$desc             	Description of line
+     *  @param    	float			$pu               	Unit price
      *  @param    	float			$qty              	Quantity
-     *  @param    	float			$remise_percent   	Pourcentage de remise de la ligne
+     *  @param    	float			$remise_percent   	Percent of discount
      *  @param    	float			$txtva           	Taux TVA
      * 	@param		float			$txlocaltax1		Local tax 1 rate
      *  @param		float			$txlocaltax2		Local tax 2 rate
      *  @param    	string			$price_base_type	HT or TTC
      *  @param    	int				$info_bits        	Miscellaneous informations on line
-     *  @param    	int		$date_start        	Start date of the line
-     *  @param    	int		$date_end          	End date of the line
+     *  @param    	int				$date_start        	Start date of the line
+     *  @param    	int				$date_end          	End date of the line
      * 	@param		int				$type				Type of line (0=product, 1=service)
      * 	@param		int				$fk_parent_line		Id of parent line (0 in most cases, used by modules adding sublevels into lines).
      * 	@param		int				$skip_update_total	Keep fields total_xxx to 0 (used for special lines by some modules)
@@ -2748,9 +2768,10 @@ class Commande extends CommonOrder
      *  @param		int				$special_code		Special code (also used by externals modules!)
 	 *  @param		array			$array_options		extrafields array
      * 	@param 		string			$fk_unit 			Code of the unit to use. Null to use the default one
+	 *  @param		double			$pu_ht_devise		Amount in currency
      *  @return   	int              					< 0 if KO, > 0 if OK
      */
-	function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1=0.0,$txlocaltax2=0.0, $price_base_type='HT', $info_bits=0, $date_start='', $date_end='', $type=0, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=null, $pa_ht=0, $label='', $special_code=0, $array_options=0, $fk_unit=null)
+	function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1=0.0,$txlocaltax2=0.0, $price_base_type='HT', $info_bits=0, $date_start='', $date_end='', $type=0, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=null, $pa_ht=0, $label='', $special_code=0, $array_options=0, $fk_unit=null, $pu_ht_devise = 0)
     {
         global $conf, $mysoc, $langs, $user;
 
@@ -2794,28 +2815,32 @@ class Commande extends CommonOrder
     		    $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
     		}
 
-            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx);
+            $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
 
             $total_ht  = $tabprice[0];
             $total_tva = $tabprice[1];
             $total_ttc = $tabprice[2];
             $total_localtax1 = $tabprice[9];
             $total_localtax2 = $tabprice[10];
+			$pu_ht  = $tabprice[3];
+			$pu_tva = $tabprice[4];
+			$pu_ttc = $tabprice[5];
 
 			// MultiCurrency
 			$multicurrency_total_ht  = $tabprice[16];
             $multicurrency_total_tva = $tabprice[17];
             $multicurrency_total_ttc = $tabprice[18];
+			$pu_ht_devise = $tabprice[19];
 
             // Anciens indicateurs: $price, $subprice, $remise (a ne plus utiliser)
-            $price = $pu;
+            $price = $pu_ht;
 			if ($price_base_type == 'TTC')
 			{
-				$subprice = $tabprice[5];
+				$subprice = $pu_ttc;
 			}
 			else
 			{
-				$subprice = $pu;
+				$subprice = $pu_ht;
 			}
             $remise = 0;
             if ($remise_percent > 0)
@@ -2893,7 +2918,7 @@ class Commande extends CommonOrder
 			$this->line->pa_ht = $pa_ht;
 
 			// Multicurrency
-			$this->line->multicurrency_subprice		= price2num($subprice * $this->multicurrency_tx);
+			$this->line->multicurrency_subprice		= $pu_ht_devise;
 			$this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
             $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
             $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
@@ -3765,7 +3790,7 @@ class OrderLine extends CommonOrderLine
         $sql.= ' cd.info_bits, cd.total_ht, cd.total_tva, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.fk_product_fournisseur_price as fk_fournprice, cd.buy_price_ht as pa_ht, cd.rang, cd.special_code,';
 	    $sql.= ' cd.fk_unit,';
 		$sql.= ' cd.fk_multicurrency, cd.multicurrency_code, cd.multicurrency_subprice, cd.multicurrency_total_ht, cd.multicurrency_total_tva, cd.multicurrency_total_ttc,';
-        $sql.= ' p.ref as product_ref, p.label as product_libelle, p.description as product_desc,';
+        $sql.= ' p.ref as product_ref, p.label as product_libelle, p.description as product_desc, p.tobatch as product_tobatch,';
         $sql.= ' cd.date_start, cd.date_end';
         $sql.= ' FROM '.MAIN_DB_PREFIX.'commandedet as cd';
         $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON cd.fk_product = p.rowid';
@@ -3810,7 +3835,8 @@ class OrderLine extends CommonOrderLine
             $this->libelle			= $objp->product_libelle;  // deprecated
             $this->product_label	= $objp->product_libelle;
             $this->product_desc     = $objp->product_desc;
-	        $this->fk_unit          = $objp->fk_unit;
+            $this->product_tobatch  = $objp->product_tobatch;
+            $this->fk_unit          = $objp->fk_unit;
 
             $this->date_start       = $this->db->jdate($objp->date_start);
             $this->date_end         = $this->db->jdate($objp->date_end);
@@ -3828,6 +3854,7 @@ class OrderLine extends CommonOrderLine
         }
         else
         {
+            $this->error = $this->db->lasterror();
             return -1;
         }
     }

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

@@ -81,7 +81,8 @@ class CommandeStats extends Stats
 			$this->where.= " c.fk_statut > 2";    // Only approved & ordered
 		}
 		//$this->where.= " AND c.fk_soc = s.rowid AND c.entity = ".$conf->entity;
-		$this->where.= " AND c.entity = ".$conf->entity;
+		$this->where.= ' AND c.entity IN ('.getEntity('commande', 1).')';
+		
 		if (!$user->rights->societe->client->voir && !$this->socid) $this->where .= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
 		if ($this->socid)
 		{

+ 54 - 61
htdocs/commande/contact.php

@@ -30,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/order.lib.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.'/projet/class/project.class.php';
 
 $langs->load("orders");
 $langs->load("sendings");
@@ -139,69 +140,61 @@ if ($id > 0 || ! empty($ref))
 
 	if ($object->fetch($id, $ref) > 0)
 	{
-		$soc = new Societe($db);
-		$soc->fetch($object->socid);
-
-
+	    $object->fetch_thirdparty();
+	    
 		$head = commande_prepare_head($object);
 		dol_fiche_head($head, 'contact', $langs->trans("CustomerOrder"), 0, 'order');
 
-
-	   /*
-		*   Facture synthese pour rappel
-		*/
-		print '<table class="border" width="100%">';
-
-		$linkback = '<a href="'.DOL_URL_ROOT.'/commande/list.php'.(! empty($socid)?'?socid='.$socid:'').'">'.$langs->trans("BackToList").'</a>';
-
-		// Ref
-		print '<tr><td class="titlefield">'.$langs->trans("Ref").'</td><td colspan="3">';
-		print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref');
-		print "</td></tr>";
-
-		// Ref commande client
-		print '<tr><td>';
-        print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
-		print $langs->trans('RefCustomer').'</td><td align="left">';
-        print '</td>';
-        print '</tr></table>';
-        print '</td><td colspan="3">';
-		print $object->ref_client;
-		print '</td>';
-		print '</tr>';
-
-		// Customer
-		if (is_null($object->thirdparty))	$object->fetch_thirdparty();
-
-		print "<tr><td>".$langs->trans("Company")."</td>";
-		print '<td colspan="3">'.$object->thirdparty->getNomUrl(1).'</td></tr>';
-
-		// Delivery address
-		if (! empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT))
-		{
-			print '<tr><td>';
-			print '<table class="nobordernopadding" width="100%"><tr><td>';
-			print $langs->trans('DeliveryAddress');
-			print '</td>';
-
-			if ($action != 'editdelivery_address' && $object->brouillon) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdelivery_address&amp;socid='.$object->socid.'&amp;id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetDeliveryAddress'),1).'</a></td>';
-			print '</tr></table>';
-			print '</td><td colspan="3">';
-
-			if ($action == 'editdelivery_address')
-			{
-				$formother->form_address($_SERVER['PHP_SELF'].'?id='.$object->id,$object->fk_delivery_address,GETPOST('socid','int'),'fk_address','commande',$object->id);
-			}
-			else
-			{
-				$formother->form_address($_SERVER['PHP_SELF'].'?id='.$object->id,$object->fk_delivery_address,GETPOST('socid','int'),'none','commande',$object->id);
-			}
-			print '</td></tr>';
-		}
-
-		print "</table>";
-
-		print '</div>';
+		
+		// Order card
+		
+		$linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
+		
+		
+		$morehtmlref='<div class="refidno">';
+		// Ref customer
+		$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1);
+		$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1);
+		// Thirdparty
+		$morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
+	    // Project
+	    if (! empty($conf->projet->enabled))
+	    {
+	        $langs->load("projects");
+	        $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
+	        if ($user->rights->commande->creer)
+	        {
+	            if ($action != 'classify')
+	                //$morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
+	                $morehtmlref.=' : ';
+	                if ($action == 'classify') {
+	                    //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
+	                    $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
+	                    $morehtmlref.='<input type="hidden" name="action" value="classin">';
+	                    $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	                    $morehtmlref.=$formproject->select_projects($object->thirdparty->id, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
+	                    $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
+	                    $morehtmlref.='</form>';
+	                } else {
+	                    $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->thirdparty->id, $object->fk_project, 'none', 0, 0, 0, 1);
+	                }
+	        } else {
+	            if (! empty($object->fk_project)) {
+	                $proj = new Project($db);
+	                $proj->fetch($object->fk_project);
+	                $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
+	                $morehtmlref.=$proj->ref;
+	                $morehtmlref.='</a>';
+	            } else {
+	                $morehtmlref.='';
+	            }
+	        }
+	    }
+		$morehtmlref.='</div>';		
+
+		dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, '', 0, '', '', 1);
+
+		dol_fiche_end();
 
 		print '<br>';
 
@@ -215,7 +208,7 @@ if ($id > 0 || ! empty($ref))
 	}
 	else
 	{
-		// Contrat non trouve
+		// Contact not found
 		print "ErrorRecordNotFound";
 	}
 }

+ 63 - 14
htdocs/commande/document.php

@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2003-2007 Rodolphe Quiedeville  <rodolphe@quiedeville.org>
- * Copyright (C) 2004-2008 Laurent Destailleur   <eldy@users.sourceforge.net>
+ * Copyright (C) 2004-2016 Laurent Destailleur   <eldy@users.sourceforge.net>
  * Copyright (C) 2005      Marc Barilley / Ocebo <marc@ocebo.com>
  * Copyright (C) 2005-2012 Regis Houssin         <regis.houssin@capnetworks.com>
  * Copyright (C) 2013      Cédric Salvador       <csalvador@gpcsolutions.fr>
@@ -94,30 +94,79 @@ if ($id > 0 || ! empty($ref))
 		$head = commande_prepare_head($object);
 		dol_fiche_head($head, 'documents', $langs->trans('CustomerOrder'), 0, 'order');
 
-
 		// Construit liste des fichiers
 		$filearray=dol_dir_list($upload_dir,"files",0,'','(\.meta|_preview\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1);
 		$totalsize=0;
 		foreach($filearray as $key => $file)
 		{
-			$totalsize+=$file['size'];
+		    $totalsize+=$file['size'];
 		}
-
-
+		
+		// Order card
+		
+		$linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
+		
+		
+		$morehtmlref='<div class="refidno">';
+		// Ref customer
+		$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1);
+		$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1);
+		// Thirdparty
+		$morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
+		// Project
+		if (! empty($conf->projet->enabled))
+		{
+		    $langs->load("projects");
+		    $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
+		    if ($user->rights->commande->creer)
+		    {
+		        if ($action != 'classify')
+		            //$morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
+		            $morehtmlref.=' : ';
+		            if ($action == 'classify') {
+		                //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
+		                $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
+		                $morehtmlref.='<input type="hidden" name="action" value="classin">';
+		                $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+		                $morehtmlref.=$formproject->select_projects($object->thirdparty->id, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
+		                $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
+		                $morehtmlref.='</form>';
+		            } else {
+		                $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->thirdparty->id, $object->fk_project, 'none', 0, 0, 0, 1);
+		            }
+		    } else {
+		        if (! empty($object->fk_project)) {
+		            $proj = new Project($db);
+		            $proj->fetch($object->fk_project);
+		            $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
+		            $morehtmlref.=$proj->ref;
+		            $morehtmlref.='</a>';
+		        } else {
+		            $morehtmlref.='';
+		        }
+		    }
+		}
+		$morehtmlref.='</div>';
+		
+		// Order card
+		
+		$linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
+		
+		dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);	
+		
+		print '<div class="fichecenter">';
+		print '<div class="underbanner clearboth"></div>';
+		
 		print '<table class="border" width="100%">';
 
-		$linkback = '<a href="'.DOL_URL_ROOT.'/commande/list.php'.(! empty($socid)?'?socid='.$socid:'').'">'.$langs->trans("BackToList").'</a>';
-
-		// Ref
-		print '<tr><td width="30%">'.$langs->trans('Ref').'</td><td colspan="3">';
-		print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref');
-		print '</td></tr>';
-
-		print '<tr><td>'.$langs->trans('Company').'</td><td colspan="3">'.$object->thirdparty->getNomUrl(1).'</td></tr>';
-		print '<tr><td>'.$langs->trans("NbOfAttachedFiles").'</td><td colspan="3">'.count($filearray).'</td></tr>';
+		print '<tr><td class="titlefield">'.$langs->trans("NbOfAttachedFiles").'</td><td colspan="3">'.count($filearray).'</td></tr>';
 		print '<tr><td>'.$langs->trans("TotalSizeOfAttachedFiles").'</td><td colspan="3">'.$totalsize.' '.$langs->trans("bytes").'</td></tr>';
+
 		print "</table>\n";
+		
 		print "</div>\n";
+		
+		print dol_fiche_end();
 
 		$modulepart = 'commande';
 		$permission = $user->rights->commande->creer;

+ 71 - 7
htdocs/commande/info.php

@@ -32,12 +32,21 @@ if (!$user->rights->commande->lire)	accessforbidden();
 $langs->load("orders");
 $langs->load("sendings");
 
-// Security check
 $socid=0;
 $comid = GETPOST("id",'int');
+$id = GETPOST("id",'int');
+$ref=GETPOST('ref','alpha');
+
+// Security check
 if ($user->societe_id) $socid=$user->societe_id;
 $result=restrictedArea($user,'commande',$comid,'');
 
+$object = new Commande($db);
+if (! $object->fetch($id, $ref) > 0)
+{
+    dol_print_error($db);
+    exit;
+}
 
 
 /*
@@ -46,21 +55,76 @@ $result=restrictedArea($user,'commande',$comid,'');
 
 llxHeader('',$langs->trans('Order'),'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes');
 
-$commande = new Commande($db);
-$commande->fetch($comid);
-$commande->info($comid);
+$object->fetch_thirdparty();
+$object->info($object->id);
+
 $soc = new Societe($db);
-$soc->fetch($commande->socid);
+$soc->fetch($object->thirdparty->id);
 
-$head = commande_prepare_head($commande);
+$head = commande_prepare_head($object);
 dol_fiche_head($head, 'info', $langs->trans("CustomerOrder"), 0, 'order');
 
+// Order card
+
+$linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
+
+
+$morehtmlref='<div class="refidno">';
+// Ref customer
+$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1);
+$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1);
+// Thirdparty
+$morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1);
+// Project
+if (! empty($conf->projet->enabled))
+{
+    $langs->load("projects");
+    $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
+    if ($user->rights->commande->creer)
+    {
+        if ($action != 'classify')
+            //$morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
+            $morehtmlref.=' : ';
+            if ($action == 'classify') {
+                //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
+                $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
+                $morehtmlref.='<input type="hidden" name="action" value="classin">';
+                $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+                $morehtmlref.=$formproject->select_projects($object->thirdparty->id, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
+                $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
+                $morehtmlref.='</form>';
+            } else {
+                $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->thirdparty->id, $object->fk_project, 'none', 0, 0, 0, 1);
+            }
+    } else {
+        if (! empty($object->fk_project)) {
+            $proj = new Project($db);
+            $proj->fetch($object->fk_project);
+            $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
+            $morehtmlref.=$proj->ref;
+            $morehtmlref.='</a>';
+        } else {
+            $morehtmlref.='';
+        }
+    }
+}
+$morehtmlref.='</div>';
+
+
+dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
+
+print '<div class="fichecenter">';
+print '<div class="underbanner clearboth"></div>';
+
+print '<br>';
 
 print '<table width="100%"><tr><td>';
-dol_print_object_info($commande);
+dol_print_object_info($object);
 print '</td></tr></table>';
 
 print '</div>';
 
+dol_fiche_end();
+
 llxFooter();
 $db->close();

+ 5 - 5
htdocs/commande/list.php

@@ -560,7 +560,7 @@ $sql.=$hookmanager->resPrint;
 $sql.= $db->order($sortfield,$sortorder);
 
 // Count total nb of records
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
 	$result = $db->query($sql);
@@ -845,7 +845,8 @@ if ($resql)
     $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 '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 
 	// Fields title
 	print '<tr class="liste_titre">';
@@ -1421,9 +1422,8 @@ if ($resql)
 	print $hookmanager->resPrint;
 				
 	print '</table>'."\n";
-
-	print '<br />';
-
+	print '</div>';
+	
 	print '</form>'."\n";
 
 	//print '<br>'.img_help(1,'').' '.$langs->trans("ToBillSeveralOrderSelectCustomer", $langs->transnoentitiesnoconv("CreateInvoiceForThisCustomer")).'<br>';

+ 59 - 30
htdocs/commande/note.php

@@ -1,8 +1,8 @@
 <?php
 /* Copyright (C) 2004      Rodolphe Quiedeville <rodolphe@quiedeville.org>
- * Copyright (C) 2004-2007 Laurent Destailleur  <eldy@users.sourceforge.net>
+ * Copyright (C) 2004-2016 Laurent Destailleur  <eldy@users.sourceforge.net>
  * Copyright (C) 2005-2012 Regis Houssin        <regis.houssin@capnetworks.com>
- * Copyright (C) 2013      Florian Henry		  	<florian.henry@open-concept.pro>
+ * Copyright (C) 2013      Florian Henry		<florian.henry@open-concept.pro>
  *
  * 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
@@ -48,6 +48,7 @@ $object = new Commande($db);
 if (! $object->fetch($id, $ref) > 0)
 {
 	dol_print_error($db);
+	exit;
 }
 
 $permissionnote=$user->rights->commande->creer;	// Used by the include of actions_setnotes.inc.php
@@ -77,38 +78,66 @@ if ($id > 0 || ! empty($ref))
 
 	dol_fiche_head($head, 'note', $langs->trans("CustomerOrder"), 0, 'order');
 
-	print '<table class="border" width="100%">';
-
-	$linkback = '<a href="'.DOL_URL_ROOT.'/commande/list.php'.(! empty($socid)?'?socid='.$socid:'').'">'.$langs->trans("BackToList").'</a>';
-
-	// Ref
-	print '<tr><td width="25%">'.$langs->trans("Ref").'</td><td colspan="3">';
-	print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref');
-	print "</td></tr>";
-
-	// Ref commande client
-	print '<tr><td>';
-	print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
-	print $langs->trans('RefCustomer').'</td><td align="left">';
-	print '</td>';
-	print '</tr></table>';
-	print '</td><td colspan="3">';
-	print $object->ref_client;
-	print '</td>';
-	print '</tr>';
-
-	// Customer
-	print "<tr><td>".$langs->trans("Company")."</td>";
-	print '<td colspan="3">'.$soc->getNomUrl(1).'</td></tr>';
-
-	print "</table>";
-
-	print '<br>';
-
+	// Order card
+	
+	$linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
+	
+	
+	$morehtmlref='<div class="refidno">';
+	// Ref customer
+	$morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1);
+	$morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1);
+	// Thirdparty
+	$morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1);
+	// Project
+	if (! empty($conf->projet->enabled))
+	{
+	    $langs->load("projects");
+	    $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
+	    if ($user->rights->commande->creer)
+	    {
+	        if ($action != 'classify')
+	            //$morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
+	            $morehtmlref.=' : ';
+	            if ($action == 'classify') {
+	                //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
+	                $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
+	                $morehtmlref.='<input type="hidden" name="action" value="classin">';
+	                $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+	                $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
+	                $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
+	                $morehtmlref.='</form>';
+	            } else {
+	                $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
+	            }
+	    } else {
+	        if (! empty($object->fk_project)) {
+	            $proj = new Project($db);
+	            $proj->fetch($object->fk_project);
+	            $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
+	            $morehtmlref.=$proj->ref;
+	            $morehtmlref.='</a>';
+	        } else {
+	            $morehtmlref.='';
+	        }
+	    }
+	}
+	$morehtmlref.='</div>';
+	
+	
+	dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
+	
+	
+	print '<div class="fichecenter">';
+	print '<div class="underbanner clearboth"></div>';
+	
+	
 	$cssclass="titlefield";
 	include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php';
 
 	print '</div>';
+	
+	dol_fiche_end();
 }
 
 

+ 13 - 10
htdocs/compta/bank/bankentries.php

@@ -501,7 +501,7 @@ $sql.=$hookmanager->resPrint;
 
 $sql.= $db->order($sortfield,$sortorder);
 
-$nbtotalofrecords = 0;
+$nbtotalofrecords = -1;
 $nbtotalofpages = 0;
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
@@ -677,7 +677,7 @@ if ($resql)
 	}	
 	
 	
-	/// ajax adjust value date
+	/// ajax to adjust value date with plus and less picto
 	print '
     <script type="text/javascript">
     $(function() {
@@ -728,18 +728,18 @@ if ($resql)
 	
 	$moreforfilter.='<div class="divsearchfield">';
 	$moreforfilter .= $langs->trans('DateOperationShort').' : ';
-	$moreforfilter .= '<div class="nowrap inline-block">'.$langs->trans('From') . ' ';
+	$moreforfilter .= '<div class="nowrap'.($conf->browser->layout=='phone'?' centpercent':'').' inline-block">'.$langs->trans('From') . ' ';
 	$moreforfilter .= $form->select_date($search_dt_start, 'search_start_dt', 0, 0, 1, "search_form", 1, 0, 1).'</div>';
-	$moreforfilter .= ' - ';
-	$moreforfilter .= '<div class="nowrap inline-block">'.$langs->trans('to') . ' ' . $form->select_date($search_dt_end, 'search_end_dt', 0, 0, 1, "search_form", 1, 0, 1).'</div>';
+	//$moreforfilter .= ' - ';
+	$moreforfilter .= '<div class="nowrap'.($conf->browser->layout=='phone'?' centpercent':'').' inline-block">'.$langs->trans('to') . ' ' . $form->select_date($search_dt_end, 'search_end_dt', 0, 0, 1, "search_form", 1, 0, 1).'</div>';
 	$moreforfilter .= '</div>';
 	
 	$moreforfilter.='<div class="divsearchfield">';
 	$moreforfilter .= $langs->trans('DateValueShort').' : ';
-	$moreforfilter .= '<div class="nowrap inline-block">'.$langs->trans('From') . ' ';
+	$moreforfilter .= '<div class="nowrap'.($conf->browser->layout=='phone'?' centpercent':'').' inline-block">'.$langs->trans('From') . ' ';
 	$moreforfilter .= $form->select_date($search_dv_start, 'search_start_dv', 0, 0, 1, "search_form", 1, 0, 1).'</div>';
-	$moreforfilter .= ' - ';
-	$moreforfilter .= '<div class="nowrap inline-block">'.$langs->trans('to') . ' ' . $form->select_date($search_dv_end, 'search_end_dv', 0, 0, 1, "search_form", 1, 0, 1).'</div>';
+	//$moreforfilter .= ' - ';
+	$moreforfilter .= '<div class="nowrap'.($conf->browser->layout=='phone'?' centpercent':'').' inline-block">'.$langs->trans('to') . ' ' . $form->select_date($search_dv_end, 'search_end_dv', 0, 0, 1, "search_form", 1, 0, 1).'</div>';
 	$moreforfilter .= '</div>';
 	
 	$parameters=array();
@@ -757,7 +757,8 @@ if ($resql)
     $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 '<div class="div-table-responsive">';
+    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
 	
 	// Fields title
 	print '<tr class="liste_titre">';
@@ -1089,7 +1090,7 @@ if ($resql)
     	   print '<td align="center" class="nowrap">';
     	   print '<span id="datevalue_'.$objp->rowid.'">'.dol_print_date($db->jdate($objp->dv),"day")."</span>";
     	   print '&nbsp;';
-    	   print '<span>';
+    	   print '<span class="inline-block">';
     	   print '<a class="ajax" href="'.$_SERVER['PHP_SELF'].'?action=dvprev&amp;account='.$objp->bankid.'&amp;rowid='.$objp->rowid.'">';
     	   print img_edit_remove() . "</a> ";
     	   print '<a class="ajax" href="'.$_SERVER['PHP_SELF'].'?action=dvnext&amp;account='.$objp->bankid.'&amp;rowid='.$objp->rowid.'">';
@@ -1295,6 +1296,8 @@ if ($resql)
 	}
 
 	print "</table>";
+	print "</div>";
+	
     print '</form>';
 	$db->free($resql);
 }

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

@@ -388,7 +388,7 @@ if ($action == 'create')
 	print '<td colspan="3">';
     // Editor wysiwyg
 	require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-	$doleditor=new DolEditor('account_comment',(GETPOST("account_comment")?GETPOST("account_comment"):$object->comment),'',90,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,4,70);
+	$doleditor=new DolEditor('account_comment',(GETPOST("account_comment")?GETPOST("account_comment"):$object->comment),'',90,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_4,'90%');
 	$doleditor->Create();
 	print '</td></tr>';
 
@@ -603,7 +603,7 @@ else
 		print '<td>'.$object->label.'</td></tr>';*/
 
 		// Type
-		print '<tr><td>'.$langs->trans("AccountType").'</td>';
+		print '<tr><td class="titlefield">'.$langs->trans("AccountType").'</td>';
 		print '<td>'.$object->type_lib[$object->type].'</td></tr>';
 
 		// Currency
@@ -683,12 +683,12 @@ else
 		
         // Categories
         if ($conf->categorie->enabled) {
-            print '<tr><td valign="middle">'.$langs->trans("Categories").'</td><td>';
+            print '<tr><td class="titlefield">'.$langs->trans("Categories").'</td><td>';
             print $form->showCategories($object->id,'account',1);
             print "</td></tr>";
         }
 
-		print '<tr><td class="tdtop">'.$langs->trans("Comment").'</td>';
+		print '<tr><td class="tdtop titlefield">'.$langs->trans("Comment").'</td>';
 		print '<td>'.dol_htmlentitiesbr($object->comment).'</td></tr>';
 
 		print '</table>';
@@ -931,7 +931,7 @@ else
 		print '<td>';
 	    // Editor wysiwyg
 		require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-		$doleditor=new DolEditor('account_comment',(GETPOST("account_comment")?GETPOST("account_comment"):$object->comment),'',90,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,4,'95%');
+		$doleditor=new DolEditor('account_comment',(GETPOST("account_comment")?GETPOST("account_comment"):$object->comment),'',90,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_4,'95%');
 		$doleditor->Create();
 		print '</td></tr>';
 

+ 8 - 3
htdocs/compta/bank/class/account.class.php

@@ -848,6 +848,7 @@ class Account extends CommonObject
         $sql.= " ba.domiciliation, ba.proprio, ba.owner_address, ba.state_id, ba.fk_pays as country_id,";
         $sql.= " ba.account_number, ba.accountancy_journal, ba.currency_code,";
         $sql.= " ba.min_allowed, ba.min_desired, ba.comment,";
+        $sql.= " ba.datec as date_creation, ba.tms as date_update,";
         $sql.= ' c.code as country_code, c.label as country,';
         $sql.= ' d.code_departement as state_code, d.nom as state';
         $sql.= " FROM ".MAIN_DB_PREFIX."bank_account as ba";
@@ -903,6 +904,9 @@ class Account extends CommonObject
                 $this->min_desired    = $obj->min_desired;
                 $this->comment        = $obj->comment;
 
+                $this->date_creation  = $this->db->jdate($obj->date_creation);
+                $this->date_update    = $this->db->jdate($obj->date_update);
+                
                 // Retreive all extrafield for thirdparty
                 // fetch optionals attributes and labels
                 require_once(DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php');
@@ -910,7 +914,6 @@ class Account extends CommonObject
                 $extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true);
                 $this->fetch_optionals($this->id,$extralabels);
 
-
                 return 1;
             }
             else
@@ -1221,8 +1224,9 @@ class Account extends CommonObject
         $label .= '<br><b>' . $langs->trans('AccountNumber') . ':</b> ' . $this->number;
         if (! empty($conf->accounting->enabled))
         {
+            include_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
             $langs->load("accountancy");
-            $label .= '<br><b>' . $langs->trans('AccountAccounting') . ':</b> ' . $this->account_number;
+            $label .= '<br><b>' . $langs->trans('AccountAccounting') . ':</b> ' . length_accountg($this->account_number);
             $label .= '<br><b>' . $langs->trans('AccountancyJournal') . ':</b> ' . $this->accountancy_journal;
         }
         $linkclose = '" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
@@ -1927,7 +1931,7 @@ class AccountLine extends CommonObject
      */
     function info($id)
     {
-        $sql = 'SELECT b.rowid, b.datec,';
+        $sql = 'SELECT b.rowid, b.datec, b.tms as datem,';
         $sql.= ' b.fk_user_author, b.fk_user_rappro';
         $sql.= ' FROM '.MAIN_DB_PREFIX.'bank as b';
         $sql.= ' WHERE b.rowid = '.$id;
@@ -1954,6 +1958,7 @@ class AccountLine extends CommonObject
                 }
 
                 $this->date_creation     = $this->db->jdate($obj->datec);
+                $this->date_modification = $this->db->jdate($obj->datem);
                 //$this->date_rappro       = $obj->daterappro;    // Not yet managed
             }
             $this->db->free($result);

+ 2 - 1
htdocs/compta/bank/class/api_bankaccounts.class.php

@@ -70,7 +70,7 @@ class BankAccounts extends DolibarrApi
         }
 
         $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank_account as t";
-        $sql.= ' WHERE t.entity IN ('.getEntity('banque', 1).')';
+        $sql.= ' WHERE t.entity IN ('.getEntity('bank_account', 1).')';
         // Add sql filters
         if ($sqlfilters) 
         {
@@ -185,6 +185,7 @@ class BankAccounts extends DolibarrApi
         }
 
         foreach ($request_data as $field => $value) {
+            if ($field == 'id') continue;
             $account->$field = $value;
         }
 

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