Browse Source

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

atm-quentin 6 years ago
parent
commit
013c078c8b
100 changed files with 3591 additions and 1526 deletions
  1. 5 1
      .travis.yml
  2. 7 0
      .tx/config
  3. 211 8
      ChangeLog
  4. 3 3
      README.md
  5. 1 0
      build/debian/source/include-binaries
  6. 14 2
      build/docker/Dockerfile
  7. 5 1
      build/makepack-dolibarr.pl
  8. 15 9
      build/perl/virtualmin/dolibarr.pl
  9. 55 0
      dev/initdemo/mysqldump_dolibarr_8.0.0.sql
  10. 55 0
      dev/initdemo/mysqldump_dolibarr_9.0.0.sql
  11. 7 0
      dev/initdemo/savedemo.sh
  12. 0 12
      dev/resources/dbmodel/dolibarr.uml
  13. 0 53
      dev/resources/dbmodel/dolibarr.umldi
  14. BIN
      dev/resources/dbmodel/dolibarr_schema.mwb
  15. 9 0
      dev/setup/codesniffer/ruleset.xml
  16. 3 3
      dev/tools/fixdosfiles.sh
  17. 130 0
      dev/tools/snakeCaseToCamelCase.sh
  18. 5 5
      doc/install/README
  19. 33 0
      doc/install/README-DE
  20. 5 1
      htdocs/.gitignore
  21. 10 9
      htdocs/accountancy/admin/card.php
  22. 8 7
      htdocs/accountancy/admin/defaultaccounts.php
  23. 15 9
      htdocs/accountancy/admin/fiscalyear.php
  24. 3 4
      htdocs/accountancy/bookkeeping/balance.php
  25. 0 1
      htdocs/accountancy/bookkeeping/list.php
  26. 71 38
      htdocs/accountancy/class/accountancycategory.class.php
  27. 3 0
      htdocs/accountancy/class/accountancyexport.class.php
  28. 16 16
      htdocs/accountancy/class/bookkeeping.class.php
  29. 1 1
      htdocs/accountancy/class/lettering.class.php
  30. 2 2
      htdocs/accountancy/customer/card.php
  31. 5 5
      htdocs/accountancy/customer/lines.php
  32. 5 5
      htdocs/accountancy/customer/list.php
  33. 8 2
      htdocs/accountancy/index.php
  34. 92 48
      htdocs/accountancy/journal/bankjournal.php
  35. 2 2
      htdocs/accountancy/journal/expensereportsjournal.php
  36. 13 12
      htdocs/accountancy/journal/purchasesjournal.php
  37. 4 4
      htdocs/accountancy/journal/sellsjournal.php
  38. 2 2
      htdocs/accountancy/supplier/card.php
  39. 2 2
      htdocs/adherents/admin/adherent_extrafields.php
  40. 58 45
      htdocs/adherents/card.php
  41. 117 59
      htdocs/adherents/class/adherent.class.php
  42. 19 6
      htdocs/adherents/class/subscription.class.php
  43. 1 1
      htdocs/adherents/index.php
  44. 71 7
      htdocs/adherents/list.php
  45. 12 2
      htdocs/adherents/subscription.php
  46. 3 3
      htdocs/adherents/subscription/card.php
  47. 397 185
      htdocs/adherents/subscription/list.php
  48. 3 3
      htdocs/adherents/type.php
  49. 1 1
      htdocs/admin/bank.php
  50. 46 17
      htdocs/admin/barcode.php
  51. 127 0
      htdocs/admin/commande_fournisseur_dispatch_extrafields.php
  52. 20 2
      htdocs/admin/dav.php
  53. 7 4
      htdocs/admin/defaultvalues.php
  54. 1 1
      htdocs/admin/dict.php
  55. 49 9
      htdocs/admin/emailcollector_card.php
  56. 52 42
      htdocs/admin/emailcollector_list.php
  57. 1 1
      htdocs/admin/events.php
  58. 1 1
      htdocs/admin/export.php
  59. 7 7
      htdocs/admin/facture.php
  60. 20 0
      htdocs/admin/geoipmaxmind.php
  61. 1 1
      htdocs/admin/mails.php
  62. 1 1
      htdocs/admin/mails_emailing.php
  63. 63 55
      htdocs/admin/mails_templates.php
  64. 46 21
      htdocs/admin/menus/edit.php
  65. 4 1
      htdocs/admin/modules.php
  66. 27 45
      htdocs/admin/multicurrency.php
  67. 127 0
      htdocs/admin/reception_extrafields.php
  68. 520 0
      htdocs/admin/reception_setup.php
  69. 1 1
      htdocs/admin/salaries.php
  70. 2 2
      htdocs/admin/sms.php
  71. 31 32
      htdocs/admin/socialnetworks.php
  72. 204 237
      htdocs/admin/stock.php
  73. 4 4
      htdocs/admin/ticket.php
  74. 2 2
      htdocs/admin/ticket_extrafields.php
  75. 8 1
      htdocs/admin/tools/dolibarr_export.php
  76. 4 1
      htdocs/admin/workflow.php
  77. 2 2
      htdocs/asset/card.php
  78. 2 2
      htdocs/blockedlog/admin/blockedlog_list.php
  79. 40 4
      htdocs/blockedlog/class/blockedlog.class.php
  80. 1 0
      htdocs/blockedlog/lib/blockedlog.lib.php
  81. 30 19
      htdocs/cashdesk/admin/cashdesk.php
  82. 7 7
      htdocs/categories/class/categorie.class.php
  83. 18 2
      htdocs/categories/photos.php
  84. 8 8
      htdocs/comm/action/card.php
  85. 27 8
      htdocs/comm/action/class/actioncomm.class.php
  86. 30 27
      htdocs/comm/action/index.php
  87. 80 35
      htdocs/comm/action/list.php
  88. 40 26
      htdocs/comm/action/peruser.php
  89. 10 10
      htdocs/comm/card.php
  90. 7 7
      htdocs/comm/mailing/card.php
  91. 6 8
      htdocs/comm/mailing/cibles.php
  92. 10 1
      htdocs/comm/mailing/class/advtargetemailing.class.php
  93. 101 13
      htdocs/comm/propal/card.php
  94. 34 31
      htdocs/comm/propal/class/propal.class.php
  95. 21 46
      htdocs/comm/propal/list.php
  96. 13 13
      htdocs/comm/remx.php
  97. 157 119
      htdocs/commande/card.php
  98. 41 39
      htdocs/commande/class/commande.class.php
  99. 20 29
      htdocs/commande/list.php
  100. 3 3
      htdocs/commande/orderstoinvoice.php

+ 5 - 1
.travis.yml

@@ -288,7 +288,8 @@ script:
   echo "Checking PHP syntax errors"
   # Ensure we catch errors
   set -e
-  parallel-lint --exclude htdocs/includes --blame .
+  #parallel-lint --exclude htdocs/includes --blame .
+  parallel-lint --exclude htdocs/includes/sabre --exclude htdocs/includes/sebastian --exclude htdocs/includes/squizlabs/php_codesniffer/tests --exclude htdocs/includes/jakub-onderka/php-parallel-lint/tests --exclude htdocs/includes/mike42/escpos-php/example --exclude htdocs/includes/phpunit/php-token-stream/tests --exclude htdocs/includes/composer/autoload_static.php --blame .
   set +e
   echo
 
@@ -341,6 +342,9 @@ script:
   php upgrade.php 8.0.0 9.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade800900.log
   php upgrade2.php 8.0.0 9.0.0 > $TRAVIS_BUILD_DIR/upgrade800900-2.log
   php step5.php 8.0.0 9.0.0 > $TRAVIS_BUILD_DIR/upgrade800900-3.log
+  php upgrade.php 9.0.0 10.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade9001000.log
+  php upgrade2.php 9.0.0 10.0.0 > $TRAVIS_BUILD_DIR/upgrade9001000-2.log
+  php step5.php 9.0.0 10.0.0 > $TRAVIS_BUILD_DIR/upgrade9001000-3.log
   cd -
   set +e
   echo

+ 7 - 0
.tx/config

@@ -314,6 +314,12 @@ source_file = htdocs/langs/en_US/receiptprinter.lang
 source_lang = en_US
 type = MOZILLAPROPERTIES
 
+[dolibarr.receptions]
+file_filter = htdocs/langs/<lang>/receptions.lang
+source_file = htdocs/langs/en_US/receptions.lang
+source_lang = en_US
+type = MOZILLAPROPERTIES
+
 [dolibarr.resource]
 file_filter = htdocs/langs/<lang>/resource.lang
 source_file = htdocs/langs/en_US/resource.lang
@@ -397,3 +403,4 @@ file_filter = htdocs/langs/<lang>/workflow.lang
 source_file = htdocs/langs/en_US/workflow.lang
 source_lang = en_US
 type = MOZILLAPROPERTIES
+

+ 211 - 8
ChangeLog

@@ -2,23 +2,127 @@
 English Dolibarr ChangeLog
 --------------------------------------------------------------
 
+***** ChangeLog for 10.0.0 compared to 9.0.0 *****
+For Users:
+NEW: Experimental module "Vendor receptions"
+
+For Developers:
+
+
+WARNING:
+
+Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
+* GetUrlTrackingStatus were renamed into getUrlTrackingStatus
+
 
 ***** ChangeLog for 9.0.0 compared to 8.0.0 *****
 For Users:
-NEW: Stable module: Website
-NEW: Stable module: WebDAV
-NEW: Stable module: Module Builder
+NEW: Stable module: DAV (WebDAV only for the moment)
 NEW: Stable module "Skype" has been replaced with module "Social Networks" to support more services.
+NEW: Stable module "Module Builder"
+NEW: Stable module: Website
 NEW: Experimental module "TakePos"
 NEW: Experimental module "Ticket"
+NEW: Experimental module "Data Privacy"
+NEW: Experimental module "Email Collector"
 NEW: Dolibarr can provide information in page title when multicompany is enabled of not, making
      Android application like DoliDroid able to provide native features for multicompany module.
-NEW: Compatibility with PHP 7.3
-
+NEW: Compatibility with PHP 7.3 => 
+NEW: Add admin page for modulebuilder
+NEW: Add civility in list of members. Close #9251
+NEW: Add configuration to disable "customer/prospect" thirdparty type
+NEW: Add CONTRACT_ALLOW_TO_LINK_FROM_OTHER_COMPANY and CONTRACT_HIDE_UNSELECTABLES by SELECT_HIDE_UNSELECTABLES
+NEW: Add __DAY_TEXT__ and __MONTH_TEXT__ substitutions vars
+NEW: Add due date column in payment lists
+NEW: Add email in event history, for reminder email of expired subsription
+NEW: Add event tab on resource record
+NEW: Add FEC Export in accountancy
+NEW: Add filter on staff range in list of thirdparties
+NEW: Add a first complete template of website
+NEW: Add format code into exported filename of ledger
+NEW: Add hidden option EXPENSEREPORT_DEFAULT_VALIDATOR_UNCHANGEABLE
+NEW: Add hidden option MAIN_DOCUMENTS_DESCRIPTION_FIRST
+NEW: Add link to inventory code
+NEW: Add more common social networks fields for business
+NEW: Add option PDF_DISABLE_MYCOMPANY_LOGO to disable logo on PDF
+NEW: add option PROPOSAL_AUTO_ADD_AUTHOR_AS_CONTACT
+NEW: Add option to display thirdparty adress in combolist
+NEW: Add option to swap sender/recipient address on PDF
+NEW: Add option to display thirdparty adress in combolist
+NEW: Add project on pament of salaries
+NEW: Add SHIPPING_PDF_HIDE_WEIGHT_AND_VOLUME and
+NEW: Add somes hooks in bank planned entries
+NEW: Add supplier ref in item reception page
+NEW: Advanced permission to ignore price min
+NEW: Allow to enter a timespent with a numeric value
+NEW: Automatic position of scroll when creating an extrafield
+NEW: Can add autorefresh=X in any URLs to refresh page after X seconds
+NEW: can add project's task to agenda on create event form
+NEW: Can delete a website in experimental website module
+NEW: Can disable meteo on smartphone only
+NEW: Can export/import a website template
+NEW: Can filter on EEC, not EEC, etc... in binding step of accountancy
+NEW: Can mix offset before and after with rules for due date of invoices
+NEW: Can record the supplier product description
+NEW: Can select several prospect level in thirdparty filter.
+NEW: Can set 2 url in url field of thirdparty
+NEW: Can set if a field is mandatory on form level.
+NEW: Can set the default focus of each page.
+NEW: Add category filter on user list
+NEW: Change forgotten password link in general parameters
+NEW: Child label of variants change if parent label changes
+NEW: Compatibility with new Paybox HMAC requirement
+NEW: Each user can set its prefered default calendar page
+NEW: Enhancement in process to make manual bank conciliation
+NEW: Enhancement in the generic file manager
+NEW: Extrafield totalizable
+NEW: Hidden conf INVOICE_USE_DEFAULT_DOCUMENT
+NEW: hidden conf to search product by supplier ref
+NEW: hidden constant to be able to use a thirdparty for donation
+NEW: hidden option to define an invoice template for each invoice type
+NEW: Highlight lines on lists when they are checked
+NEW: Notification module support expense report+holiday validation and approval
+NEW: On customer/supplier card, add simple tooltip to amount boxes
+NEW: Page to check if the operations/items created between two dates have attached item(s) and possibility to download all attachements
+NEW: possibility to add all rights of all modules in one time
+NEW: redirect if only one result on global search on card
+NEW: Permission to ignore price min
+NEW: Can build an archive of full documents directory from backup page
+NEW: tag odt line_product_ref_fourn for supplier doc lines
+NEW: The binding step in accountancy has a country filter with autocompletion
+NEW: Top menu is always on screen with MD theme.
+NEW: Withdraw request massaction can include already partially paid invoices
+NEW: Option "Simplify interface for blind persons"
+NEW: Generic cash fence feature (compatible with several POS modules)
 
 For developers:
-* Code changes to be more compatible with PSR2
-* Removed trigger USER_LOGOUT, USER_LOGIN, USER_LOGIN_FAILED (Some hooks are already dedicated for that)
+NEW: Add lib for multiselect with checkboxes
+NEW: Add function isValidMXRecord
+NEW: Add hook changeRoundingMode in update_price
+NEW: Add hook formconfirm to contractcard
+NEW: Add hook for virtual stock
+NEW: ADD url to see the last version of a external module
+NEW: Can enable a module, even external module, from command line
+NEW: Can set a tooltip help text on extrafields
+NEW: Add product search from barcode via REST api
+NEW: can add documents on agenda events using API REST
+NEW: Can set the datestart and dateend of cron job into module descriptor
+NEW: Close #9296 Add field ref_ext into llx_categorie
+NEW: move ticket dictionary in API /setup
+NEW: PHPUnitTest on Loan class #3163
+NEW: Code changes to be more compatible with PSR2
+NEW: Removed trigger USER_LOGOUT, USER_LOGIN, USER_LOGIN_FAILED (Some hooks are already dedicated for that)
+NEW: Add agenda documents in API REST
+NEW: Add "checked" field for new list engine compatibility
+NEW: REST API improvements
+NEW: Save external payment IDs into table of payment
+NEW: triggers add commercial and del commercial
+NEW: #9236 Allow to import shipment lines via API
+NEW: ADD civility list in API
+NEW: support selllist in the  module builder
+NEW: optional param to show a specific extrafield
+NEW: hook formConfirm always called if hooked
+NEW: hook on dispatch order fourn
 
 WARNING:
 
@@ -27,7 +131,74 @@ Following changes may create regressions for some external modules, but were nec
   replace them with links like viewimages.php?modulepart=mycompany&file=logos/... (note that link change only for
   modulepart=mycompany that now works like others).
 * Hidden option MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT has been renamed into SHIPPING_PDF_DISPLAY_AMOUNT_HT
-
+* Remove the no more used and deprecated dol_print_graph function
+
+
+***** ChangeLog for 8.0.4 compared to 8.0.3 *****
+FIX: #10030 better german chart
+FIX: #10036
+FIX: #10080 Supplier translations are in english
+FIX: #10183 using backport of fix done in 9.0
+FIX: #10218 Bad redirection after deleting a user or group
+FIX: #3234
+FIX: #6580
+FIX: #8741
+FIX: #9629 #9625
+FIX: #9971
+FIX: avoid Class 'AdherentType' not found
+FIX: Can relaunch install on v8
+FIX: Can't create a thirdparty from member if customer code is mandatory.
+FIX: Can't delete a line of minimal stock per warehouse
+FIX: check if "entity" is already defined in "$param"
+FIX: contact/address tab issue when changing company
+FIX: contact/adress tab: when changing company ajax combo, the first contact change is not taken into account
+FIX: CVE-2018-19799
+FIX: CVE-2018-19992
+FIX: CVE-2018-19993
+FIX: CVE-2018-19994
+FIX: CVE-2018-19995 and CVE-2018-19998
+FIX: Error reported when creation of thirdparty from member fails
+FIX: export only prices of the current entity !
+FIX: Extrafields on shipment module
+FIX: filter on product category doesn't work
+FIX: form actions: select_type_actions could be too small + bad $db init
+FIX: form actions: select_type_actions could be too small + bad  init
+FIX: fourn payment modes musn't be available on customer docs
+FIX: Function updatePrice with wrong parameters
+FIX: hidden extrafield
+FIX: if qty is 0
+FIX: If we change customer/supplier rule we can't edit old thirdparty.
+FIX: lang not loaded
+FIX: Lines are not inserted correctly if VAT have code
+FIX: marge sign
+FIX: Method setValid not found
+FIX: Migration do not create not used table
+FIX: missing action "edit" for the hook
+FIX: missing field "visible"
+FIX: Missing last month on vat report per month
+FIX: mode is only customer in stats fichinter
+FIX: OppStatusShort doesn't exists
+FIX: Remote ip detection was wrong with proxy (example: cloudflare)
+FIX: Removed not use table
+FIX: Replenishment with option STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE
+FIX: responsive
+FIX: Same on customer card
+FIX: same on lines
+FIX: screen size fall
+FIX: Select first mail model by default
+FIX: slow SQL query on creating a new supplier invoice
+FIX: sql query performance on list_qualified_avoir_supplier_invoices.
+FIX: supplier order list keep socid
+FIX: Same on customer card
+FIX: same on lines
+FIX: screen size fall
+FIX: Select first mail model by default
+FIX: slow SQL query on creating a new supplier invoice
+FIX: sql query performance on list_qualified_avoir_supplier_invoices.
+FIX: supplier order list keep socid
+FIX: Vendor translations are in english
+FIX: Warning: count()
+FIX: We want to be able to send PDF of paid invoices
 
 ***** ChangeLog for 8.0.3 compared to 8.0.2 *****
 FIX: #9161
@@ -366,6 +537,38 @@ Following changes may create regressions for some external modules, but were nec
   where {TYPE} is contact type code (BILLING, SHIPPING, CUSTOMER, ... see contact type dictionnary). 
 
 
+***** ChangeLog for 7.0.5 compared to 7.0.4 *****
+FIX: #3234
+FIX: #6580
+FIX: #8741
+FIX: #9934
+FIX: avoid Class 'AdherentType' not found
+FIX: Can't create a thirdparty from member if customer code is mandatory.
+FIX: Can't generate invoice pdf
+FIX: contact/adress tab: when changing company ajax combo, the first contact change is not taken into account
+FIX: Error generating ODT when option to use contact on doc on
+FIX: Error reported when creation of thirdparty from member fails
+FIX: filter on product category doesn't work
+FIX: form actions: select_type_actions could be too small + bad  init
+FIX: fourn payment modes musn't be available on customer docs
+FIX: Function updatePrice with wrong parameters
+FIX: If we change customer/supplier rule we can't edit old thirdparty.
+FIX: Interface regression for bind people. Fix option MAIN_OPTIMIZEFORTEXTBROWSER
+FIX: Lines are not inserted correctly if VAT have code
+FIX: OppStatusShort doesn't exists
+FIX: pdf typhon: order reference duplicate
+FIX: propal pdf: missing parenthesis for customs code
+FIX: Same on customer card
+FIX: same on lines
+FIX: Select first mail model by default
+FIX: sql query performance on list_qualified_avoir_supplier_invoices.
+FIX: task time screen: last fix was overkill
+FIX: task time screen: prevent users with access to all project from assigning to tasks they're not allowed to do
+FIX: use discount with multicurrency
+FIX: Variable name
+FIX: We want to be able to send PDF of paid invoices
+FIX: When delete a product, llx_product_association rows are not deleted
+FIX: wrong occurence number of contract on contact card, we must only count externals
 
 ***** ChangeLog for 7.0.4 compared to 7.0.3 *****
 FIX: #8984 button create expense report

+ 3 - 3
README.md

@@ -3,9 +3,9 @@
 ![Downloads per day](https://img.shields.io/sourceforge/dm/dolibarr.svg)
 [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
 
-|6|7|8|develop|
-|----------|----------|----------|----------|
-|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/6.0.svg)|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/7.0.svg)|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/8.0.svg)|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/develop.svg)|
+|6|7|8|9|develop|
+|----------|----------|----------|----------|----------|
+|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/6.0.svg)|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/7.0.svg)|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/8.0.svg)|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/9.0.svg)|![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/develop.svg)|
 
 Dolibarr ERP & CRM is a modern software package to manage your organization's activity (contacts, suppliers, invoices, orders, stocks, agenda…).
 

+ 1 - 0
build/debian/source/include-binaries

@@ -0,0 +1 @@
+htdocs/install/doctemplates/websites/website_template-corporate.zip

+ 14 - 2
build/docker/Dockerfile

@@ -3,18 +3,30 @@ FROM php:7.0-apache
 ENV HOST_USER_ID 33
 ENV PHP_INI_DATE_TIMEZONE 'UTC'
 
-RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev libldap2-dev \
+RUN apt-get update && apt-get install -y libpng-dev libjpeg-dev libldap2-dev \
 	&& rm -rf /var/lib/apt/lists/* \
 	&& docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \
 	&& docker-php-ext-install gd \
 	&& docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \
         && docker-php-ext-install ldap \
         && docker-php-ext-install mysqli \
-        && apt-get purge -y libpng12-dev libjpeg-dev libldap2-dev
+        && apt-get purge -y libjpeg-dev libldap2-dev
 
 COPY docker-run.sh /usr/local/bin/
 RUN chmod +x /usr/local/bin/docker-run.sh
 
+RUN pecl install xdebug-2.5.5 && docker-php-ext-enable xdebug
+RUN echo 'zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so"' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.remote_autostart=0' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.remote_enable=1' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.default_enable=0' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.remote_host=docker.for.mac.host.internal' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.remote_port=9000' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.remote_connect_back=0' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.profiler_enable=0' >> /usr/local/etc/php/php.ini
+RUN echo 'xdebug.remote_log="/tmp/xdebug.log"' >> /usr/local/etc/php/php.ini
+
+
 EXPOSE 80
 
 ENTRYPOINT ["docker-run.sh"]

+ 5 - 1
build/makepack-dolibarr.pl

@@ -535,6 +535,8 @@ if ($nboftargetok) {
    	    $ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type l -exec rm -fr {} \\; >/dev/null 2>&1`;	# For custom we want to remove all subdirs, even symbolic links, but not files
 
 		# Removed known external modules to avoid any error when packaging from env where external modules are tested 
+		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/abricot*`;
+		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/accountingexport*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/allscreens*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/ancotec*`;
 	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/cabinetmed*`;
@@ -549,12 +551,14 @@ if ($nboftargetok) {
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/multicompany*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/ndf*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/nltechno*`;
+		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/nomenclature*`;
+	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/of/`;
 	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/oscim*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/pos*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/teclib*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/timesheet*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/webmail*`;
-		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/accountingexport*`;
+		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/workstation*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/oblyon*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/themes/allscreen*`;
 		# Removed other test files

+ 15 - 9
build/perl/virtualmin/dolibarr.pl

@@ -30,7 +30,7 @@ return "Regis Houssin";
 # script_dolibarr_versions()
 sub script_dolibarr_versions
 {
-return ( "7.0.0", "6.0.5", "5.0.7" );
+return ( "9.0.0", "8.0.3", "7.0.4", "6.0.8", "5.0.7" );
 }
 
 sub script_dolibarr_release
@@ -263,15 +263,16 @@ if ($upgrade) {
 	local @params = ( [ "action", "upgrade" ],
 			  [ "versionfrom", $upgrade->{'version'} ],
 			  [ "versionto", $ver ],
+			  [ "installlock", "444" ],
 			 );
 	local $p = $ver >= 3.8 ? "step5" : "etape5";
 	local $err = &call_dolibarr_wizard_page(\@params, $p, $d, $opts);
 	return (-1, "Dolibarr wizard failed : $err") if ($err);
 	
-	# Remove the installation directory.
-	local $dinstall = "$opts->{'dir'}/install";
-	$dinstall  =~ s/\/$//;
-	$out = &run_as_domain_user($d, "rm -rf ".quotemeta($dinstall));
+	# Remove the installation directory. (deprecated)
+	# local $dinstall = "$opts->{'dir'}/install";
+	# $dinstall  =~ s/\/$//;
+	# $out = &run_as_domain_user($d, "rm -rf ".quotemeta($dinstall));
 	
 	}
 else {
@@ -306,15 +307,18 @@ else {
 			  [ "login", "admin" ],
 			  [ "pass", $dompass ],
 			  [ "pass_verif", $dompass ],
+			  [ "installlock", "444" ],
 	 		 );
 	local $p = $ver >= 3.8 ? "step5" : "etape5";
 	local $err = &call_dolibarr_wizard_page(\@params, $p, $d, $opts);
 	return (-1, "Dolibarr wizard failed : $err") if ($err);
 	
-	# Remove the installation directory and protect config file.
-	local $dinstall = "$opts->{'dir'}/install";
-	$dinstall  =~ s/\/$//;
-	$out = &run_as_domain_user($d, "rm -rf ".quotemeta($dinstall));
+	# Remove the installation directory (deprecated)
+	# local $dinstall = "$opts->{'dir'}/install";
+	# $dinstall  =~ s/\/$//;
+	# $out = &run_as_domain_user($d, "rm -rf ".quotemeta($dinstall));
+	
+	# Protect config file
 	&set_permissions_as_domain_user($d, 0644, $cfile);
 	&set_permissions_as_domain_user($d, 0755, $cfiledir);
 	}
@@ -386,6 +390,8 @@ sub script_dolibarr_check_latest
 {
 local ($ver) = @_;
 local @vers = &osdn_package_versions("dolibarr",
+				$ver >= 9.0 ? "dolibarr\\-(9\\.0\\.[0-9\\.]+)\\.tgz" :
+				$ver >= 8.0 ? "dolibarr\\-(8\\.0\\.[0-9\\.]+)\\.tgz" :
 				$ver >= 7.0 ? "dolibarr\\-(7\\.0\\.[0-9\\.]+)\\.tgz" :
 				$ver >= 6.0 ? "dolibarr\\-(6\\.0\\.[0-9\\.]+)\\.tgz" :
 				$ver >= 5.0 ? "dolibarr\\-(5\\.0\\.[0-9\\.]+)\\.tgz" :

File diff suppressed because it is too large
+ 55 - 0
dev/initdemo/mysqldump_dolibarr_8.0.0.sql


File diff suppressed because it is too large
+ 55 - 0
dev/initdemo/mysqldump_dolibarr_9.0.0.sql


+ 7 - 0
dev/initdemo/savedemo.sh

@@ -171,6 +171,8 @@ export list="
     --ignore-table=$base.llx_abonne_extrafields 
     --ignore-table=$base.llx_abonne_type
     --ignore-table=$base.llx_abonnement 
+    --ignore-table=$base.llx_accountingaccount 
+    --ignore-table=$base.llx_accountingsystem 
     --ignore-table=$base.llx_advanced_extrafields 
     --ignore-table=$base.llx_advanced_extrafields_options 
     --ignore-table=$base.llx_advanced_extrafields_values
@@ -189,6 +191,9 @@ export list="
 	--ignore-table=$base.llx_c_dolicloud_plans
 	--ignore-table=$base.llx_c_pays
 	--ignore-table=$base.llx_c_source
+	--ignore-table=$base.llx_c_ticketsup_category
+	--ignore-table=$base.llx_c_ticketsup_severity
+	--ignore-table=$base.llx_c_ticketsup_type
 	--ignore-table=$base.llx_cabinetmed_c_banques
 	--ignore-table=$base.llx_cabinetmed_c_ccam
 	--ignore-table=$base.llx_cabinetmed_c_examconclusion
@@ -246,6 +251,8 @@ export list="
 	--ignore-table=$base.llx_residence
 	--ignore-table=$base.llx_residence_building
 	--ignore-table=$base.llx_residence_building_links
+	--ignore-table=$base.llx_societe_rib2
+	--ignore-table=$base.llx_ticketsup
 	--ignore-table=$base.llx_ultimatepdf
 	--ignore-table=$base.llx_update_modules
 	--ignore-table=$base.llx_ventilation_achat

+ 0 - 12
dev/resources/dbmodel/dolibarr.uml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<uml:Model xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML" xmi:id="_qb8akM37EdqwVrslYOdUDA">
-  <packagedElement xmi:type="uml:Package" xmi:id="_w8IxIM37EdqwVrslYOdUDA" name="dolibarr">
-    <packagedElement xmi:type="uml:Package" xmi:id="_T5aZ4FK9Ed60vaZbVikprw" name="OrdersModule"/>
-    <packagedElement xmi:type="uml:Package" xmi:id="_ZhuGMlK9Ed60vaZbVikprw" name="InvoiceModule"/>
-    <packagedElement xmi:type="uml:Package" xmi:id="_cf3SUlK9Ed60vaZbVikprw" name="UserModule"/>
-    <packagedElement xmi:type="uml:Package" xmi:id="_maM0glK9Ed60vaZbVikprw" name="FoundationModule"/>
-    <packagedElement xmi:type="uml:Package" xmi:id="_oqTO4lK9Ed60vaZbVikprw" name="ContractsModule"/>
-    <packagedElement xmi:type="uml:Package" xmi:id="_rEq_klK9Ed60vaZbVikprw" name="ProposalsModule"/>
-    <packagedElement xmi:type="uml:Package" xmi:id="_vxYmUlK9Ed60vaZbVikprw" name="EMailingManagement"/>
-  </packagedElement>
-</uml:Model>

+ 0 - 53
dev/resources/dbmodel/dolibarr.umldi

@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<diagrams:Diagrams xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.topcased.org/DI/1.0" xmlns:diagrams="http://www.topcased.org/Diagrams/1.0" xmi:id="_SI6FkFK9Ed60vaZbVikprw" activeDiagram="_SI6FkVK9Ed60vaZbVikprw">
-  <model href="dolibarr.uml#_w8IxIM37EdqwVrslYOdUDA"/>
-  <diagrams xmi:id="_SI6FkVK9Ed60vaZbVikprw" position="0,0" size="100,100" name="dolibarr" viewport="0,0">
-    <property xmi:id="_SJ9OcFK9Ed60vaZbVikprw" key="pageFormatName" value="A4"/>
-    <property xmi:id="_SJ9OcVK9Ed60vaZbVikprw" key="diagramWidth" value="840"/>
-    <property xmi:id="_SJ9OclK9Ed60vaZbVikprw" key="diagramHeight" value="1188"/>
-    <property xmi:id="_SJ9Oc1K9Ed60vaZbVikprw" key="pageMarginName" value="Small Margin"/>
-    <property xmi:id="_SJ9OdFK9Ed60vaZbVikprw" key="diagramTopMargin" value="20"/>
-    <property xmi:id="_SJ9OdVK9Ed60vaZbVikprw" key="diagramBottomMargin" value="20"/>
-    <property xmi:id="_SJ9OdlK9Ed60vaZbVikprw" key="diagramLeftMargin" value="20"/>
-    <property xmi:id="_SJ9Od1K9Ed60vaZbVikprw" key="diagramRightMargin" value="20"/>
-    <property xmi:id="_SJ9OeFK9Ed60vaZbVikprw" key="orientation" value="portrait"/>
-    <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_SI6FklK9Ed60vaZbVikprw" presentation="org.topcased.modeler.uml.classdiagram">
-      <element href="dolibarr.uml#_w8IxIM37EdqwVrslYOdUDA"/>
-    </semanticModel>
-    <contained xsi:type="di:GraphNode" xmi:id="_T2b-YFK9Ed60vaZbVikprw" position="15,190" size="176,81">
-      <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_T2b-YVK9Ed60vaZbVikprw" presentation="default">
-        <element href="dolibarr.uml#_T5aZ4FK9Ed60vaZbVikprw"/>
-      </semanticModel>
-    </contained>
-    <contained xsi:type="di:GraphNode" xmi:id="_ZhuGMFK9Ed60vaZbVikprw" position="15,118" size="177,68">
-      <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_ZhuGMVK9Ed60vaZbVikprw" presentation="default">
-        <element href="dolibarr.uml#_ZhuGMlK9Ed60vaZbVikprw"/>
-      </semanticModel>
-    </contained>
-    <contained xsi:type="di:GraphNode" xmi:id="_cf3SUFK9Ed60vaZbVikprw" position="15,10" size="174,81">
-      <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_cf3SUVK9Ed60vaZbVikprw" presentation="default">
-        <element href="dolibarr.uml#_cf3SUlK9Ed60vaZbVikprw"/>
-      </semanticModel>
-    </contained>
-    <contained xsi:type="di:GraphNode" xmi:id="_maM0gFK9Ed60vaZbVikprw" position="291,118" size="145,73">
-      <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_maM0gVK9Ed60vaZbVikprw" presentation="default">
-        <element href="dolibarr.uml#_maM0glK9Ed60vaZbVikprw"/>
-      </semanticModel>
-    </contained>
-    <contained xsi:type="di:GraphNode" xmi:id="_oqTO4FK9Ed60vaZbVikprw" position="15,274" size="179,80">
-      <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_oqTO4VK9Ed60vaZbVikprw" presentation="default">
-        <element href="dolibarr.uml#_oqTO4lK9Ed60vaZbVikprw"/>
-      </semanticModel>
-    </contained>
-    <contained xsi:type="di:GraphNode" xmi:id="_rEq_kFK9Ed60vaZbVikprw" position="15,358" size="181,73">
-      <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_rEq_kVK9Ed60vaZbVikprw" presentation="default">
-        <element href="dolibarr.uml#_rEq_klK9Ed60vaZbVikprw"/>
-      </semanticModel>
-    </contained>
-    <contained xsi:type="di:GraphNode" xmi:id="_vxYmUFK9Ed60vaZbVikprw" position="15,490" size="181,80">
-      <semanticModel xsi:type="di:EMFSemanticModelBridge" xmi:id="_vxYmUVK9Ed60vaZbVikprw" presentation="default">
-        <element href="dolibarr.uml#_vxYmUlK9Ed60vaZbVikprw"/>
-      </semanticModel>
-    </contained>
-  </diagrams>
-</diagrams:Diagrams>

BIN
dev/resources/dbmodel/dolibarr_schema.mwb


+ 9 - 0
dev/setup/codesniffer/ruleset.xml

@@ -50,6 +50,15 @@
     <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter.Found">
 		<severity>0</severity>
     </rule>
+    <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed">
+		<severity>0</severity>
+    </rule>
+    <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass">
+		<severity>0</severity>
+    </rule>
+    <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed">
+		<severity>0</severity>
+    </rule>
 
     <rule ref="Generic.CodeAnalysis.UselessOverridingMethod" />
 

+ 3 - 3
dev/tools/fixdosfiles.sh

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

+ 130 - 0
dev/tools/snakeCaseToCamelCase.sh

@@ -0,0 +1,130 @@
+#!/bin/bash
+
+## Need "rpl" package
+RPL_INSTALLED=$(dpkg -s rpl)
+if [[ -z ${RPL_INSTALLED} ]]; then
+    echo "This bash need rpl command, you can install it with: sudo apt install rpl"
+fi
+
+DIR_HTDOCS=$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../htdocs" >/dev/null && pwd )
+
+PATTERN=""
+if [[ -f $1 ]]; then
+    TFile=("$1")        # specific file
+elif [[ -n $1 ]]; then
+    PATTERN=$1  # name of a particular file or pattern (ex: societe.class.php)
+else
+    PATTERN="*.class.php" # *.lib.php
+fi
+
+if [[ -n ${PATTERN} ]]; then
+    TCLASSFILE=$(find "${DIR_HTDOCS}" -name "${PATTERN}" | grep -v "/custom/" | grep -v "/includes/" | grep -v -F -f "${DIR_HTDOCS}/../.gitignore")
+    TFile=()
+    I=0
+    for f in ${TCLASSFILE}; do
+        TFile[${I}]="${f}"
+        ((I++))
+    done
+fi
+
+
+REGEX_FNC_W='^([[:blank:]]*)(public|private|protected)?[ \t]*(static)?[ \t]*[^\$\(]function[ \t]*([a-zA-Z0-9\-\_]*)[\(](.*)[\)][ \t]*([\{]?)$'
+INDENT="    "
+
+for f in ${TFile[@]}; do
+#    echo ${f}
+
+    IFS=$'\n'
+    TLine=($(cat "${f}" | grep -E "${REGEX_FNC_W}"))
+
+    for LINE in ${TLine[@]}; do
+
+        if [[ ${LINE} =~ ^${REGEX_FNC_W}$ ]]; then
+            FIRST_INDENT=${BASH_REMATCH[1]}       # seem not work
+            FNC_TYPE=${BASH_REMATCH[2]}
+            STATIC=${BASH_REMATCH[3]}
+            FNC_NAME=${BASH_REMATCH[4]}
+            PARAMETERS_ORIGIN=${BASH_REMATCH[5]}
+            BRACKET_END=${BASH_REMATCH[6]}
+
+            if [[ ${LINE} =~ ^([[:blank:]]*) ]]; then # but this seems work to get indentation
+                FIRST_INDENT=${BASH_REMATCH[1]}
+            fi
+
+            [[ ${FNC_NAME} =~ ^__ ]] && continue    # skip magic function
+
+            CAMEL_CASE=$(echo "${FNC_NAME}" | sed -r 's/(_)([a-zA-Z0-9])/\U\2/g')
+            [[ ${CAMEL_CASE} = ${FNC_NAME} ]] && continue       # skip if no difference
+
+#echo A: ${#FIRST_INDENT}
+#printf "${FIRST_INDENT}TEST INDENT\n"
+#echo B: ${FNC_TYPE}
+#echo C: ${STATIC}
+#echo D: ${FNC_NAME}
+#echo D: ${CAMEL_CASE}
+#echo E: ${PARAMETERS_ORIGIN}
+#echo F: ${BRACKET_END}
+#exit
+
+            [[ -n $(cat "${f}" | grep -i "function[[:blank:]]*${CAMEL_CASE}") ]] && continue   # skip if already exists
+
+            TCommentLine=()
+            J=1
+            while :; do
+                COMMENT=$(cat ${f} | grep -B ${J} ${LINE/\$/\\$} | head -n1 | grep -P '^[\t\ ]*(/\*\*|\*[^/]?|\*/)')
+                if [[ -n ${COMMENT}  ]]; then
+                    TCommentLine[${J}]="${COMMENT}"
+                    ((J++))
+                else
+                    break
+                fi
+            done
+
+            COMMENT_ORIGIN=""
+            COMMENT_ORIGIN_WITH_DEPRECATED=""
+            COMMENT_DUPLICATE=""
+            if [[ ${#TCommentLine[@]} -gt 0 ]]; then
+                for (( idx=${#TCommentLine[@]} ; idx>0 ; idx-- )) ; do
+                    COMMENT_ORIGIN="${COMMENT_ORIGIN}\n${TCommentLine[idx]}"
+                done
+
+                COMMENT_DUPLICATE=${COMMENT_ORIGIN}
+
+                COMMENT_ORIGIN_WITH_DEPRECATED=$(echo "${COMMENT_ORIGIN%?} @deprecated\n${FIRST_INDENT} * @see ${CAMEL_CASE}\n${FIRST_INDENT} */")
+            fi
+
+            PARAMETERS=${PARAMETERS_ORIGIN}
+            TParam=()
+            I=0
+            while [[ ${PARAMETERS} =~ (\$[a-zA-Z0-9\_\-]+) ]]; do
+                TParam[${I}]=${BASH_REMATCH[1]}
+                PARAMETERS=${PARAMETERS#*"${BASH_REMATCH[1]}"}
+                ((I++))
+            done
+
+            PARAMS_STR=$(printf ", %s" "${TParam[@]}")
+            PARAMS_STR=${PARAMS_STR:2}
+
+            REPLACE=${LINE}
+            [[ -z ${BRACKET_END} ]] && REPLACE="${LINE}\n${FIRST_INDENT}{\n${FIRST_INDENT}${INDENT}" || REPLACE="${LINE}\n${FIRST_INDENT}${INDENT}"
+            [[ -n ${STATIC} ]] && REPLACE="${REPLACE}return self::" || REPLACE="${REPLACE}return \$this->"
+            REPLACE="${REPLACE}${CAMEL_CASE}(${PARAMS_STR});\n${FIRST_INDENT}}\n\n"
+            REPLACE="${REPLACE}${FIRST_INDENT}${COMMENT_ORIGIN}\n${FIRST_INDENT}"
+            [[ -n ${STATIC} ]] && REPLACE="${REPLACE}${STATIC} "
+            [[ -n ${FNC_TYPE} ]] && REPLACE="${REPLACE}${FNC_TYPE} "
+            REPLACE="${REPLACE}function ${CAMEL_CASE}(${PARAMETERS_ORIGIN})"
+            [[ -n ${BRACKET_END} ]] && REPLACE="${REPLACE}\n${FIRST_INDENT}{"
+
+            echo " ${FNC_NAME} -> ${CAMEL_CASE}"
+
+            if [[ -n ${COMMENT_ORIGIN_WITH_DEPRECATED} ]]; then
+                rpl -e --quiet "${COMMENT_ORIGIN}" ${COMMENT_ORIGIN_WITH_DEPRECATED} "${f}"
+            fi
+            rpl -e --quiet "${LINE}" ${REPLACE} "${f}"
+
+        fi
+
+    done
+done
+
+

+ 5 - 5
doc/install/README

@@ -7,12 +7,12 @@ Download
 --------------------------------
 
 * Dolibarr ERP/CRM can be downloaded at sourceforge:
-http://sourceforge.net/projects/dolibarr/files
-or from Dolibarr official web site:
-http://www.dolibarr.org
+    https://sourceforge.net/projects/dolibarr/files
+  or from Dolibarr official web site:
+    https://www.dolibarr.org
 
 * Most external modules are only available on DoliStore:
-http://www.dolistore.org
+    https://www.dolistore.com 
 
 
 --------------------------------
@@ -22,4 +22,4 @@ Install
 * For a Quick guide, take a look at README file into root directory.
 
 * More complete documentations are also available on line on the Dolibarr Wiki:
-http://wiki.dolibarr.org
+    https://wiki.dolibarr.org

+ 33 - 0
doc/install/README-DE

@@ -0,0 +1,33 @@
+README (deutsch / german / allemand)
+--------------------------------
+
+
+--------------------------------
+Download / Herunterladen
+--------------------------------
+
+* Dolibarr ERP/CRM kann man über die offizielle Dolibarr Website
+    https://www.dolibarr.org/downloads 
+  oder direkt von Sourceforge
+    https://sourceforge.net/projects/dolibarr/files/
+  herunterladen.
+  
+  
+  
+* Die meisten externen Module/Themens sind über den DoliStore verfügbar:
+    https://www.dolistore.com/de/
+
+
+--------------------------------
+Installation
+--------------------------------
+
+* Für eine kurze Einleitung, schau auf die README Datei im Hauptverzeichnis.
+
+* Umfangreiche Dokumentationen sind im Dolibarr Wiki zu finden:
+    https://wiki.dolibarr.org/index.php/Hauptseite 
+    
+* eine Deutsche Community bietet der Dolibarr e.V. unter 
+    https://www.dolibarr.de/ 
+    
+    

+ 5 - 1
htdocs/.gitignore

@@ -23,4 +23,8 @@
 /cabinetmed*
 /webmail*
 /conf/conf.php
-/subtotal/
+/subtotal*
+/abricot*
+/nomenclature*
+/of/
+/workstation/

+ 10 - 9
htdocs/accountancy/admin/card.php

@@ -1,7 +1,7 @@
 <?php
-/* Copyright (C) 2013-2014 Olivier Geffroy      <jeff@jeffinfo.com>
- * Copyright (C) 2013-2017 Alexandre Spangaro   <aspangaro@zendsi.com>
- * Copyright (C) 2014      Florian Henry        <florian.henry@open-concept.pro>
+/* Copyright (C) 2013-2014  Olivier Geffroy     <jeff@jeffinfo.com>
+ * Copyright (C) 2013-2018  Alexandre Spangaro  <aspangaro@zendsi.com>
+ * Copyright (C) 2014       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
@@ -18,9 +18,9 @@
  */
 
 /**
- * \file 		htdocs/accountancy/admin/card.php
- * \ingroup		Advanced accountancy
- * \brief 		Card of accounting account
+ *  \file       htdocs/accountancy/admin/card.php
+ *  \ingroup    Advanced accountancy
+ *  \brief      Card of accounting account
  */
 
 require '../../main.inc.php';
@@ -41,6 +41,7 @@ $id = GETPOST('id', 'int');
 $ref = GETPOST('ref', 'alpha');
 $rowid = GETPOST('rowid', 'int');
 $cancel = GETPOST('cancel','alpha');
+$accountingaccount = GETPOST('accountingaccount','alpha');
 
 // Security check
 
@@ -229,7 +230,7 @@ if ($action == 'create') {
 
 	// Account number
 	print '<tr><td class="titlefieldcreate"><span class="fieldrequired">' . $langs->trans("AccountNumber") . '</span></td>';
-	print '<td><input name="account_number" size="30" value="' . $object->account_number . '"></td></tr>';
+	print '<td><input name="account_number" size="30" value="' . $accountingaccount . '"></td></tr>';
 
 	// Label
 	print '<tr><td><span class="fieldrequired">' . $langs->trans("Label") . '</span></td>';
@@ -387,13 +388,13 @@ else if ($id > 0 || $ref) {
 			if (! empty($user->rights->accounting->chartofaccount)) {
 				print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?action=update&id=' . $id . '">' . $langs->trans('Modify') . '</a>';
 			} else {
-				print '<a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('Modify') . '</a>';
+				print '<a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('Modify') . '</a>';
 			}
 
 			if (! empty($user->rights->accounting->chartofaccount)) {
 				print '<a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?action=delete&id=' . $id . '">' . $langs->trans('Delete') . '</a>';
 			} else {
-				print '<a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('Delete') . '</a>';
+				print '<a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('Delete') . '</a>';
 			}
 
 			print '</div>';

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

@@ -1,11 +1,11 @@
 <?php
-/* Copyright (C) 2013-2014 Olivier Geffroy      <jeff@jeffinfo.com>
- * Copyright (C) 2013-2014 Florian Henry        <florian.henry@open-concept.pro>
- * Copyright (C) 2013-2017 Alexandre Spangaro   <aspangaro@zendsi.com>
- * Copyright (C) 2014-2015 Ari Elbaz (elarifr)  <github@accedinfo.com>
- * Copyright (C) 2014      Marcos García        <marcosgdf@gmail.com>
- * Copyright (C) 2014      Juanjo Menent        <jmenent@2byte.es>
- * Copyright (C) 2015      Jean-François Ferry  <jfefe@aternatik.fr>
+/* Copyright (C) 2013-2014  Olivier Geffroy         <jeff@jeffinfo.com>
+ * Copyright (C) 2013-2014  Florian Henry           <florian.henry@open-concept.pro>
+ * Copyright (C) 2013-2018  Alexandre Spangaro      <aspangaro@open-dsi.fr>
+ * Copyright (C) 2014-2015  Ari Elbaz (elarifr)     <github@accedinfo.com>
+ * Copyright (C) 2014       Marcos García           <marcosgdf@gmail.com>
+ * Copyright (C) 2014       Juanjo Menent           <jmenent@2byte.es>
+ * Copyright (C) 2015       Jean-François Ferry     <jfefe@aternatik.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -63,6 +63,7 @@ $list_account = array (
     'ACCOUNTING_ACCOUNT_SUSPENSE',
     'ACCOUNTING_ACCOUNT_TRANSFER_CASH',
     'DONATION_ACCOUNTINGACCOUNT',
+    'ADHERENT_SUBSCRIPTION_ACCOUNTINGACCOUNT',
     'LOAN_ACCOUNTING_ACCOUNT_CAPITAL',
     'LOAN_ACCOUNTING_ACCOUNT_INTEREST',
     'LOAN_ACCOUNTING_ACCOUNT_INSURANCE'

+ 15 - 9
htdocs/accountancy/admin/fiscalyear.php

@@ -1,5 +1,5 @@
 <?php
-/* Copyright (C) 2013-2016 Alexandre Spangaro   <aspangaro@zendsi.com>
+/* Copyright (C) 2013-2018  Alexandre Spangaro  <aspangaro@zendsi.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,9 +16,9 @@
  */
 
 /**
- * \file        htdocs/accountancy/admin/fiscalyear.php
- * \ingroup     Advanced accountancy
- * \brief       Setup page to configure fiscal year
+ *  \file       htdocs/accountancy/admin/fiscalyear.php
+ *  \ingroup    Advanced accountancy
+ *  \brief      Setup page to configure fiscal year
  */
 
 require '../../main.inc.php';
@@ -45,8 +45,8 @@ $langs->loadLangs(array("admin","compta"));
 // Security check
 if ($user->societe_id > 0)
 	accessforbidden();
-if (! $user->rights->accounting->fiscalyear)              // If we can read accounting records, we shoul be able to see fiscal year.
-    accessforbidden();
+if (! $user->rights->accounting->fiscalyear)              // If we can read accounting records, we should be able to see fiscal year.
+	accessforbidden();
 
 $error = 0;
 
@@ -113,23 +113,26 @@ if ($result)
 
 	if (! empty($user->rights->accounting->fiscalyear))
 	{
-		$addbutton = '<a class="butAction" href="fiscalyear_card.php?action=create">' . $langs->trans("NewFiscalYear") . '</a>';
+		$addbutton = '<a class="butActionNew" href="fiscalyear_card.php?action=create"><span class="valignmiddle">' . $langs->trans("NewFiscalYear") .'</span><span class="fa fa-plus-circle valignmiddle"></span></a>';
 	}
 	else
 	{
-		$addbutton = '<a class="butActionRefused" href="#">' . $langs->trans("NewFiscalYear") . '</a>';
+		$addbutton = '<a class="butActionRefused classfortooltip" href="#"><span class="valignmiddle" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">' . $langs->trans("NewFiscalYear") .'</span><span class="fa fa-plus-circle valignmiddle"></span></a>';
 	}
 
 	$title = $langs->trans('AccountingPeriods');
 	print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $params, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy', 0, $addbutton, '', $limit, 1);
 
 	// Load attribute_label
-	print '<table class="noborder" width="100%">';
+	print '<div class="div-table-responsive">';
+	print '<table class="tagtable liste" width="100%">';
 	print '<tr class="liste_titre">';
 	print '<td>' . $langs->trans("Ref") . '</td>';
 	print '<td>' . $langs->trans("Label") . '</td>';
 	print '<td>' . $langs->trans("DateStart") . '</td>';
 	print '<td>' . $langs->trans("DateEnd") . '</td>';
+	print '<td align="center">' . $langs->trans("NumberOfAccountancyEntries") . '</td>';
+	print '<td align="center">' . $langs->trans("NumberOfAccountancyMovements") . '</td>';
 	print '<td align="right">' . $langs->trans("Statut") . '</td>';
 	print '</tr>';
 
@@ -144,6 +147,8 @@ if ($result)
 			print '<td align="left">' . $obj->label . '</td>';
 			print '<td align="left">' . dol_print_date($db->jdate($obj->date_start), 'day') . '</td>';
 			print '<td align="left">' . dol_print_date($db->jdate($obj->date_end), 'day') . '</td>';
+			print '<td align="center">' . $object->getAccountancyEntriesByFiscalYear($obj->date_start, $obj->date_end) . '</td>';
+			print '<td align="center">' . $object->getAccountancyMovementsByFiscalYear($obj->date_start, $obj->date_end) . '</td>';
 			print '<td align="right">' . $fiscalyearstatic->LibStatut($obj->statut, 5) . '</td>';
 			print '</tr>';
 			$i++;
@@ -152,6 +157,7 @@ if ($result)
 		print '<tr class="oddeven"><td colspan="5" class="opacitymedium">' . $langs->trans("None") . '</td></tr>';
 	}
 	print '</table>';
+	print '</div>';
 } else {
 	dol_print_error($db);
 }

+ 3 - 4
htdocs/accountancy/bookkeeping/balance.php

@@ -58,7 +58,7 @@ $pagenext = $page + 1;
 
 
 $search_date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int'));
-$search_date_end = dol_mktime(0, 0, 0, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int'));
+$search_date_end = dol_mktime(23, 59, 59, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int'));
 
 $search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha');
 if ($search_accountancy_code_start == - 1) {
@@ -127,7 +127,6 @@ if (! empty($search_accountancy_code_end)) {
 	$param .= '&amp;search_accountancy_code_end=' . $search_accountancy_code_end;
 }
 
-
 /*
  * Action
  */
@@ -154,7 +153,7 @@ if ($action == 'export_csv')
 	$type_export = 'balance';
 	include DOL_DOCUMENT_ROOT . '/accountancy/tpl/export_journal.tpl.php';
 
-	$result = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
+	$result = $object->fetchAllBalance($sortorder, $sortfield, $limit, 0, $filter);
 	if ($result < 0) {
 		setEventMessages($object->error, $object->errors, 'errors');
 	}
@@ -266,7 +265,7 @@ if ($action != 'export_csv')
 		$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>';
+			$link = '<a href="../admin/card.php?action=create&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
 		}
 		print '<tr class="oddeven">';
 

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

@@ -641,7 +641,6 @@ if ($num > 0)
 			$object->id = $line->id;
 			$object->piece_num = $line->piece_num;
 			print $object->getNomUrl(1,'',0,'',1);
-			//print '<a href="./card.php?piece_num=' . $line->piece_num . '&save_lastsearch_values=1">' . $line->piece_num . '</a>';
 			print '</td>';
 			if (! $i) $totalarray['nbfield']++;
 		}

+ 71 - 38
htdocs/accountancy/class/accountancycategory.class.php

@@ -78,7 +78,7 @@ class AccountancyCategory // extends CommonObject
 	public $range_account;
 
 	/**
-	 * @var mixed Sample property 1
+	 * @var int Sens of the account:  0: credit - debit, 1: debit - credit
 	 */
 	public $sens;
 
@@ -163,16 +163,17 @@ class AccountancyCategory // extends CommonObject
 
 		// Insert request
 		$sql = "INSERT INTO ".MAIN_DB_PREFIX."c_accounting_category(";
-		if ($this->rowid > 0) $sql.= "rowid,";
-		$sql.= "code,";
-		$sql.= "label,";
-		$sql.= "range_account,";
-		$sql.= "sens,";
-		$sql.= "category_type,";
-		$sql.= "formula,";
-		$sql.= "position,";
-		$sql.= "fk_country,";
-		$sql.= "active";
+		if ($this->rowid > 0) $sql.= "rowid, ";
+		$sql.= "code, ";
+		$sql.= "label, ";
+		$sql.= "range_account, ";
+		$sql.= "sens, ";
+		$sql.= "category_type, ";
+		$sql.= "formula, ";
+		$sql.= "position, ";
+		$sql.= "fk_country, ";
+		$sql.= "active, ";
+		$sql.= "entity";
 		$sql.= ") VALUES (";
 		if ($this->rowid > 0) $sql.= " ".$this->rowid.",";
 		$sql.= " ".(! isset($this->code)?'NULL':"'".$this->db->escape($this->code)."'").",";
@@ -184,6 +185,7 @@ class AccountancyCategory // extends CommonObject
 		$sql.= " ".(! isset($this->position)?'NULL':$this->db->escape($this->position)).",";
 		$sql.= " ".(! isset($this->fk_country)?'NULL':$this->db->escape($this->fk_country)).",";
 		$sql.= " ".(! isset($this->active)?'NULL':$this->db->escape($this->active));
+		$sql.= ", ".$conf->entity;
 		$sql.= ")";
 
 		$this->db->begin();
@@ -237,9 +239,8 @@ class AccountancyCategory // extends CommonObject
 	 *  @param		string	$label	Label
 	 *  @return     int          	<0 if KO, >0 if OK
 	 */
-	function fetch($id,$code='',$label='')
+	function fetch($id, $code='', $label='')
 	{
-		global $langs;
 		$sql = "SELECT";
 		$sql.= " t.rowid,";
 		$sql.= " t.code,";
@@ -253,8 +254,12 @@ class AccountancyCategory // extends CommonObject
 		$sql.= " t.active";
 		$sql.= " FROM ".MAIN_DB_PREFIX."c_accounting_category as t";
 		if ($id)   $sql.= " WHERE t.rowid = ".$id;
-		elseif ($code) $sql.= " WHERE t.code = '".$this->db->escape($code)."'";
-		elseif ($label) $sql.= " WHERE t.label = '".$this->db->escape($label)."'";
+		else
+		{
+			$sql.= " WHERE t.entity IN (".getEntity('c_accounting_category').")"; // Dont't use entity if you use rowid
+			if ($code) $sql.= " AND t.code = '".$this->db->escape($code)."'";
+			elseif ($label) $sql.= " AND t.label = '".$this->db->escape($label)."'";
+		}
 
 		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
 		$resql=$this->db->query($sql);
@@ -480,7 +485,7 @@ class AccountancyCategory // extends CommonObject
 		$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 .= " AND aa.entity = = " . $conf->entity . ")";
+		$sql .= " AND aa.entity = " . $conf->entity . ")";
 		$sql .= " GROUP BY t.numero_compte, t.label_operation, t.doc_ref";
 		$sql .= " ORDER BY t.numero_compte";
 
@@ -712,49 +717,76 @@ class AccountancyCategory // extends CommonObject
 	/**
 	 * Function to show result of an accounting account from the ledger with a direction and a period
 	 *
-	 * @param int 		$cpt 				Id accounting account
-	 * @param string 	$month 				Specifig month - Can be empty
+	 * @param int|array	$cpt 				Accounting account or array of accounting account
 	 * @param string 	$date_start			Date start
 	 * @param string 	$date_end			Date end
 	 * @param int 		$sens 				Sens of the account:  0: credit - debit, 1: debit - credit
 	 * @param string	$thirdparty_code	Thirdparty code
-	 * @return integer 						Result in table
+	 * @param int       $month 				Specifig month - Can be empty
+	 * @param int       $year 				Specifig year - Can be empty
+	 * @return integer 						<0 if KO, >= 0 if OK
 	 */
-	public function getResult($cpt, $month, $date_start, $date_end, $sens, $thirdparty_code='nofilter')
+	public function getSumDebitCredit($cpt, $date_start, $date_end, $sens, $thirdparty_code='nofilter', $month=0, $year=0)
 	{
+		global $conf;
+
+		$this->sdc = 0;
+		$this->sdcpermonth = array();
+
 		$sql = "SELECT SUM(t.debit) as debit, SUM(t.credit) as credit";
+		if (is_array($cpt)) $sql.=", t.numero_compte as accountancy_account";
 		$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as t";
-		$sql .= " WHERE t.numero_compte = '" . $cpt."'";
-		if (! empty($date_start) && ! empty($date_end))
-			$sql.= " AND t.doc_date >= '".$this->db->idate($date_start)."' AND t.doc_date <= '".$this->db->idate($date_end)."'";
-		if (! empty($month)) {
-			$sql .= " AND MONTH(t.doc_date) = " . $month;
+		//if (in_array($this->db->type, array('mysql', 'mysqli'))) $sql.=' USE INDEX idx_accounting_bookkeeping_doc_date';
+		$sql .= " WHERE t.entity = ".$conf->entity;
+		if (is_array($cpt))
+		{
+			$listofaccount='';
+			foreach($cpt as $cptcursor)
+			{
+				if ($listofaccount) $listofaccount.=",";
+				$listofaccount.="'".$cptcursor."'";
+			}
+			$sql .= " AND t.numero_compte IN (" .$listofaccount. ")";
+		}
+		else
+		{
+			$sql .= " AND t.numero_compte = '" . $this->db->escape($cpt) . "'";
+		}
+		if (! empty($date_start) && ! empty($date_end) && (empty($month) || empty($year)))	// If month/year provided, it is stronger than filter date_start/date_end
+			$sql .= " AND (t.doc_date BETWEEN '".$this->db->idate($date_start)."' AND '".$this->db->idate($date_end)."')";
+		if (! empty($month) && ! empty($year)) {
+			$sql .= " AND (t.doc_date BETWEEN '".$this->db->idate(dol_get_first_day($year, $month))."' AND '".$this->db->idate(dol_get_last_day($year, $month))."')";
 		}
 		if ($thirdparty_code != 'nofilter')
 		{
-			$sql .= " AND thirdparty_code = '".$this->db->escape($thirdparty_code)."'";
+			$sql .= " AND t.thirdparty_code = '".$this->db->escape($thirdparty_code)."'";
 		}
+		if (is_array($cpt)) $sql.=" GROUP BY t.numero_compte";
+		//print $sql;
 
-		dol_syslog(__METHOD__ . " sql=" . $sql, LOG_DEBUG);
 		$resql = $this->db->query($sql);
-
-		if ($resql) {
+		if ($resql)
+		{
 			$num = $this->db->num_rows($resql);
-			$this->sdc = 0;
-			if ($num) {
+			if ($num)
+			{
 				$obj = $this->db->fetch_object($resql);
 				if ($sens == 1) {
 					$this->sdc = $obj->debit - $obj->credit;
 				} else {
 					$this->sdc = $obj->credit - $obj->debit;
 				}
+				if (is_array($cpt))
+				{
+					$this->sdcperaccount[$obj->accountancy_account] = $this->sdc;
+				}
 			}
 			return $num;
 		} else {
 			$this->error = "Error " . $this->db->lasterror();
+			$this->errors[] = $this->error;
 			dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR);
-
-			return - 1;
+			return -1;
 		}
 	}
 
@@ -766,7 +798,7 @@ class AccountancyCategory // extends CommonObject
 	 */
 	public function getCats($categorytype=-1)
 	{
-		global $db, $langs, $user, $mysoc, $conf;
+		global $conf, $mysoc;
 
 		if (empty($mysoc->country_id)) {
 			dol_print_error('', 'Call to select_accounting_account with mysoc country not yet defined');
@@ -775,7 +807,7 @@ class AccountancyCategory // extends CommonObject
 
 		$sql = "SELECT c.rowid, c.code, c.label, c.formula, c.position, c.category_type";
 		$sql .= " FROM " . MAIN_DB_PREFIX . "c_accounting_category as c";
-		$sql .= " WHERE c.active = 1 ";
+		$sql .= " WHERE c.active = 1";
 		$sql .= " AND c.entity = " . $conf->entity;
 		if ($categorytype >= 0) $sql.=" AND c.category_type = 1";
 		$sql .= " AND (c.fk_country = ".$mysoc->country_id." OR c.fk_country = 0)";
@@ -823,7 +855,7 @@ class AccountancyCategory // extends CommonObject
 	 */
 	public function getCptsCat($cat_id, $predefinedgroupwhere='')
 	{
-		global $mysoc;
+		global $conf, $mysoc;
 		$sql = '';
 
 		if (empty($mysoc->country_id) && empty($mysoc->country_code)) {
@@ -836,6 +868,7 @@ class AccountancyCategory // extends CommonObject
 			$sql = "SELECT t.rowid, t.account_number, t.label as account_label";
 			$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as t";
 			$sql .= " WHERE t.fk_accounting_category = ".$cat_id;
+			$sql .= " AND t.entity = " . $conf->entity;
 			$sql .= " ORDER BY t.account_number";
 		}
 		else
@@ -843,6 +876,7 @@ class AccountancyCategory // extends CommonObject
 			$sql = "SELECT t.rowid, t.account_number, t.label as account_label";
 			$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as t";
 			$sql .= " WHERE ".$predefinedgroupwhere;
+			$sql .= " AND t.entity = " . $conf->entity;
 			$sql .= " ORDER BY t.account_number";
 		}
 		//echo $sql;
@@ -856,13 +890,12 @@ class AccountancyCategory // extends CommonObject
 			if ($num) {
 				while ($obj = $this->db->fetch_object($resql))
 				{
-					$name_cat = $obj->name_cat;
 					$data[] = array (
 							'id' => $obj->rowid,
 							'account_number' => $obj->account_number,
 							'account_label' => $obj->account_label,
 					);
-					$i ++;
+					$i++;
 				}
 			}
 			return $data;

+ 3 - 0
htdocs/accountancy/class/accountancyexport.class.php

@@ -572,8 +572,10 @@ class AccountancyExport
 
 			if (empty($line->subledger_account)) {
 				print length_accountg($line->numero_compte) . $separator;
+				print $line->label_compte . $separator;
 			} else {
 				print length_accounta($line->subledger_account) . $separator;
+				print $line->subledger_label . $separator;
 			}
 
 			print $line->doc_ref . $separator;
@@ -581,6 +583,7 @@ class AccountancyExport
 			print price($line->credit) . $separator;
 			print price($line->montant) . $separator;
 			print $line->sens . $separator;
+			print $line->lettering_code . $separator;
 			print $line->code_journal;
 			print $end_line;
 		}

+ 16 - 16
htdocs/accountancy/class/bookkeeping.class.php

@@ -221,7 +221,7 @@ class BookKeeping extends CommonObject
 		if (empty($this->credit)) $this->credit = 0;
 
 		// Check parameters
-		if (empty($this->numero_compte) || $this->numero_compte == '-1' || $this->numero_compte == 'NotDefined')
+		if (($this->numero_compte == "") || $this->numero_compte == '-1' || $this->numero_compte == 'NotDefined')
 		{
 			$langs->loadLangs(array("errors"));
 			if (in_array($this->doc_type, array('bank', 'expense_report')))
@@ -817,7 +817,7 @@ class BookKeeping extends CommonObject
 			$num = $this->db->num_rows($resql);
 
 			$i = 0;
-			while ($obj = $this->db->fetch_object($resql) && (empty($limit) || $i < min($limit, $num))) {
+			while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) {
 				$line = new BookKeepingLine();
 
 				$line->id = $obj->rowid;
@@ -866,14 +866,13 @@ class BookKeeping extends CommonObject
 	/**
 	 * Load object in memory from the database
 	 *
-	 * @param string $sortorder Sort Order
-	 * @param string $sortfield Sort field
-	 * @param int $limit offset limit
-	 * @param int $offset offset limit
-	 * @param array $filter filter array
-	 * @param string $filtermode filter mode (AND or OR)
-	 *
-	 * @return int <0 if KO, >0 if OK
+	 * @param string 		$sortorder 		Sort Order
+	 * @param string 		$sortfield 		Sort field
+	 * @param int 			$limit 			Offset limit
+	 * @param int 			$offset 		Offset limit
+	 * @param array 		$filter 		Filter array
+	 * @param string 		$filtermode 	Filter mode (AND or OR)
+	 * @return int 							<0 if KO, >0 if OK
 	 */
     public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
     {
@@ -932,7 +931,7 @@ class BookKeeping extends CommonObject
 				}
 			}
 		}
-		$sql.= ' WHERE entity IN (' . getEntity('accountancy') . ')';
+		$sql.= ' WHERE t.entity IN (' . getEntity('accountancy') . ')';
 		if (count($sqlwhere) > 0) {
 			$sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere);
 		}
@@ -950,7 +949,8 @@ class BookKeeping extends CommonObject
 			$num = $this->db->num_rows($resql);
 
 			$i = 0;
-			while ($obj = $this->db->fetch_object($resql) && (empty($limit) || $i < min($limit, $num))) {
+			while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num)))
+			{
 				$line = new BookKeepingLine();
 
 				$line->id = $obj->rowid;
@@ -989,8 +989,7 @@ class BookKeeping extends CommonObject
 		} else {
 			$this->errors[] = 'Error ' . $this->db->lasterror();
 			dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR);
-
-			return - 1;
+			return -1;
 		}
 	}
 
@@ -1067,6 +1066,7 @@ class BookKeeping extends CommonObject
 				$line->numero_compte = $obj->numero_compte;
 				$line->debit = $obj->debit;
 				$line->credit = $obj->credit;
+
 				$this->lines[] = $line;
 
 				$i++;
@@ -1577,7 +1577,7 @@ class BookKeeping extends CommonObject
 		$result = $this->db->query($sql);
 		if ($result) {
 
-			while ( $obj = $this->db->fetch_object($result) ) {
+			while ($obj = $this->db->fetch_object($result)) {
 
 				$line = new BookKeepingLine();
 
@@ -1641,7 +1641,7 @@ class BookKeeping extends CommonObject
 			$this->linesexport = array ();
 
 			$num = $this->db->num_rows($resql);
-			while ( $obj = $this->db->fetch_object($resql) ) {
+			while ($obj = $this->db->fetch_object($resql)) {
 				$line = new BookKeepingLine();
 
 				$line->id = $obj->rowid;

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

@@ -211,7 +211,7 @@ class Lettering extends BookKeeping
 				}
 
 				if (count($ids) > 1) {
-					$result = $this->updatelettrage($ids);
+					$result = $this->updateLettering($ids);
 				}
 			}
 		}

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

@@ -94,7 +94,7 @@ $facture_static = new Facture($db);
 $formaccounting = new FormAccounting($db);
 
 if (! empty($id)) {
-	$sql = "SELECT f.facnumber, f.rowid as facid, l.fk_product, l.description, l.price,";
+	$sql = "SELECT f.ref, f.rowid as facid, l.fk_product, l.description, l.price,";
 	$sql .= " l.qty, l.rowid, l.tva_tx, l.remise_percent, l.subprice, p.accountancy_code_sell as code_sell,";
 	$sql .= " l.fk_code_ventilation, aa.account_number, aa.label";
 	$sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as l";
@@ -128,7 +128,7 @@ if (! empty($id)) {
 
 			// Ref facture
 			print '<tr><td>' . $langs->trans("Invoice") . '</td>';
-			$facture_static->ref = $objp->facnumber;
+			$facture_static->ref = $objp->ref;
 			$facture_static->id = $objp->facid;
 			print '<td>' . $facture_static->getNomUrl(1) . '</td>';
 			print '</tr>';

+ 5 - 5
htdocs/accountancy/customer/lines.php

@@ -64,7 +64,7 @@ $pageprev = $page - 1;
 $pagenext = $page + 1;
 $offset = $limit * $page;
 if (! $sortfield)
-	$sortfield = "f.datef, f.facnumber, fd.rowid";
+	$sortfield = "f.datef, f.ref, fd.rowid";
 if (! $sortorder) {
 	if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE > 0) {
 		$sortorder = "DESC";
@@ -167,7 +167,7 @@ print '<script type="text/javascript">
 /*
  * Customer Invoice lines
  */
-$sql = "SELECT f.rowid as facid, f.facnumber as ref, f.type, f.datef, f.ref_client,";
+$sql = "SELECT f.rowid as facid, f.ref as ref, f.type, f.datef, f.ref_client,";
 $sql.= " fd.rowid, fd.description, fd.product_type as line_type, fd.total_ht, fd.total_tva, fd.tva_tx, fd.vat_src_code, 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.fk_product_type as product_type, 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,";
@@ -195,7 +195,7 @@ if ($search_lineid) {
     $sql .= natural_search("fd.rowid", $search_lineid, 1);
 }
 if (strlen(trim($search_invoice))) {
-	$sql .= natural_search("f.facnumber", $search_invoice);
+	$sql .= natural_search("f.ref", $search_invoice);
 }
 if (strlen(trim($search_ref))) {
 	$sql .= natural_search("p.ref", $search_ref);
@@ -331,8 +331,8 @@ if ($result) {
 
 	print '<tr class="liste_titre">';
 	print_liste_field_titre("LineId", $_SERVER["PHP_SELF"], "fd.rowid", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre("Invoice", $_SERVER["PHP_SELF"], "f.facnumber", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "f.datef, f.facnumber, fd.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
+	print_liste_field_titre("Invoice", $_SERVER["PHP_SELF"], "f.ref", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "f.datef, f.ref, fd.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
 	print_liste_field_titre("ProductRef", $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
 	//print_liste_field_titre("ProductLabel", $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre("Description", $_SERVER["PHP_SELF"], "fd.description", "", $param, '', $sortfield, $sortorder);

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

@@ -75,7 +75,7 @@ $offset = $limit * $page;
 $pageprev = $page - 1;
 $pagenext = $page + 1;
 if (! $sortfield)
-	$sortfield = "f.datef, f.facnumber, l.rowid";
+	$sortfield = "f.datef, f.ref, l.rowid";
 if (! $sortorder) {
 	if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO > 0) {
 		$sortorder = "DESC";
@@ -209,7 +209,7 @@ if (empty($chartaccountcode))
 }
 
 // Customer Invoice lines
-$sql = "SELECT f.rowid as facid, f.facnumber as ref, f.datef, f.type as ftype,";
+$sql = "SELECT f.rowid as facid, f.ref as ref, f.datef, f.type as ftype,";
 $sql.= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,";
 $sql.= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.accountancy_code_sell as code_sell, p.tva_tx as tva_tx_prod,";
 $sql.= " aa.rowid as aarowid,";
@@ -233,7 +233,7 @@ if ($search_lineid) {
     $sql .= natural_search("l.rowid", $search_lineid, 1);
 }
 if (strlen(trim($search_invoice))) {
-    $sql .= natural_search("f.facnumber", $search_invoice);
+    $sql .= natural_search("f.ref", $search_invoice);
 }
 if (strlen(trim($search_ref))) {
     $sql .= natural_search("p.ref", $search_ref);
@@ -399,8 +399,8 @@ if ($result) {
 
 	print '<tr class="liste_titre">';
 	print_liste_field_titre("LineId", $_SERVER["PHP_SELF"], "l.rowid", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre("Invoice", $_SERVER["PHP_SELF"], "f.facnumber", "", $param, '', $sortfield, $sortorder);
-	print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "f.datef, f.facnumber, l.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
+	print_liste_field_titre("Invoice", $_SERVER["PHP_SELF"], "f.ref", "", $param, '', $sortfield, $sortorder);
+	print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "f.datef, f.ref, l.rowid", "", $param, 'align="center"', $sortfield, $sortorder);
 	print_liste_field_titre("ProductRef", $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
 	//print_liste_field_titre("ProductLabel", $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder);
 	print_liste_field_titre("Description", $_SERVER["PHP_SELF"], "l.description", "", $param, '', $sortfield, $sortorder);

+ 8 - 2
htdocs/accountancy/index.php

@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2016       Laurent Destailleur      <eldy@users.sourceforge.net>
- * Copyright (C) 2016-2018  Alexandre Spangaro       <aspangaro@zendsi.com>
+ * Copyright (C) 2016-2018  Alexandre Spangaro       <aspangaro@open-dsi.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
@@ -118,7 +118,13 @@ if ($conf->accounting->enabled)
 	if (! empty($conf->don->enabled))
 	{
 	    $step++;
-	    print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescDonation", $step, '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDonationAccounts").'</strong>');
+	    print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescDonation", $step, '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>');
+	    print "<br>\n";
+	}
+	if (! empty($conf->adherents->enabled))
+	{
+	    $step++;
+	    print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescSubscription", $step, '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>');
 	    print "<br>\n";
 	}*/
 

+ 92 - 48
htdocs/accountancy/journal/bankjournal.php

@@ -4,10 +4,11 @@
  * Copyright (C) 2011       Juanjo Menent           <jmenent@2byte.es>
  * Copyright (C) 2012       Regis Houssin           <regis.houssin@inodbox.com>
  * Copyright (C) 2013       Christophe Battarel     <christophe.battarel@altairis.fr>
- * Copyright (C) 2013-2018  Alexandre Spangaro      <aspangaro@zendsi.com>
+ * Copyright (C) 2013-2018  Alexandre Spangaro      <aspangaro@open-dsi.fr>
  * Copyright (C) 2013-2014  Florian Henry           <florian.henry@open-concept.pro>
  * Copyright (C) 2013-2014  Olivier Geffroy         <jeff@jeffinfo.com>
  * Copyright (C) 2017-2018  Frédéric France         <frederic.france@netlogic.fr>
+ * Copyright (C) 2018		Ferran Marcet		    <fmarcet@2byte.es>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -56,9 +57,10 @@ require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/paymentvarious.class.php';
 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
 require_once DOL_DOCUMENT_ROOT . '/loan/class/loan.class.php';
 require_once DOL_DOCUMENT_ROOT . '/loan/class/paymentloan.class.php';
+require_once DOL_DOCUMENT_ROOT . '/adherents/class/subscription.class.php';
 
 // Load translation files required by the page
-$langs->loadLangs(array("companies","other","compta","banks","bills","donations","loan","accountancy","trips","salaries","hrm"));
+$langs->loadLangs(array("companies","other","compta","banks","bills","donations","loan","accountancy","trips","salaries","hrm","members"));
 
 // Multi journal
 $id_journal = GETPOST('id_journal', 'int');
@@ -149,6 +151,7 @@ $paymentexpensereportstatic = new PaymentExpenseReport($db);
 $paymentvariousstatic = new PaymentVarious($db);
 $paymentloanstatic = new PaymentLoan($db);
 $accountLinestatic=new AccountLine($db);
+$paymentsubscriptionstatic = new Subscription($db);
 
 $accountingaccount = new AccountingAccount($db);
 
@@ -167,12 +170,13 @@ if ($result) {
 	//print $sql;
 
 	// Variables
-	$account_supplier = (! empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : 'NotDefined');	// NotDefined is a reserved word
-	$account_customer = (! empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) ? $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER : 'NotDefined');	// NotDefined is a reserved word
-	$account_employee = (! empty($conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT) ? $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT : 'NotDefined');	// NotDefined is a reserved word
-	$account_pay_vat = (! empty($conf->global->ACCOUNTING_VAT_PAY_ACCOUNT) ? $conf->global->ACCOUNTING_VAT_PAY_ACCOUNT : 'NotDefined');	// NotDefined is a reserved word
-	$account_pay_donation = (! empty($conf->global->DONATION_ACCOUNTINGACCOUNT) ? $conf->global->DONATION_ACCOUNTINGACCOUNT : 'NotDefined');	// NotDefined is a reserved word
-	$account_transfer = (! empty($conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH) ? $conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH : 'NotDefined');	// NotDefined is a reserved word
+	$account_supplier			= (! empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : 'NotDefined');	// NotDefined is a reserved word
+	$account_customer			= (! empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) ? $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER : 'NotDefined');	// NotDefined is a reserved word
+	$account_employee			= (! empty($conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT) ? $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT : 'NotDefined');	// NotDefined is a reserved word
+	$account_pay_vat			= (! empty($conf->global->ACCOUNTING_VAT_PAY_ACCOUNT) ? $conf->global->ACCOUNTING_VAT_PAY_ACCOUNT : 'NotDefined');	// NotDefined is a reserved word
+	$account_pay_donation		= (! empty($conf->global->DONATION_ACCOUNTINGACCOUNT) ? $conf->global->DONATION_ACCOUNTINGACCOUNT : 'NotDefined');	// NotDefined is a reserved word
+	$account_pay_subscription	= (! empty($conf->global->ADHERENT_SUBSCRIPTION_ACCOUNTINGACCOUNT) ? $conf->global->ADHERENT_SUBSCRIPTION_ACCOUNTINGACCOUNT : 'NotDefined');	// NotDefined is a reserved word
+	$account_transfer			= (! empty($conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH) ? $conf->global->ACCOUNTING_ACCOUNT_TRANSFER_CASH : 'NotDefined');	// NotDefined is a reserved word
 
 	$tabcompany = array();
 	$tabuser = array();
@@ -263,7 +267,7 @@ if ($result) {
 			// Now loop on each link of record in bank.
 			foreach ($links as $key => $val) {
 
-				if (in_array($links[$key]['type'], array('sc', 'payment_sc', 'payment', 'payment_supplier', 'payment_vat', 'payment_expensereport', 'banktransfert', 'payment_donation', 'payment_loan', 'payment_salary', 'payment_various')))
+				if (in_array($links[$key]['type'], array('sc', 'payment_sc', 'payment', 'payment_supplier', 'payment_vat', 'payment_expensereport', 'banktransfert', 'payment_donation', 'member', 'payment_loan', 'payment_salary', 'payment_various')))
 				{
 					// So we excluded 'company' and 'user' here. We want only payment lines
 
@@ -341,6 +345,14 @@ if ($result) {
 					$tabpay[$obj->rowid]["lib"] .= ' ' . $paymentdonstatic->getNomUrl(2);
 					$tabpay[$obj->rowid]["paymentdonationid"] = $paymentdonstatic->id;
 					$tabtp[$obj->rowid][$account_pay_donation] += $obj->amount;
+				} else if ($links[$key]['type'] == 'member') {
+					$paymentsubscriptionstatic->id = $links[$key]['url_id'];
+					$paymentsubscriptionstatic->ref = $links[$key]['url_id'];
+					$paymentsubscriptionstatic->label = $links[$key]['label'];
+					$tabpay[$obj->rowid]["lib"] .= ' ' . $paymentsubscriptionstatic->getNomUrl(2);
+					$tabpay[$obj->rowid]["paymentsubscriptionid"] = $paymentsubscriptionstatic->id;
+					$paymentsubscriptionstatic->fetch($paymentsubscriptionstatic->id);
+					$tabtp[$obj->rowid][$account_pay_subscription] += $obj->amount;
 				} else if ($links[$key]['type'] == 'payment_vat') {				// Payment VAT
 					$paymentvatstatic->id = $links[$key]['url_id'];
 					$paymentvatstatic->ref = $links[$key]['url_id'];
@@ -374,6 +386,18 @@ if ($result) {
 					$tabpay[$obj->rowid]["lib"] .= ' ' . $paymentloanstatic->getNomUrl(2);
 					$tabpay[$obj->rowid]["paymentloanid"] = $paymentloanstatic->id;
 					//$tabtp[$obj->rowid][$account_pay_loan] += $obj->amount;
+					$sqlmid = 'SELECT pl.amount_capital, pl.amount_insurance, pl.amount_interest, l.accountancy_account_capital, l.accountancy_account_insurance, l.accountancy_account_interest';
+					$sqlmid.= ' FROM '.MAIN_DB_PREFIX.'payment_loan as pl, '.MAIN_DB_PREFIX.'loan as l';
+					$sqlmid.= ' WHERE l.rowid = pl.fk_loan AND pl.fk_bank = '.$obj->rowid;
+
+					dol_syslog("accountancy/journal/bankjournal.php:: sqlmid=" . $sqlmid, LOG_DEBUG);
+					$resultmid = $db->query($sqlmid);
+					if ($resultmid) {
+						$objmid = $db->fetch_object($resultmid);
+						$tabtp[$obj->rowid][$objmid->accountancy_account_capital] -= $objmid->amount_capital;
+						$tabtp[$obj->rowid][$objmid->accountancy_account_insurance] -= $objmid->amount_insurance;
+						$tabtp[$obj->rowid][$objmid->accountancy_account_interest] -= $objmid->amount_interest;
+					}
 				} else if ($links[$key]['type'] == 'banktransfert') {
 					$accountLinestatic->fetch($links[$key]['url_id']);
 					$tabpay[$obj->rowid]["lib"] .= ' '.$langs->trans("BankTransfer").'- ' .$accountLinestatic ->getNomUrl(1);
@@ -573,35 +597,42 @@ if (! $error && $action == 'writebookkeeping') {
 							$bookkeeping->subledger_label = '';
 							$bookkeeping->numero_compte = $k;
 
-							$accountingaccount->fetch($k, null, true);
+							$accountingaccount->fetch(null, $k, true);
 							$bookkeeping->label_compte = $accountingaccount->label;
 						} else if ($tabtype[$key] == 'payment_donation') {
 							$bookkeeping->subledger_account = '';
 							$bookkeeping->subledger_label = '';
 							$bookkeeping->numero_compte = $k;
 
-							$accountingaccount->fetch($k, null, true);
+							$accountingaccount->fetch(null, $k, true);
+							$bookkeeping->label_compte = $accountingaccount->label;
+						} else if ($tabtype[$key] == 'member') {
+							$bookkeeping->subledger_account = '';
+							$bookkeeping->subledger_label = '';
+							$bookkeeping->numero_compte = $k;
+
+							$accountingaccount->fetch(null, $k, true);
 							$bookkeeping->label_compte = $accountingaccount->label;
 						} else if ($tabtype[$key] == 'payment_loan') {
 							$bookkeeping->subledger_account = '';
 							$bookkeeping->subledger_label = '';
 							$bookkeeping->numero_compte = $k;
 
-							$accountingaccount->fetch($k, null, true);
+							$accountingaccount->fetch(null, $k, true);
 							$bookkeeping->label_compte = $accountingaccount->label;
 						} else if ($tabtype[$key] == 'payment_various') {
 							$bookkeeping->subledger_account = '';
 							$bookkeeping->subledger_label = '';
 							$bookkeeping->numero_compte = $k;
 
-							$accountingaccount->fetch($k, null, true);
+							$accountingaccount->fetch(null, $k, true);
 							$bookkeeping->label_compte = $accountingaccount->label;
 						} else if ($tabtype[$key] == 'banktransfert') {
 							$bookkeeping->subledger_account = '';
 							$bookkeeping->subledger_label = '';
 							$bookkeeping->numero_compte = $k;
 
-							$accountingaccount->fetch($k, null, true);
+							$accountingaccount->fetch(null, $k, true);
 							$bookkeeping->label_compte = $accountingaccount->label;
 						} else {
 							if ($tabtype[$key] == 'unknown')	// Unknown transaction, we will use a waiting account for thirdparty.
@@ -891,7 +922,7 @@ if (empty($action) || $action == 'view') {
 
 
 	// Test that setup is complete
-	$sql = 'SELECT COUNT(rowid) as nb FROM '.MAIN_DB_PREFIX.'bank_account WHERE fk_accountancy_journal IS NULL';
+	$sql = 'SELECT COUNT(rowid) as nb FROM '.MAIN_DB_PREFIX.'bank_account WHERE fk_accountancy_journal IS NULL AND clos=0';
 	$resql = $db->query($sql);
 	if ($resql)
 	{
@@ -915,9 +946,18 @@ if (empty($action) || $action == 'view') {
 
 
 	print '<div class="tabsAction tabsActionNoBottom">';
+
 	if (! empty($conf->global->ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL)) print '<input type="button" class="butAction" name="exportcsv" value="' . $langs->trans("ExportDraftJournal") . '" onclick="launch_export();" />';
-	if ($in_bookkeeping == 'notyet') print '<input type="button" class="butAction" name="writebookkeeping" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-	else print '<a class="butActionRefused" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
+
+	if (empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) || $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER == '-1'
+	    || empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) || $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER == '-1') {
+	   print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="' . $langs->trans("WriteBookKeeping") . '" />';
+	}
+	else {
+	    if ($in_bookkeeping == 'notyet') print '<input type="button" class="butAction" name="writebookkeeping" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
+        else print '<a class="butActionRefused classfortooltip" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
+	}
+
 	print '</div>';
 
 	// TODO Avoid using js. We can use a direct link with $param
@@ -1027,11 +1067,13 @@ if (empty($action) || $action == 'view') {
 					print "<td>";
 					$account_ledger = $k;
 					// Try to force general ledger account depending on type
-					if ($tabtype[$key] == 'payment') $account_ledger = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
-					if ($tabtype[$key] == 'payment_supplier') $account_ledger = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
-					if ($tabtype[$key] == 'payment_expensereport') $account_ledger = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT;
-					if ($tabtype[$key] == 'payment_salary') $account_ledger = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT;
-					if ($tabtype[$key] == 'payment_vat') $account_ledger = $conf->global->ACCOUNTING_VAT_PAY_ACCOUNT;
+					if ($tabtype[$key] == 'payment')				$account_ledger = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
+					if ($tabtype[$key] == 'payment_supplier')		$account_ledger = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
+					if ($tabtype[$key] == 'payment_expensereport')	$account_ledger = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT;
+					if ($tabtype[$key] == 'payment_salary')			$account_ledger = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT;
+					if ($tabtype[$key] == 'payment_vat')			$account_ledger = $conf->global->ACCOUNTING_VAT_PAY_ACCOUNT;
+					if ($tabtype[$key] == 'member')					$account_ledger = $conf->global->ADHERENT_SUBSCRIPTION_ACCOUNTINGACCOUNT;
+
 					$accounttoshow = length_accounta($account_ledger);
 					if (empty($accounttoshow) || $accounttoshow == 'NotDefined')
 					{
@@ -1051,11 +1093,12 @@ if (empty($action) || $action == 'view') {
 						{
 							// We will refuse writing
 							$errorstring='UnknownAccountForThirdpartyBlocking';
-							if ($tabtype[$key] == 'payment') $errorstring='MainAccountForCustomersNotDefined';
-							if ($tabtype[$key] == 'payment_supplier') $errorstring='MainAccountForSuppliersNotDefined';
-							if ($tabtype[$key] == 'payment_expensereport') $errorstring='MainAccountForUsersNotDefined';
-							if ($tabtype[$key] == 'payment_salary') $errorstring='MainAccountForUsersNotDefined';
-							if ($tabtype[$key] == 'payment_vat') $errorstring='MainAccountForVatPaymentNotDefined';
+							if ($tabtype[$key] == 'payment')				$errorstring='MainAccountForCustomersNotDefined';
+							if ($tabtype[$key] == 'payment_supplier')		$errorstring='MainAccountForSuppliersNotDefined';
+							if ($tabtype[$key] == 'payment_expensereport')	$errorstring='MainAccountForUsersNotDefined';
+							if ($tabtype[$key] == 'payment_salary')			$errorstring='MainAccountForUsersNotDefined';
+							if ($tabtype[$key] == 'payment_vat')			$errorstring='MainAccountForVatPaymentNotDefined';
+							if ($tabtype[$key] == 'member')					$errorstring='MainAccountForSubscriptionPaymentNotDefined';
 							print '<span class="error">'.$langs->trans($errorstring).'</span>';
 						}
 					}
@@ -1142,7 +1185,7 @@ $db->close();
  *
  * @param 	string 	$val			Array of val
  * @param 	string	$typerecord		Type of record ('payment', 'payment_supplier', 'payment_expensereport', 'payment_vat', ...)
- * @return string|unknown
+ * @return 	string					A string label to describe a record into llx_bank_url
  */
 function getSourceDocRef($val, $typerecord)
 {
@@ -1152,93 +1195,93 @@ function getSourceDocRef($val, $typerecord)
 	// WE MUST HAVE SAME REF FOR ALL LINES WE WILL RECORD INTO THE BOOKKEEPING
 	$ref = $val['ref'];
 	if ($ref == '(SupplierInvoicePayment)' || $ref == '(SupplierInvoicePaymentBack)') {
-		$ref = $langs->trans('Supplier');
+		$ref = $langs->transnoentitiesnoconv('Supplier');
 	}
 	if ($ref == '(CustomerInvoicePayment)' || $ref == '(CustomerInvoicePaymentBack)') {
-		$ref = $langs->trans('Customer');
+		$ref = $langs->transnoentitiesnoconv('Customer');
 	}
 	if ($ref == '(SocialContributionPayment)') {
-		$ref = $langs->trans('SocialContribution');
+		$ref = $langs->transnoentitiesnoconv('SocialContribution');
 	}
 	if ($ref == '(DonationPayment)') {
-		$ref = $langs->trans('Donation');
+		$ref = $langs->transnoentitiesnoconv('Donation');
 	}
 	if ($ref == '(SubscriptionPayment)') {
-		$ref = $langs->trans('Subscription');
+		$ref = $langs->transnoentitiesnoconv('Subscription');
 	}
 	if ($ref == '(ExpenseReportPayment)') {
-		$ref = $langs->trans('Employee');
+		$ref = $langs->transnoentitiesnoconv('Employee');
 	}
 	if ($ref == '(LoanPayment)') {
-		$ref = $langs->trans('Loan');
+		$ref = $langs->transnoentitiesnoconv('Loan');
 	}
 	if ($ref == '(payment_salary)') {
-		$ref = $langs->trans('Employee');
+		$ref = $langs->transnoentitiesnoconv('Employee');
 	}
 
 	$sqlmid = '';
 	if ($typerecord == 'payment')
 	{
-		$sqlmid = 'SELECT payfac.fk_facture as id, f.facnumber as ref';
+		$sqlmid = 'SELECT payfac.fk_facture as id, f.ref as ref';
 		$sqlmid .= " FROM ".MAIN_DB_PREFIX."paiement_facture as payfac, ".MAIN_DB_PREFIX."facture as f";
 		$sqlmid .= " WHERE payfac.fk_facture = f.rowid AND payfac.fk_paiement=" . $val["paymentid"];
-		$ref = $langs->trans("Invoice");
+		$ref = $langs->transnoentitiesnoconv("Invoice");
 	}
 	elseif ($typerecord == 'payment_supplier')
 	{
 		$sqlmid = 'SELECT payfac.fk_facturefourn as id, f.ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "paiementfourn_facturefourn as payfac, ".MAIN_DB_PREFIX."facture_fourn as f";
 		$sqlmid .= " WHERE payfac.fk_facturefourn = f.rowid AND payfac.fk_paiementfourn=" . $val["paymentsupplierid"];
-		$ref = $langs->trans("SupplierInvoice");
+		$ref = $langs->transnoentitiesnoconv("SupplierInvoice");
 	}
 	elseif ($typerecord == 'payment_expensereport')
 	{
 		$sqlmid = 'SELECT e.rowid as id, e.ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "payment_expensereport as pe, " . MAIN_DB_PREFIX . "expensereport as e";
 		$sqlmid .= " WHERE pe.rowid=" . $val["paymentexpensereport"]." AND pe.fk_expensereport = e.rowid";
-		$ref = $langs->trans("ExpenseReport");
+		$ref = $langs->transnoentitiesnoconv("ExpenseReport");
 	}
 	elseif ($typerecord == 'payment_salary')
 	{
 		$sqlmid = 'SELECT s.rowid as ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "payment_salary as s";
 		$sqlmid .= " WHERE s.rowid=" . $val["paymentsalid"];
-		$ref = $langs->trans("SalaryPayment");
+		$ref = $langs->transnoentitiesnoconv("SalaryPayment");
 	}
 	elseif ($typerecord == 'sc')
 	{
 		$sqlmid = 'SELECT sc.rowid as ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "paiementcharge as sc";
 		$sqlmid .= " WHERE sc.rowid=" . $val["paymentscid"];
-		$ref = $langs->trans("SocialContribution");
+		$ref = $langs->transnoentitiesnoconv("SocialContribution");
 	}
 	elseif ($typerecord == 'payment_vat')
 	{
 		$sqlmid = 'SELECT v.rowid as ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "tva as v";
 		$sqlmid .= " WHERE v.rowid=" . $val["paymentvatid"];
-		$ref = $langs->trans("PaymentVat");
+		$ref = $langs->transnoentitiesnoconv("PaymentVat");
 	}
 	elseif ($typerecord == 'payment_donation')
 	{
 		$sqlmid = 'SELECT payd.fk_donation as ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "payment_donation as payd";
 		$sqlmid .= " WHERE payd.fk_donation=" . $val["paymentdonationid"];
-		$ref = $langs->trans("Donation");
+		$ref = $langs->transnoentitiesnoconv("Donation");
 	}
 	elseif ($typerecord == 'payment_loan')
 	{
 		$sqlmid = 'SELECT l.rowid as ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "payment_loan as l";
 		$sqlmid .= " WHERE l.rowid=" . $val["paymentloanid"];
-		$ref = $langs->trans("LoanPayment");
+		$ref = $langs->transnoentitiesnoconv("LoanPayment");
 	}
 	elseif ($typerecord == 'payment_various')
 	{
 		$sqlmid = 'SELECT v.rowid as ref';
 		$sqlmid .= " FROM " . MAIN_DB_PREFIX . "payment_various as v";
 		$sqlmid .= " WHERE v.rowid=" . $val["paymentvariousid"];
-		$ref = $langs->trans("VariousPayment");
+		$ref = $langs->transnoentitiesnoconv("VariousPayment");
 	}
 	// Add warning
 	if (empty($sqlmid))
@@ -1250,7 +1293,8 @@ function getSourceDocRef($val, $typerecord)
 	{
 		dol_syslog("accountancy/journal/bankjournal.php::sqlmid=" . $sqlmid, LOG_DEBUG);
 		$resultmid = $db->query($sqlmid);
-		if ($resultmid) {
+		if ($resultmid)
+		{
 			while ($objmid = $db->fetch_object($resultmid))
 			{
 				$ref.=' '.$objmid->ref;
@@ -1259,6 +1303,6 @@ function getSourceDocRef($val, $typerecord)
 		else dol_print_error($db);
 	}
 
-	$ref = dol_trunc($langs->trans("BankId").' '.$val['fk_bank'].' - '.$ref, 295);	// 295 + 3 ... i< < than max size of 300
+	$ref = dol_trunc($langs->transnoentitiesnoconv("BankId").' '.$val['fk_bank'].' - '.$ref, 295);	// 295 + 3 dots (...) is < than max size of 300
 	return $ref;
 }

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

@@ -561,11 +561,11 @@ if (empty($action) || $action == 'view') {
 	}
 	print '<div class="tabsAction tabsActionNoBottom">';
 	if (empty($conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT) || $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT == '-1') {
-		print '<input type="button" class="butActionRefused" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="' . $langs->trans("WriteBookKeeping") . '" />';
+		print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="' . $langs->trans("WriteBookKeeping") . '" />';
 	}
 	else {
 		if ($in_bookkeeping == 'notyet') print '<input type="button" class="butAction" name="writebookkeeping" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-		else print '<a href="#" class="butActionRefused" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
+		else print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
 	}
 	//print '<input type="button" class="butAction" name="exportcsv" value="' . $langs->trans("ExportDraftJournal") . '" onclick="launch_export();" />';
 	print '</div>';

+ 13 - 12
htdocs/accountancy/journal/purchasesjournal.php

@@ -7,6 +7,7 @@
  * Copyright (C) 2013-2016  Olivier Geffroy         <jeff@jeffinfo.com>
  * Copyright (C) 2013-2016  Florian Henry           <florian.henry@open-concept.pro>
  * Copyright (C) 2018       Frédéric France         <frederic.france@netlogic.fr>
+ * Copyright (C) 2018       Eric Seigne             <eric.seigne@cap-rel.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
@@ -139,7 +140,7 @@ if ($result) {
 	$num = $db->num_rows($result);
 
 	// Variables
-	$cptfour = (! empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER)) ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : 'NotDefined';
+	$cptfour = ($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER != "") ? $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER : 'NotDefined';
 	$cpttva = (! empty($conf->global->ACCOUNTING_VAT_BUY_ACCOUNT)) ? $conf->global->ACCOUNTING_VAT_BUY_ACCOUNT : 'NotDefined';
 
 	$i = 0;
@@ -147,7 +148,7 @@ if ($result) {
 		$obj = $db->fetch_object($result);
 
 		// Controls
-		$compta_soc = (! empty($obj->code_compta_fournisseur)) ? $obj->code_compta_fournisseur : $cptfour;
+		$compta_soc = ($obj->code_compta_fournisseur != "") ? $obj->code_compta_fournisseur : $cptfour;
 
 		$compta_prod = $obj->compte;
 		if (empty($compta_prod)) {
@@ -741,18 +742,18 @@ if (empty($action) || $action == 'view') {
 	journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
 
 	// Button to write into Ledger
-	if (empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) || $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER == '-1') {
+	if (($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER == "") || $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER == '-1') {
 		print img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
 		print ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>');
 	}
 	print '<div class="tabsAction tabsActionNoBottom">';
 	if (! empty($conf->global->ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL)) print '<input type="button" class="butAction" name="exportcsv" value="' . $langs->trans("ExportDraftJournal") . '" onclick="launch_export();" />';
-	if (empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) || $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER == '-1') {
-		print '<input type="button" class="butActionRefused" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="' . $langs->trans("WriteBookKeeping") . '" />';
+	if (empty($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) || $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER == '-1') {
+		print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="' . $langs->trans("WriteBookKeeping") . '" />';
 	}
 	else {
 		if ($in_bookkeeping == 'notyet') print '<input type="button" class="butAction" name="writebookkeeping" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-		else print '<a href="#" class="butActionRefused" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
+		else print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
 	}
 	print '</div>';
 
@@ -876,16 +877,16 @@ if (empty($action) || $action == 'view') {
 				// Account
 				print "<td>";
 				$accountoshow = length_accounta($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER);
-				if (empty($accountoshow) || $accountoshow == 'NotDefined')
+				if (($accountoshow == "") || $accountoshow == 'NotDefined')
 				{
-					print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
+					print '<span class="error">'.$langs->trans("MainAccountForSupplierssNotDefined").'</span>';
 				}
 				else print $accountoshow;
 				print '</td>';
 				// Subledger account
 				print "<td>";
 				$accountoshow = length_accounta($k);
-				if (empty($accountoshow) || $accountoshow == 'NotDefined')
+				if (($accountoshow == "") || $accountoshow == 'NotDefined')
 				{
 					print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
 				}
@@ -911,7 +912,7 @@ if (empty($action) || $action == 'view') {
 				// Account
 				print "<td>";
 				$accountoshow = length_accountg($k);
-				if (empty($accountoshow) || $accountoshow == 'NotDefined')
+				if (($accountoshow == "") || $accountoshow == 'NotDefined')
 				{
 					print '<span class="error">'.$langs->trans("ProductAccountNotDefined").'</span>';
 				}
@@ -945,7 +946,7 @@ if (empty($action) || $action == 'view') {
 					// Account
 					print "<td>";
 					$accountoshow = length_accountg($k);
-					if (empty($accountoshow) || $accountoshow == 'NotDefined')
+					if (($accountoshow == "") || $accountoshow == 'NotDefined')
 					{
 						print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("Purchase").')'.'</span>';
 					}
@@ -976,7 +977,7 @@ if (empty($action) || $action == 'view') {
 					// Account
 					print "<td>";
 					$accountoshow = length_accountg($k);
-					if (empty($accountoshow) || $accountoshow == 'NotDefined')
+					if (($accountoshow == "") || $accountoshow == 'NotDefined')
 					{
 						print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("NPR counterpart").'). Set ACCOUNTING_COUNTERPART_VAT_NPR to the subvention account'.'</span>';
 					}

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

@@ -97,7 +97,7 @@ if (! GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end)
 
 $idpays = $mysoc->country_id;
 
-$sql = "SELECT f.rowid, f.facnumber, f.type, f.datef as df, f.ref_client, f.date_lim_reglement as dlr, f.close_code,";
+$sql = "SELECT f.rowid, f.ref, f.type, f.datef as df, f.ref_client, f.date_lim_reglement as dlr, f.close_code,";
 $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.situation_percent, fd.vat_src_code,";
 $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,";
 $sql .= " p.rowid as pid, p.ref as pref, p.accountancy_code_sell, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte";
@@ -195,7 +195,7 @@ if ($result) {
 		// Invoice lines
 		$tabfac[$obj->rowid]["date"] = $db->jdate($obj->df);
 		$tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr);
-		$tabfac[$obj->rowid]["ref"] = $obj->facnumber;
+		$tabfac[$obj->rowid]["ref"] = $obj->ref;
 		$tabfac[$obj->rowid]["type"] = $obj->type;
 		$tabfac[$obj->rowid]["description"] = $obj->label_compte;
 		$tabfac[$obj->rowid]["close_code"] = $obj->close_code;		// close_code = 'replaced' for replacement invoices (not used in most european countries)
@@ -686,11 +686,11 @@ if (empty($action) || $action == 'view') {
 	print '<div class="tabsAction tabsActionNoBottom">';
 	if (! empty($conf->global->ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL)) print '<input type="button" class="butAction" name="exportcsv" value="' . $langs->trans("ExportDraftJournal") . '" onclick="launch_export();" />';
 	if (empty($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) || $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER == '-1') {
-		print '<input type="button" class="butActionRefused" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="' . $langs->trans("WriteBookKeeping") . '" />';
+		print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="' . $langs->trans("WriteBookKeeping") . '" />';
 	}
 	else {
 		if ($in_bookkeeping == 'notyet') print '<input type="button" class="butAction" name="writebookkeeping" value="' . $langs->trans("WriteBookKeeping") . '" onclick="writebookkeeping();" />';
-		else print '<a href="#" class="butActionRefused" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
+		else print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">' . $langs->trans("WriteBookKeeping") . '</a>';
 	}
 	print '</div>';
 

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

@@ -96,7 +96,7 @@ $facturefournisseur_static = new FactureFournisseur($db);
 $formaccounting = new FormAccounting($db);
 
 if (! empty($id)) {
-	$sql = "SELECT f.ref as facnumber, f.rowid as facid, l.fk_product, l.description, l.rowid, l.fk_code_ventilation, ";
+	$sql = "SELECT f.ref as ref, f.rowid as facid, l.fk_product, l.description, l.rowid, l.fk_code_ventilation, ";
 	$sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label";
 	$sql .= ", aa.account_number, aa.label";
 	$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn_det as l";
@@ -129,7 +129,7 @@ if (! empty($id)) {
 
 			// ref invoice
 			print '<tr><td>' . $langs->trans("BillsSuppliers") . '</td>';
-			$facturefournisseur_static->ref = $objp->facnumber;
+			$facturefournisseur_static->ref = $objp->ref;
 			$facturefournisseur_static->id = $objp->facid;
 			print '<td>' . $facturefournisseur_static->getNomUrl(1) . '</td>';
 			print '</tr>';

+ 2 - 2
htdocs/adherents/admin/adherent_extrafields.php

@@ -94,7 +94,7 @@ if ($action != 'create' && $action != 'edit')
 
 if ($action == 'create')
 {
-	print "<br>";
+	print '<div name="topofform"></div><br>';
 	print load_fiche_titre($langs->trans('NewAttribute'));
 
     require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php';
@@ -107,7 +107,7 @@ if ($action == 'create')
 /* ************************************************************************** */
 if ($action == 'edit' && ! empty($attrname))
 {
-	print "<br>";
+	print '<div name="topofform"></div><br>';
 	print load_fiche_titre($langs->trans("FieldEdition", $attrname));
 
     require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php';

+ 58 - 45
htdocs/adherents/card.php

@@ -5,7 +5,7 @@
  * Copyright (C) 2005-2018  Regis Houssin           <regis.houssin@inodbox.com>
  * Copyright (C) 2012       Marcos García           <marcosgdf@gmail.com>
  * Copyright (C) 2012-2018  Philippe Grand          <philippe.grand@atoo-net.com>
- * Copyright (C) 2015-2016  Alexandre Spangaro      <aspangaro.dolibarr@gmail.com>
+ * Copyright (C) 2015-2018  Alexandre Spangaro      <aspangaro@zendsi.com>
  * Copyright (C) 2018       Frédéric France         <frederic.france@netlogic.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,9 +23,9 @@
  */
 
 /**
- *       \file       htdocs/adherents/card.php
- *       \ingroup    member
- *       \brief      Page of member
+ *  \file       htdocs/adherents/card.php
+ *  \ingroup    member
+ *  \brief      Page of member
  */
 
 require '../main.inc.php';
@@ -94,7 +94,7 @@ if ($id > 0)
 	// Define variables to know what current user can do on properties of user linked to edited member
 	if ($object->user_id)
 	{
-		// $ User is the user who edits, $ object->user_id is the id of the related user in the edited member
+		// $User is the user who edits, $object->user_id is the id of the related user in the edited member
 		$caneditfielduser=((($user->id == $object->user_id) && $user->rights->user->self->creer)
 				|| (($user->id != $object->user_id) && $user->rights->user->user->creer));
 		$caneditpassworduser=((($user->id == $object->user_id) && $user->rights->user->self->password)
@@ -249,6 +249,7 @@ if (empty($reshook))
 		}
 		$lastname=$_POST["lastname"];
 		$firstname=$_POST["firstname"];
+		$gender = $_POST["gender"];
 		$societe=$_POST["societe"];
 		$morphy=$_POST["morphy"];
 		$login=$_POST["login"];
@@ -267,7 +268,7 @@ if (empty($reshook))
 			$langs->load("errors");
 			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Company")), null, 'errors');
 		}
-		// Test si le login existe deja
+		// Check if the login already exists
 		if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED))
 		{
 			if (empty($login)) {
@@ -284,6 +285,7 @@ if (empty($reshook))
 			$object->civility_id = trim(GETPOST("civility_id",'alpha'));
 			$object->firstname   = trim(GETPOST("firstname",'alpha'));
 			$object->lastname    = trim(GETPOST("lastname",'alpha'));
+			$object->gender      = trim(GETPOST("gender",'alpha'));
 			$object->login       = trim(GETPOST("login",'alpha'));
 			$object->pass        = trim(GETPOST("pass",'alpha'));
 
@@ -431,9 +433,10 @@ if (empty($reshook))
 		}
 
 		$typeid=GETPOST("typeid",'int');
-		$civility_id=GETPOST("civility_id",'int');
+		$civility_id=GETPOST("civility_id",'alpha');
 		$lastname=GETPOST("lastname",'alpha');
 		$firstname=GETPOST("firstname",'alpha');
+		$gender=GETPOST("gender",'alpha');
 		$societe=GETPOST("societe",'alpha');
 		$address=GETPOST("address",'alpha');
 		$zip=GETPOST("zipcode",'alpha');
@@ -462,6 +465,7 @@ if (empty($reshook))
 		$object->civility_id = $civility_id;
 		$object->firstname   = $firstname;
 		$object->lastname    = $lastname;
+		$object->gender      = $gender;
 		$object->societe     = $societe;
 		$object->address     = $address;
 		$object->zip         = $zip;
@@ -954,19 +958,26 @@ else
 		print '<tr><td id="tdfirstname">'.$langs->trans("Firstname").'</td><td><input type="text" name="firstname" class="minwidth300" maxlength="50" value="'.(GETPOST('firstname','alpha')?GETPOST('firstname','alpha'):$object->firstname).'"></td>';
 		print '</tr>';
 
+		// Gender
+		print '<tr><td>'.$langs->trans("Gender").'</td>';
+		print '<td>';
+		$arraygender=array('man'=>$langs->trans("Genderman"),'woman'=>$langs->trans("Genderwoman"));
+		print $form->selectarray('gender', $arraygender, GETPOST('gender'), 1);
+		print '</td></tr>';
+
 		// EMail
 		print '<tr><td>'.($conf->global->ADHERENT_MAIL_REQUIRED?'<span class="fieldrequired">':'').$langs->trans("EMail").($conf->global->ADHERENT_MAIL_REQUIRED?'</span>':'').'</td><td><input type="text" name="member_email" class="minwidth300" maxlength="255" value="'.(GETPOST('member_email','alpha')?GETPOST('member_email','alpha'):$object->email).'"></td></tr>';
 
 		// Address
 		print '<tr><td class="tdtop">'.$langs->trans("Address").'</td><td>';
-		print '<textarea name="address" wrap="soft" class="quatrevingtpercent" rows="2">'.(GETPOST('address','alpha')?GETPOST('address','alpha'):$object->address).'</textarea>';
+		print '<textarea name="address" wrap="soft" class="quatrevingtpercent" rows="2">'.(GETPOST('address','alphanohtml')?GETPOST('address','alphanohtml'):$object->address).'</textarea>';
 		print '</td></tr>';
 
 		// Zip / Town
 		print '<tr><td>'.$langs->trans("Zip").' / '.$langs->trans("Town").'</td><td>';
-		print $formcompany->select_ziptown((GETPOST('zipcode','alpha')?GETPOST('zipcode','alpha'):$object->zip),'zipcode',array('town','selectcountry_id','state_id'),6);
+		print $formcompany->select_ziptown((GETPOST('zipcode','alphanohtml')?GETPOST('zipcode','alphanohtml'):$object->zip),'zipcode',array('town','selectcountry_id','state_id'),6);
 		print ' ';
-		print $formcompany->select_ziptown((GETPOST('town','alpha')?GETPOST('town','alpha'):$object->town),'town',array('zipcode','selectcountry_id','state_id'));
+		print $formcompany->select_ziptown((GETPOST('town','alphanohtml')?GETPOST('town','alphanohtml'):$object->town),'town',array('zipcode','selectcountry_id','state_id'));
 		print '</td></tr>';
 
 		// Country
@@ -1031,7 +1042,7 @@ else
 		// Categories
 		if (! empty($conf->categorie->enabled)  && ! empty($user->rights->categorie->lire))
 		{
-			print '<tr><td>' . fieldLabel('Categories', 'memcars') . '</td><td>';
+			print '<tr><td>' .$form->editfieldkey("Categories", 'memcats', '', $object, 0) . '</td><td>';
 			$cate_arbo = $form->select_all_categories(Categorie::TYPE_MEMBER, null, 'parent', null, null, 1);
 			print $form->multiselectarray('memcats', $cate_arbo, GETPOST('memcats', 'array'), null, null, null, null, '100%');
 			print "</td></tr>";
@@ -1154,7 +1165,7 @@ else
 			print '<tr><td><span class="fieldrequired">'.$langs->trans("Login").' / '.$langs->trans("Id").'</span></td><td><input type="text" name="login" class="minwidth300" maxlength="50" value="'.(isset($_POST["login"])?GETPOST("login",'alpha',2):$object->login).'"></td></tr>';
 		}
 
-	// Password
+		// Password
 		if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED))
 		{
 			print '<tr><td class="fieldrequired">'.$langs->trans("Password").'</td><td><input type="password" name="pass" class="minwidth300" maxlength="50" value="'.(isset($_POST["pass"])?GETPOST("pass",'',2):$object->pass).'"></td></tr>';
@@ -1196,6 +1207,13 @@ else
 		print '<tr><td id="tdfirstname">'.$langs->trans("Firstname").'</td><td><input type="text" name="firstname" class="minwidth300" maxlength="50" value="'.(isset($_POST["firstname"])?GETPOST("firstname",'',3):$object->firstname).'"></td>';
 		print '</tr>';
 
+		// Gender
+		print '<tr><td>'.$langs->trans("Gender").'</td>';
+		print '<td>';
+		$arraygender=array('man'=>$langs->trans("Genderman"),'woman'=>$langs->trans("Genderwoman"));
+		print $form->selectarray('gender', $arraygender, GETPOST('gender')?GETPOST('gender'):$object->gender, 1);
+		print '</td></tr>';
+
 		// Photo
 		print '<tr><td>'.$langs->trans("Photo").'</td>';
 		print '<td class="hideonsmartphone" valign="middle">';
@@ -1281,13 +1299,16 @@ else
 		// Categories
 		if (! empty( $conf->categorie->enabled ) && !empty( $user->rights->categorie->lire ))
 		{
-			print '<tr><td>' . fieldLabel('Categories', 'memcats') . '</td>';
+			print '<tr><td>' . $form->editfieldkey("Categories", 'memcats', '', $object, 0) . '</td>';
 			print '<td>';
 			$cate_arbo = $form->select_all_categories(Categorie::TYPE_MEMBER, null, null, null, null, 1);
 			$c = new Categorie($db);
 			$cats = $c->containing($object->id, Categorie::TYPE_MEMBER);
-			foreach ($cats as $cat) {
-				$arrayselected[] = $cat->id;
+			$arrayselected = array();
+			if (is_array($cats)) {
+				foreach ($cats as $cat) {
+					$arrayselected[] = $cat->id;
+				}
 			}
 			print $form->multiselectarray('memcats', $cate_arbo, $arrayselected, '', 0, '', 0, '100%');
 			print "</td></tr>";
@@ -1580,6 +1601,12 @@ else
 		print '<tr><td>'.$langs->trans("Nature").'</td><td class="valeur" >'.$object->getmorphylib().'</td>';
 		print '</tr>';
 
+		// Gender
+		print '<tr><td>'.$langs->trans("Gender").'</td>';
+		print '<td>';
+		if ($object->gender) print $langs->trans("Gender".$object->gender);
+		print '</td></tr>';
+
 		// Company
 		print '<tr><td>'.$langs->trans("Company").'</td><td class="valeur">'.$object->societe.'</td></tr>';
 
@@ -1634,11 +1661,8 @@ else
 		if (! empty($conf->societe->enabled))
 		{
 			print '<tr><td>';
-			print '<table class="nobordernopadding" width="100%"><tr><td>';
-			print $langs->trans("LinkedToDolibarrThirdParty");
-			print '</td>';
-			if ($action != 'editthirdparty' && $user->rights->adherent->creer) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editthirdparty&amp;rowid='.$object->id.'">'.img_edit($langs->trans('SetLinkToThirdParty'),1).'</a></td>';
-			print '</tr></table>';
+			$editenable = $user->rights->adherent->creer;
+			print $form->editfieldkey('LinkedToDolibarrThirdParty', 'thirdparty', '', $object, $editenable);
 			print '</td><td colspan="2" class="valeur">';
 			if ($action == 'editthirdparty')
 			{
@@ -1672,19 +1696,8 @@ else
 
 		// Login Dolibarr
 		print '<tr><td>';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans("LinkedToDolibarrUser");
-		print '</td>';
-		if ($action != 'editlogin' && $user->rights->adherent->creer)
-		{
-			print '<td align="right">';
-			if ($user->rights->user->user->creer)
-			{
-				print '<a href="'.$_SERVER["PHP_SELF"].'?action=editlogin&amp;rowid='.$object->id.'">'.img_edit($langs->trans('SetLinkToUser'),1).'</a>';
-			}
-			print '</td>';
-		}
-		print '</tr></table>';
+		$editenable = $user->rights->adherent->creer && $user->rights->user->user->creer;
+		print $form->editfieldkey('LinkedToDolibarrUser', 'login', '', $object, $editenable);
 		print '</td><td colspan="2" class="valeur">';
 		if ($action == 'editlogin')
 		{
@@ -1757,16 +1770,16 @@ else
 					if ($object->statut >= 1)
 					{
 						if ($object->email) print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$object->id.'&action=sendinfo">'.$langs->trans("SendCardByMail")."</a></div>\n";
-						else print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NoEMail")).'">'.$langs->trans("SendCardByMail")."</a></div>\n";
+						else print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NoEMail")).'">'.$langs->trans("SendCardByMail")."</a></div>\n";
 					}
 					else
 					{
-						print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("SendCardByMail")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("SendCardByMail")."</font></div>";
 					}
 				}
 				else
 				{
-					print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("SendCardByMail")."</font></div>";
+					print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("SendCardByMail")."</font></div>";
 				}*/
 
 				// Modify
@@ -1776,7 +1789,7 @@ else
 				}
 				else
 				{
-					print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Modify").'</font></div>';
+					print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Modify").'</font></div>';
 				}
 
 				// Validate
@@ -1788,7 +1801,7 @@ else
 					}
 					else
 					{
-						print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Validate").'</font></div>';
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Validate").'</font></div>';
 					}
 				}
 
@@ -1801,7 +1814,7 @@ else
 					}
 					else
 					{
-						print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Reenable")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Reenable")."</font></div>";
 					}
 				}
 
@@ -1814,7 +1827,7 @@ else
 					}
 					else
 					{
-						print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Resiliate")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Resiliate")."</font></div>";
 					}
 				}
 
@@ -1824,11 +1837,11 @@ else
 					if ($user->rights->societe->creer)
 					{
 						if ($object->statut != -1) print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$object->id.'&amp;action=create_thirdparty">'.$langs->trans("CreateDolibarrThirdParty").'</a></div>';
-						else print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrThirdParty").'</a></div>';
+						else print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrThirdParty").'</a></div>';
 					}
 					else
 					{
-						print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrThirdParty")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrThirdParty")."</font></div>";
 					}
 				}
 
@@ -1838,11 +1851,11 @@ else
 					if ($user->rights->user->user->creer)
 					{
 						if ($object->statut != -1) print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$object->id.'&amp;action=create_user">'.$langs->trans("CreateDolibarrLogin").'</a></div>';
-						else print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrLogin").'</a></div>';
+						else print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrLogin").'</a></div>';
 					}
 					else
 					{
-						print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrLogin")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrLogin")."</font></div>";
 					}
 				}
 
@@ -1853,7 +1866,7 @@ else
 				}
 				else
 				{
-					print '<div class="inline-block divButAction"><font class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Delete")."</font></div>";
+					print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Delete")."</font></div>";
 				}
 
 				// Action SPIP

+ 117 - 59
htdocs/adherents/class/adherent.class.php

@@ -5,7 +5,7 @@
  * Copyright (C) 2004		Sebastien Di Cintio		<sdicintio@ressource-toi.org>
  * Copyright (C) 2004		Benoit Mortier			<benoit.mortier@opensides.be>
  * Copyright (C) 2009-2017	Regis Houssin			<regis.houssin@inodbox.com>
- * Copyright (C) 2014-2016	Alexandre Spangaro		<aspangaro.dolibarr@gmail.com>
+ * Copyright (C) 2014-2018	Alexandre Spangaro		<aspangaro@zendsi.com>
  * Copyright (C) 2015		Marcos García			<marcosgdf@gmail.com>
  * Copyright (C) 2015-2018  Frédéric France			<frederic.france@netlogic.fr>
  * Copyright (C) 2015		Raphaël Doursenaud		<rdoursenaud@gpcsolutions.fr>
@@ -59,6 +59,9 @@ class Adherent extends CommonObject
 
 	public $mesgs;
 
+    /**
+     * @var string login of member
+     */
 	public $login;
 
 	//! Clear password in memory
@@ -68,29 +71,70 @@ class Adherent extends CommonObject
 	//! Encrypted password in database (always defined)
 	public $pass_indatabase_crypted;
 
+    /**
+     * @var string company name
+     * @deprecated
+     */
 	public $societe;
 
 	/**
-	 * @var Societe $company {@type Societe}
+	 * @var string company name
 	 */
 	public $company;
 
+	/**
+	 * @var int Thirdparty ID
+	 */
+    public $fk_soc;
+
 	/**
 	 * @var string Address
 	 */
 	public $address;
 
-	public $zip;
+    /**
+     * @var string zipcode
+     */
+    public $zip;
+
+    /**
+     * @var string town
+     */
 	public $town;
 
-	public $state_id;              // Id of department
-	public $state_code;            // Code of department
-	public $state;                 // Label of department
+    /**
+     * @var int Id of state
+     */
+    public $state_id;
 
+    /**
+     * @var string Code of state
+     */
+    public $state_code;
+
+    /**
+     * @var string Label of state
+     */
+	public $state;
+
+    /**
+     * @var string email
+     */
 	public $email;
 
-	public $skype;
-	public $twitter;
+    /**
+     * @var string skype account
+     */
+    public $skype;
+
+    /**
+     * @var string twitter account
+     */
+    public $twitter;
+
+    /**
+     * @var string facebook account
+     */
 	public $facebook;
 
     /**
@@ -120,30 +164,34 @@ class Adherent extends CommonObject
 
 	public $morphy;
 	public $public;
-	public $statut;			// -1:brouillon, 0:resilie, >=1:valide,paye
-	public $photo;
+
+    // -1:brouillon, 0:resilie, >=1:valide,paye
+    // def in common object
+    //public $statut;
+
+    public $photo;
 
 	public $datec;
 	public $datem;
 	public $datevalid;
 
+	public $gender;
 	public $birth;
 
-	public $note_public;
-	public $note_private;
+    /**
+     * @var int id type member
+     */
+	public $typeid;
 
-	public $typeid;			// Id type adherent
-	public $type;				// Libelle type adherent
+    /**
+     * @var string label type member
+     */
+	public $type;
 	public $need_subscription;
 
 	public $user_id;
 	public $user_login;
 
-	/**
-	 * @var int Thirdparty ID
-	 */
-    public $fk_soc;
-
 	public $datefin;	// From member table
 
 	// Fields loaded by fetch_subscriptions()
@@ -155,7 +203,10 @@ class Adherent extends CommonObject
 	public $last_subscription_amount;
 	public $subscriptions=array();
 
-	public $oldcopy;		// To contains a clone of this when we need to save old properties of object
+    /**
+     * @var Adherent To contains a clone of this when we need to save old properties of object
+     */
+	public $oldcopy;
 
 	/**
 	 * @var int Entity
@@ -275,22 +326,22 @@ class Adherent extends CommonObject
 		// Substitutions
 		$substitutionarray=array(
 			'__CIVILITY__'=>$this->getCivilityLabel(),
-			'__FIRSTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->firstname):$this->firstname,
-			'__LASTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->lastname):$this->lastname,
+			'__FIRSTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->firstname):($this->firstname?$this->firstname:''),
+			'__LASTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->lastname):($this->lastname?$this->lastname:''),
 			'__FULLNAME__'=>$msgishtml?dol_htmlentitiesbr($this->getFullName($langs)):$this->getFullName($langs),
-			'__COMPANY__'=>$msgishtml?dol_htmlentitiesbr($this->societe):$this->societe,
-			'__ADDRESS__'=>$msgishtml?dol_htmlentitiesbr($this->address):$this->address,
-			'__ZIP__'=>$msgishtml?dol_htmlentitiesbr($this->zip):$this->zip,
-			'__TOWN__'=>$msgishtml?dol_htmlentitiesbr($this->town):$this->town,
-			'__COUNTRY__'=>$msgishtml?dol_htmlentitiesbr($this->country):$this->country,
-			'__EMAIL__'=>$msgishtml?dol_htmlentitiesbr($this->email):$this->email,
-			'__BIRTH__'=>$msgishtml?dol_htmlentitiesbr($birthday):$birthday,
-			'__PHOTO__'=>$msgishtml?dol_htmlentitiesbr($this->photo):$this->photo,
-			'__LOGIN__'=>$msgishtml?dol_htmlentitiesbr($this->login):$this->login,
-			'__PASSWORD__'=>$msgishtml?dol_htmlentitiesbr($this->pass):$this->pass,
-			'__PHONE__'=>$msgishtml?dol_htmlentitiesbr($this->phone):$this->phone,
-			'__PHONEPRO__'=>$msgishtml?dol_htmlentitiesbr($this->phone_perso):$this->phone_perso,
-			'__PHONEMOBILE__'=>$msgishtml?dol_htmlentitiesbr($this->phone_mobile):$this->phone_mobile,
+			'__COMPANY__'=>$msgishtml?dol_htmlentitiesbr($this->societe):($this->societe?$this->societe:''),
+			'__ADDRESS__'=>$msgishtml?dol_htmlentitiesbr($this->address):($this->address?$this->address:''),
+			'__ZIP__'=>$msgishtml?dol_htmlentitiesbr($this->zip):($this->zip?$this->zip:''),
+			'__TOWN__'=>$msgishtml?dol_htmlentitiesbr($this->town):($this->town?$this->town:''),
+			'__COUNTRY__'=>$msgishtml?dol_htmlentitiesbr($this->country):($this->country?$this->country:''),
+			'__EMAIL__'=>$msgishtml?dol_htmlentitiesbr($this->email):($this->email?$this->email:''),
+			'__BIRTH__'=>$msgishtml?dol_htmlentitiesbr($birthday):($birthday?$birthday:''),
+			'__PHOTO__'=>$msgishtml?dol_htmlentitiesbr($this->photo):($this->photo?$this->photo:''),
+			'__LOGIN__'=>$msgishtml?dol_htmlentitiesbr($this->login):($this->login?$this->login:''),
+			'__PASSWORD__'=>$msgishtml?dol_htmlentitiesbr($this->pass):($this->pass?$this->pass:''),
+			'__PHONE__'=>$msgishtml?dol_htmlentitiesbr($this->phone):($this->phone?$this->phone:''),
+			'__PHONEPRO__'=>$msgishtml?dol_htmlentitiesbr($this->phone_perso):($this->phone_perso?$this->phone_perso:''),
+			'__PHONEMOBILE__'=>$msgishtml?dol_htmlentitiesbr($this->phone_mobile):($this->phone_mobile?$this->phone_mobile:'')
 		);
 
 		complete_substitutions_array($substitutionarray, $langs, $this);
@@ -457,17 +508,18 @@ class Adherent extends CommonObject
 		dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncuser=".$nosyncuser.", nosyncuserpass=".$nosyncuserpass." nosyncthirdparty=".$nosyncthirdparty.", email=".$this->email);
 
 		// Clean parameters
-		$this->lastname=trim($this->lastname)?trim($this->lastname):trim($this->lastname);
-		$this->firstname=trim($this->firstname)?trim($this->firstname):trim($this->firstname);
-		$this->address=($this->address?$this->address:$this->address);
-		$this->zip=($this->zip?$this->zip:$this->zip);
-		$this->town=($this->town?$this->town:$this->town);
-		$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);
+		$this->lastname     = trim($this->lastname)?trim($this->lastname):trim($this->lastname);
+		$this->firstname    = trim($this->firstname)?trim($this->firstname):trim($this->firstname);
+		$this->gender       = trim($this->gender);
+		$this->address      = ($this->address?$this->address:$this->address);
+		$this->zip          = ($this->zip?$this->zip:$this->zip);
+		$this->town         = ($this->town?$this->town:$this->town);
+		$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));
-		$this->note_public=($this->note_public?$this->note_public:$this->note_public);
-		$this->note_private=($this->note_private?$this->note_private:$this->note_private);
+		$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))
@@ -483,6 +535,7 @@ class Adherent extends CommonObject
 		$sql.= " civility = ".($this->civility_id?"'".$this->db->escape($this->civility_id)."'":"null");
 		$sql.= ", firstname = ".($this->firstname?"'".$this->db->escape($this->firstname)."'":"null");
 		$sql.= ", lastname = ".($this->lastname?"'".$this->db->escape($this->lastname)."'":"null");
+		$sql.= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null");	// 'man' or 'woman'
 		$sql.= ", login = ".($this->login?"'".$this->db->escape($this->login)."'":"null");
 		$sql.= ", societe = ".($this->societe?"'".$this->db->escape($this->societe)."'":"null");
 		$sql.= ", fk_soc = ".($this->fk_soc > 0?$this->db->escape($this->fk_soc):"null");
@@ -589,15 +642,17 @@ class Adherent extends CommonObject
 						$luser->civility_id=$this->civility_id;
 						$luser->firstname=$this->firstname;
 						$luser->lastname=$this->lastname;
+						$luser->gender=$this->gender;
 						$luser->pass=$this->pass;
 						$luser->societe_id=$this->societe;
 
 						$luser->birth=$this->birth;
-                                                $luser->address=$this->address;
-                                                $luser->zip=$this->zip;
-                                                $luser->town=$this->town;
-                                                $luser->country_id=$this->country_id;
-                                                $luser->state_id=$this->state_id;
+
+						$luser->address=$this->address;
+						$luser->zip=$this->zip;
+						$luser->town=$this->town;
+						$luser->country_id=$this->country_id;
+						$luser->state_id=$this->state_id;
 
 						$luser->email=$this->email;
 						$luser->skype=$this->skype;
@@ -647,13 +702,14 @@ class Adherent extends CommonObject
 						$lthirdparty->phone=$this->phone;
 						$lthirdparty->state_id=$this->state_id;
 						$lthirdparty->country_id=$this->country_id;
-						$lthirdparty->country_id=$this->country_id;
 						//$lthirdparty->phone_mobile=$this->phone_mobile;
 
-						$result=$lthirdparty->update($this->fk_soc,$user,0,1,1,'update');	// Use sync to 0 to avoid cyclic updates
+						$result=$lthirdparty->update($this->fk_soc, $user, 0, 1, 1, 'update');	// Use sync to 0 to avoid cyclic updates
+
 						if ($result < 0)
 						{
 							$this->error=$lthirdparty->error;
+							$this->errors=$lthirdparty->errors;
 							dol_syslog(get_class($this)."::update ".$this->error,LOG_ERR);
 							$error++;
 						}
@@ -1129,7 +1185,7 @@ class Adherent extends CommonObject
 	{
 		global $langs;
 
-		$sql = "SELECT d.rowid, d.ref_ext, d.civility as civility_id, d.firstname, d.lastname, d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
+		$sql = "SELECT d.rowid, d.ref_ext, d.civility as civility_id, d.gender, d.firstname, d.lastname, d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
 		$sql.= " d.note_public,";
 		$sql.= " d.email, d.skype, d.twitter, d.facebook, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,";
 		$sql.= " d.photo, d.fk_adherent_type, d.morphy, d.entity,";
@@ -1176,6 +1232,7 @@ class Adherent extends CommonObject
 				$this->civility_id		= $obj->civility_id;
 				$this->firstname		= $obj->firstname;
 				$this->lastname			= $obj->lastname;
+				$this->gender			= $obj->gender;
 				$this->login			= $obj->login;
 				$this->societe			= $obj->company;
 				$this->company			= $obj->company;
@@ -1983,8 +2040,8 @@ class Adherent extends CommonObject
 			$label.= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
 		if (! empty($this->firstname) || ! empty($this->lastname))
 			$label.= '<br><b>' . $langs->trans('Name') . ':</b> ' . $this->getFullName($langs);
-		if (! empty($this->societe))
-			$label.= '<br><b>' . $langs->trans('Company') . ':</b> ' . $this->societe;
+		if (! empty($this->company))
+			$label.= '<br><b>' . $langs->trans('Company') . ':</b> ' . $this->company;
 		$label.='</div>';
 
 		$url = DOL_URL_ROOT.'/adherents/card.php?rowid='.$this->id;
@@ -2288,6 +2345,7 @@ class Adherent extends CommonObject
 		$this->civility_id = 0;
 		$this->lastname = 'DOLIBARR';
 		$this->firstname = 'SPECIMEN';
+		$this->gender='man';
 		$this->login='dolibspec';
 		$this->pass='dolibspec';
 		$this->societe = 'Societe ABC';
@@ -2656,7 +2714,7 @@ class Adherent extends CommonObject
 			$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
 			return 0;
 		}
-		
+
 		$now = dol_now();
 		$nbok = 0;
 		$nbko = 0;
@@ -2760,9 +2818,9 @@ class Adherent extends CommonObject
 									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
 									$actionmsg = dol_concatdesc($actionmsg, $message);
 								}
-								
+
 								require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
-								
+
 	    						// Insert record of emails sent
 	    						$actioncomm = new ActionComm($this->db);
 
@@ -2787,10 +2845,10 @@ class Adherent extends CommonObject
 	    						$actioncomm->email_tobcc = $sendtobcc;
 	    						$actioncomm->email_subject = $subject;
 	    						$actioncomm->errors_to   = '';
-	    						
+
 	    						$actioncomm->fk_element  = $adherent->id;
 	    						$actioncomm->elementtype = $adherent->element;
-	    						
+
 	    						$actioncomm->extraparams = $extraparams;
 
 	    						$actioncomm->create($user);

+ 19 - 6
htdocs/adherents/class/subscription.class.php

@@ -337,11 +337,14 @@ class Subscription extends CommonObject
 	/**
 	 *  Return clicable name (with picto eventually)
 	 *
-	 *	@param	int		$withpicto		0=No picto, 1=Include picto into link, 2=Only picto
-     *  @param	int  	$notooltip		1=Disable tooltip
-	 *	@return	string					Chaine avec URL
+	 *	@param	int		$withpicto					0=No picto, 1=Include picto into link, 2=Only picto
+     *  @param	int  	$notooltip					1=Disable tooltip
+	 *	@param	string	$option						Page for link ('', 'nolink', ...)
+	 *  @param  string  $morecss        			Add more css on link
+	 *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
+	 *	@return	string								Chaine avec URL
 	 */
-	function getNomUrl($withpicto=0, $notooltip=0)
+	function getNomUrl($withpicto=0, $notooltip=0, $option='', $morecss='', $save_lastsearch_value=-1)
 	{
 		global $langs;
 
@@ -350,8 +353,18 @@ class Subscription extends CommonObject
 		$langs->load("members");
         $label=$langs->trans("ShowSubscription").': '.$this->ref;
 
-        $linkstart = '<a href="'.DOL_URL_ROOT.'/adherents/subscription/card.php?rowid='.$this->id.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
-		$linkend='</a>';
+        $url = DOL_URL_ROOT.'/adherents/subscription/card.php?rowid='.$this->id;
+
+        if ($option != 'nolink')
+        {
+        	// Add param to save lastsearch_values or not
+        	$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
+        	if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
+        	if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
+        }
+
+        $linkstart = '<a href="'.$url.'" class="classfortooltip" title="'.dol_escape_htmltag($label, 1).'">';
+		$linkend = '</a>';
 
 		$picto='payment';
 

+ 1 - 1
htdocs/adherents/index.php

@@ -375,7 +375,7 @@ if ($resql)
 			$staticmember->lastname=$obj->lastname;
 			$staticmember->firstname=$obj->firstname;
 			if (! empty($obj->fk_soc)) {
-				$staticmember->socid = $obj->fk_soc;
+				$staticmember->fk_soc = $obj->fk_soc;
 				$staticmember->fetch_thirdparty();
 				$staticmember->name=$staticmember->thirdparty->name;
 			} else {

+ 71 - 7
htdocs/adherents/list.php

@@ -4,6 +4,7 @@
  * Copyright (C) 2004-2016  Laurent Destailleur     <eldy@users.sourceforge.net>
  * Copyright (C) 2013-2015  Raphaël Doursenaud      <rdoursenaud@gpcsolutions.fr>
  * Copyright (C) 2014-2016  Juanjo Menent           <jmenent@2byte.es>
+ * Copyright (C) 2018       Alexandre Spangaro      <aspangaro@zendsi.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,9 +21,9 @@
  */
 
 /**
- *      \file       htdocs/adherents/list.php
- *      \ingroup    member
- *		\brief      Page to list all members of foundation
+ *  \file       htdocs/adherents/list.php
+ *  \ingroup    member
+ *  \brief      Page to list all members of foundation
  */
 
 require '../main.inc.php';
@@ -48,6 +49,7 @@ $search=GETPOST("search",'alpha');
 $search_ref=GETPOST("search_ref",'alpha');
 $search_lastname=GETPOST("search_lastname",'alpha');
 $search_firstname=GETPOST("search_firstname",'alpha');
+$search_gender=GETPOST("search_gender",'alpha');
 $search_civility=GETPOST("search_civility",'alpha');
 $search_login=GETPOST("search_login",'alpha');
 $search_address=GETPOST("search_address",'alpha');
@@ -79,8 +81,9 @@ $pagenext = $page + 1;
 if (! $sortorder) { $sortorder=($filter=='outofdate'?"DESC":"ASC"); }
 if (! $sortfield) { $sortfield=($filter=='outofdate'?"d.datefin":"d.lastname"); }
 
-// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
 $object = new Adherent($db);
+
+// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
 $hookmanager->initHooks(array('memberlist'));
 $extrafields = new ExtraFields($db);
 
@@ -109,6 +112,7 @@ $arrayfields=array(
 	'd.civility'=>array('label'=>$langs->trans("Civility"), 'checked'=>0),
 	'd.lastname'=>array('label'=>$langs->trans("Lastname"), 'checked'=>1),
 	'd.firstname'=>array('label'=>$langs->trans("Firstname"), 'checked'=>1),
+	'd.gender'=>array('label'=>$langs->trans("Gender"), 'checked'=>0),
 	'd.company'=>array('label'=>$langs->trans("Company"), 'checked'=>1),
 	'd.login'=>array('label'=>$langs->trans("Login"), 'checked'=>1),
 	'd.morphy'=>array('label'=>$langs->trans("MorPhy"), 'checked'=>1),
@@ -162,6 +166,7 @@ if (empty($reshook))
 		$search_ref="";
 		$search_lastname="";
 		$search_firstname="";
+		$search_gender="";
 		$search_civility="";
 		$search_login="";
 		$search_company="";
@@ -205,7 +210,7 @@ $memberstatic=new Adherent($db);
 
 $now=dol_now();
 
-$sql = "SELECT d.rowid, d.login, d.lastname, d.firstname, d.societe as company, d.fk_soc,";
+$sql = "SELECT d.rowid, d.login, d.lastname, d.firstname, d.gender, d.societe as company, d.fk_soc,";
 $sql.= " d.civility, d.datefin, d.address, d.zip, d.town, d.state_id, d.country,";
 $sql.= " d.email, d.phone, d.phone_perso, d.phone_mobile, d.skype, d.birth, d.public, d.photo,";
 $sql.= " d.fk_adherent_type as type_id, d.morphy, d.statut, d.datec as date_creation, d.tms as date_update,";
@@ -240,6 +245,7 @@ if ($search_ref)
 if ($search_civility) $sql.= natural_search("d.civility", $search_civility);
 if ($search_firstname) $sql.= natural_search("d.firstname", $search_firstname);
 if ($search_lastname) $sql.= natural_search(array("d.firstname", "d.lastname", "d.societe"), $search_lastname);
+if ($search_gender != '' && $search_gender != '-1') $sql.= " AND d.gender = '".$search_gender."'";
 if ($search_login) $sql.= natural_search("d.login", $search_login);
 if ($search_email) $sql.= natural_search("d.email", $search_email);
 if ($search_town)     $sql.= natural_search("d.town",$search_town);
@@ -329,6 +335,7 @@ if ($search_nom)   $param.="&search_nom=".urlencode($search_nom);
 if ($search_civility) $param.="&search_civility=".urlencode($search_civility);
 if ($search_firstname) $param.="&search_firstname=".urlencode($search_firstname);
 if ($search_lastname)  $param.="&search_lastname=".urlencode($search_lastname);
+if ($search_gender)  $param.="&search_gender=".urlencode($search_gender);
 if ($search_login)   $param.="&search_login=".urlencode($search_login);
 if ($search_email)   $param.="&search_email=".urlencode($search_email);
 if ($search_company) $param.="&search_company=".urlencode($search_company);
@@ -348,8 +355,8 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
 
 // List of mass actions available
 $arrayofmassactions =  array(
-//    'presend'=>$langs->trans("SendByMail"),
-//    'builddoc'=>$langs->trans("PDFMerge"),
+	//'presend'=>$langs->trans("SendByMail"),
+	//'builddoc'=>$langs->trans("PDFMerge"),
 );
 if ($user->rights->adherent->supprimer) $arrayofmassactions['predelete']=$langs->trans("Delete");
 if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
@@ -447,6 +454,13 @@ if (! empty($arrayfields['d.lastname']['checked']))
 	print '<td class="liste_titre" align="left">';
 	print '<input class="flat maxwidth50" type="text" name="search_lastname" value="'.dol_escape_htmltag($search_lastname).'"></td>';
 }
+if (! empty($arrayfields['d.gender']['checked']))
+{
+	print '<td class="liste_titre">';
+	$arraygender=array('man'=>$langs->trans("Genderman"),'woman'=>$langs->trans("Genderwoman"));
+	print $form->selectarray('search_gender', $arraygender, $search_gender, 1);
+	print '</td>';
+}
 if (! empty($arrayfields['d.company']['checked']))
 {
 	print '<td class="liste_titre" align="left">';
@@ -575,6 +589,7 @@ if (! empty($arrayfields['d.ref']['checked']))            print_liste_field_titr
 if (! empty($arrayfields['d.civility']['checked']))       print_liste_field_titre($arrayfields['d.civility']['label'],$_SERVER["PHP_SELF"],'d.civility','',$param,'',$sortfield,$sortorder);
 if (! empty($arrayfields['d.firstname']['checked']))      print_liste_field_titre($arrayfields['d.firstname']['label'],$_SERVER["PHP_SELF"],'d.firstname','',$param,'',$sortfield,$sortorder);
 if (! empty($arrayfields['d.lastname']['checked']))       print_liste_field_titre($arrayfields['d.lastname']['label'],$_SERVER["PHP_SELF"],'d.lastname','',$param,'',$sortfield,$sortorder);
+if (! empty($arrayfields['d.gender']['checked']))         print_liste_field_titre($arrayfields['d.gender']['label'],$_SERVER['PHP_SELF'],'d.gender',$param,"","",$sortfield,$sortorder);
 if (! empty($arrayfields['d.company']['checked']))        print_liste_field_titre($arrayfields['d.company']['label'],$_SERVER["PHP_SELF"],'d.societe','',$param,'',$sortfield,$sortorder);
 if (! empty($arrayfields['d.login']['checked']))          print_liste_field_titre($arrayfields['d.login']['label'],$_SERVER["PHP_SELF"],'d.login','',$param,'',$sortfield,$sortorder);
 if (! empty($arrayfields['d.morphy']['checked']))         print_liste_field_titre($arrayfields['d.morphy']['label'],$_SERVER["PHP_SELF"],'d.morphy','',$param,'',$sortfield,$sortorder);
@@ -603,6 +618,7 @@ print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="c
 print "</tr>\n";
 
 $i = 0;
+$totalarray=array();
 while ($i < min($num, $limit))
 {
 	$obj = $db->fetch_object($resql);
@@ -613,6 +629,7 @@ while ($i < min($num, $limit))
 	$memberstatic->civility_id=$obj->civility;
 	$memberstatic->lastname=$obj->lastname;
 	$memberstatic->firstname=$obj->firstname;
+	$memberstatic->gender=$obj->gender;
 	$memberstatic->statut=$obj->statut;
 	$memberstatic->datefin= $datefin;
 	$memberstatic->socid = $obj->fk_soc;
@@ -631,6 +648,7 @@ while ($i < min($num, $limit))
 	if (! empty($conf->global->MAIN_SHOW_TECHNICAL_ID))
 	{
 		print '<td align="center">'.$obj->rowid.'</td>';
+		if (! $i) $totalarray['nbfield']++;
 	}
 
 	// Ref
@@ -639,6 +657,7 @@ while ($i < min($num, $limit))
 		print "<td>";
 		print $memberstatic->getNomUrl(-1, 0, 'card', 'ref');
 		print "</td>\n";
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Civility
 	if (! empty($arrayfields['d.civility']['checked']))
@@ -646,6 +665,7 @@ while ($i < min($num, $limit))
 		print "<td>";
 		print $obj->civility;
 		print "</td>\n";
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Firstname
 	if (! empty($arrayfields['d.firstname']['checked']))
@@ -653,6 +673,7 @@ while ($i < min($num, $limit))
 		print "<td>";
 		print $obj->firstname;
 		print "</td>\n";
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Lastname
 	if (! empty($arrayfields['d.lastname']['checked']))
@@ -660,6 +681,15 @@ while ($i < min($num, $limit))
 		print "<td>";
 		print $obj->lastname;
 		print "</td>\n";
+		if (! $i) $totalarray['nbfield']++;
+	}
+	// Gender
+	if (! empty($arrayfields['d.gender']['checked']))
+	{
+		print '<td>';
+		if ($obj->gender) print $langs->trans("Gender".$obj->gender);
+		print '</td>';
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Company
 	if (! empty($arrayfields['d.company']['checked']))
@@ -672,11 +702,13 @@ while ($i < min($num, $limit))
 	if (! empty($arrayfields['d.login']['checked']))
 	{
 		print "<td>".$obj->login."</td>\n";
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Moral/Physique
 	if (! empty($arrayfields['d.morphy']['checked']))
 	{
 		print "<td>".$memberstatic->getmorphylib($obj->morphy)."</td>\n";
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Type label
 	if (! empty($arrayfields['t.libelle']['checked']))
@@ -686,6 +718,7 @@ while ($i < min($num, $limit))
 		print '<td class="nowrap">';
 		print $membertypestatic->getNomUrl(1,32);
 		print '</td>';
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Address
 	if (! empty($arrayfields['d.address']['checked']))
@@ -693,6 +726,7 @@ while ($i < min($num, $limit))
 		print '<td class="nocellnopadd">';
 		print $obj->address;
 		print '</td>';
+		if (! $i) $totalarray['nbfield']++;
 	}
 	// Zip
 	if (! empty($arrayfields['d.zip']['checked']))
@@ -828,6 +862,36 @@ while ($i < min($num, $limit))
 	$i++;
 }
 
+// Show total line
+if (isset($totalarray['pos']))
+{
+	print '<tr class="liste_total">';
+	$i=0;
+	while ($i < $totalarray['nbfield'])
+	{
+		$i++;
+		if (! empty($totalarray['pos'][$i]))  print '<td align="right">'.price($totalarray['val'][$totalarray['pos'][$i]]).'</td>';
+		else
+		{
+			if ($i == 1)
+			{
+				if ($num < $limit) print '<td align="left">'.$langs->trans("Total").'</td>';
+				else print '<td align="left">'.$langs->trans("Totalforthispage").'</td>';
+			}
+			else print '<td></td>';
+		}
+	}
+	print '</tr>';
+}
+
+// If no record found
+if ($num == 0)
+{
+	$colspan=1;
+	foreach($arrayfields as $key => $val) { if (! empty($val['checked'])) $colspan++; }
+	print '<tr><td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
+}
+
 $db->free($resql);
 
 $parameters=array('sql' => $sql);

+ 12 - 2
htdocs/adherents/subscription.php

@@ -121,7 +121,7 @@ if ($action == 'confirm_create_thirdparty' && $confirm == 'yes' && $user->rights
 	{
 		// Creation of thirdparty
 		$company = new Societe($db);
-		$result=$company->create_from_member($object, GETPOST('companyname', 'alpha'), GETPOST('companyalias', 'alpha'));
+		$result=$company->create_from_member($object, GETPOST('companyname', 'alpha'), GETPOST('companyalias', 'alpha'), GETPOST('customercode', 'alpha'));
 
 		if ($result < 0)
 		{
@@ -361,6 +361,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && !
             	$outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang);
             	// Load traductions files requiredby by page
             	$outputlangs->loadLangs(array("main", "members"));
+
             	// Get email content from template
             	$arraydefaultmessage=null;
             	$labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_SUBSCRIPTION;
@@ -654,7 +655,7 @@ if ($rowid > 0)
             print '<div class="tabsAction">';
 
             if ($object->statut > 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$rowid.'&action=addsubscription">'.$langs->trans("AddSubscription")."</a></div>";
-            else print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("AddSubscription").'</a></div>';
+            else print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("AddSubscription").'</a></div>';
 
             print '</div>';
         }
@@ -856,6 +857,15 @@ if ($rowid > 0)
 				array('label' => $langs->trans("NameToCreate"), 'type' => 'text', 'name' => 'companyname', 'value' => $companyname, 'morecss' => 'minwidth300', 'moreattr' => 'maxlength="128"'),
 				array('label' => $langs->trans("AliasNames"), 'type' => 'text', 'name' => 'companyalias', 'value' => $companyalias, 'morecss' => 'minwidth300', 'moreattr' => 'maxlength="128"')
 			);
+			// If customer code was forced to "required", we ask it at creation to avoid error later
+			if (! empty($conf->global->MAIN_COMPANY_CODE_ALWAYS_REQUIRED))
+			{
+				$tmpcompany = new Societe($db);
+				$tmpcompany->name=$companyname;
+				$customercode = $tmpcompany->get_codeclient($tmpcompany,0);
+				$formquestion[]=array('label' => $langs->trans("CustomerCode"), 'type' => 'text', 'name' => 'customercode', 'value' => $customercode, 'morecss' => 'minwidth300', 'moreattr' => 'maxlength="128"');
+			}
+			// @TODO Add other extrafields mandatory for thirdparty creation
 
 			print $form->formconfirm($_SERVER["PHP_SELF"]."?rowid=".$object->id,$langs->trans("CreateDolibarrThirdParty"),$langs->trans("ConfirmCreateThirdParty"),"confirm_create_thirdparty",$formquestion,1);
 		}

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

@@ -191,7 +191,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'edit')
 
 	dol_fiche_head($head, 'general', $langs->trans("Subscription"), 0, 'payment');
 
-    $linkback = '<a href="'.DOL_URL_ROOT.'/adherents/subscription/list.php">'.$langs->trans("BackToList").'</a>';
+    $linkback = '<a href="'.DOL_URL_ROOT.'/adherents/subscription/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
 
     print "\n";
 	print '<table class="border" width="100%">';
@@ -290,7 +290,7 @@ if ($rowid && $action != 'edit')
     print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
     print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 
-    $linkback = '<a href="'.DOL_URL_ROOT.'/adherents/subscription/list.php">'.$langs->trans("BackToList").'</a>';
+    $linkback = '<a href="'.DOL_URL_ROOT.'/adherents/subscription/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
 
     dol_banner_tab($object, 'rowid', $linkback, 1);
 
@@ -368,7 +368,7 @@ if ($rowid && $action != 'edit')
 		}
 		else
 		{
-			print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.$langs->trans("BankLineConciliated")."\" href=\"#\">".$langs->trans("Modify")."</a></div>";
+			print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.$langs->trans("BankLineConciliated")."\" href=\"#\">".$langs->trans("Modify")."</a></div>";
 		}
 	}
 

+ 397 - 185
htdocs/adherents/subscription/list.php

@@ -28,12 +28,18 @@ require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
 require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
 
-$langs->load("members");
+$langs->load(array("members","companies"));
 
-$filter=$_GET["filter"];
-$statut=isset($_GET["statut"])?$_GET["statut"]:1;
+$action=GETPOST('action','aZ09');
+$massaction=GETPOST('massaction','alpha');
+$confirm=GETPOST('confirm','alpha');
+$toselect = GETPOST('toselect', 'array');
+
+$filter=GETPOST("filter","alpha");
+$statut=(GETPOSTISSET("statut")?GETPOST("statut","alpha"):1);
 $search_ref=GETPOST('search_ref','alpha');
 $search_lastname=GETPOST('search_lastname','alpha');
+$search_firstname=GETPOST('search_firstname','alpha');
 $search_login=GETPOST('search_login','alpha');
 $search_note=GETPOST('search_note','alpha');
 $search_account=GETPOST('search_account','int');
@@ -67,6 +73,20 @@ $search_array_options=$extrafields->getOptionalsFromPost($object->table_element,
 $fieldstosearchall = array(
 );
 $arrayfields=array(
+	'd.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1),
+	'd.lastname'=>array('label'=>$langs->trans("Lastname"), 'checked'=>1),
+	'd.firstname'=>array('label'=>$langs->trans("Firstname"), 'checked'=>1),
+	'd.login'=>array('label'=>$langs->trans("Login"), 'checked'=>1),
+	't.libelle'=>array('label'=>$langs->trans("Type"), 'checked'=>1),
+	'd.bank'=>array('label'=>$langs->trans("BankAccount"), 'checked'=>1, 'enabled'=>(! empty($conf->banque->enabled))),
+	/*'d.note_public'=>array('label'=>$langs->trans("NotePublic"), 'checked'=>0),
+	 'd.note_private'=>array('label'=>$langs->trans("NotePrivate"), 'checked'=>0),*/
+	'd.datedebut'=>array('label'=>$langs->trans("DateSubscription"), 'checked'=>1, 'position'=>100),
+	'd.datefin'=>array('label'=>$langs->trans("EndSubscription"), 'checked'=>1, 'position'=>101),
+	'd.amount'=>array('label'=>$langs->trans("Amount"), 'checked'=>1, 'position'=>102),
+	'd.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500),
+	'd.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500),
+//	'd.statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000)
 );
 
 // Security check
@@ -74,7 +94,7 @@ $result=restrictedArea($user,'adherent','','','cotisation');
 
 
 /*
- *	Actions
+ * Actions
  */
 
 if (GETPOST('cancel','alpha')) { $action='list'; $massaction=''; }
@@ -111,15 +131,16 @@ if (empty($reshook))
  */
 
 $form=new Form($db);
+$subscription=new Subscription($db);
+$adherent=new Adherent($db);
+$accountstatic=new Account($db);
 
-llxHeader('',$langs->trans("ListOfSubscriptions"),'EN:Module_Foundations|FR:Module_Adh&eacute;rents|ES:M&oacute;dulo_Miembros');
-
+$now=dol_now();
 
 // List of subscriptions
 $sql = "SELECT d.rowid, d.login, d.firstname, d.lastname, d.societe, d.photo,";
 $sql.= " c.rowid as crowid, c.subscription,";
-$sql.= " c.dateadh,";
-$sql.= " c.datef,";
+$sql.= " c.dateadh, c.datef, c.datec as date_creation, c.tms as date_update,";
 $sql.= " c.fk_bank as bank, c.note,";
 $sql.= " b.fk_account";
 $sql.= " FROM ".MAIN_DB_PREFIX."adherent as d, ".MAIN_DB_PREFIX."subscription as c";
@@ -136,253 +157,444 @@ if ($search_ref)
 	if (is_numeric($search_ref)) $sql.= " AND (c.rowid = ".$db->escape($search_ref).")";
 	else $sql.=" AND 1 = 2";    // Always wrong
 }
-if ($search_lastname) $sql.= natural_search(array('d.firstname','d.lastname','d.societe'), $search_lastname);
-if ($search_login) $sql.= natural_search('c.subscription', $search_login);
+if ($search_lastname) $sql.= natural_search(array('d.lastname','d.societe'), $search_lastname);
+if ($search_firstname) $sql.= natural_search(array('d.firstname'), $search_firstname);
+if ($search_login) $sql.= natural_search('d.login', $search_login);
 if ($search_note)  $sql.= natural_search('c.note', $search_note);
-if ($search_account > 0) $sql.= " AND b.fk_account = ".$search_account;
+if ($search_account > 0) $sql.= " AND b.fk_account = ".urldecode($search_account);
 if ($search_amount) $sql.= natural_search('c.subscription', $search_amount, 1);
+
+// Add where from extra fields
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
+
+// Add where from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+
 $sql.= $db->order($sortfield,$sortorder);
 
+// Count total nb of records with no order and no limits
 $nbtotalofrecords = '';
 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 {
-    $result = $db->query($sql);
-    $nbtotalofrecords = $db->num_rows($result);
+    $resql = $db->query($sql);
+    if ($resql) $nbtotalofrecords = $db->num_rows($resql);
+    else dol_print_error($db);
     if (($page * $limit) > $nbtotalofrecords)	// if total resultset is smaller then paging size (filtering), goto and load page 0
     {
     	$page = 0;
     	$offset = 0;
     }
 }
-
+// Add limit
 $sql.= $db->plimit($limit+1, $offset);
 
 $result = $db->query($sql);
-if ($result)
-{
-    $num = $db->num_rows($result);
-
-	$arrayofselected=is_array($toselect)?$toselect:array();
-
-	$i = 0;
-
-    $title=$langs->trans("ListOfSubscriptions");
-    if (! empty($date_select)) $title.=' ('.$langs->trans("Year").' '.$date_select.')';
-
-    $param='';
-    if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage;
-    if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit;
-    if ($statut != '')    $param.="&statut=".$statut;
-    if ($date_select)     $param.="&date_select=".$date_select;
-    if ($search_lastname) $param.="&search_lastname=".$search_lastname;
-	if ($search_login)    $param.="&search_login=".$search_login;
-	if ($search_acount)   $param.="&search_account=".$search_account;
-	if ($search_amount)   $param.="&search_amount=".$search_amount;
-	if ($optioncss != '') $param.='&optioncss='.$optioncss;
-
-	// List of mass actions available
-	$arrayofmassactions =  array(
-	    //'presend'=>$langs->trans("SendByMail"),
-	    //'builddoc'=>$langs->trans("PDFMerge"),
-	);
-	if ($user->rights->adherent->supprimer) $arrayofmassactions['predelete']=$langs->trans("Delete");
-	if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
-	$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
-
-	$newcardbutton='';
-	if ($user->rights->adherent->cotisation->creer)
-	{
-		$newcardbutton='<a class="butActionNew" href="'.DOL_URL_ROOT.'/adherents/list.php?status=-1,1"><span class="valignmiddle">'.$langs->trans('NewSubscription').'</span>';
-		$newcardbutton.= '<span class="fa fa-plus-circle valignmiddle"></span>';
-		$newcardbutton.= '</a>';
-	}
+if (! $result)
+{
+	dol_print_error($db);
+	exit;
+}
 
-    print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
-    if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
-    print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
-    print '<input type="hidden" name="view" value="'.dol_escape_htmltag($view).'">';
-    print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
-    print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
-    print '<input type="hidden" name="page" value="'.$page.'">';
-    print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
-
-    print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_generic.png', 0, $newcardbutton, '', $limit);
-
-	$topicmail="Information";
-	$modelmail="subscription";
-	$objecttmp=new Subscription($db);
-	$trackid='sub'.$object->id;
-	include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
-
-	if ($sall)
-	{
-		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;
-	}
+$num = $db->num_rows($result);
 
-    $moreforfilter = '';
+$arrayofselected=is_array($toselect)?$toselect:array();
 
-    $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
-    $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
-    if ($massactionbutton) $selectedfields.=$form->showCheckAddButtons('checkforselect', 1);
+if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall)
+{
+	$obj = $db->fetch_object($resql);
+	$id = $obj->rowid;
+	header("Location: ".DOL_URL_ROOT.'/adherents/subscription/card.php?id='.$id);
+	exit;
+}
 
-    print '<div class="div-table-responsive">';
-    print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+llxHeader('',$langs->trans("ListOfSubscriptions"),'EN:Module_Foundations|FR:Module_Adh&eacute;rents|ES:M&oacute;dulo_Miembros');
 
-	// Line for filters fields
-	print '<tr class="liste_titre_filter">';
+$i = 0;
+
+$title=$langs->trans("ListOfSubscriptions");
+if (! empty($date_select)) $title.=' ('.$langs->trans("Year").' '.$date_select.')';
+
+$param='';
+if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage);
+if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit);
+if ($statut != '')    $param.="&statut=".urlencode($statut);
+if ($date_select)     $param.="&date_select=".urlencode($date_select);
+if ($search_lastname) $param.="&search_lastname=".urlencode($search_lastname);
+if ($search_login)    $param.="&search_login=".urlencode($search_login);
+if ($search_acount)   $param.="&search_account=".urlencode($search_account);
+if ($search_amount)   $param.="&search_amount=".urlencode($search_amount);
+if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss);
+// Add $param from extra fields
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
+
+// List of mass actions available
+$arrayofmassactions =  array(
+	//'presend'=>$langs->trans("SendByMail"),
+	//'builddoc'=>$langs->trans("PDFMerge"),
+);
+//if ($user->rights->adherent->supprimer) $arrayofmassactions['predelete']=$langs->trans("Delete");
+if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
+$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
 
+$newcardbutton='';
+if ($user->rights->adherent->cotisation->creer)
+{
+	$newcardbutton='<a class="butActionNew" href="'.DOL_URL_ROOT.'/adherents/list.php?status=-1,1"><span class="valignmiddle">'.$langs->trans('NewSubscription').'</span>';
+	$newcardbutton.= '<span class="fa fa-plus-circle valignmiddle"></span>';
+	$newcardbutton.= '</a>';
+}
+
+print '<form method="POST" 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="formfilteraction" id="formfilteraction" value="list">';
+print '<input type="hidden" name="action" value="list">';
+print '<input type="hidden" name="view" value="'.dol_escape_htmltag($view).'">';
+print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
+print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
+print '<input type="hidden" name="page" value="'.$page.'">';
+print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
+
+print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_generic.png', 0, $newcardbutton, '', $limit);
+
+$topicmail="Information";
+$modelmail="subscription";
+$objecttmp=new Subscription($db);
+$trackid='sub'.$object->id;
+include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
+
+if ($sall)
+{
+	foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val);
+	print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $sall) . join(', ',$fieldstosearchall).'</div>';
+}
+
+$moreforfilter = '';
+
+$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
+$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage);	// This also change content of $arrayfields
+if ($massactionbutton) $selectedfields.=$form->showCheckAddButtons('checkforselect', 1);
+
+print '<div class="div-table-responsive">';
+print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"").'">'."\n";
+
+
+// Line for filters fields
+print '<tr class="liste_titre_filter">';
+
+// Line numbering
+if (! empty($conf->global->MAIN_SHOW_TECHNICAL_ID))
+{
+	print '<td class="liste_titre">&nbsp;</td>';
+}
+
+// Ref
+if (! empty($arrayfields['d.ref']['checked']))
+{
 	print '<td class="liste_titre" align="left">';
 	print '<input class="flat" type="text" name="search_ref" value="'.dol_escape_htmltag($search_ref).'" size="4"></td>';
+}
+
+if (! empty($arrayfields['d.lastname']['checked']))
+{
+	print '<td class="liste_titre" align="left">';
+	print '<input class="flat" type="text" name="search_lastname" value="'.dol_escape_htmltag($search_lastname).'" size="7"></td>';
+}
 
+if (! empty($arrayfields['d.firstname']['checked']))
+{
 	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_lastname" value="'.dol_escape_htmltag($search_lastname).'" size="12"></td>';
+	print '<input class="flat" type="text" name="search_firstname" value="'.dol_escape_htmltag($search_firstname).'" size="12"></td>';
+}
 
+if (! empty($arrayfields['d.login']['checked']))
+{
 	print '<td class="liste_titre" align="left">';
 	print '<input class="flat" type="text" name="search_login" value="'.dol_escape_htmltag($search_login).'" size="7"></td>';
+}
 
-	print '<td class="liste_titre" align="left">';
-	print '<input class="flat" type="text" name="search_note" value="'.dol_escape_htmltag($search_note).'" size="7"></td>';
+if (! empty($arrayfields['t.libelle']['checked']))
+{
+	print '<td class="liste_titre">';
+	print '';
+	print '</td>';
+}
 
-    if (! empty($conf->banque->enabled))
-    {
-		print '<td class="liste_titre">';
-		print $form->select_comptes($search_account, 'search_account', 0, '', 1);
-		print '</td>';
-    }
+if (! empty($arrayfields['d.bank']['checked']))
+{
+	print '<td class="liste_titre">';
+	print $form->select_comptes($search_account, 'search_account', 0, '', 1);
+	print '</td>';
+}
 
+if (! empty($arrayfields['d.date_debut']['checked']))
+{
 	print '<td class="liste_titre">&nbsp;</td>';
+}
 
+if (! empty($arrayfields['d.date_fin']['checked']))
+{
 	print '<td class="liste_titre">&nbsp;</td>';
+}
 
+if (! empty($arrayfields['d.amount']['checked']))
+{
 	print '<td align="right" class="liste_titre">';
 	print '<input class="flat" type="text" name="search_amount" value="'.dol_escape_htmltag($search_amount).'" size="4">';
 	print '</td>';
+}
+// Extra fields
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
+
+// Fields from hook
+$parameters=array('arrayfields'=>$arrayfields);
+$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters);    // Note that $action and $object may have been modified by hook
+print $hookmanager->resPrint;
+// Date creation
+if (! empty($arrayfields['d.datec']['checked']))
+{
+	print '<td class="liste_titre">';
+	print '</td>';
+}
+// Date modification
+if (! empty($arrayfields['d.tms']['checked']))
+{
+	print '<td class="liste_titre">';
+	print '</td>';
+}
 
-    // Action column
-    print '<td class="liste_titre" align="right">';
-    $searchpicto=$form->showFilterButtons();
-    print $searchpicto;
-    print '</td>';
+// Action column
+print '<td class="liste_titre" align="right">';
+$searchpicto=$form->showFilterButtons();
+print $searchpicto;
+print '</td>';
 
-	print "</tr>\n";
+print "</tr>\n";
 
 
-	print '<tr class="liste_titre">';
+print '<tr class="liste_titre">';
+if (! empty($arrayfields['d.ref']['checked']))
+{
 	print_liste_field_titre("Ref",$_SERVER["PHP_SELF"],"c.rowid",$param,"","",$sortfield,$sortorder);
-	print_liste_field_titre("Name",$_SERVER["PHP_SELF"],"d.lastname",$param,"","",$sortfield,$sortorder);
+}
+if (! empty($arrayfields['d.lastname']['checked']))
+{
+	print_liste_field_titre("LastName",$_SERVER["PHP_SELF"],"d.lastname",$param,"","",$sortfield,$sortorder);
+}
+if (! empty($arrayfields['d.firstname']['checked']))
+{
+	print_liste_field_titre("FirstName",$_SERVER["PHP_SELF"],"d.firstname",$param,"","",$sortfield,$sortorder);
+}
+if (! empty($arrayfields['d.login']['checked']))
+{
 	print_liste_field_titre("Login",$_SERVER["PHP_SELF"],"d.login",$param,"","",$sortfield,$sortorder);
+}
+if (! empty($arrayfields['t.libelle']['checked']))
+{
 	print_liste_field_titre("Label",$_SERVER["PHP_SELF"],"c.note",$param,"",'align="left"',$sortfield,$sortorder);
-	if (! empty($conf->banque->enabled))
-	{
-	    print_liste_field_titre("Account",$_SERVER["PHP_SELF"],"b.fk_account",$pram,"","",$sortfield,$sortorder);
-	}
+}
+if (! empty($arrayfields['d.bank']['checked']))
+{
+	print_liste_field_titre("Account",$_SERVER["PHP_SELF"],"b.fk_account",$pram,"","",$sortfield,$sortorder);
+}
+if (! empty($arrayfields['d.date_debut']['checked']))
+{
 	print_liste_field_titre("Date",$_SERVER["PHP_SELF"],"c.dateadh",$param,"",'align="center"',$sortfield,$sortorder);
+}
+if (! empty($arrayfields['d.date_fin']['checked']))
+{
 	print_liste_field_titre("DateEnd",$_SERVER["PHP_SELF"],"c.datef",$param,"",'align="center"',$sortfield,$sortorder);
+}
+if (! empty($arrayfields['d.amount']['checked']))
+{
 	print_liste_field_titre("Amount",$_SERVER["PHP_SELF"],"c.subscription",$param,"",'align="right"',$sortfield,$sortorder);
-	//print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ');
-	print_liste_field_titre('', $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ');
-	print "</tr>\n";
+}
+// Extra fields
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
+
+// Hook fields
+$parameters=array('arrayfields'=>$arrayfields,'param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder);
+$reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters);    // Note that $action and $object may have been modified by hook
+print $hookmanager->resPrint;
+if (! empty($arrayfields['d.datec']['checked']))     print_liste_field_titre($arrayfields['d.datec']['label'],$_SERVER["PHP_SELF"],"d.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+if (! empty($arrayfields['d.tms']['checked']))       print_liste_field_titre($arrayfields['d.tms']['label'],$_SERVER["PHP_SELF"],"d.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder);
+print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ');
+print "</tr>\n";
+
+
+$total=0;
+$totalarray=array();
+while ($i < min($num, $limit))
+{
+	$obj = $db->fetch_object($result);
+	$total+=$obj->subscription;
 
+	$subscription->ref=$obj->crowid;
+	$subscription->id=$obj->crowid;
 
-    // Static objects
-    $subscription=new Subscription($db);
-    $adherent=new Adherent($db);
-    $accountstatic=new Account($db);
+	$adherent->lastname=$obj->lastname;
+	$adherent->firstname=$obj->firstname;
+	$adherent->ref=$obj->rowid;
+	$adherent->id=$obj->rowid;
+	$adherent->statut=$obj->statut;
+	$adherent->login=$obj->login;
+	$adherent->photo=$obj->photo;
 
-    $total=0;
-    while ($i < min($num, $limit))
-    {
-        $obj = $db->fetch_object($result);
-        $total+=$obj->subscription;
 
-        $subscription->ref=$obj->crowid;
-        $subscription->id=$obj->crowid;
-
-        $adherent->lastname=$obj->lastname;
-        $adherent->firstname=$obj->firstname;
-        $adherent->ref=$obj->rowid;
-        $adherent->id=$obj->rowid;
-        $adherent->statut=$obj->statut;
-        $adherent->login=$obj->login;
-        $adherent->photo=$obj->photo;
+	print '<tr class="oddeven">';
 
+	// Ref
+	if (! empty($arrayfields['d.ref']['checked']))
+	{
+		print '<td>'.$subscription->getNomUrl(1).'</td>';
+		if (! $i) $totalarray['nbfield']++;
+	}
 
+	// Lastname
+	if (! empty($arrayfields['d.lastname']['checked']))
+	{
+		$adherent->firstname = '';
+		print '<td>'.$adherent->getNomUrl(-1).'</td>';
+		$adherent->firstname = $obj->firstname;
+		if (! $i) $totalarray['nbfield']++;
+	}
+	// Firstname
+	if (! empty($arrayfields['d.firstname']['checked']))
+	{
+		print '<td>'.$adherent->firstname.'</td>';
+		if (! $i) $totalarray['nbfield']++;
+	}
 
-        print '<tr class="oddeven">';
+	// Login
+	if (! empty($arrayfields['d.login']['checked']))
+	{
+		print '<td>'.$adherent->login.'</td>';
+		if (! $i) $totalarray['nbfield']++;
+	}
 
-        // Ref
-        print '<td>'.$subscription->getNomUrl(1).'</td>';
+	// Label
+	if (! empty($arrayfields['t.libelle']['checked']))
+	{
+		print '<td>';
+		print dol_trunc($obj->note,128);
+		print '</td>';
+		if (! $i) $totalarray['nbfield']++;
+	}
 
-        // Lastname
-        print '<td>'.$adherent->getNomUrl(-1).'</td>';
+	// Banque
+	if (! empty($arrayfields['d.bank']['checked']))
+	{
+		print "<td>";
+		if ($obj->fk_account > 0)
+		{
+			$accountstatic->id=$obj->fk_account;
+			$accountstatic->fetch($obj->fk_account);
+			//$accountstatic->label=$obj->label;
+			print $accountstatic->getNomUrl(1);
+		}
+		print "</td>\n";
+		if (! $i) $totalarray['nbfield']++;
+	}
 
-        // Login
-        print '<td>'.$adherent->login.'</td>';
+	// Date start
+	if (! empty($arrayfields['d.date_start']['checked']))
+	{
+		print '<td align="center">'.dol_print_date($db->jdate($obj->dateadh),'day')."</td>\n";
+		if (! $i) $totalarray['nbfield']++;
+	}
+	// Date end
+	if (! empty($arrayfields['d.date_end']['checked']))
+	{
+		print '<td align="center">'.dol_print_date($db->jdate($obj->datef),'day')."</td>\n";
+		if (! $i) $totalarray['nbfield']++;
+	}
+	// Price
+	if (! empty($arrayfields['d.amount']['checked']))
+	{
+		print '<td align="right">'.price($obj->subscription).'</td>';
+		if (! $i) $totalarray['nbfield']++;
+		if (! $i) $totalarray['pos'][$totalarray['nbfield']]='d.amount';
+		$totalarray['val']['d.amount'] += $obj->subscription;
+	}
+	// Extra fields
+	include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
+	// Fields from hook
+	$parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj);
+	$reshook=$hookmanager->executeHooks('printFieldListValue',$parameters);    // Note that $action and $object may have been modified by hook
+	print $hookmanager->resPrint;
+	// Date creation
+	if (! empty($arrayfields['d.datec']['checked']))
+	{
+		print '<td align="center" class="nowrap">';
+		print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
+		print '</td>';
+		if (! $i) $totalarray['nbfield']++;
+	}
+	// Date modification
+	if (! empty($arrayfields['d.tms']['checked']))
+	{
+		print '<td align="center" class="nowrap">';
+		print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser');
+		print '</td>';
+		if (! $i) $totalarray['nbfield']++;
+	}
+	// Action column
+	print '<td align="center">';
+	if ($massactionbutton || $massaction)   // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
+	{
+		$selected=0;
+		if (in_array($obj->rowid, $arrayofselected)) $selected=1;
+		print '<input id="cb'.$obj->rowid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->rowid.'"'.($selected?' checked="checked"':'').'>';
+	}
+	print '</td>';
+	if (! $i) $totalarray['nbfield']++;
 
-        // Libelle
-        print '<td>';
-        print dol_trunc($obj->note,32);
-        print '</td>';
+	print "</tr>\n";
+	$i++;
+}
 
-		// Banque
-		if (! empty($conf->banque->enabled))
+// Show total line
+if (isset($totalarray['pos']))
+{
+	print '<tr class="liste_total">';
+	$i=0;
+	while ($i < $totalarray['nbfield'])
+	{
+		$i++;
+		if (! empty($totalarray['pos'][$i]))  print '<td align="right">'.price($totalarray['val'][$totalarray['pos'][$i]]).'</td>';
+		else
 		{
-			if ($obj->fk_account > 0)
-			{
-				$accountstatic->id=$obj->fk_account;
-				$accountstatic->fetch($obj->fk_account);
-				//$accountstatic->label=$obj->label;
-				print '<td>'.$accountstatic->getNomUrl(1).'</td>';
-			}
-			else
+			if ($i == 1)
 			{
-				print "<td>";
-				print "</td>\n";
+				if ($num < $limit) print '<td align="left">'.$langs->trans("Total").'</td>';
+				else print '<td align="left">'.$langs->trans("Totalforthispage").'</td>';
 			}
+			else print '<td></td>';
 		}
+	}
+	print '</tr>';
+}
 
-        // Date start
-        print '<td align="center">'.dol_print_date($db->jdate($obj->dateadh),'day')."</td>\n";
-
-        // Date end
-        print '<td align="center">'.dol_print_date($db->jdate($obj->datef),'day')."</td>\n";
-
-        // Price
-        print '<td align="right">'.price($obj->subscription).'</td>';
-
-        print '<td></td>';
-
-        print "</tr>";
+// If no record found
+if ($num == 0)
+{
+	$colspan=1;
+	foreach($arrayfields as $key => $val) { if (! empty($val['checked'])) $colspan++; }
+	print '<tr><td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
+}
 
-        $i++;
-    }
+$db->free($resql);
 
-    // Total
+$parameters=array('sql' => $sql);
+$reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters);    // Note that $action and $object may have been modified by hook
+print $hookmanager->resPrint;
 
-    print '<tr class="liste_total">';
-    print "<td>".$langs->trans("Total")."</td>\n";
-    print "<td align=\"right\">&nbsp;</td>\n";
-    print "<td align=\"right\">&nbsp;</td>\n";
-    print "<td align=\"right\">&nbsp;</td>\n";
-    if (! empty($conf->banque->enabled))
-    {
-        print '<td>&nbsp;</td>';
-    }
-   	print '<td>&nbsp;</td>';
-   	print '<td>&nbsp;</td>';
-   	print '<td align="right">'.price($total)."</td>\n";
-   	print '<td></td>';
-    print "</tr>\n";
+print "</table>";
+print '</div>';
+print '</form>';
 
-    print "</table>";
-    print '</div>';
-	print '</form>';
-}
-else
-{
-    dol_print_error($db);
-}
 
 // End of page
 llxFooter();

+ 3 - 3
htdocs/adherents/type.php

@@ -42,7 +42,7 @@ $backtopage = GETPOST('backtopage','alpha');
 $search_lastname	= GETPOST('search_lastname','alpha');
 $search_login		= GETPOST('search_login','alpha');
 $search_email		= GETPOST('search_email','alpha');
-$type				= GETPOST('type','alpha');
+$type				= GETPOST('type','intcomma');
 $status				= GETPOST('status','alpha');
 
 $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit;
@@ -59,8 +59,8 @@ if (! $sortfield) {  $sortfield="d.lastname"; }
 $label=GETPOST("label","alpha");
 $subscription=GETPOST("subscription","int");
 $vote=GETPOST("vote","int");
-$comment=GETPOST("comment");
-$mail_valid=GETPOST("mail_valid");
+$comment=GETPOST("comment",'alphanohtml');
+$mail_valid=GETPOST("mail_valid",'none');
 
 // Security check
 $result=restrictedArea($user,'adherent',$rowid,'adherent_type');

+ 1 - 1
htdocs/admin/bank.php

@@ -397,7 +397,7 @@ print '<br><br>';
  */
 //if (! empty($conf->global->MAIN_FEATURES_LEVEL))
 //{
-print load_fiche_titre($langs->trans("BankAccountReleveModule"), '', '');
+print load_fiche_titre($langs->trans("Other"), '', '');
 
 
 print "<table class=\"noborder\" width=\"100%\">\n";

+ 46 - 17
htdocs/admin/barcode.php

@@ -63,7 +63,7 @@ if ($action == 'setcoder')
 	$resql=$db->query($sqlp);
 	if (! $resql) dol_print_error($db);
 }
-else if ($action == 'update')
+elseif ($action == 'update')
 {
 	$location = GETPOST('GENBARCODE_LOCATION','alpha');
 	$res = dolibarr_set_const($db, "GENBARCODE_LOCATION",$location,'chaine',0,'',$conf->entity);
@@ -71,17 +71,8 @@ else if ($action == 'update')
 	$res = dolibarr_set_const($db, "PRODUIT_DEFAULT_BARCODE_TYPE", $coder_id,'chaine',0,'',$conf->entity);
 	$coder_id = GETPOST('GENBARCODE_BARCODETYPE_THIRDPARTY','alpha');
 	$res = dolibarr_set_const($db, "GENBARCODE_BARCODETYPE_THIRDPARTY", $coder_id,'chaine',0,'',$conf->entity);
-}
-else if ($action == 'updateengine')
-{
-    // TODO Update engines.
-}
-
-if ($action && $action != 'setcoder' && $action != 'setModuleOptions')
-{
-	if (! $res > 0) $error++;
 
- 	if (! $error)
+	if ($res > 0)
     {
         setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
     }
@@ -90,6 +81,42 @@ if ($action && $action != 'setcoder' && $action != 'setModuleOptions')
         setEventMessages($langs->trans("Error"), null, 'errors');
     }
 }
+elseif ($action == 'updateengine')
+{
+    $sql = "SELECT rowid, coder";
+    $sql.= " FROM ".MAIN_DB_PREFIX."c_barcode_type";
+    $sql.= " WHERE entity = ".$conf->entity;
+    $sql.= " ORDER BY code";
+
+    $resql=$db->query($sql);
+    if ($resql)
+    {
+	   $num = $db->num_rows($resql);
+	   $i = 0;
+
+	   while ($i <	$num)
+	   {
+	       $obj = $db->fetch_object($resql);
+
+	       if (GETPOST('coder'.$obj->rowid, 'alpha'))
+	       {
+	           $coder = GETPOST('coder'.$obj->rowid,'alpha');
+	           $code_id = $obj->rowid;
+
+	           $sqlp = "UPDATE ".MAIN_DB_PREFIX."c_barcode_type";
+	           $sqlp.= " SET coder = '" . $coder."'";
+	           $sqlp.= " WHERE rowid = ". $code_id;
+	           $sqlp.= " AND entity = ".$conf->entity;
+
+	           $upsql=$db->query($sqlp);
+	           if (! $upsql) dol_print_error($db);
+	       }
+
+	       $i++;
+	   }
+    }
+}
+
 
 /*
  * View
@@ -161,9 +188,12 @@ foreach($dirbarcode as $reldir)
 print '<br>';
 print load_fiche_titre($langs->trans("BarcodeEncodeModule"),'','');
 
-//print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
-//print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-//print "<input type=\"hidden\" name=\"action\" value=\"updateengine\">";
+if (empty($conf->use_javascript_ajax))
+{
+    print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" id="form_engine">';
+    print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+    print '<input type="hidden" name="action" value="updateengine">';
+}
 
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
@@ -258,10 +288,9 @@ print "</table>\n";
 
 if (empty($conf->use_javascript_ajax))
 {
-    // TODO Implement code behind action updateengine
-    //print '<div class="center"><input type="submit" class="button" name="save" value="'.$langs->trans("Save").'"></div>';
+    print '<div class="center"><input type="submit" class="button" name="save" value="'.$langs->trans("Save").'"></div>';
+    print '</form>';
 }
-//print '</form>';
 
 print "<br>";
 

+ 127 - 0
htdocs/admin/commande_fournisseur_dispatch_extrafields.php

@@ -0,0 +1,127 @@
+<?php
+/* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
+ * Copyright (C) 2003		Jean-Louis Bergamo		<jlb@j1b.org>
+ * Copyright (C) 2004-2013	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2012		Regis Houssin			<regis.houssin@capnetworks.com>
+ * Copyright (C) 2012		Florian Henry			<florian.henry@open-concept.pro>
+ * Copyright (C) 2013		Philippe Grand			<philippe.grand@atoo-net.com>
+ * Copyright (C) 2013		Florian Henry			<florian.henry@open-concept.pro>
+ * Copyright (C) 2015		Claudio Aschieri		<c.aschieri@19.coop>
+ * Copyright (C) 2018	   Quentin Vial-Gouteyron   <quentin.vial-gouteyron@atm-consulting.fr>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ *      \file       htdocs/admin/commandefournisseurdispatch_extrafields.php
+ *		\ingroup    reception
+ *		\brief      Page to setup extra fields of reception
+ */
+
+require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+
+
+if (!$user->admin)
+	accessforbidden();
+
+$langs->load("admin");
+$langs->load("other");
+$langs->load("receptions");
+
+$extrafields = new ExtraFields($db);
+$form = new Form($db);
+
+// List of supported format
+$tmptype2label=ExtraFields::$type2label;
+$type2label=array('');
+foreach ($tmptype2label as $key => $val) $type2label[$key]=$langs->trans($val);
+
+$action=GETPOST('action', 'alpha');
+$attrname=GETPOST('attrname', 'alpha');
+$elementtype='commande_fournisseur_dispatch'; //Must be the $table_element of the class that manage extrafield
+
+if (!$user->admin) accessforbidden();
+
+
+/*
+ * Actions
+ */
+
+require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php';
+
+
+
+/*
+ * View
+ */
+
+$textobject=$langs->transnoentitiesnoconv("Receptions");
+
+llxHeader('',$langs->trans("ReceptionsSetup"));
+
+$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+print load_fiche_titre($langs->trans("ReceptionsSetup"),$linkback,'title_setup');
+print "<br>\n";
+
+$head = reception_admin_prepare_head();
+
+dol_fiche_head($head, 'attributeslines_reception', $langs->trans("Receptions"), -1, 'sending');
+
+require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
+
+dol_fiche_end();
+
+
+// Buttons
+if ($action != 'create' && $action != 'edit')
+{
+    print '<div class="tabsAction">';
+    print "<a class=\"butAction\" href=\"".$_SERVER["PHP_SELF"]."?action=create\">".$langs->trans("NewAttribute")."</a>";
+    print "</div>";
+}
+
+
+/* ************************************************************************** */
+/*                                                                            */
+/* Creation of an optional field											  */
+/*                                                                            */
+/* ************************************************************************** */
+
+if ($action == 'create')
+{
+    print "<br>";
+    print load_fiche_titre($langs->trans('NewAttribute'));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php';
+}
+
+/* ************************************************************************** */
+/*                                                                            */
+/* Edition of an optional field                                               */
+/*                                                                            */
+/* ************************************************************************** */
+if ($action == 'edit' && ! empty($attrname))
+{
+    print "<br>";
+    print load_fiche_titre($langs->trans("FieldEdition", $attrname));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php';
+}
+
+llxFooter();
+
+$db->close();

+ 20 - 2
htdocs/admin/dav.php

@@ -83,7 +83,16 @@ if ($action == 'edit')
 
 		print '<tr class="oddeven"><td>';
 		print $form->textwithpicto($langs->trans($key), $langs->trans($key.'Tooltip'));
-		print '</td><td><input name="'.$key.'"  class="flat '.(empty($val['css'])?'minwidth200':$val['css']).'" value="' . $conf->global->$key . '"></td></tr>';
+		print '</td><td>';
+		if ($key == 'DAV_ALLOW_PUBLIC_DIR' || $key == 'DAV_ALLOW_ECM_DIR')
+		{
+			print $form->selectyesno($key, $conf->global->$key, 1);
+		}
+		else
+		{
+			print '<input name="'.$key.'"  class="flat '.(empty($val['css'])?'minwidth200':$val['css']).'" value="' . $conf->global->$key . '">';
+		}
+		print '</td></tr>';
 	}
 
 	print '</table>';
@@ -104,7 +113,16 @@ else
 	{
 		print '<tr class="oddeven"><td>';
 		print $form->textwithpicto($langs->trans($key),$langs->trans($key.'Tooltip'));
-		print '</td><td>' . $conf->global->$key . '</td></tr>';
+		print '</td><td>';
+		if ($key == 'DAV_ALLOW_PUBLIC_DIR' || $key == 'DAV_ALLOW_ECM_DIR')
+		{
+			print yn($conf->global->$key);
+		}
+		else
+		{
+			print $conf->global->$key;
+		}
+		print '</td></tr>';
 	}
 
 	print '</table>';

+ 7 - 4
htdocs/admin/defaultvalues.php

@@ -250,7 +250,7 @@ print '<tr class="liste_titre">';
 // Page
 $texthelp=$langs->trans("PageUrlForDefaultValues");
 if ($mode == 'createform') $texthelp.=$langs->trans("PageUrlForDefaultValuesCreate", 'societe/card.php', 'societe/card.php?abc=val1&def=val2');
-else $texthelp.=$langs->trans("PageUrlForDefaultValuesList", 'societe/list.php', 'societe/card.php?abc=val1&def=val2');
+else $texthelp.=$langs->trans("PageUrlForDefaultValuesList", 'societe/list.php', 'societe/list.php?abc=val1&def=val2');
 $texturl=$form->textwithpicto($langs->trans("Url"), $texthelp);
 print_liste_field_titre($texturl,$_SERVER["PHP_SELF"],'page,param','',$param,'',$sortfield,$sortorder);
 // Field
@@ -288,8 +288,9 @@ if ($mode != 'focus' && $mode != 'mandatory')
 }
 // Entity
 if (! empty($conf->multicompany->enabled) && !$user->entity) print_liste_field_titre("Entity",$_SERVER["PHP_SELF"],'entity,page','',$param,'',$sortfield,$sortorder);
+else print_liste_field_titre("",$_SERVER["PHP_SELF"],'','',$param,'',$sortfield,$sortorder);
 // Actions
-print '<td align="center"></td>';
+print_liste_field_titre("",$_SERVER["PHP_SELF"],'','',$param,'',$sortfield,$sortorder);
 print "</tr>\n";
 
 
@@ -382,8 +383,10 @@ if ($result)
     		print '</td>';
 		}
 
-		// Multicompany
-		print '<td></td>';
+		if (! empty($conf->multicompany->enabled) && !$user->entity)
+		{
+		    print '<td></td>';
+		}
 
 		// Actions
 		print '<td align="center">';

+ 1 - 1
htdocs/admin/dict.php

@@ -423,7 +423,7 @@ $tabcond[14]= (! empty($conf->product->enabled) && (! empty($conf->ecotax->enabl
 $tabcond[15]= true;
 $tabcond[16]= (! empty($conf->societe->enabled) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS));
 $tabcond[17]= (! empty($conf->deplacement->enabled) || ! empty($conf->expensereport->enabled));
-$tabcond[18]= ! empty($conf->expedition->enabled);
+$tabcond[18]= ! empty($conf->expedition->enabled) || ! empty($conf->reception->enabled);
 $tabcond[19]= ! empty($conf->societe->enabled);
 $tabcond[20]= ! empty($conf->fournisseur->enabled);
 $tabcond[21]= ! empty($conf->propal->enabled);

+ 49 - 9
htdocs/admin/emailcollector_card.php

@@ -141,9 +141,11 @@ if (GETPOST('addoperation','alpha'))
 {
 	$emailcollectoroperation = new EmailCollectorAction($db);
 	$emailcollectoroperation->type = GETPOST('operationtype','az09');
-	$emailcollectoroperation->actionparam = GETPOST('actionparam', 'alpha');
+	$emailcollectoroperation->actionparam = GETPOST('operationparam', 'none');
 	$emailcollectoroperation->fk_emailcollector = $object->id;
 	$emailcollectoroperation->status = 1;
+	$emailcollectoroperation->position = 50;
+
 	$result = $emailcollectoroperation->create($user);
 
 	if ($result > 0)
@@ -378,11 +380,24 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 	$sourcedir = $object->source_directory;
 	$targetdir = ($object->target_directory ? $object->target_directory : '');			// Can be '[Gmail]/Trash' or 'mytag'
 
-	$connectstringserver = $object->getConnectStringIMAP();
-	$connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir);
-	$connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir);
+	$connection = null;
+	$connectstringserver = '';
+	$connectstringsource = '';
+	$connectstringtarget = '';
+
+	if (function_exists('imap_open'))
+	{
+		$connectstringserver = $object->getConnectStringIMAP();
+		$connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir);
+		$connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir);
+
+		$connection = imap_open($connectstringsource, $object->user, $object->password);
+	}
+	else
+	{
+		$morehtml .= 'IMAP functions not available on your PHP';
+	}
 
-	$connection = imap_open($connectstringsource, $object->user, $object->password);
 	if (! $connection)
 	{
 		$morehtml .= 'Failed to open IMAP connection '.$connectstringsource;
@@ -393,7 +408,10 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 		$morehtml .= imap_num_msg($connection);
 	}
 
-	imap_close($connection);
+	if ($connection)
+	{
+		imap_close($connection);
+	}
 
 	dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref.'<div class="refidno">'.$morehtml.'</div>', '', 0, '', '', 0, '');
 
@@ -457,9 +475,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 	print '<div class="clearboth"></div><br>';
 
 	// Operations
-	print '<table class="border centpercent">';
+	print '<table id="tablelines" class="noborder noshadow">';
 	print '<tr class="liste_titre">';
-	print '<td>'.$langs->trans("EmailcollectorOperations").'</td><td></td><td></td>';
+	print '<td>'.$langs->trans("EmailcollectorOperations").'</td><td></td><td></td><td></td>';
 	print '</tr>';
 	// Add operation
 	print '<tr class="oddeven">';
@@ -469,16 +487,24 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 	print $form->selectarray('operationtype', $arrayoftypes, '', 1, 0, 0, '', 1);
 	print '</td><td>';
 	print '<input type="text" name="operationparam">';
+	$htmltext=$langs->transnoentitiesnoconv("OperationParamDesc");
+	//var_dump($htmltext);
+	print $form->textwithpicto('', $htmltext);
 	print '</td>';
+	print '<td></td>';
 	print '<td align="right"><input type="submit" name="addoperation" id="addoperation" class="flat button" value="'.$langs->trans("Add").'"></td>';
 	print '</tr>';
 	// List operations
+	$nboflines = count($object->actions);
+	$table_element_line = 'emailcollector_emailcollectoraction';
+	$fk_element='position';
+	$i=0;
 	foreach($object->actions as $ruleaction)
 	{
 		$ruleactionobj=new EmailcollectorAction($db);
 		$ruleactionobj->fetch($ruleaction['id']);
 
-		print '<tr class="oddeven">';
+		print '<tr class="drag drop oddeven" id="row-'.$ruleaction['id'].'">';
 		print '<td>';
 		print $langs->trans($arrayoftypes[$ruleaction['type']]);
 		print '</td>';
@@ -487,12 +513,26 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 		//print $ruleactionobj->getLibStatut(3);
 		print ' <a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deleteoperation&operationid='.$ruleaction['id'].'">'.img_delete().'</a>';
 		print '</td>';
+		print '<td class="center linecolmove tdlineupdown">';
+		if ($i > 0)
+		{
+			print '<a class="lineupdown" href="'.$_SERVER['PHP_SELF'].'?action=up&amp;rowid='.$ruleaction['id'].'">'.img_up('default', 0, 'imgupforline').'</a>';
+		}
+		if ($i < count($object->actions)-1) {
+			print '<a class="lineupdown" href="'.$_SERVER['PHP_SELF'].'?action=down&amp;rowid='.$ruleaction['id'].'">'.img_down('default', 0, 'imgdownforline').'</a>';
+		}
+		print '</td>';
 		print '</tr>';
+		$i++;
 	}
 
 	print '</tr>';
 	print '</table>';
 
+	if (! empty($conf->use_javascript_ajax)) {
+		include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
+	}
+
 	print '</form>';
 
 	print '</div>';

+ 52 - 42
htdocs/admin/emailcollector_list.php

@@ -120,8 +120,6 @@ $arrayfields = dol_sort_array($arrayfields, 'position');
 
 /*
  * Actions
- *
- * Put here all code to do according to value of "$action" parameter
  */
 
 if (GETPOST('cancel','alpha')) { $action='list'; $massaction=''; }
@@ -165,8 +163,6 @@ if (empty($reshook))
 
 /*
  * View
- *
- * Put here all code to render page
  */
 
 $form=new Form($db);
@@ -212,20 +208,20 @@ $reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters, $object)
 $sql.=$hookmanager->resPrint;
 
 /* If a group by is required
- $sql.= " GROUP BY "
- foreach($object->fields as $key => $val)
- {
- $sql.='t.'.$key.', ';
- }
- // Add fields from extrafields
- if (! empty($extrafields->attributes[$object->table_element]['label'])) {
- foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
- // Add where from hooks
- $parameters=array();
- $reshook=$hookmanager->executeHooks('printFieldListGroupBy',$parameters);    // Note that $action and $object may have been modified by hook
- $sql.=$hookmanager->resPrint;
- $sql=preg_replace('/, $/','', $sql);
- */
+$sql.= " GROUP BY "
+foreach($object->fields as $key => $val)
+{
+	$sql.='t.'.$key.', ';
+}
+// Add fields from extrafields
+if (! empty($extrafields->attributes[$object->table_element]['label'])) {
+	foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
+// Add where from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListGroupBy',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+$sql=preg_replace('/, $/','', $sql);
+*/
 
 $sql.=$db->order($sortfield,$sortorder);
 
@@ -305,8 +301,8 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
 
 // List of mass actions available
 $arrayofmassactions =  array(
-//'presend'=>$langs->trans("SendByMail"),
-//'builddoc'=>$langs->trans("PDFMerge"),
+	//'presend'=>$langs->trans("SendByMail"),
+	//'builddoc'=>$langs->trans("PDFMerge"),
 );
 if ($user->rights->emailcollector->delete) $arrayofmassactions['predelete']=$langs->trans("Delete");
 if (GETPOST('nomassaction','int') || in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
@@ -324,7 +320,7 @@ print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
 
 $newcardbutton='';
 //if ($user->rights->emailcollector->creer)
-	//{
+//{
 $newcardbutton='<a class="butActionNew" href="emailcollector_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']).'"><span class="valignmiddle">'.$langs->trans('New').'</span>';
 $newcardbutton.= '<span class="fa fa-plus-circle valignmiddle"></span>';
 $newcardbutton.= '</a>';
@@ -333,6 +329,10 @@ $newcardbutton.= '</a>';
 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_companies', 0, $newcardbutton, '', $limit);
 
 // Add code for pre mass action (confirmation or email presend form)
+/*$topicmail="";
+$modelmail="";
+$objecttmp=new EmailCollector($db);
+$trackid='xxxx'.$object->id;*/
 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
 
 if ($sall)
@@ -343,8 +343,8 @@ if ($sall)
 
 $moreforfilter = '';
 /*$moreforfilter.='<div class="divsearchfield">';
- $moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
- $moreforfilter.= '</div>';*/
+$moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
+$moreforfilter.= '</div>';*/
 
 $parameters=array();
 $reshook=$hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object);    // Note that $action and $object may have been modified by hook
@@ -371,11 +371,11 @@ print '<table class="tagtable liste'.($moreforfilter?" listwithfilterbefore":"")
 print '<tr class="liste_titre">';
 foreach($object->fields as $key => $val)
 {
-	$align='';
-	if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center';
-	if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap';
-	if ($key == 'status') $align.=($align?' ':'').'center';
-	if (! empty($arrayfields['t.'.$key]['checked'])) print '<td class="liste_titre'.($align?' '.$align:'').'"><input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag($search[$key]).'"></td>';
+    $cssforfield='';
+    if (in_array($val['type'], array('date','datetime','timestamp'))) $cssforfield.=($cssforfield?' ':'').'center';
+    if (in_array($val['type'], array('timestamp'))) $cssforfield.=($cssforfield?' ':'').'nowrap';
+    if ($key == 'status') $cssforfield.=($cssforfield?' ':'').'center';
+    if (! empty($arrayfields['t.'.$key]['checked'])) print '<td class="liste_titre'.($cssforfield?' '.$cssforfield:'').'"><input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag($search[$key]).'"></td>';
 }
 // Extra fields
 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
@@ -397,11 +397,14 @@ print '</tr>'."\n";
 print '<tr class="liste_titre">';
 foreach($object->fields as $key => $val)
 {
-	$align='';
-	if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center';
-	if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap';
-	if ($key == 'status') $align.=($align?' ':'').'center';
-	if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n";
+    $cssforfield='';
+    if (in_array($val['type'], array('date','datetime','timestamp'))) $cssforfield.=($cssforfield?' ':'').'center';
+    if (in_array($val['type'], array('timestamp'))) $cssforfield.=($cssforfield?' ':'').'nowrap';
+    if ($key == 'status') $cssforfield.=($cssforfield?' ':'').'center';
+    if (! empty($arrayfields['t.'.$key]['checked']))
+    {
+        print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield?'class="'.$cssforfield.'"':''), $sortfield, $sortorder, ($cssforfield?$cssforfield.' ':''))."\n";
+    }
 }
 // Extra fields
 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
@@ -444,15 +447,22 @@ while ($i < min($num, $limit))
 	print '<tr class="oddeven">';
 	foreach($object->fields as $key => $val)
 	{
-		$align='';
-		if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center';
-		if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap';
-		if ($key == 'status') $align.=($align?' ':'').'center';
-		if (! empty($arrayfields['t.'.$key]['checked']))
-		{
-			print '<td';
-			if ($align) print ' class="'.$align.'"';
-			print '>';
+	    $cssforfield='';
+	    if (in_array($val['type'], array('date','datetime','timestamp'))) $cssforfield.=($cssforfield?' ':'').'center';
+	    elseif ($key == 'status') $cssforfield.=($cssforfield?' ':'').'center';
+	    
+	    if (in_array($val['type'], array('timestamp'))) $cssforfield.=($cssforfield?' ':'').'nowrap';
+	    elseif ($key == 'ref') $cssforfield.=($cssforfield?' ':'').'nowrap';
+	    
+	    if (! empty($arrayfields['t.'.$key]['checked']))
+	    {
+	        print '<td';
+	        if ($cssforfield || $val['css']) print ' class="';
+	        print $cssforfield;
+	        if ($cssforfield && $val['css']) print ' ';
+	        print $val['css'];
+	        if ($cssforfield || $val['css']) print '"';
+	        print '>';
 			print $object->showOutputField($val, $key, $obj->$key, '');
 			print '</td>';
 			if (! $i) $totalarray['nbfield']++;

+ 1 - 1
htdocs/admin/events.php

@@ -74,7 +74,7 @@ llxHeader('',$langs->trans("Audit"),$wikihelp);
 //$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
 print load_fiche_titre($langs->trans("SecuritySetup"),'','title_setup');
 
-print $langs->trans("LogEventDesc")."<br>\n";
+print $langs->trans("LogEventDesc", $langs->transnoentitiesnoconv("AdminTools"), $langs->transnoentitiesnoconv("Audit"))."<br>\n";
 print "<br>\n";
 
 

+ 1 - 1
htdocs/admin/export.php

@@ -57,7 +57,7 @@ llxHeader('', $langs->trans($page_name));
 // Subheader
 $linkback = '<a href="' . DOL_URL_ROOT . '/admin/modules.php">'
     . $langs->trans("BackToModuleList") . '</a>';
-print_fiche_titre($langs->trans($page_name), $linkback);
+print load_fiche_titre($langs->trans($page_name), $linkback);
 
 // Configuration header
 

+ 7 - 7
htdocs/admin/facture.php

@@ -241,17 +241,17 @@ if ($action == 'setforcedate')
 if ($action == 'setDefaultPDFModulesByType')
 {
     $invoicetypemodels =  GETPOST('invoicetypemodels');
-    
+
     if(!empty($invoicetypemodels) && is_array($invoicetypemodels))
     {
         $error = 0;
-        
+
         foreach ($invoicetypemodels as $type => $value)
         {
             $res = dolibarr_set_const($db, 'FACTURE_ADDON_PDF_'.intval($type),$value,'chaine',0,'',$conf->entity);
             if (! $res > 0) $error++;
         }
-        
+
         if (! $error)
         {
             setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
@@ -621,7 +621,7 @@ if(!empty($conf->global->INVOICE_USE_DEFAULT_DOCUMENT)) // Hidden conf
     print '<td>'.$langs->trans("Name").'</td>';
     print '<td align="right"><input type="submit" class="button" value="'.$langs->trans("Modify").'"></td>';
     print "</tr>\n";
-    
+
     $listtype=array(
         Facture::TYPE_STANDARD=>$langs->trans("InvoiceStandard"),
         Facture::TYPE_REPLACEMENT=>$langs->trans("InvoiceReplacement"),
@@ -632,7 +632,7 @@ if(!empty($conf->global->INVOICE_USE_DEFAULT_DOCUMENT)) // Hidden conf
     {
         $listtype[Facture::TYPE_SITUATION] = $langs->trans("InvoiceSituation");
     }
-    
+
     foreach ($listtype as $type => $trans)
     {
         $thisTypeConfName = 'FACTURE_ADDON_PDF_'.$type;
@@ -642,7 +642,7 @@ if(!empty($conf->global->INVOICE_USE_DEFAULT_DOCUMENT)) // Hidden conf
         print '<td colspan="2" >'.$form->selectarray('invoicetypemodels['.$type.']', ModelePDFFactures::liste_modeles($db), $current,0,0, 0).'</td>';
         print "</tr>\n";
     }
-    
+
     print '</table>';
     print "</form>";
 }
@@ -698,7 +698,7 @@ if (! empty($conf->banque->enabled))
         }
         else
         {
-        	print "<i>".$langs->trans("NoActiveBankAccountDefined")."</i>";
+        	print '<span class="opacitymedium">'.$langs->trans("NoActiveBankAccountDefined").'</span>';
         }
     }
 }

+ 20 - 0
htdocs/admin/geoipmaxmind.php

@@ -24,6 +24,7 @@
 
 require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeoip.class.php';
 
 // Security check
@@ -150,6 +151,25 @@ if ($geoip)
 	if ($result) print $result;
 	else print $langs->trans("Error");
 	*/
+	//var_dump($_SERVER);
+	$ip = getUserRemoteIP();
+	//$ip='91.161.249.43';
+	$isip=is_ip($ip);
+	if ($isip == 1)
+	{
+		print '<br>'.$ip.' -> ';
+		$result=dol_print_ip($ip,1);
+		if ($result) print $result;
+		else print $langs->trans("Error");
+	}
+	else
+	{
+		print '<br>'.$ip.' -> ';
+		$result=dol_print_ip($ip,1);
+		if ($result) print $result;
+		else print $langs->trans("NotAPublicIp");
+	}
+
 	$geoip->close();
 }
 

+ 1 - 1
htdocs/admin/mails.php

@@ -735,7 +735,7 @@ else
 	}
 	else
 	{
-		print '<a class="butActionRefused" href="#" title="'.$langs->trans("FeatureNotAvailableOnLinux").'">'.$langs->trans("DoTestServerAvailability").'</a>';
+		print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("FeatureNotAvailableOnLinux").'">'.$langs->trans("DoTestServerAvailability").'</a>';
 	}
 
 	print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=test&mode=init#formmailbeforetitle">'.$langs->trans("DoTestSend").'</a>';

+ 1 - 1
htdocs/admin/mails_emailing.php

@@ -509,7 +509,7 @@ else
 		}
 		else
 		{
-			print '<a class="butActionRefused" href="#" title="'.$langs->trans("FeatureNotAvailableOnLinux").'">'.$langs->trans("DoTestServerAvailability").'</a>';
+			print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("FeatureNotAvailableOnLinux").'">'.$langs->trans("DoTestServerAvailability").'</a>';
 		}
 
 		print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=test&amp;mode=init">'.$langs->trans("DoTestSend").'</a>';

+ 63 - 55
htdocs/admin/mails_templates.php

@@ -11,6 +11,7 @@
  * Copyright (C) 2011-2016  Alexandre Spangaro      <aspangaro.dolibarr@gmail.com>
  * Copyright (C) 2015       Ferran Marcet           <fmarcet@2byte.es>
  * Copyright (C) 2016       Raphaël Doursenaud      <rdoursenaud@gpcsolutions.fr>
+ * Copyright (C) 2018       Frédéric France         <frederic.france@netlogic.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
@@ -74,7 +75,7 @@ $offset = $listlimit * $page ;
 $pageprev = $page - 1;
 $pagenext = $page + 1;
 
-if (empty($sortfield)) $sortfield='label, lang, position';
+if (empty($sortfield)) $sortfield='type_template, lang, position, label';
 if (empty($sortorder)) $sortorder='ASC';
 
 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
@@ -84,10 +85,6 @@ $hookmanager->initHooks(array('emailtemplates'));
 $tabname=array();
 $tabname[25]= MAIN_DB_PREFIX."c_email_templates";
 
-// Criteria to sort dictionaries
-$tabsqlsort=array();
-$tabsqlsort[25]="label ASC, lang ASC, position ASC";
-
 // Nom des champs en resultat de select pour affichage du dictionnaire
 $tabfield=array();
 $tabfield[25]= "label,lang,type_template,fk_user,private,position,topic,joinfiles,content";
@@ -160,6 +157,7 @@ if ($conf->propal->enabled)            $elementList['propal_send']=$langs->trans
 if ($conf->commande->enabled)          $elementList['order_send']=$langs->trans('MailToSendOrder');
 if ($conf->facture->enabled)           $elementList['facture_send']=$langs->trans('MailToSendInvoice');
 if ($conf->expedition->enabled)        $elementList['shipping_send']=$langs->trans('MailToSendShipment');
+if ($conf->reception->enabled) 		   $elementList['reception_send']=$langs->trans('MailToSendReception');
 if ($conf->ficheinter->enabled)        $elementList['fichinter_send']=$langs->trans('MailToSendIntervention');
 if ($conf->supplier_proposal->enabled) $elementList['supplier_proposal_send']=$langs->trans('MailToSendSupplierRequestForQuotation');
 if ($conf->fournisseur->enabled)       $elementList['order_supplier_send']=$langs->trans('MailToSendSupplierOrder');
@@ -421,7 +419,7 @@ if ($action == 'delete')
 //var_dump($elementList);
 
 
-$sql="SELECT rowid as rowid, label, type_template, lang, fk_user, private, position, topic, joinfiles, content_lines, content, active";
+$sql="SELECT rowid as rowid, label, type_template, lang, fk_user, private, position, topic, joinfiles, content_lines, content, enabled, active";
 $sql.=" FROM ".MAIN_DB_PREFIX."c_email_templates";
 $sql.=" WHERE entity IN (".getEntity('email_template').")";
 if (! $user->admin)
@@ -447,8 +445,6 @@ $sql.=$db->plimit($listlimit+1,$offset);
 $fieldlist=explode(',',$tabfield[$id]);
 
 // Form to add a new line
-$alabelisused=0;
-
 print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="from" value="'.dol_escape_htmltag(GETPOST('from','alpha')).'">';
@@ -460,38 +456,37 @@ print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
 foreach ($fieldlist as $field => $value)
 {
-        // Determine le nom du champ par rapport aux noms possibles
-        // dans les dictionnaires de donnees
-        $valuetoshow=ucfirst($fieldlist[$field]);   // Par defaut
-        $valuetoshow=$langs->trans($valuetoshow);   // try to translate
-        $align="left";
-        if ($fieldlist[$field]=='fk_user')         { $valuetoshow=$langs->trans("Owner");}
-        if ($fieldlist[$field]=='lang')            { $valuetoshow=(empty($conf->global->MAIN_MULTILANGS) ? '&nbsp;' : $langs->trans("Language")); }
-        if ($fieldlist[$field]=='type')            { $valuetoshow=$langs->trans("Type"); }
-        if ($fieldlist[$field]=='code')            { $valuetoshow=$langs->trans("Code"); }
-        if ($fieldlist[$field]=='libelle' || $fieldlist[$field]=='label') { $valuetoshow=$langs->trans("Code"); }
-        if ($fieldlist[$field]=='type_template')   { $valuetoshow=$langs->trans("TypeOfTemplate"); }
-    	if ($fieldlist[$field]=='private')         { $align='center'; }
-    	if ($fieldlist[$field]=='position')        { $align='center'; }
-
-    	if ($fieldlist[$field]=='topic')           { $valuetoshow=''; }
-    	if ($fieldlist[$field]=='joinfiles')       { $valuetoshow=''; }
-    	if ($fieldlist[$field]=='content')         { $valuetoshow=''; }
-    	if ($fieldlist[$field]=='content_lines')   { $valuetoshow=''; }
-
-        if ($valuetoshow != '')
-        {
-            print '<td align="'.$align.'">';
-        	if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1,$valuetoshow).'</a>';
-        	else if (! empty($tabhelp[$id][$value]))
-        	{
-        	    if (in_array($value, array('topic'))) print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, $value);   // Tooltip on click
-        	    else print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2);                             // Tooltip on hover
-        	}
-        	else print $valuetoshow;
-            print '</td>';
-         }
-         if ($fieldlist[$field]=='libelle' || $fieldlist[$field]=='label') $alabelisused=1;
+	// Determine le nom du champ par rapport aux noms possibles
+	// dans les dictionnaires de donnees
+	$valuetoshow=ucfirst($fieldlist[$field]);   // Par defaut
+	$valuetoshow=$langs->trans($valuetoshow);   // try to translate
+	$align="left";
+	if ($fieldlist[$field]=='fk_user')         { $valuetoshow=$langs->trans("Owner");}
+	if ($fieldlist[$field]=='lang')            { $valuetoshow=(empty($conf->global->MAIN_MULTILANGS) ? '&nbsp;' : $langs->trans("Language")); }
+	if ($fieldlist[$field]=='type')            { $valuetoshow=$langs->trans("Type"); }
+	if ($fieldlist[$field]=='code')            { $valuetoshow=$langs->trans("Code"); }
+	if ($fieldlist[$field]=='libelle' || $fieldlist[$field]=='label') { $valuetoshow=$langs->trans("Code"); }
+	if ($fieldlist[$field]=='type_template')   { $valuetoshow=$langs->trans("TypeOfTemplate"); }
+	if ($fieldlist[$field]=='private')         { $align='center'; }
+	if ($fieldlist[$field]=='position')        { $align='center'; }
+
+	if ($fieldlist[$field]=='topic')           { $valuetoshow=''; }
+	if ($fieldlist[$field]=='joinfiles')       { $valuetoshow=''; }
+	if ($fieldlist[$field]=='content')         { $valuetoshow=''; }
+	if ($fieldlist[$field]=='content_lines')   { $valuetoshow=''; }
+
+	if ($valuetoshow != '')
+	{
+		print '<td align="'.$align.'">';
+		if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1,$valuetoshow).'</a>';
+		else if (! empty($tabhelp[$id][$value]))
+		{
+			if (in_array($value, array('topic'))) print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, $value);   // Tooltip on click
+			else print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2);                             // Tooltip on hover
+		}
+		else print $valuetoshow;
+		print '</td>';
+	}
 }
 print '<td>';
 print '<input type="hidden" name="id" value="' . $id . '">';
@@ -534,6 +529,7 @@ print '<td align="right">';
 print '</td>';
 print "</tr>";
 
+// Show fields for topic, join files and body
 $fieldsforcontent = array('topic', 'joinfiles', 'content');
 if (! empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES)) { $fieldsforcontent = array('content','content_lines'); }
 foreach ($fieldsforcontent as $tmpfieldlist)
@@ -611,10 +607,16 @@ if ($resql)
     $i = 0;
 
     $param = '&id='.$id;
+    if ($search_label)                 $param.= '&search_label='.urlencode($search_label);
+    if ($search_lang > 0)              $param.= '&search_lang='.urlencode($search_lang);
+    if ($search_type_template != '-1') $param.= '&search_type_template='.urlencode($search_type_template);
+    if ($search_fk_user > 0)           $param.= '&search_fk_user='.urlencode($search_fk_user);
+    if ($search_topic)                 $param.= '&search_topic='.urlencode($search_topic);
+
     $paramwithsearch = $param;
-    if ($sortorder) $paramwithsearch.= '&sortorder='.$sortorder;
-    if ($sortfield) $paramwithsearch.= '&sortfield='.$sortfield;
-    if (GETPOST('from')) $paramwithsearch.= '&from='.GETPOST('from','alpha');
+    if ($sortorder) $paramwithsearch.= '&sortorder='.urlencode($sortorder);
+    if ($sortfield) $paramwithsearch.= '&sortfield='.urlencode($sortfield);
+    if (GETPOST('from','alpha')) $paramwithsearch.= '&from='.urlencode(GETPOST('from','alpha'));
 
     // There is several pages
     if ($num > $listlimit)
@@ -630,11 +632,11 @@ if ($resql)
     $filterfound=0;
     foreach ($fieldlist as $field => $value)
     {
-        if ($value == 'label') print '<td class="liste_titre"><input type="text" name="search_label" value="'.dol_escape_htmltag($search_label).'"></td>';
+        if ($value == 'label') print '<td class="liste_titre"><input type="text" name="search_label" class="maxwidth100" value="'.dol_escape_htmltag($search_label).'"></td>';
         elseif ($value == 'lang')
         {
         	print '<td class="liste_titre">';
-        	print $formadmin->select_language($search_lang, 'search_lang', 0, null, 1, 0, 0, 'maxwidth150');
+        	print $formadmin->select_language($search_lang, 'search_lang', 0, null, 1, 0, 0, 'maxwidth100');
         	print '</td>';
         }
         elseif ($value == 'fk_user')
@@ -643,13 +645,13 @@ if ($resql)
         	$restrictid=array();
         	if (! $user->admin) $restrictid=array($user->id);
         	//var_dump($restrictid);
-        	print $form->select_dolusers($search_fk_user, 'search_fk_user', 1, null, 0, 'hierarchyme', null, 0, 0, 1, '', 0, '', 'maxwidth200');
+        	print $form->select_dolusers($search_fk_user, 'search_fk_user', 1, null, 0, 'hierarchyme', null, 0, 0, 1, '', 0, '', 'maxwidth100');
         	print '</td>';
         }
         elseif ($value == 'topic') print '<td class="liste_titre"><input type="text" name="search_topic" value="'.dol_escape_htmltag($search_topic).'"></td>';
         elseif ($value == 'type_template')
         {
-        	print '<td class="liste_titre">'.$form->selectarray('search_type_template', $elementList, $search_type_template, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth200 maxwidth100onsmartphone').'</td>';
+        	print '<td class="liste_titre">'.$form->selectarray('search_type_template', $elementList, $search_type_template, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100 maxwidth100onsmartphone').'</td>';
         }
         elseif (! in_array($value, array('content', 'content_lines'))) print '<td class="liste_titre"></td>';
     }
@@ -671,6 +673,7 @@ if ($resql)
         $align="left";
         $sortable=1;
         $valuetoshow='';
+        $forcenowrap=1;
         /*
         $tmparray=getLabelOfField($fieldlist[$field]);
         $showfield=$tmp['showfield'];
@@ -688,7 +691,7 @@ if ($resql)
 		if ($fieldlist[$field]=='private')         { $align='center'; }
 		if ($fieldlist[$field]=='position')        { $align='center'; }
 
-		if ($fieldlist[$field]=='joinfiles')       { $valuetoshow=$langs->trans("FilesAttachedToEmail"); $align='center'; }
+		if ($fieldlist[$field]=='joinfiles')       { $valuetoshow=$langs->trans("FilesAttachedToEmail"); $align='center'; $forcenowrap=0; }
 		if ($fieldlist[$field]=='content')         { $valuetoshow=$langs->trans("Content"); $showfield=0;}
 		if ($fieldlist[$field]=='content_lines')   { $valuetoshow=$langs->trans("ContentLines"); $showfield=0; }
 
@@ -697,8 +700,8 @@ if ($resql)
         {
             if (! empty($tabhelp[$id][$value]))
             {
-                if (in_array($value, array('topic'))) $valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, 'tooltip'.$value);   // Tooltip on click
-                else $valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, '', 1);	// Tooltip on hover
+            	if (in_array($value, array('topic'))) $valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, 'tooltip'.$value, $forcenowrap);   // Tooltip on click
+                else $valuetoshow = $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, '', $forcenowrap);	// Tooltip on hover
             }
             print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable?$fieldlist[$field]:''), ($page?'page='.$page.'&':''), $param, "align=".$align, $sortfield, $sortorder);
         }
@@ -787,8 +790,12 @@ if ($resql)
             		$i++;
             		continue;		// It means this is a type of template not into elementList (may be because enabled condition of this type is false because module is not enabled)
             	}
-				// TODO Test on 'enabled'
-
+				// Test on 'enabled'
+				if (! dol_eval($obj->enabled, 1))
+				{
+					$i++;
+					continue;		// Email template not qualified
+				}
 
             	print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
 
@@ -991,7 +998,7 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='')
 			print '<td>';
 			if (! empty($conf->global->MAIN_MULTILANGS))
 			{
-				$selectedlang = GETPOSTISSET('langcode','aZ09')?GETPOST('langcode','aZ09'):$langs->defaultlang;
+				$selectedlang = GETPOSTISSET('langcode')?GETPOST('langcode', 'aZ09'):$langs->defaultlang;
 				if ($context == 'edit') $selectedlang = $obj->{$fieldlist[$field]};
 				print $formadmin->select_language($selectedlang, 'langcode', 0, null, 1, 0, 0, 'maxwidth150');
 			}
@@ -1019,17 +1026,18 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='')
 			}
 			else
 			{
-				print $form->selectarray('type_template', $elementList, (! empty($obj->{$fieldlist[$field]})?$obj->{$fieldlist[$field]}:''), 1, 0, 0, '', 0, 0, 0, '', 'maxwidth200');
+				print $form->selectarray('type_template', $elementList, (! empty($obj->{$fieldlist[$field]})?$obj->{$fieldlist[$field]}:''), 1, 0, 0, '', 0, 0, 0, '', 'maxwidth150 maxwidth100onsmartphone');
 			}
 			print '</td>';
 		}
-		elseif ($context == 'add' && in_array($fieldlist[$field], array('topic', 'joinfiles', 'content', 'content_lines'))) continue;
+		elseif ($context == 'add'  && in_array($fieldlist[$field], array('topic', 'joinfiles', 'content', 'content_lines'))) continue;
 		elseif ($context == 'edit' && in_array($fieldlist[$field], array('topic', 'joinfiles', 'content', 'content_lines'))) continue;
 		elseif ($context == 'hide' && in_array($fieldlist[$field], array('topic', 'joinfiles', 'content', 'content_lines'))) continue;
 		else
 		{
 			$size=''; $class=''; $classtd='';
 			if ($fieldlist[$field]=='code') $class='maxwidth100';
+			if ($fieldlist[$field]=='label') $class='maxwidth100';
 			if ($fieldlist[$field]=='private') { $class='maxwidth50'; $classtd='center'; }
 			if ($fieldlist[$field]=='position') { $class='maxwidth50'; $classtd='center'; }
 			if ($fieldlist[$field]=='libelle') $class='quatrevingtpercent';

+ 46 - 21
htdocs/admin/menus/edit.php

@@ -96,6 +96,7 @@ if ($action == 'update')
             $menu->perms=GETPOST('perms','alpha');
             $menu->target=GETPOST('target','alpha');
             $menu->user=GETPOST('user','alpha');
+            $menu->mainmenu=GETPOST('propertymainmenu','alpha');
             if (is_numeric(GETPOST('menuIdParent','alpha')))
             {
             	$menu->fk_menu=GETPOST('menuIdParent','alpha');
@@ -123,14 +124,11 @@ if ($action == 'update')
 	        setEventMessages($menu->error, $menu->errors, 'errors');
         }
         $action = "edit";
-    }
-    else
-    {
+
         header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
         exit;
     }
-
-    if ($_GET['return'])
+    else
     {
         header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
         exit;
@@ -215,6 +213,7 @@ if ($action == 'add')
         $menu->perms=GETPOST('perms','alpha');
         $menu->target=GETPOST('target','alpha');
         $menu->user=GETPOST('user','alpha');
+        $menu->mainmenu=GETPOST('propertymainmenu','alpha');
         if (is_numeric(GETPOST('menuId','int')))
         {
         	$menu->fk_menu=GETPOST('menuId','int');
@@ -289,10 +288,13 @@ if ($action == 'create')
     		{
 				jQuery("#menuId").prop("disabled", true);
 	    		jQuery("#menuId").val(\'\');
+				jQuery("#propertymainmenu").removeAttr("disabled");
+	    		jQuery("#propertymainmenu").val(\'\');
 			}
-    		else
+    		if (jQuery("#topleft").val() == \'left\')
     		{
 				jQuery("#menuId").removeAttr("disabled");
+				jQuery("#propertymainmenu").prop("disabled", true);
     		}
     	}
     	init_topleft();
@@ -338,7 +340,7 @@ if ($action == 'create')
     print '</td>';
     print '<td>'.$langs->trans('DetailMenuHandler').'</td></tr>';
 
-    //User
+    // User
     print '<tr><td class="nowrap fieldrequired">'.$langs->trans('MenuForUsers').'</td>';
     print '<td><select class="flat" name="user">';
     print '<option value="2" selected>'.$langs->trans("AllMenus").'</option>';
@@ -362,9 +364,15 @@ if ($action == 'create')
         print '<option value="left"'.($_POST["type"] && $_POST["type"]=='left'?' selected':'').'>'.$langs->trans('Left').'</option>';
         print '</select>';
     }
-    //	print '<input type="text" size="50" name="type" value="'.$type.'">';
     print '</td><td>'.$langs->trans('DetailType').'</td></tr>';
 
+    // Mainmenu code
+    print '<tr><td class="fieldrequired">'.$langs->trans('MainMenuCode').'</td>';
+   	print '<td><input type="text" class="minwidth300" id="propertymainmenu" name="propertymainmenu" value="'.(GETPOST("propertymainmenu", 'alpha')?GETPOST("propertymainmenu", 'alpha'):'').'"></td>';
+    print '<td>';
+    print $langs->trans("Example").': mytopmenukey';
+    print '</td></tr>';
+
     // MenuId Parent
     print '<tr><td class="fieldrequired">'.$langs->trans('MenuIdParent').'</td>';
     if ($parent_rowid)
@@ -373,23 +381,23 @@ if ($action == 'create')
     }
     else
     {
-        print '<td><input type="text" size="48" id="menuId" name="menuId" value="'.(GETPOST("menuId", 'int')?GETPOST("menuId", 'int'):'').'"></td>';
+        print '<td><input type="text" class="minwidth300" id="menuId" name="menuId" value="'.(GETPOST("menuId", 'int')?GETPOST("menuId", 'int'):'').'"></td>';
     }
     print '<td>'.$langs->trans('DetailMenuIdParent');
     print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def';
     print '</td></tr>';
 
     // Title
-    print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" size="30" name="titre" value="'.dol_escape_htmltag(GETPOST("titre",'alpha')).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
+    print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag(GETPOST("titre",'alpha')).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
 
     // URL
-    print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td><td><input type="text" size="60" name="url" value="'.GETPOST("url",'alpha').'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
+    print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td><td><input type="text" class="minwidth500" name="url" value="'.GETPOST("url",'alpha').'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
 
     // Langs
-    print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" size="30" name="langs" value="'.$parent_langs.'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
+    print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" class="minwidth300" name="langs" value="'.$parent_langs.'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
 
     // Position
-    print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" size="5" name="position" value="'.dol_escape_htmltag(isset($_POST["position"])?$_POST["position"]:100).'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
+    print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" class="width100" name="position" value="'.dol_escape_htmltag(isset($_POST["position"])?$_POST["position"]:100).'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
 
     // Target
     print '<tr><td>'.$langs->trans('Target').'</td><td><select class="flat" name="target">';
@@ -398,10 +406,10 @@ if ($action == 'create')
     print '</select></td></td><td>'.$langs->trans('DetailTarget').'</td></tr>';
 
     // Enabled
-    print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" size="60" name="enabled" value="'.GETPOST("enabled",'alpha').'"></td><td>'.$langs->trans('DetailEnabled').'</td></tr>';
+    print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" class="minwidth500" name="enabled" value="'.(GETPOSTISSET('enabled')?GETPOST("enabled",'alpha'):'1').'"></td><td>'.$langs->trans('DetailEnabled').'</td></tr>';
 
     // Perms
-    print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" size="60" name="perms" value="'.GETPOST('perms','alpha').'"></td><td>'.$langs->trans('DetailRight').'</td></tr>';
+    print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" class="minwidth500" name="perms" value="'.(GETPOSTISSET('perms')?GETPOST('perms','alpha'):'1').'"></td><td>'.$langs->trans('DetailRight').'</td></tr>';
 
     print '</table>';
 
@@ -455,13 +463,30 @@ elseif ($action == 'edit')
     // Type
     print '<tr><td class="fieldrequired">'.$langs->trans('Type').'</td><td>'.$langs->trans(ucfirst($menu->type)).'</td><td>'.$langs->trans('DetailType').'</td></tr>';
 
+    // Mainmenu code
+    if ($menu->type == 'top')
+    {
+	    print '<tr><td class="fieldrequired">'.$langs->trans('MainMenuCode').'</td>';
+	    /*if ($parent_rowid)
+	     {
+	     print '<td>'.$parent_rowid.'<input type="hidden" name="propertyleftmenu" value="'.$parent_rowid.'"></td>';
+	     }
+	     else
+	     {*/
+	    print '<td><input type="text" class="minwidth300" id="propertymainmenu" name="propertymainmenu" value="'.(GETPOST("propertymainmenu", 'alpha')?GETPOST("propertymainmenu", 'alpha'):$menu->mainmenu).'"></td>';
+	    //}
+	    print '<td>';
+	    print $langs->trans("Example").': mytopmenukey';
+	    print '</td></tr>';
+    }
+
     // MenuId Parent
     print '<tr><td class="fieldrequired">'.$langs->trans('MenuIdParent');
     print '</td>';
     $valtouse=$menu->fk_menu;
     if ($menu->fk_mainmenu) $valtouse='fk_mainmenu='.$menu->fk_mainmenu;
     if ($menu->fk_leftmenu) $valtouse.='&fk_leftmenu='.$menu->fk_leftmenu;
-    print '<td><input type="text" name="menuIdParent" value="'.$valtouse.'" size="48"></td>';
+    print '<td><input type="text" name="menuIdParent" value="'.$valtouse.'" class="minwidth300"></td>';
     print '<td>'.$langs->trans('DetailMenuIdParent');
     print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def';
     print '</td></tr>';
@@ -470,16 +495,16 @@ elseif ($action == 'edit')
     //print '<tr><td>'.$langs->trans('Level').'</td><td>'.$menu->level.'</td><td>'.$langs->trans('DetailLevel').'</td></tr>';
 
     // Title
-    print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" size="30" name="titre" value="'.dol_escape_htmltag($menu->titre).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
+    print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td><td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag($menu->titre).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
 
     // Url
     print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td><td><input type="text" class="quatrevingtpercent" name="url" value="'.$menu->url.'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
 
     // Langs
-    print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" size="30" name="langs" value="'.dol_escape_htmltag($menu->langs).'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
+    print '<tr><td>'.$langs->trans('LangFile').'</td><td><input type="text" class="minwidth300" name="langs" value="'.dol_escape_htmltag($menu->langs).'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
 
     // Position
-    print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" size="5" name="position" value="'.$menu->position.'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
+    print '<tr><td>'.$langs->trans('Position').'</td><td><input type="text" class="minwidth100" name="position" value="'.$menu->position.'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
 
     // Target
     print '<tr><td>'.$langs->trans('Target').'</td><td><select class="flat" name="target">';
@@ -488,12 +513,12 @@ elseif ($action == 'edit')
     print '</select></td><td>'.$langs->trans('DetailTarget').'</td></tr>';
 
     // Enabled
-    print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" size="60" name="enabled" value="'.dol_escape_htmltag($menu->enabled).'"></td><td>'.$langs->trans('DetailEnabled');
+    print '<tr><td>'.$langs->trans('Enabled').'</td><td><input type="text" class="minwidth500" name="enabled" value="'.dol_escape_htmltag($menu->enabled).'"></td><td>'.$langs->trans('DetailEnabled');
     if (! empty($menu->enabled)) print ' ('.$langs->trans("ConditionIsCurrently").': '.yn(dol_eval($menu->enabled,1)).')';
     print '</td></tr>';
 
     // Perms
-    print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" size="60" name="perms" value="'.dol_escape_htmltag($menu->perms).'"></td><td>'.$langs->trans('DetailRight');
+    print '<tr><td>'.$langs->trans('Rights').'</td><td><input type="text" class="minwidth500" name="perms" value="'.dol_escape_htmltag($menu->perms).'"></td><td>'.$langs->trans('DetailRight');
     if (! empty($menu->perms)) print ' ('.$langs->trans("ConditionIsCurrently").': '.yn(dol_eval($menu->perms,1)).')';
     print '</td></tr>';
 

+ 4 - 1
htdocs/admin/modules.php

@@ -701,7 +701,10 @@ if ($mode == 'common')
         	else if (! empty($objMod->always_enabled) || ((! empty($conf->multicompany->enabled) && $objMod->core_enabled) && ($user->entity || $conf->entity!=1)))
         	{
         		if (method_exists($objMod, 'alreadyUsed') && $objMod->alreadyUsed()) print $langs->trans("Used");
-        		else print $langs->trans("Required");
+        		else {
+        			print img_picto($langs->trans("Required"),'switch_on');
+        			print $langs->trans("Required");
+        		}
         		if (! empty($conf->multicompany->enabled) && $user->entity) $disableSetup++;
         	}
         	else

+ 27 - 45
htdocs/admin/multicurrency.php

@@ -45,36 +45,6 @@ $action = GETPOST('action', 'alpha');
  * Actions
  */
 
-
-if (preg_match('/set_([a-z0-9_\-]+)/i',$action,$reg))
-{
-	$code=$reg[1];
-	$value=(GETPOST($code, 'alpha') ? GETPOST($code, 'alpha') : 1);
-	if (dolibarr_set_const($db, $code, $value, 'chaine', 0, '', $conf->entity) > 0)
-	{
-		header("Location: ".$_SERVER["PHP_SELF"]);
-		exit;
-	}
-	else
-	{
-		dol_print_error($db);
-	}
-}
-
-if (preg_match('/del_([a-z0-9_\-]+)/i',$action,$reg))
-{
-	$code=$reg[1];
-	if (dolibarr_del_const($db, $code, 0) > 0)
-	{
-		header("Location: ".$_SERVER["PHP_SELF"]);
-		exit;
-	}
-	else
-	{
-		dol_print_error($db);
-	}
-}
-
 if ($action == 'add_currency')
 {
 	$error=0;
@@ -181,30 +151,42 @@ dol_fiche_head($head, 'settings', $langs->trans("ModuleSetup"), -1, "multicurren
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
 print '<td>'.$langs->trans("Parameters").'</td>'."\n";
-print '<td align="center">'.$langs->trans("Value").'</td>'."\n";
+print '<td align="center">'.$langs->trans("Status").'</td>'."\n";
 print '</tr>';
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->transnoentitiesnoconv("MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE").'</td>';
-print '<td align="right">';
-print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
-print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-print '<input type="hidden" name="action" value="set_MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE">';
-print $form->selectyesno("MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE",$conf->global->MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE,1);
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print '</form>';
+print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE", $arrval, $conf->global->MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE);
+}
 print '</td></tr>';
 
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->transnoentitiesnoconv("multicurrency_useOriginTx").'</td>';
-print '<td align="right">';
-print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
-print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-print '<input type="hidden" name="action" value="set_MULTICURRENCY_USE_ORIGIN_TX">';
-print $form->selectyesno("MULTICURRENCY_USE_ORIGIN_TX",$conf->global->MULTICURRENCY_USE_ORIGIN_TX,1);
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print '</form>';
+print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('MULTICURRENCY_USE_ORIGIN_TX');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("MULTICURRENCY_USE_ORIGIN_TX", $arrval, $conf->global->MULTICURRENCY_USE_ORIGIN_TX);
+}
+print '</td></tr>';
+
+//Online payment with currency on document
+print '<tr class="oddeven">';
+print '<td>'.$langs->transnoentitiesnoconv("multicurrency_useCurrency").'</td>';
+print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT", $arrval, $conf->global->MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT);
+}
 print '</td></tr>';
 
 /* TODO uncomment when the functionality will integrated

+ 127 - 0
htdocs/admin/reception_extrafields.php

@@ -0,0 +1,127 @@
+<?php
+/* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
+ * Copyright (C) 2003		Jean-Louis Bergamo		<jlb@j1b.org>
+ * Copyright (C) 2004-2013	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2012		Regis Houssin			<regis.houssin@capnetworks.com>
+ * Copyright (C) 2012		Florian Henry			<florian.henry@open-concept.pro>
+ * Copyright (C) 2013		Philippe Grand			<philippe.grand@atoo-net.com>
+ * Copyright (C) 2015		Claudio Aschieri		<c.aschieri@19.coop>
+ * Copyright (C) 2018	   Quentin Vial-Gouteyron   <quentin.vial-gouteyron@atm-consulting.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ *      \file       htdocs/admin/reception_extrafields.php
+ *		\ingroup    reception
+ *		\brief      Page to setup extra fields of reception
+ */
+
+require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+
+
+if (!$user->admin)
+	accessforbidden();
+
+$langs->load("admin");
+$langs->load("other");
+$langs->load("receptions");
+$langs->load("deliveries");
+
+
+$extrafields = new ExtraFields($db);
+$form = new Form($db);
+
+// List of supported format
+$tmptype2label=ExtraFields::$type2label;
+$type2label=array('');
+foreach ($tmptype2label as $key => $val) $type2label[$key]=$langs->trans($val);
+
+$action=GETPOST('action', 'alpha');
+$attrname=GETPOST('attrname', 'alpha');
+$elementtype='reception'; //Must be the $table_element of the class that manage extrafield
+
+if (!$user->admin) accessforbidden();
+
+
+/*
+ * Actions
+ */
+
+require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php';
+
+
+
+/*
+ * View
+ */
+
+$textobject=$langs->transnoentitiesnoconv("Receptions");
+
+llxHeader('',$langs->trans("ReceptionsSetup"));
+
+$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+print load_fiche_titre($langs->trans("ReceptionsSetup"),$linkback,'title_setup');
+print "<br>\n";
+
+$head = reception_admin_prepare_head();
+
+dol_fiche_head($head, 'attributes_reception', $langs->trans("Receptions"), -1, 'sending');
+
+require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
+
+dol_fiche_end();
+
+
+// Buttons
+if ($action != 'create' && $action != 'edit')
+{
+    print '<div class="tabsAction">';
+    print "<a class=\"butAction\" href=\"".$_SERVER["PHP_SELF"]."?action=create\">".$langs->trans("NewAttribute")."</a>";
+    print "</div>";
+}
+
+
+/* ************************************************************************** */
+/*                                                                            */
+/* Creation of an optional field											  */
+/*                                                                            */
+/* ************************************************************************** */
+
+if ($action == 'create')
+{
+    print "<br>";
+    print load_fiche_titre($langs->trans('NewAttribute'));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php';
+}
+
+/* ************************************************************************** */
+/*                                                                            */
+/* Edition of an optional field                                                */
+/*                                                                            */
+/* ************************************************************************** */
+if ($action == 'edit' && ! empty($attrname))
+{
+    print "<br>";
+    print load_fiche_titre($langs->trans("FieldEdition", $attrname));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php';
+}
+
+llxFooter();
+
+$db->close();

+ 520 - 0
htdocs/admin/reception_setup.php

@@ -0,0 +1,520 @@
+<?php
+/* Copyright (C) 2018	   Quentin Vial-Gouteyron    <quentin.vial-gouteyron@atm-consulting.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ *	    \file       htdocs/admin/confexped.php
+ *		\ingroup    produit
+ *		\brief      Page to setup reception module
+ */
+
+require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php';
+
+$langs->load("admin");
+$langs->load("receptions");
+$langs->load('other');
+
+
+if (!$user->admin)
+  accessforbidden();
+
+$action=GETPOST('action','alpha');
+$value=GETPOST('value','alpha');
+$label = GETPOST('label','alpha');
+$scandir = GETPOST('scan_dir','alpha');
+$type='reception';
+
+
+/*
+ * Actions
+ */
+
+if (! empty($conf->reception->enabled) && empty($conf->global->MAIN_SUBMODULE_RECEPTION))
+{
+    // This option should always be set to on when module is on.
+    dolibarr_set_const($db, "MAIN_SUBMODULE_RECEPTION", "1",'chaine',0,'',$conf->entity);
+}
+
+if (empty($conf->global->RECEPTION_ADDON_NUMBER))
+{
+    $conf->global->RECEPTION_ADDON_NUMBER='mod_reception_beryl';
+}
+
+
+/*
+ * Actions
+ */
+
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
+if ($action == 'updateMask')
+{
+	$maskconst=GETPOST('maskconstreception','alpha');
+	$maskvalue=GETPOST('maskreception','alpha');
+	if (! empty($maskconst))
+		$res = dolibarr_set_const($db,$maskconst,$maskvalue,'chaine',0,'',$conf->entity);
+
+	if (isset($res))
+	{
+		if ($res > 0)
+			setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+		else
+			setEventMessages($langs->trans("Error"), null, 'errors');
+	}
+}
+
+else if ($action == 'set_param')
+{
+	$freetext=GETPOST('RECEPTION_FREE_TEXT','none');	// No alpha here, we want exact string
+	$res = dolibarr_set_const($db, "RECEPTION_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity);
+	if ($res <= 0)
+	{
+		$error++;
+		setEventMessages($langs->trans("Error"), null, 'errors');
+	}
+
+	$draft=GETPOST('RECEPTION_DRAFT_WATERMARK','alpha');
+	$res = dolibarr_set_const($db, "RECEPTION_DRAFT_WATERMARK",trim($draft),'chaine',0,'',$conf->entity);
+	if ($res <= 0)
+	{
+		$error++;
+		setEventMessages($langs->trans("Error"), null, 'errors');
+	}
+
+	if (! $error)
+	{
+		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+	}
+}
+
+else if ($action == 'specimen')
+{
+	$modele=GETPOST('module','alpha');
+
+	$exp = new Reception($db);
+	$exp->initAsSpecimen();
+
+	// Search template files
+	$file=''; $classname=''; $filefound=0;
+	$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
+	foreach($dirmodels as $reldir)
+	{
+	    $file=dol_buildpath($reldir."core/modules/reception/doc/pdf_".$modele.".modules.php",0);
+		if (file_exists($file))
+		{
+			$filefound=1;
+			$classname = "pdf_".$modele;
+			break;
+		}
+	}
+
+	if ($filefound)
+	{
+		require_once $file;
+
+		$module = new $classname($db);
+
+		if ($module->write_file($exp,$langs) > 0)
+		{
+			header("Location: ".DOL_URL_ROOT."/document.php?modulepart=reception&file=SPECIMEN.pdf");
+			return;
+		}
+		else
+		{
+			setEventMessages($module->error, $module->errors, 'errors');
+			dol_syslog($module->error, LOG_ERR);
+		}
+	}
+	else
+	{
+		setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
+		dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
+	}
+}
+
+// Activate a model
+else if ($action == 'set')
+{
+	$ret = addDocumentModel($value, $type, $label, $scandir);
+}
+
+else if ($action == 'del')
+{
+	$ret = delDocumentModel($value, $type);
+	if ($ret > 0)
+	{
+        if ($conf->global->RECEPTION_ADDON_PDF == "$value") dolibarr_del_const($db, 'RECEPTION_ADDON_PDF',$conf->entity);
+	}
+}
+
+// Set default model
+else if ($action == 'setdoc')
+{
+	if (dolibarr_set_const($db, "RECEPTION_ADDON_PDF",$value,'chaine',0,'',$conf->entity))
+	{
+		// La constante qui a ete lue en avant du nouveau set
+		// on passe donc par une variable pour avoir un affichage coherent
+		$conf->global->RECEPTION_ADDON_PDF = $value;
+	}
+
+	// On active le modele
+	$ret = delDocumentModel($value, $type);
+	if ($ret > 0)
+	{
+		$ret = addDocumentModel($value, $type, $label, $scandir);
+	}
+}
+
+else if ($action == 'setmodel')
+{
+	dolibarr_set_const($db, "RECEPTION_ADDON_NUMBER",$value,'chaine',0,'',$conf->entity);
+}
+
+
+
+
+/*
+ * View
+ */
+
+$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
+
+$form=new Form($db);
+
+llxHeader("",$langs->trans("ReceptionsSetup"));
+
+$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+print load_fiche_titre($langs->trans("ReceptionsSetup"),$linkback,'title_setup');
+print '<br>';
+$head = reception_admin_prepare_head();
+
+dol_fiche_head($head, 'reception', $langs->trans("Receptions"), -1, 'sending');
+
+// Reception numbering model
+
+print load_fiche_titre($langs->trans("ReceptionsNumberingModules"));
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td width="100">'.$langs->trans("Name").'</td>';
+print '<td>'.$langs->trans("Description").'</td>';
+print '<td>'.$langs->trans("Example").'</td>';
+print '<td class="center" width="60">'.$langs->trans("Status").'</td>';
+print '<td class="center" width="80">'.$langs->trans("ShortInfo").'</td>';
+print "</tr>\n";
+
+clearstatcache();
+
+foreach ($dirmodels as $reldir)
+{
+	$dir = dol_buildpath($reldir."core/modules/reception/");
+	
+	if (is_dir($dir))
+	{
+		$handle = opendir($dir);
+		if (is_resource($handle))
+		{
+			while (($file = readdir($handle))!==false)
+			{
+				if (substr($file, 0, 14) == 'mod_reception_' && substr($file, dol_strlen($file)-3, 3) == 'php')
+				{
+					$file = substr($file, 0, dol_strlen($file)-4);
+
+					require_once $dir.$file.'.php';
+
+					$module = new $file;
+
+					if ($module->isEnabled())
+					{
+						// Show modules according to features level
+						if ($module->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
+						if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
+
+						print '<tr><td>'.$module->nom."</td>\n";
+						print '<td>';
+						print $module->info();
+						print '</td>';
+
+                        // Show example of numbering module
+                        print '<td class="nowrap">';
+                        $tmp=$module->getExample();
+                        if (preg_match('/^Error/',$tmp)) {
+							$langs->load("errors"); print '<div class="error">'.$langs->trans($tmp).'</div>';
+						}
+                        elseif ($tmp=='NotConfigured') print $langs->trans($tmp);
+                        else print $tmp;
+                        print '</td>'."\n";
+
+						print '<td align="center">';
+						if ($conf->global->RECEPTION_ADDON_NUMBER == "$file")
+						{
+							print img_picto($langs->trans("Activated"),'switch_on');
+						}
+						else
+						{
+							print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmodel&amp;value='.$file.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'">';
+							print img_picto($langs->trans("Disabled"),'switch_off');
+							print '</a>';
+						}
+						print '</td>';
+
+						$reception=new Reception($db);
+						$reception->initAsSpecimen();
+
+						// Info
+						$htmltooltip='';
+						$htmltooltip.=''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
+						$nextval=$module->getNextValue($mysoc,$reception);
+                        if ("$nextval" != $langs->trans("NotAvailable")) {  // Keep " on nextval
+                            $htmltooltip.=''.$langs->trans("NextValue").': ';
+                            if ($nextval) {
+                                if (preg_match('/^Error/',$nextval) || $nextval=='NotConfigured')
+                                    $nextval = $langs->trans($nextval);
+                                $htmltooltip.=$nextval.'<br>';
+                            } else {
+                                $htmltooltip.=$langs->trans($module->error).'<br>';
+                            }
+                        }
+
+						print '<td align="center">';
+						print $form->textwithpicto('',$htmltooltip,1,0);
+						print '</td>';
+
+						print '</tr>';
+					}
+				}
+			}
+			closedir($handle);
+		}
+	}
+}
+
+print '</table><br>';
+
+
+/*
+ *  Documents models for Receptions Receipt
+ */
+print load_fiche_titre($langs->trans("ReceptionsReceiptModel"));
+
+// Defini tableau def de modele invoice
+$type="reception";
+$def = array();
+
+$sql = "SELECT nom";
+$sql.= " FROM ".MAIN_DB_PREFIX."document_model";
+$sql.= " WHERE type = '".$type."'";
+$sql.= " AND entity = ".$conf->entity;
+
+$resql=$db->query($sql);
+if ($resql)
+{
+	$i = 0;
+	$num_rows=$db->num_rows($resql);
+	while ($i < $num_rows)
+	{
+		$array = $db->fetch_array($resql);
+		array_push($def, $array[0]);
+		$i++;
+	}
+}
+else
+{
+	dol_print_error($db);
+}
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td width="140">'.$langs->trans("Name").'</td>';
+print '<td>'.$langs->trans("Description").'</td>';
+print '<td align="center" width="60">'.$langs->trans("Status").'</td>';
+print '<td align="center" width="60">'.$langs->trans("Default").'</td>';
+print '<td align="center" width="80" class="nowrap">'.$langs->trans("ShortInfo").'</td>';
+print '<td align="center" width="80" class="nowrap">'.$langs->trans("Preview").'</td>';
+print "</tr>\n";
+
+clearstatcache();
+
+foreach ($dirmodels as $reldir)
+{
+    foreach (array('','/doc') as $valdir)
+    {
+    	$dir = dol_buildpath($reldir."core/modules/reception".$valdir);
+
+        if (is_dir($dir))
+        {
+            $handle=opendir($dir);
+            if (is_resource($handle))
+            {
+                while (($file = readdir($handle))!==false)
+                {
+                    $filelist[]=$file;
+                }
+                closedir($handle);
+                arsort($filelist);
+
+                foreach($filelist as $file)
+                {
+                    if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file))
+                    {
+
+                    	if (file_exists($dir.'/'.$file))
+                    	{
+                    		$name = substr($file, 4, dol_strlen($file) -16);
+	                        $classname = substr($file, 0, dol_strlen($file) -12);
+
+	                        require_once $dir.'/'.$file;
+	                        $module = new $classname($db);
+
+	                        $modulequalified=1;
+	                        if ($module->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) $modulequalified=0;
+	                        if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) $modulequalified=0;
+
+	                        if ($modulequalified)
+	                        {
+	                            print '<tr><td width="100">';
+	                            print (empty($module->name)?$name:$module->name);
+	                            print "</td><td>\n";
+	                            if (method_exists($module,'info')) print $module->info($langs);
+	                            else print $module->description;
+	                            print '</td>';
+
+	                            // Active
+	                            if (in_array($name, $def))
+	                            {
+	                            	print '<td align="center">'."\n";
+	                            	print '<a href="'.$_SERVER["PHP_SELF"].'?action=del&value='.$name.'">';
+	                            	print img_picto($langs->trans("Enabled"),'switch_on');
+	                            	print '</a>';
+	                            	print '</td>';
+	                            }
+	                            else
+	                            {
+	                                print '<td align="center">'."\n";
+	                                print '<a href="'.$_SERVER["PHP_SELF"].'?action=set&value='.$name.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"),'switch_off').'</a>';
+	                                print "</td>";
+	                            }
+
+	                            // Defaut
+	                            print '<td align="center">';
+	                            if ($conf->global->RECEPTION_ADDON_PDF == $name)
+	                            {
+	                                print img_picto($langs->trans("Default"),'on');
+	                            }
+	                            else
+	                            {
+	                                print '<a href="'.$_SERVER["PHP_SELF"].'?action=setdoc&value='.$name.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').'</a>';
+	                            }
+	                            print '</td>';
+
+	                           // Info
+		    					$htmltooltip =    ''.$langs->trans("Name").': '.$module->name;
+					    		$htmltooltip.='<br>'.$langs->trans("Type").': '.($module->type?$module->type:$langs->trans("Unknown"));
+			                    if ($module->type == 'pdf')
+			                    {
+			                        $htmltooltip.='<br>'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur;
+			                    }
+					    		$htmltooltip.='<br><br><u>'.$langs->trans("FeaturesSupported").':</u>';
+					    		$htmltooltip.='<br>'.$langs->trans("Logo").': '.yn($module->option_logo,1,1);
+					    		$htmltooltip.='<br>'.$langs->trans("PaymentMode").': '.yn($module->option_modereg,1,1);
+					    		$htmltooltip.='<br>'.$langs->trans("PaymentConditions").': '.yn($module->option_condreg,1,1);
+					    		$htmltooltip.='<br>'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang,1,1);
+					    		$htmltooltip.='<br>'.$langs->trans("WatermarkOnDraftOrders").': '.yn($module->option_draft_watermark,1,1);
+
+	                            print '<td align="center">';
+	                            print $form->textwithpicto('',$htmltooltip,1,0);
+	                            print '</td>';
+
+	                            // Preview
+	                            print '<td align="center">';
+	                            if ($module->type == 'pdf')
+	                            {
+	                                print '<a href="'.$_SERVER["PHP_SELF"].'?action=specimen&module='.$name.'&amp;scan_dir='.$module->scandir.'&amp;label='.urlencode($module->name).'">'.img_object($langs->trans("Preview"),'reception').'</a>';
+	                            }
+	                            else
+	                            {
+	                                print img_object($langs->trans("PreviewNotAvailable"),'generic');
+	                            }
+	                            print '</td>';
+
+	                            print "</tr>\n";
+	                        }
+                    	}
+                    }
+                }
+            }
+        }
+    }
+}
+
+print '</table>';
+print '<br>';
+
+
+/*
+ * Other options
+ *
+ */
+/*
+print load_fiche_titre($langs->trans("OtherOptions"));
+
+print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
+print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+print '<input type="hidden" name="action" value="set_param">';
+
+print "<table class=\"noborder\" width=\"100%\">";
+print "<tr class=\"liste_titre\">";
+print "<td>".$langs->trans("Parameter")."</td>\n";
+print "</tr>";
+
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
+print '<tr><td>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnReceptions"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
+$variablename='RECEPTION_FREE_TEXT';
+if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
+{
+    print '<textarea name="'.$variablename.'" class="flat" cols="120">'.$conf->global->$variablename.'</textarea>';
+}
+else
+{
+    include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
+    $doleditor=new DolEditor($variablename, $conf->global->$variablename,'',80,'dolibarr_notes');
+    print $doleditor->Create();
+}
+print "</td></tr>\n";
+
+print '<tr><td>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftContractCards"), $htmltext).'<br>';
+print '<input size="50" class="flat" type="text" name="RECEPTION_DRAFT_WATERMARK" value="'.$conf->global->RECEPTION_DRAFT_WATERMARK.'">';
+print "</td></tr>\n";
+*/
+print '</table>';
+
+print '<div class="center"><input type="submit" class="button" value="'.$langs->trans("Modify").'"></div>';
+
+print '</form>';
+
+llxFooter();
+$db->close();

+ 1 - 1
htdocs/admin/salaries.php

@@ -129,4 +129,4 @@ print '</form>';
 
 // End of page
 llxFooter();
-$db->close();;
+$db->close();

+ 2 - 2
htdocs/admin/sms.php

@@ -258,7 +258,7 @@ else
 	}
 	else
 	{
-		print '<a class="butActionRefused" href="#" title="'.$langs->trans("FeatureNotAvailableOnLinux").'">'.$langs->trans("DoTestServerAvailability").'</a>';
+		print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("FeatureNotAvailableOnLinux").'">'.$langs->trans("DoTestServerAvailability").'</a>';
 	}*/
 
 	if (count($listofmethods) && ! empty($conf->global->MAIN_SMS_SENDMODE))
@@ -267,7 +267,7 @@ else
 	}
 	else
 	{
-       print '<a class="butActionRefused" href="#">'.$langs->trans("DoTestSend").'</a>';
+       print '<a class="butActionRefused classfortooltip" href="#">'.$langs->trans("DoTestSend").'</a>';
 	}
 	print '</div>';
 

+ 31 - 32
htdocs/admin/socialnetworks.php

@@ -38,27 +38,34 @@ $action = GETPOST('action','aZ09');
 
 
 /*
- * Actions
+ * Action
  */
-
-// Action activation d'un sous module du module adherent
-if ($action == 'set')
+if (preg_match('/set_([a-z0-9_\-]+)/i',$action,$reg))
 {
-	$result=dolibarr_set_const($db, $_GET["name"], $_GET["value"], '', 0, '', $conf->entity);
-	if ($result < 0)
-	{
-		dol_print_error($db);
-	}
+    $code=$reg[1];
+    if (dolibarr_set_const($db, $code, 1, 'chaine', 0, '', $conf->entity) > 0)
+    {
+        header("Location: ".$_SERVER["PHP_SELF"]);
+        exit;
+    }
+    else
+    {
+        dol_print_error($db);
+    }
 }
 
-// Action desactivation d'un sous module du module adherent
-if ($action == 'unset')
+if (preg_match('/del_([a-z0-9_\-]+)/i',$action,$reg))
 {
-	$result=dolibarr_del_const($db, $_GET["name"], $conf->entity);
-	if ($result < 0)
-	{
-		dol_print_error($db);
-	}
+    $code=$reg[1];
+    if (dolibarr_del_const($db, $code, $conf->entity) > 0)
+    {
+        header("Location: ".$_SERVER["PHP_SELF"]);
+        exit;
+    }
+    else
+    {
+        dol_print_error($db);
+    }
 }
 
 
@@ -89,26 +96,18 @@ dol_fiche_head($head, 'setup', '', 0, 'user');
 
 print '<br>';
 
-$arrayofsocialnetworks=array('skype'=>'Skype', 'twitter'=>'Twitter', 'facebook'=>'Facebook');
+$arrayofsocialnetworks=array('jabber'=>'Jabber', 'skype'=>'Skype', 'twitter'=>'Twitter', 'facebook'=>'Facebook');
 
 foreach($arrayofsocialnetworks as $snkey => $snlabel)
 {
 	$consttocheck = 'SOCIALNETWORKS_'.strtoupper($snkey);
-	if (! empty($conf->global->$consttocheck))
-	{
-		//$link=img_picto($langs->trans("Active"),'tick').' ';
-		$link='<a href="'.$_SERVER["PHP_SELF"].'?action=unset&value=0&name='.$consttocheck.'">';
-		//$link.=$langs->trans("Disable");
-		$link.=img_picto($langs->trans("Activated"),'switch_on');
-		$link.='</a>';
-	}
-	else
-	{
-		$link='<a href="'.$_SERVER["PHP_SELF"].'?action=set&value=1&name='.$consttocheck.'">';
-		//$link.=img_$langs->trans("Activate")
-		$link.=img_picto($langs->trans("Disabled"),'switch_off');
-		$link.='</a>';
-	}
+  if ($conf->use_javascript_ajax) {
+    $link = ajax_constantonoff($consttocheck);
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    $link = $form->selectarray($consttocheck, $arrval, $conf->global->$consttocheck);
+}
+  
 	print $langs->trans('EnableFeatureFor', $snlabel).' '.$link.'<br><br>';
 }
 

+ 204 - 237
htdocs/admin/stock.php

@@ -38,97 +38,35 @@ $action = GETPOST('action','alpha');
 
 
 /*
- * Actions
+ * Action
  */
-
-if($action)
+if (preg_match('/set_([a-z0-9_\-]+)/i',$action,$reg))
 {
-	$db->begin();
-
-	if ($action == 'STOCK_SUPPORTS_SERVICES')
-	{
-		$res = dolibarr_set_const($db, "STOCK_SUPPORTS_SERVICES", GETPOST('STOCK_SUPPORTS_SERVICES','alpha'),'chaine',0,'',$conf->entity);
-	}
-	if ($action == 'STOCK_USERSTOCK_AUTOCREATE')
-	{
-		$res = dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", GETPOST('STOCK_USERSTOCK_AUTOCREATE','alpha'),'chaine',0,'',$conf->entity);
-	}
-	if ($action == 'STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE') {
-		$res = dolibarr_set_const($db, "STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE", GETPOST('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE','alpha'),'chaine',0,'',$conf->entity);
-	}
-	if ($action == 'STOCK_ALLOW_NEGATIVE_TRANSFER')
-	{
-		$res = dolibarr_set_const($db, "STOCK_ALLOW_NEGATIVE_TRANSFER", GETPOST('STOCK_ALLOW_NEGATIVE_TRANSFER','alpha'),'chaine',0,'',$conf->entity);
-	}
-	// Mode of stock decrease
-	if ($action == 'STOCK_CALCULATE_ON_BILL'
-	|| $action == 'STOCK_CALCULATE_ON_VALIDATE_ORDER'
-	|| $action == 'STOCK_CALCULATE_ON_SHIPMENT'
-	|| $action == 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE')
-	{
-		$res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_BILL", '','chaine',0,'',$conf->entity);
-		$res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_VALIDATE_ORDER", '','chaine',0,'',$conf->entity);
-		$res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SHIPMENT", '','chaine',0,'',$conf->entity);
-		$res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SHIPMENT_CLOSE", '','chaine',0,'',$conf->entity);
-		if ($action == 'STOCK_CALCULATE_ON_BILL')           $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_BILL", GETPOST('STOCK_CALCULATE_ON_BILL','alpha'),'chaine',0,'',$conf->entity);
-		if ($action == 'STOCK_CALCULATE_ON_VALIDATE_ORDER') $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_VALIDATE_ORDER", GETPOST('STOCK_CALCULATE_ON_VALIDATE_ORDER','alpha'),'chaine',0,'',$conf->entity);
-		if ($action == 'STOCK_CALCULATE_ON_SHIPMENT')       $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SHIPMENT", GETPOST('STOCK_CALCULATE_ON_SHIPMENT','alpha'),'chaine',0,'',$conf->entity);
-		if ($action == 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE')       $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SHIPMENT_CLOSE", GETPOST('STOCK_CALCULATE_ON_SHIPMENT_CLOSE','alpha'),'chaine',0,'',$conf->entity);
-	}
-	// Mode of stock increase
-	if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_BILL'
-	|| $action == 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER'
-	|| $action == 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')
-	{
-		//Use variable cause empty(GETPOST()) do not work with php version < 5.4
-		$valdispatch=GETPOST('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER','alpha');
-
-		$res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_BILL", '','chaine',0,'',$conf->entity);
-		$res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", '','chaine',0,'',$conf->entity);
-		$res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", '','chaine',0,'',$conf->entity);
-		if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_BILL')           $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_BILL", GETPOST('STOCK_CALCULATE_ON_SUPPLIER_BILL','alpha'),'chaine',0,'',$conf->entity);
-		if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", GETPOST('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER','alpha'),'chaine',0,'',$conf->entity);
-		if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $valdispatch,'chaine',0,'',$conf->entity);
-		if (empty($valdispatch)) {
-			$res=dolibarr_set_const($db, "SUPPLIER_ORDER_USE_DISPATCH_STATUS", '','chaine',0,'',$conf->entity);
-		}
-	}
-
-	if($action == 'SUPPLIER_ORDER_USE_DISPATCH_STATUS') {
-		$res = dolibarr_set_const($db, "SUPPLIER_ORDER_USE_DISPATCH_STATUS", GETPOST('SUPPLIER_ORDER_USE_DISPATCH_STATUS','alpha'),'chaine',0,'',$conf->entity);
-	}
-
-	if($action == 'STOCK_USE_VIRTUAL_STOCK') {
-	    $res = dolibarr_set_const($db, "STOCK_USE_VIRTUAL_STOCK", GETPOST('STOCK_USE_VIRTUAL_STOCK','alpha'),'chaine',0,'',$conf->entity);
-	}
-
-	if($action == 'STOCK_MUST_BE_ENOUGH_FOR_INVOICE') {
-	    $res = dolibarr_set_const($db, "STOCK_MUST_BE_ENOUGH_FOR_INVOICE", GETPOST('STOCK_MUST_BE_ENOUGH_FOR_INVOICE','alpha'),'chaine',0,'',$conf->entity);
-	}
-	if($action == 'STOCK_MUST_BE_ENOUGH_FOR_ORDER') {
-	    $res = dolibarr_set_const($db, "STOCK_MUST_BE_ENOUGH_FOR_ORDER", GETPOST('STOCK_MUST_BE_ENOUGH_FOR_ORDER','alpha'),'chaine',0,'',$conf->entity);
-	}
-	if($action == 'STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT') {
-	    $res = dolibarr_set_const($db, "STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT", GETPOST('STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT','alpha'),'chaine',0,'',$conf->entity);
-	}
-	if($action == 'INDEPENDANT_SUBPRODUCT_STOCK') {
-	    $res = dolibarr_set_const($db, "INDEPENDANT_SUBPRODUCT_STOCK", GETPOST('INDEPENDANT_SUBPRODUCT_STOCK','alpha'),'chaine',0,'',$conf->entity);
-	}
-
-	if (! $res > 0) $error++;
-
- 	if (! $error)
+    $code=$reg[1];
+    if (dolibarr_set_const($db, $code, 1, 'chaine', 0, '', $conf->entity) > 0)
     {
-    	$db->commit();
-        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+        header("Location: ".$_SERVER["PHP_SELF"]);
+        exit;
     }
     else
     {
-    	$db->rollback();
-        setEventMessages($langs->trans("Error"), null, 'errors');
+        dol_print_error($db);
     }
 }
 
+if (preg_match('/del_([a-z0-9_\-]+)/i',$action,$reg))
+{
+    $code=$reg[1];
+    if (dolibarr_del_const($db, $code, $conf->entity) > 0)
+    {
+        header("Location: ".$_SERVER["PHP_SELF"]);
+        exit;
+    }
+    else
+    {
+        dol_print_error($db);
+    }
+}
 
 /*
  * View
@@ -159,23 +97,23 @@ print '<br>';
 // Title rule for stock decrease
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
-print "  <td>".$langs->trans("RuleForStockManagementDecrease")."</td>\n";
-print "  <td align=\"right\">&nbsp;</td>\n";
+print "<td>".$langs->trans("RuleForStockManagementDecrease")."</td>\n";
+print '<td align="center">'.$langs->trans("Status").'</td>'."\n";
 print '</tr>'."\n";
 
 $found=0;
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("DeStockOnBill").'</td>';
-print '<td align="right">';
+print '<td align="center">';
 if (! empty($conf->facture->enabled))
 {
-    print "<form method=\"post\" action=\"stock.php\">";
-	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print "<input type=\"hidden\" name=\"action\" value=\"STOCK_CALCULATE_ON_BILL\">";
-	print $form->selectyesno("STOCK_CALCULATE_ON_BILL",$conf->global->STOCK_CALCULATE_ON_BILL,1,$disabled);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-	print "</form>\n";
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_BILL');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_BILL);
+}
 }
 else
 {
@@ -187,15 +125,15 @@ $found++;
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("DeStockOnValidateOrder").'</td>';
-print '<td align="right">';
+print '<td align="center">';
 if (! empty($conf->commande->enabled))
 {
-    print "<form method=\"post\" action=\"stock.php\">";
-	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print "<input type=\"hidden\" name=\"action\" value=\"STOCK_CALCULATE_ON_VALIDATE_ORDER\">";
-	print $form->selectyesno("STOCK_CALCULATE_ON_VALIDATE_ORDER",$conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER,1,$disabled);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-	print "</form>\n";
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_VALIDATE_ORDER');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER);
+}
 }
 else
 {
@@ -209,15 +147,15 @@ $found++;
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("DeStockOnShipment").'</td>';
-print '<td align="right">';
+print '<td align="center">';
 if (! empty($conf->expedition->enabled))
 {
-	print "<form method=\"post\" action=\"stock.php\">";
-	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print "<input type=\"hidden\" name=\"action\" value=\"STOCK_CALCULATE_ON_SHIPMENT\">";
-	print $form->selectyesno("STOCK_CALCULATE_ON_SHIPMENT",$conf->global->STOCK_CALCULATE_ON_SHIPMENT,1,$disabled);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-	print "</form>\n";
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT);
+}
 }
 else
 {
@@ -229,15 +167,15 @@ $found++;
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("DeStockOnShipmentOnClosing").'</td>';
-print '<td align="right">';
+print '<td align="center">';
 if (! empty($conf->expedition->enabled))
 {
-	print "<form method=\"post\" action=\"stock.php\">";
-	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print "<input type=\"hidden\" name=\"action\" value=\"STOCK_CALCULATE_ON_SHIPMENT_CLOSE\">";
-	print $form->selectyesno("STOCK_CALCULATE_ON_SHIPMENT_CLOSE",$conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE,1,$disabled);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-	print "</form>\n";
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT_CLOSE');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT_CLOSE", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE);
+}
 }
 else
 {
@@ -261,23 +199,23 @@ print '<br>';
 // Title rule for stock increase
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
-print "  <td>".$langs->trans("RuleForStockManagementIncrease")."</td>\n";
-print "  <td align=\"right\">&nbsp;</td>\n";
+print "<td>".$langs->trans("RuleForStockManagementIncrease")."</td>\n";
+print '<td align="center">'.$langs->trans("Status").'</td>'."\n";
 print '</tr>'."\n";
 
 $found=0;
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("ReStockOnBill").'</td>';
-print '<td align="right">';
+print '<td align="center">';
 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=\"STOCK_CALCULATE_ON_SUPPLIER_BILL\">";
-	print $form->selectyesno("STOCK_CALCULATE_ON_SUPPLIER_BILL",$conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL,1,$disabled);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-	print "</form>\n";
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_BILL');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL);
+}
 }
 else
 {
@@ -290,15 +228,15 @@ $found++;
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("ReStockOnValidateOrder").'</td>';
-print '<td align="right">';
+print '<td align="center">';
 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=\"STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER\">";
-	print $form->selectyesno("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER",$conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER,1,$disabled);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-	print "</form>\n";
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER);
+}
 }
 else
 {
@@ -307,25 +245,57 @@ else
 print "</td>\n</tr>\n";
 $found++;
 
+if (!empty($conf->reception->enabled))
+{
+	print '<tr class="oddeven">';
+	print '<td width="60%">'.$langs->trans("StockOnReception").'</td>';
+  print '<td align="center">';
+
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION", $arrval, $conf->global->STOCK_CALCULATE_ON_RECEPTION);
+}
+
+	print "</td>\n</tr>\n";
+	$found++;
+
 
 print '<tr class="oddeven">';
-print '<td>'.$langs->trans("ReStockOnDispatchOrder").'</td>';
-print '<td 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=\"STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER\">";
-	print $form->selectyesno("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER",$conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER,1,$disabled);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>';
-	print "</form>\n";
+	print '<td width="60%">'.$langs->trans("StockOnReceptionOnClosing").'</td>';
+  print '<td align="center">';
+
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION_CLOSE');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION_CLOSE", $arrval, $conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE);
+}
+	print "</td>\n</tr>\n";
+	$found++;
 }
 else
 {
-    print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name"));
+	print '<tr class="oddeven">';
+	print '<td>'.$langs->trans("ReStockOnDispatchOrder").'</td>';
+  print '<td align="center">';
+	if (! empty($conf->fournisseur->enabled))
+	{
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER);
+}
+	}
+	else
+	{
+		print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name"));
+	}
+	print "</td>\n</tr>\n";
+	$found++;
 }
-print "</td>\n</tr>\n";
-$found++;
 
 /*if (! $found)
 {
@@ -340,20 +310,20 @@ print '</table>';
 print '<br>';
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
-print "  <td>".$langs->trans("RuleForStockAvailability")."</td>\n";
-print "  <td align=\"right\">&nbsp;</td>\n";
+print "<td>".$langs->trans("RuleForStockAvailability")."</td>\n";
+print '<td align="center">'.$langs->trans("Status").'</td>'."\n";
 print '</tr>'."\n";
 
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("WarehouseAllowNegativeTransfer").'</td>';
-print '<td 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=\"STOCK_ALLOW_NEGATIVE_TRANSFER\">";
-print $form->selectyesno("STOCK_ALLOW_NEGATIVE_TRANSFER",$conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER,1);
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print '</form>';
+print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_ALLOW_NEGATIVE_TRANSFER');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_ALLOW_NEGATIVE_TRANSFER", $arrval, $conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER);
+}
 print "</td>\n";
 print "</tr>\n";
 
@@ -362,13 +332,13 @@ if($conf->invoice->enabled)
 {
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("StockMustBeEnoughForInvoice").'</td>';
-	print '<td 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=\"STOCK_MUST_BE_ENOUGH_FOR_INVOICE\">";
-	print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_INVOICE",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_INVOICE,1);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-	print '</form>';
+  print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_INVOICE');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_INVOICE", $arrval, $conf->global->STOCK_MUST_BE_ENOUGH_FOR_INVOICE);
+}
 	print "</td>\n";
 	print "</tr>\n";
 }
@@ -377,13 +347,13 @@ if($conf->order->enabled)
 {
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("StockMustBeEnoughForOrder").'</td>';
-	print '<td 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=\"STOCK_MUST_BE_ENOUGH_FOR_ORDER\">";
-	print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_ORDER",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_ORDER,1);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-	print '</form>';
+  print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_ORDER');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_ORDER", $arrval, $conf->global->STOCK_MUST_BE_ENOUGH_FOR_ORDER);
+}
 	print "</td>\n";
 	print "</tr>\n";
 }
@@ -392,13 +362,13 @@ if($conf->expedition->enabled)
 {
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("StockMustBeEnoughForShipment").'</td>';
-	print '<td 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=\"STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT\">";
-	print $form->selectyesno("STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT",$conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT,1);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-	print '</form>';
+  print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT", $arrval, $conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT);
+}
 	print "</td>\n";
 	print "</tr>\n";
 }
@@ -413,21 +383,21 @@ if (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
 
 if ($virtualdiffersfromphysical)
 {
-	print '<table class="noborder" width="100%">';
-	print '<tr class="liste_titre">';
-	print "  <td>".$langs->trans("RuleForStockReplenishment")." ".img_help('help',$langs->trans("VirtualDiffersFromPhysical"))."</td>\n";
-	print "  <td align=\"right\">&nbsp;</td>\n";
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+	print "<td>".$langs->trans("RuleForStockReplenishment")." ".img_help('help',$langs->trans("VirtualDiffersFromPhysical"))."</td>\n";
+  print '<td align="center">'.$langs->trans("Status").'</td>'."\n";
 	print '</tr>'."\n";
 
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("UseVirtualStockByDefault").'</td>';
-	print '<td 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=\"STOCK_USE_VIRTUAL_STOCK\">";
-	print $form->selectyesno("STOCK_USE_VIRTUAL_STOCK",$conf->global->STOCK_USE_VIRTUAL_STOCK,1);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-	print '</form>';
+  print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_USE_VIRTUAL_STOCK');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_USE_VIRTUAL_STOCK", $arrval, $conf->global->STOCK_USE_VIRTUAL_STOCK);
+}
 	print "</td>\n";
 	print "</tr>\n";
 	print '</table>';
@@ -438,19 +408,19 @@ if ($virtualdiffersfromphysical)
 print '<table class="noborder" width="100%">';
 
 print '<tr class="liste_titre">';
-print "  <td>".$langs->trans("Other")."</td>\n";
-print "  <td align=\"right\">&nbsp;</td>\n";
+print "<td>".$langs->trans("Other")."</td>\n";
+print '<td align="center">'.$langs->trans("Status").'</td>'."\n";
 print '</tr>'."\n";
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("UserWarehouseAutoCreate").'</td>';
-print '<td 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=\"STOCK_USERSTOCK_AUTOCREATE\">";
-print $form->selectyesno("STOCK_USERSTOCK_AUTOCREATE",$conf->global->STOCK_USERSTOCK_AUTOCREATE,1);
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print '</form>';
+print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_USERSTOCK_AUTOCREATE');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_USERSTOCK_AUTOCREATE", $arrval, $conf->global->STOCK_USERSTOCK_AUTOCREATE);
+}
 print "</td>\n";
 print "</tr>\n";
 
@@ -458,25 +428,25 @@ print '<tr class="oddeven">';
 print '<td>';
 print $form->textwithpicto($langs->trans("StockSupportServices"), $langs->trans("StockSupportServicesDesc"));
 print '</td>';
-print '<td 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=\"STOCK_SUPPORTS_SERVICES\">";
-print $form->selectyesno("STOCK_SUPPORTS_SERVICES",$conf->global->STOCK_SUPPORTS_SERVICES,1);
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print '</form>';
+print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_SUPPORTS_SERVICES');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_SUPPORTS_SERVICES", $arrval, $conf->global->STOCK_SUPPORTS_SERVICES);
+}
 print "</td>\n";
 print "</tr>\n";
 
 print '<tr class="oddeven">';
 print '<td>'.$langs->trans("AllowAddLimitStockByWarehouse").'</td>';
-print '<td 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=\"STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE\">";
-print $form->selectyesno("STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE",$conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE,1);
-print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-print '</form>';
+print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE", $arrval, $conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE);
+}
 print "</td>\n";
 print "</tr>\n";
 
@@ -485,12 +455,12 @@ if (! empty($conf->fournisseur->enabled) && !empty($conf->global->STOCK_CALCULAT
     print '<tr class="oddeven">';
     print '<td>'.$langs->trans("UseDispatchStatus").'</td>';
     print '<td 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";
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('SUPPLIER_ORDER_USE_DISPATCH_STATUS');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("SUPPLIER_ORDER_USE_DISPATCH_STATUS", $arrval, $conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS);
+}
     print "</td>\n</tr>\n";
 }
 
@@ -502,46 +472,43 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
 	print '<table class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
 	print '<td>'.$langs->trans("Inventory").'</td>'."\n";
-	print '<td align="center" width="20">&nbsp;</td>';
-	print '<td align="center">&nbsp;</td>'."\n";
+  print '<td align="center">'.$langs->trans("Status").'</td>'."\n";
+  print '</tr>'."\n";
 
 	// Example with a yes / no select
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("INVENTORY_DISABLE_VIRTUAL").'</td>';
-	print '<td align="center" width="20">&nbsp;</td>';
-	print '<td align="right" width="300">';
-	print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
-	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print '<input type="hidden" name="action" value="set_INVENTORY_DISABLE_VIRTUAL">';
-	print $form->selectyesno("INVENTORY_DISABLE_VIRTUAL",$conf->global->INVENTORY_DISABLE_VIRTUAL,1);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-	print '</form>';
+  print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('INVENTORY_DISABLE_VIRTUAL');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("INVENTORY_DISABLE_VIRTUAL", $arrval, $conf->global->INVENTORY_DISABLE_VIRTUAL);
+}
 	print '</td></tr>';
 
 	// Example with a yes / no select
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA").'</td>';
-	print '<td align="center" width="20">&nbsp;</td>';
-	print '<td align="right" width="300">';
-	print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
-	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print '<input type="hidden" name="action" value="set_INVENTORY_USE_MIN_PA_IF_NO_LAST_PA">';
-	print $form->selectyesno("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA",$conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA,1);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-	print '</form>';
+  print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('INVENTORY_USE_MIN_PA_IF_NO_LAST_PA');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA", $arrval, $conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA);
+}
 	print '</td></tr>';
 
 	// Example with a yes / no select
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT").'</td>';
-	print '<td align="center" width="20">&nbsp;</td>';
-	print '<td align="right" width="300">';
-	print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
-	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-	print '<input type="hidden" name="action" value="set_INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT">';
-	print $form->selectyesno("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT",$conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT,1);
-	print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
-	print '</form>';
+  print '<td align="center">';
+if ($conf->use_javascript_ajax) {
+    print ajax_constantonoff('INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT');
+} else {
+    $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
+    print $form->selectarray("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT", $arrval, $conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT);
+}
 	print '</td></tr>';
 
 	print '</table>';

+ 4 - 4
htdocs/admin/ticket.php

@@ -253,7 +253,7 @@ dol_fiche_end();
  * Projects Numbering model
  */
 
-print_titre($langs->trans("TicketNumberingModules"));
+print load_fiche_titre($langs->trans("TicketNumberingModules"));
 
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
@@ -353,7 +353,7 @@ if (!$conf->use_javascript_ajax) {
     print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
     print '<input type="hidden" name="action" value="setvarother">';
 }
-print_titre($langs->trans("TicketParamPublicInterface"));
+print load_fiche_titre($langs->trans("TicketParamPublicInterface"));
 
 print '<table class="noborder" width="100%">';
 
@@ -422,7 +422,7 @@ print '</tr>';
 
 print '</table><br>';
 
-print_titre($langs->trans("TicketParams"));
+print load_fiche_titre($langs->trans("TicketParams"));
 print '<table class="noborder" width="100%">';
 
 // Activate email notifications
@@ -515,7 +515,7 @@ if (!$conf->use_javascript_ajax) {
 }
 
 // Admin var of module
-print_titre($langs->trans("TicketParamMail"));
+print load_fiche_titre($langs->trans("TicketParamMail"));
 
 print '<table class="noborder" width="100%">';
 

+ 2 - 2
htdocs/admin/ticket_extrafields.php

@@ -92,7 +92,7 @@ if ($action != 'create' && $action != 'edit') {
 
 if ($action == 'create') {
     print "<br>";
-    print_titre($langs->trans('NewAttribute'));
+    print load_fiche_titre($langs->trans('NewAttribute'));
 
     include DOL_DOCUMENT_ROOT . '/core/tpl/admin_extrafields_add.tpl.php';
 }
@@ -104,7 +104,7 @@ if ($action == 'create') {
 /* ************************************************************************** */
 if ($action == 'edit' && !empty($attrname)) {
     print "<br>";
-    print_titre($langs->trans("FieldEdition", $attrname));
+    print load_fiche_titre($langs->trans("FieldEdition", $attrname));
 
     include DOL_DOCUMENT_ROOT . '/core/tpl/admin_extrafields_edit.tpl.php';
 }

+ 8 - 1
htdocs/admin/tools/dolibarr_export.php

@@ -517,7 +517,6 @@ print '<br>';
 <input type="hidden" name="export_type" value="server" />
 
 <fieldset><legend class="legendforfieldsetstep" style="font-size: 3em">2</legend>
-<div class="fichehalfleft">
 
 <?php
 print $langs->trans("BackupDesc2",DOL_DATA_ROOT).'<br>';
@@ -525,6 +524,13 @@ print $langs->trans("BackupDescX").'<br><br>';
 
 ?>
 
+<div id="backupfilesleft" class="fichehalfleft">
+
+<?php
+
+print load_fiche_titre($title?$title:$langs->trans("BackupDumpWizard"));
+?>
+
 <label for="zipfilename_template"> <?php echo $langs->trans("FileNameToGenerate"); ?></label><br>
 <input type="text" name="zipfilename_template" style="width: 90%"
 	id="zipfilename_template"
@@ -537,6 +543,7 @@ echo $file;
 ?>" /> <br>
 <br>
 
+
 <?php
 // Show compression choices
 print '<div class="formelementrow">';

+ 4 - 1
htdocs/admin/workflow.php

@@ -28,7 +28,7 @@ require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
 
 // Load translation files required by the page
-$langs->loadLangs(array("admin","workflow","propal","workflow","orders","supplier_proposals"));
+$langs->loadLangs(array("admin","workflow","propal","workflow","orders","supplier_proposals","receptions"));
 
 if (! $user->admin) accessforbidden();
 
@@ -86,6 +86,8 @@ $workflowcodes=array(
 	'WORKFLOW_ORDER_CLASSIFY_BILLED_SUPPLIER_PROPOSAL'=>array('family'=>'classify_supplier_proposal', 'position'=>60, 'enabled'=>'! empty($conf->supplier_proposal->enabled) && ! empty($conf->fournisseur->enabled)', 'picto'=>'propal','warning'=>''),
 	// Automatic classification supplier order
 	'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER'=>array('family'=>'classify_supplier_order', 'position'=>62, 'enabled'=>'! empty($conf->fournisseur->enabled)', 'picto'=>'order','warning'=>''),
+	//Automatic classification reception
+	'WORKFLOW_BILL_ON_RECEPTION'=>array('family'=>'classify_reception', 'position'=>30, 'enabled'=>'! empty($conf->reception->enabled) && ! empty($conf->fournisseur->enabled)', 'picto'=>'bill'),
 );
 
 if (! empty($conf->modules_parts['workflow']) && is_array($conf->modules_parts['workflow']))
@@ -138,6 +140,7 @@ foreach($workflowcodes as $key => $params)
 			if ($reg[1] == 'order') print ' - '.$langs->trans('Order');
 			if ($reg[1] == 'supplier_proposal') print ' - '.$langs->trans('SupplierProposal');
 			if ($reg[1] == 'supplier_order') print ' - '.$langs->trans('SupplierOrder');
+			if ($reg[1] == 'reception') print ' - '.$langs->trans('Reception');
 		}
 		else
 		{

+ 2 - 2
htdocs/asset/card.php

@@ -287,7 +287,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 			}
 			else
 			{
-				print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Modify').'</a>'."\n";
+				print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Modify').'</a>'."\n";
 			}
 
 			if ($user->rights->asset->delete)
@@ -296,7 +296,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
 			}
 			else
 			{
-				print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Delete').'</a>'."\n";
+				print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Delete').'</a>'."\n";
 			}
 		}
 		print '</div>'."\n";

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

@@ -304,7 +304,7 @@ if (GETPOST('withtab','alpha'))
 	dol_fiche_head($head, 'fingerprints', '', -1);
 }
 
-print '<span class="opacitymedium">'.$langs->trans("FingerprintsDesc")."</span><br>\n";
+print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("FingerprintsDesc")."<br></span>\n";
 
 print '<br>';
 
@@ -342,7 +342,7 @@ for ($month = 1 ; $month <= 12 ; $month++)
 }
 $retstring.="</select>";
 print $retstring;
-print '<input type="text" name="yeartoexport" class="valignmiddle maxwidth75" value="'.GETPOST('yeartoexport','int').'">';
+print '<input type="text" name="yeartoexport" class="valignmiddle maxwidth50imp" value="'.GETPOST('yeartoexport','int').'">';
 print '<input type="hidden" name="withtab" value="'.GETPOST('withtab','alpha').'">';
 print '<input type="submit" name="downloadcsv" class="button" value="'.$langs->trans('DownloadLogCSV').'">';
 if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY)) print ' | <a href="?action=downloadblockchain'.(GETPOST('withtab','alpha')?'&withtab='.GETPOST('withtab','alpha'):'').'">'.$langs->trans('DownloadBlockChain').'</a>';

+ 40 - 4
htdocs/blockedlog/class/blockedlog.class.php

@@ -172,6 +172,10 @@ class BlockedLog
 		if ($conf->banque->enabled) $this->trackedevents['PAYMENT_VARIOUS_CREATE']='logPAYMENT_VARIOUS_CREATE';
 		if ($conf->banque->enabled) $this->trackedevents['PAYMENT_VARIOUS_MODIFY']='logPAYMENT_VARIOUS_MODIFY';
 		if ($conf->banque->enabled) $this->trackedevents['PAYMENT_VARIOUS_DELETE']='logPAYMENT_VARIOUS_DELETE';
+
+		// $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all POS modules
+		$moduleposenabled = ($conf->cashdesk->enabled || $conf->takepos->enabled || ! empty($conf->global->BANK_ENABLE_POS_CASHCONTROL));
+		if ($moduleposenabled) $this->trackedevents['CASHCONTROL_VALIDATE']='logCASHCONTROL_VALIDATE';
 	}
 
 	/**
@@ -270,6 +274,17 @@ class BlockedLog
 				$this->error++;
 			}
 		}
+		else if($this->element === 'cashcontrol') {
+			require_once DOL_DOCUMENT_ROOT.'/compta/cashcontrol/class/cashcontrol.class.php';
+
+			$object = new CashControl($this->db);
+			if ($object->fetch($this->fk_object)>0) {
+				return $object->getNomUrl(1);
+			}
+			else{
+				$this->error++;
+			}
+		}
 		else if ($this->action == 'MODULE_SET')
 		{
 			return '<i class="opacitymedium">System to track events into unalterable logs were enabled</i>';
@@ -351,6 +366,10 @@ class BlockedLog
 		{
 			$this->date_object = $object->dateh;
 		}
+		elseif ($object->element=='cashcontrol')
+		{
+			$this->date_object = $object->date_creation;
+		}
 		else {
 			$this->date_object = $object->date;
 		}
@@ -364,7 +383,24 @@ class BlockedLog
 
 		// Set object_data
 		$this->object_data=new stdClass();
-		$arrayoffieldstoexclude = array('table_element','fields','ref_previous','ref_next','origin','origin_id','oldcopy','picto','error','modelpdf','table_element_line','linkedObjectsIds','linkedObjects','fk_delivery_address');
+		// Add fields to exclude
+		$arrayoffieldstoexclude = array(
+			'table_element','fields','ref_previous','ref_next','origin','origin_id','oldcopy','picto','error','errors','modelpdf','civility_id','contact','contact_id',
+			'table_element_line','ismultientitymanaged','isextrafieldmanaged',
+			'linkedObjectsIds','linkedObjects','fk_delivery_address',
+			'context',
+		    'projet'          // There is already ->fk_project
+		);
+		// Add more fields to exclude depending on object type
+		if ($this->element == 'cashcontrol')
+		{
+		    $arrayoffieldstoexclude = array_merge($arrayoffieldstoexclude, array(
+		        'name','lastname','firstname','region','region_id','region_code','state','state_id','state_code','country','country_id','country_code',
+		        'total_ht','total_tva','total_ttc','total_localtax1','total_localtax2',
+		        'barcode_type','barcode_type_code','barcode_type_label','barcode_type_coder','mode_reglement_id','cond_reglement_id','mode_reglement','cond_reglement','shipping_method_id',
+		        'fk_incoterms','libelle_incoterms','location_incoterms','lines')
+		    );
+		}
 
 		// Add thirdparty info
 		if (empty($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) $object->fetch_thirdparty();
@@ -413,7 +449,7 @@ class BlockedLog
 			{
 				if (in_array($key, $arrayoffieldstoexclude)) continue;	// Discard some properties
 				if (! in_array($key, array(
-				'ref','facnumber','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public','lines'
+				'ref','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public','lines'
 				))) continue;									// Discard if not into a dedicated list
 				if ($key == 'lines')
 				{
@@ -444,7 +480,7 @@ class BlockedLog
 			{
 				if (in_array($key, $arrayoffieldstoexclude)) continue;	// Discard some properties
 				if (! in_array($key, array(
-				'ref','facnumber','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public'
+				'ref','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public'
 				))) continue;									// Discard if not into a dedicated list
 				if (!is_object($value)) $this->object_data->{$key} = $value;
 			}
@@ -557,7 +593,7 @@ class BlockedLog
 					{
 						if (in_array($key, $arrayoffieldstoexclude)) continue;	// Discard some properties
 						if (! in_array($key, array(
-						'ref','facnumber','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public'
+						'ref','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public'
 						))) continue;									// Discard if not into a dedicated list
 						if (!is_object($value))
 						{

+ 1 - 0
htdocs/blockedlog/lib/blockedlog.lib.php

@@ -38,6 +38,7 @@ function blockedlogadmin_prepare_head()
 	$head[$h][2] = 'blockedlog';
 	$h++;
 
+	$langs->load("blockedlog");
 	$head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_list.php?withtab=1";
 	$head[$h][1] = $langs->trans("BrowseBlockedLog");
 

+ 30 - 19
htdocs/cashdesk/admin/cashdesk.php

@@ -86,7 +86,7 @@ $formproduct=new FormProduct($db);
 llxHeader('',$langs->trans("CashDeskSetup"));
 
 $linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
-print load_fiche_titre($langs->trans("CashDeskSetup"),$linkback,'title_setup');
+print load_fiche_titre($langs->trans("CashDeskSetup").' (SimplePOS)',$linkback,'title_setup');
 print '<br>';
 
 
@@ -95,30 +95,49 @@ print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set">';
 
+if (! empty($conf->service->enabled))
+{
+	print '<table class="noborder" width="100%">';
+	print '<tr class="liste_titre">';
+	print '<td>'.$langs->trans("Parameters").'</td><td>'.$langs->trans("Value").'</td>';
+	print "</tr>\n";
+
+	print '<tr class="oddeven"><td>';
+	print $langs->trans("CashdeskShowServices");
+	print '<td colspan="2">';
+	print $form->selectyesno("CASHDESK_SERVICES",$conf->global->CASHDESK_SERVICES,1);
+	print "</td></tr>\n";
+
+	print '</table>';
+
+	print '<br>';
+}
+
+
 print '<table class="noborder" width="100%">';
 print '<tr class="liste_titre">';
-print '<td>'.$langs->trans("Parameters").'</td><td>'.$langs->trans("Value").'</td>';
+print '<td>'.$langs->trans("Terminal").' 0</td><td>'.$langs->trans("Value").'</td>';
 print "</tr>\n";
 
 print '<tr class="oddeven"><td width=\"50%\">'.$langs->trans("CashDeskThirdPartyForSell").'</td>';
 print '<td colspan="2">';
-print $form->select_company($conf->global->CASHDESK_ID_THIRDPARTY,'socid','s.client in (1,3) AND s.status = 1',1,0,1,array(),0);
+print $form->select_company($conf->global->CASHDESK_ID_THIRDPARTY,'socid','s.client in (1,3) AND s.status = 1', 1, 0, 0, array(), 0);
 print '</td></tr>';
 if (! empty($conf->banque->enabled))
 {
-	
+
 	print '<tr class="oddeven"><td>'.$langs->trans("CashDeskBankAccountForSell").'</td>';
 	print '<td colspan="2">';
 	$form->select_comptes($conf->global->CASHDESK_ID_BANKACCOUNT_CASH,'CASHDESK_ID_BANKACCOUNT_CASH',0,"courant=2",1);
 	print '</td></tr>';
 
-	
+
 	print '<tr class="oddeven"><td>'.$langs->trans("CashDeskBankAccountForCheque").'</td>';
 	print '<td colspan="2">';
 	$form->select_comptes($conf->global->CASHDESK_ID_BANKACCOUNT_CHEQUE,'CASHDESK_ID_BANKACCOUNT_CHEQUE',0,"courant=1",1);
 	print '</td></tr>';
 
-	
+
 	print '<tr class="oddeven"><td>'.$langs->trans("CashDeskBankAccountForCB").'</td>';
 	print '<td colspan="2">';
 	$form->select_comptes($conf->global->CASHDESK_ID_BANKACCOUNT_CB,'CASHDESK_ID_BANKACCOUNT_CB',0,"courant=1",1);
@@ -127,7 +146,7 @@ if (! empty($conf->banque->enabled))
 
 if (! empty($conf->stock->enabled))
 {
-	
+
 	print '<tr class="oddeven"><td>'.$langs->trans("CashDeskDoNotDecreaseStock").'</td>';	// Force warehouse (this is not a default value)
 	print '<td colspan="2">';
 	if (empty($conf->productbatch->enabled)) {
@@ -138,13 +157,14 @@ if (! empty($conf->stock->enabled))
 	    if (!$conf->global->CASHDESK_NO_DECREASE_STOCK) {
 	       $res = dolibarr_set_const($db,"CASHDESK_NO_DECREASE_STOCK",1,'chaine',0,'',$conf->entity);
 	    }
-	    print $langs->trans('StockDecreaseForPointOfSaleDisabledbyBatch');
+	    print $langs->trans("Yes").'<br>';
+	    print '<span class="opacitymedium">'.$langs->trans('StockDecreaseForPointOfSaleDisabledbyBatch').'</span>';
 	}
 	print '</td></tr>';
 
 	$disabled=$conf->global->CASHDESK_NO_DECREASE_STOCK;
 
-	
+
 	print '<tr class="oddeven"><td>'.$langs->trans("CashDeskIdWareHouse").'</td>';	// Force warehouse (this is not a default value)
 	print '<td colspan="2">';
 	if (! $disabled)
@@ -154,20 +174,11 @@ if (! empty($conf->stock->enabled))
 	}
 	else
 	{
-		print $langs->trans("StockDecreaseForPointOfSaleDisabled");
+		print '<span class="opacitymedium">'.$langs->trans("StockDecreaseForPointOfSaleDisabled").'</span>';
 	}
 	print '</td></tr>';
 }
 
-if (! empty($conf->service->enabled))
-{
-    print '<tr class="oddeven"><td>';
-    print $langs->trans("CashdeskShowServices");
-    print '<td colspan="2">';
-    print $form->selectyesno("CASHDESK_SERVICES",$conf->global->CASHDESK_SERVICES,1);
-    print "</td></tr>\n";
-}
-
 // Use Dolibarr Receipt Printer
 if (! empty($conf->receiptprinter->enabled))
 {

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

@@ -65,7 +65,7 @@ class Categorie extends CommonObject
 	 *
 	 * @note This array should be remove in future, once previous constants are moved to the string value. Deprecated
 	 */
-	private $MAP_ID = array(
+	protected $MAP_ID = array(
 		'product'      => 0,
 		'supplier'     => 1,
 		'customer'     => 2,
@@ -97,7 +97,7 @@ class Categorie extends CommonObject
 	 *
 	 * @note Move to const array when PHP 5.6 will be our minimum target
 	 */
-	private $MAP_CAT_FK = array(
+	protected $MAP_CAT_FK = array(
 		'product'  => 'product',
 		'customer' => 'soc',
 		'supplier' => 'soc',
@@ -114,7 +114,7 @@ class Categorie extends CommonObject
 	 *
 	 * @note Move to const array when PHP 5.6 will be our minimum target
 	 */
-	private $MAP_CAT_TABLE = array(
+	protected $MAP_CAT_TABLE = array(
 		'product'  => 'product',
 		'customer' => 'societe',
 		'supplier' => 'fournisseur',
@@ -131,7 +131,7 @@ class Categorie extends CommonObject
 	 *
 	 * @note Move to const array when PHP 5.6 will be our minimum target
 	 */
-	private $MAP_OBJ_CLASS = array(
+	protected $MAP_OBJ_CLASS = array(
 		'product'  => 'Product',
 		'customer' => 'Societe',
 		'supplier' => 'Fournisseur',
@@ -148,7 +148,7 @@ class Categorie extends CommonObject
 	 *
 	 * @note Move to const array when PHP 5.6 will be our minimum target
 	 */
-	private $MAP_OBJ_TABLE = array(
+	protected $MAP_OBJ_TABLE = array(
 		'product'  => 'product',
 		'customer' => 'societe',
 		'supplier' => 'societe',
@@ -944,7 +944,7 @@ class Categorie extends CommonObject
 	 *
 	 *	@return		int		<0 if KO, >0 if OK
 	 */
-	private function load_motherof()
+	protected function load_motherof()
 	{
         // phpcs:enable
 		global $conf;
@@ -1536,7 +1536,7 @@ class Categorie extends CommonObject
 			if (colorIsLight($this->color)) $forced_color='categtextblack';
 		}
 
-        $link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$this->id.'&type='.$this->type.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip '.$forced_color .'">';
+		$link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$this->id.'&type='.$this->type.'&backtopage='.urlencode($_SERVER['PHP_SELF']).'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip '.$forced_color .'">';
 		$linkend='</a>';
 
 		$picto='category';

+ 18 - 2
htdocs/categories/photos.php

@@ -69,7 +69,23 @@ if ($id > 0)
 if (isset($_FILES['userfile']) && $_FILES['userfile']['size'] > 0 && $_POST["sendit"] && ! empty($conf->global->MAIN_UPLOAD_DOC))
 {
     if ($object->id) {
-	    $object->add_photo($upload_dir, $_FILES['userfile']);
+
+        $file = $_FILES['userfile'];
+        if (is_array($file['name']) && count($file['name']) > 0)
+        {
+            foreach ($file['name'] as $i => $name)
+            {
+                if(empty($file['tmp_name'][$i]) || intval($conf->global->MAIN_UPLOAD_DOC) * 1000 <= filesize($file['tmp_name'][$i]) )
+                {
+                    setEventMessage($file['name'][$i] .' : '. $langs->trans(empty($file['tmp_name'][$i])? 'ErrorFailedToSaveFile' : 'MaxSizeForUploadedFiles' ) );
+                    unset($file['name'][$i],$file['type'][$i],$file['tmp_name'][$i],$file['error'][$i],$file['size'][$i]);
+                }
+            }
+        }
+
+        if(!empty($file['tmp_name'])) {
+            $object->add_photo($upload_dir, $file);
+        }
     }
 }
 
@@ -173,7 +189,7 @@ if ($object->id)
 		}
 		else
 		{
-			print '<a class="butActionRefused hideonsmartphone" href="#">';
+			print '<a class="butActionRefused classfortooltip hideonsmartphone" href="#">';
 			print $langs->trans("AddPhoto").'</a>';
 		}
 	}

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

@@ -432,8 +432,8 @@ if ($action == 'update')
 		foreach ($socpeopleassigned as $cid) $object->socpeopleassigned[$cid] = array('id' => $cid);
 		$object->contactid   = GETPOST("contactid",'int');
 		$object->fk_project  = GETPOST("projectid",'int');
-		$object->note        = GETPOST("note");
-		$object->pnote       = GETPOST("note");
+		$object->note        = GETPOST("note","none");	// deprecated
+		$object->note_private= GETPOST("note","none");
 		$object->fk_element	 = GETPOST("fk_element");
 		$object->elementtype = GETPOST("elementtype");
 
@@ -1302,7 +1302,6 @@ if ($id > 0)
 		print '<tr><td class="titlefieldcreate nowrap">'.$langs->trans("Priority").'</td><td>';
 		print '<input type="text" name="priority" value="'.($object->priority?$object->priority:'').'" size="5">';
 		print '</td></tr>';
-
 		// Object linked
 		if (! empty($object->fk_element) && ! empty($object->elementtype))
 		{
@@ -1610,8 +1609,9 @@ if ($id > 0)
 		print ($object->priority?$object->priority:'');
 		print '</td></tr>';
 
-		// Object linked
-		if (! empty($object->fk_element) && ! empty($object->elementtype))
+		// Object linked (if link is for thirdparty, contact, project it is a recording error. We should not have links in link table
+		// for such objects because there is already a dedicated field into table llx_actioncomm.
+		if (! empty($object->fk_element) && ! empty($object->elementtype) && ! in_array($object->elementtype, array('societe','contact','project')))
 		{
 			include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
 			print '<tr><td>'.$langs->trans("LinkedObject").'</td>';
@@ -1658,7 +1658,7 @@ if ($id > 0)
 			}
 			else
 			{
-				print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Modify").'</a></div>';
+				print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Modify").'</a></div>';
 			}
 
 			if ($user->rights->agenda->allactions->create ||
@@ -1668,7 +1668,7 @@ if ($id > 0)
 			}
 			else
 			{
-				print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("ToClone").'</a></div>';
+				print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("ToClone").'</a></div>';
 			}
 
 			if ($user->rights->agenda->allactions->delete ||
@@ -1678,7 +1678,7 @@ if ($id > 0)
 			}
 			else
 			{
-				print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Delete").'</a></div>';
+				print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Delete").'</a></div>';
 			}
 		}
 	}

+ 27 - 8
htdocs/comm/action/class/actioncomm.class.php

@@ -334,7 +334,16 @@ class ActionComm extends CommonObject
         $sql.= "fk_element,";
         $sql.= "elementtype,";
         $sql.= "entity,";
-        $sql.= "extraparams";
+        $sql.= "extraparams,";
+		// Fields emails
+        $sql.= "email_msgid,";
+        $sql.= "email_from,";
+        $sql.= "email_sender,";
+        $sql.= "email_to,";
+        $sql.= "email_tocc,";
+        $sql.= "email_tobcc,";
+        $sql.= "email_subject,";
+        $sql.= "errors_to";
         $sql.= ") VALUES (";
         $sql.= "'".$this->db->idate($now)."', ";
         $sql.= (strval($this->datep)!=''?"'".$this->db->idate($this->datep)."'":"null").", ";
@@ -354,7 +363,16 @@ class ActionComm extends CommonObject
         $sql.= (! empty($this->fk_element)?$this->fk_element:"null").", ";
         $sql.= (! empty($this->elementtype)?"'".$this->db->escape($this->elementtype)."'":"null").", ";
         $sql.= $conf->entity.",";
-        $sql.= (! empty($this->extraparams)?"'".$this->db->escape($this->extraparams)."'":"null");
+        $sql.= (! empty($this->extraparams)?"'".$this->db->escape($this->extraparams)."'":"null").", ";
+        // Fields emails
+        $sql.= (! empty($this->email_msgid)?"'".$this->db->escape($this->email_msgid)."'":"null").", ";
+        $sql.= (! empty($this->email_from)?"'".$this->db->escape($this->email_from)."'":"null").", ";
+        $sql.= (! empty($this->email_sender)?"'".$this->db->escape($this->email_sender)."'":"null").", ";
+        $sql.= (! empty($this->email_to)?"'".$this->db->escape($this->email_to)."'":"null").", ";
+        $sql.= (! empty($this->email_tocc)?"'".$this->db->escape($this->email_tocc)."'":"null").", ";
+        $sql.= (! empty($this->email_tobcc)?"'".$this->db->escape($this->email_tobcc)."'":"null").", ";
+        $sql.= (! empty($this->email_subject)?"'".$this->db->escape($this->email_subject)."'":"null").", ";
+        $sql.= (! empty($this->errors_to)?"'".$this->db->escape($this->errors_to)."'":"null");
         $sql.= ")";
 
         dol_syslog(get_class($this)."::add", LOG_DEBUG);
@@ -1274,7 +1292,8 @@ class ActionComm extends CommonObject
 			$tooltip .= '<br><b>' . $langs->trans('Type') . ':</b> ' . $labeltype;
 		if (! empty($this->location))
 			$tooltip .= '<br><b>' . $langs->trans('Location') . ':</b> ' . $this->location;
-
+		if (! empty($this->note))
+			$tooltip .= '<br><b>' . $langs->trans('Note') . ':</b> ' . (dol_textishtml($this->note) ? str_replace(array("\r","\n"), "", $this->note) : $this->note);
 		$linkclose='';
 		if (! empty($conf->global->AGENDA_USE_EVENT_TYPE) && $this->type_color)
 			$linkclose = ' style="background-color:#'.$this->type_color.'"';
@@ -1315,10 +1334,10 @@ class ActionComm extends CommonObject
 		$linkstart.=$linkclose.'>';
 		$linkend='</a>';
 
-                if ($option == 'nolink') {
-                    $linkstart = '';
-                    $linkend = '';
-                }
+		if ($option == 'nolink') {
+			$linkstart = '';
+			$linkend = '';
+		}
 		//print 'rrr'.$this->libelle.'rrr'.$this->label.'rrr'.$withpicto;
 
         if ($withpicto == 2)
@@ -1691,7 +1710,7 @@ class ActionComm extends CommonObject
     		$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
     		return 0;
     	}
-		
+
     	$now = dol_now();
 
     	dol_syslog(__METHOD__, LOG_DEBUG);

+ 30 - 27
htdocs/comm/action/index.php

@@ -7,6 +7,7 @@
  * Copyright (C) 2014      Cedric GROSS         <c.gross@kreiz-it.fr>
  * Copyright (C) 2015      Marcos García        <marcosgdf@gmail.com>
  * Copyright (C) 2017      Open-DSI             <support@open-dsi.fr>
+ * Copyright (C) 2018       Frédéric France         <frederic.france@netlogic.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
@@ -44,9 +45,9 @@ if (! isset($conf->global->AGENDA_MAX_EVENTS_DAY_VIEW)) $conf->global->AGENDA_MA
 if (empty($conf->global->AGENDA_EXT_NB)) $conf->global->AGENDA_EXT_NB=5;
 $MAXAGENDA=$conf->global->AGENDA_EXT_NB;
 
-$filter = GETPOST("filter",'alpha',3);
-$filtert = GETPOST("filtert","int",3);
-$usergroup = GETPOST("usergroup","int",3);
+$filter = GETPOST("search_filter",'alpha',3)?GETPOST("search_filter",'alpha',3):GETPOST("filter",'alpha',3);
+$filtert = GETPOST("search_filtert","int",3)?GETPOST("search_filtert","int",3):GETPOST("filtert","int",3);
+$usergroup = GETPOST("search_usergroup","int",3)?GETPOST("search_usergroup","int",3):GETPOST("usergroup","int",3);
 $showbirthday = empty($conf->use_javascript_ajax)?GETPOST("showbirthday","int"):1;
 
 // If not choice done on calendar owner (like on left menu link "Agenda"), we filter on user.
@@ -65,7 +66,7 @@ if (! $sortorder) $sortorder="ASC";
 if (! $sortfield) $sortfield="a.datec";
 
 // Security check
-$socid = GETPOST("socid","int");
+$socid = GETPOST("search_socid","int")?GETPOST("search_socid","int"):GETPOST("socid","int");
 if ($user->societe_id) $socid=$user->societe_id;
 $result = restrictedArea($user, 'agenda', 0, '', 'myactions');
 if ($socid < 0) $socid='';
@@ -79,32 +80,32 @@ if (! $user->rights->agenda->allactions->read || $filter =='mine')  // If no per
 }
 
 $action=GETPOST('action','alpha');
-$resourceid=GETPOST("resourceid","int");
+$resourceid=GETPOST("search_resourceid","int");
 $year=GETPOST("year","int")?GETPOST("year","int"):date("Y");
 $month=GETPOST("month","int")?GETPOST("month","int"):date("m");
 $week=GETPOST("week","int")?GETPOST("week","int"):date("W");
 $day=GETPOST("day","int")?GETPOST("day","int"):date("d");
-$pid=GETPOST("projectid","int",3);
-$status=GETPOST("status",'aZ09');		// status may be 0, 50, 100, 'todo'
-$type=GETPOST("type",'az09');
+$pid=GETPOST("search_projectid","int",3)?GETPOST("search_projectid","int",3):GETPOST("projectid","int",3);
+$status=GETPOST("search_status",'aZ09')?GETPOST("search_status",'aZ09'):GETPOST("status",'aZ09');		// status may be 0, 50, 100, 'todo'
+$type=GETPOST("search_type",'az09')?GETPOST("search_type",'az09'):GETPOST("type",'az09');
 $maxprint=(isset($_GET["maxprint"])?GETPOST("maxprint"):$conf->global->AGENDA_MAX_EVENTS_DAY_VIEW);
 // Set actioncode (this code must be same for setting actioncode into peruser, listacton and index)
-if (GETPOST('actioncode','array'))
+if (GETPOST('search_actioncode','array'))
 {
-    $actioncode=GETPOST('actioncode','array',3);
+    $actioncode=GETPOST('search_actioncode','array',3);
     if (! count($actioncode)) $actioncode='0';
 }
 else
 {
-    $actioncode=GETPOST("actioncode","alpha",3)?GETPOST("actioncode","alpha",3):(GETPOST("actioncode")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE));
+    $actioncode=GETPOST("search_actioncode","alpha",3)?GETPOST("search_actioncode","alpha",3):(GETPOST("search_actioncode")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE));
 }
 if ($actioncode == '' && empty($actioncodearray)) $actioncode=(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE);
 
-if ($status == ''   && ! isset($_GET['status']) && ! isset($_POST['status'])) $status=(empty($conf->global->AGENDA_DEFAULT_FILTER_STATUS)?'':$conf->global->AGENDA_DEFAULT_FILTER_STATUS);
+if ($status == '' && ! GETPOSTISSET('search_status')) $status=(empty($conf->global->AGENDA_DEFAULT_FILTER_STATUS)?'':$conf->global->AGENDA_DEFAULT_FILTER_STATUS);
 
 $defaultview = (empty($conf->global->AGENDA_DEFAULT_VIEW) ? 'show_month' : $conf->global->AGENDA_DEFAULT_VIEW);
 $defaultview = (empty($user->conf->AGENDA_DEFAULT_VIEW) ? $defaultview : $user->conf->AGENDA_DEFAULT_VIEW);
-if (empty($action) && ! isset($_GET['action']) && ! isset($_POST['action'])) $action=$defaultview;
+if (empty($action) && ! GETPOSTISSET('action')) $action=$defaultview;
 if ($action == 'default')	// When action is default, we want a calendar view and not the list
 {
 	$action = (($defaultview != 'show_list') ? $defaultview : 'show_month');
@@ -301,21 +302,22 @@ if ($status == 'done') $title=$langs->trans("DoneActions");
 if ($status == 'todo') $title=$langs->trans("ToDoActions");
 
 $param='';
-if ($actioncode || isset($_GET['actioncode']) || isset($_POST['actioncode'])) {
+if ($actioncode || isset($_GET['search_actioncode']) || isset($_POST['search_actioncode'])) {
 	if(is_array($actioncode)) {
-		foreach($actioncode as $str_action) $param.="&actioncode[]=".$str_action;
-	} else $param.="&actioncode=".$actioncode;
+		foreach($actioncode as $str_action) $param.="&search_actioncode[]=".urlencode($str_action);
+	} else $param.="&search_actioncode=".urlencode($actioncode);
 }
-if ($resourceid > 0)  $param.="&resourceid=".$resourceid;
-if ($status || isset($_GET['status']) || isset($_POST['status'])) $param.="&status=".$status;
-if ($filter)  $param.="&filter=".$filter;
-if ($filtert) $param.="&filtert=".$filtert;
-if ($socid)   $param.="&socid=".$socid;
-if ($showbirthday) $param.="&showbirthday=1";
-if ($pid)     $param.="&projectid=".$pid;
-if ($type)   $param.="&type=".$type;
-if ($action == 'show_day' || $action == 'show_week' || $action == 'show_month') $param.='&action='.$action;
-$param.="&maxprint=".$maxprint;
+if ($resourceid > 0)  $param.="&search_resourceid=".urlencode($resourceid);
+if ($status || isset($_GET['status']) || isset($_POST['status'])) $param.="&search_status=".urlencode($status);
+if ($filter)       $param.="&search_filter=".urlencode($filter);
+if ($filtert)      $param.="&search_filtert=".urlencode($filtert);
+if ($usergroup)    $param.="&search_usergroup=".urlencode($usergroup);
+if ($socid)        $param.="&search_socid=".urlencode($socid);
+if ($showbirthday) $param.="&search_showbirthday=1";
+if ($pid)          $param.="&search_projectid=".urlencode($pid);
+if ($type)         $param.="&search_type=".urlencode($type);
+if ($action == 'show_day' || $action == 'show_week' || $action == 'show_month') $param.='&action='.urlencode($action);
+$param.="&maxprint=".urlencode($maxprint);
 
 // Show navigation bar
 if (empty($action) || $action=='show_month')
@@ -1278,7 +1280,7 @@ $db->close();
 function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventarray, $maxprint=0, $maxnbofchar=16, $newparam='', $showinfo=0, $minheight=60, $nonew=0)
 {
     global $user, $conf, $langs;
-    global $action, $filter, $filtert, $status, $actioncode;	// Filters used into search form
+    global $action, $filter, $filtert, $status, $actioncode, $usergroup;	// Filters used into search form
     global $theme_datacolor;
     global $cachethirdparties, $cachecontacts, $cacheusers, $colorindexused;
 
@@ -1637,6 +1639,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa
                 	print '<a href="'.DOL_URL_ROOT.'/comm/action/index.php?action='.$action.'&maxprint=0&month='.$monthshown.'&year='.$year;
                     print ($status?'&status='.$status:'').($filter?'&filter='.$filter:'');
                     print ($filtert?'&filtert='.$filtert:'');
+                    print ($usergroup?'&usergroup='.$usergroup:'');
                     print ($actioncode!=''?'&actioncode='.$actioncode:'');
                     print '">'.img_picto("all","1downarrow_selected.png").' ...';
                     print ' +'.(count($eventarray[$daykey])-$maxprint);

+ 80 - 35
htdocs/comm/action/list.php

@@ -41,27 +41,28 @@ $langs->loadLangs(array("users","companies","agenda","commercial"));
 
 $action=GETPOST('action','alpha');
 $contextpage=GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'actioncommlist';   // To manage different context of search
-$resourceid=GETPOST("resourceid","int");
+$resourceid=GETPOST("search_resourceid","int")?GETPOST("search_resourceid","int"):GETPOST("resourceid","int");
+$pid=GETPOST("search_projectid",'int',3)?GETPOST("search_projectid",'int',3):GETPOST("projectid",'int',3);
+$status=GETPOST("search_status",'alpha')?GETPOST("search_status",'alpha'):GETPOST("status",'alpha');
+$type=GETPOST('search_type','alphanohtml')?GETPOST('search_type','alphanohtml'):GETPOST('type','alphanohtml');
+$optioncss = GETPOST('optioncss','alpha');
 $year=GETPOST("year",'int');
 $month=GETPOST("month",'int');
 $day=GETPOST("day",'int');
-$pid=GETPOST("projectid",'int',3);
-$status=GETPOST("status",'alpha');
-$type=GETPOST('type','alphanohtml');
-$optioncss = GETPOST('optioncss','alpha');
 // Set actioncode (this code must be same for setting actioncode into peruser, listacton and index)
-if (GETPOST('actioncode','array'))
+if (GETPOST('search_actioncode','array'))
 {
-    $actioncode=GETPOST('actioncode','array',3);
+    $actioncode=GETPOST('search_actioncode','array',3);
     if (! count($actioncode)) $actioncode='0';
 }
 else
 {
-    $actioncode=GETPOST("actioncode","alpha",3)?GETPOST("actioncode","alpha",3):(GETPOST("actioncode")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE));
+    $actioncode=GETPOST("search_actioncode","alpha",3)?GETPOST("search_actioncode","alpha",3):(GETPOST("search_actioncode")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE));
 }
 if ($actioncode == '' && empty($actioncodearray)) $actioncode=(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE);
 $search_id=GETPOST('search_id','alpha');
 $search_title=GETPOST('search_title','alpha');
+$search_note=GETPOST('search_note','alpha');
 
 $dateselect=dol_mktime(0, 0, 0, GETPOST('dateselectmonth','int'), GETPOST('dateselectday','int'), GETPOST('dateselectyear','int'));
 $datestart=dol_mktime(0, 0, 0, GETPOST('datestartmonth','int'), GETPOST('datestartday','int'), GETPOST('datestartyear','int'));
@@ -69,10 +70,10 @@ $dateend=dol_mktime(0, 0, 0, GETPOST('dateendmonth','int'), GETPOST('dateendday'
 if ($status == ''   && ! isset($_GET['status']) && ! isset($_POST['status'])) $status=(empty($conf->global->AGENDA_DEFAULT_FILTER_STATUS)?'':$conf->global->AGENDA_DEFAULT_FILTER_STATUS);
 if (empty($action) && ! isset($_GET['action']) && ! isset($_POST['action'])) $action=(empty($conf->global->AGENDA_DEFAULT_VIEW)?'show_month':$conf->global->AGENDA_DEFAULT_VIEW);
 
-$filter = GETPOST("filter",'alpha',3);
-$filtert = GETPOST("filtert","int",3);
-$usergroup = GETPOST("usergroup","int",3);
-$showbirthday = empty($conf->use_javascript_ajax)?GETPOST("showbirthday","int"):1;
+$filter = GETPOST("search_filter",'alpha',3)?GETPOST("search_filter",'alpha',3):GETPOST("filter",'alpha',3);
+$filtert = GETPOST("search_filtert","int",3)?GETPOST("search_filtert","int",3):GETPOST("filtert","int",3);
+$usergroup = GETPOST("search_usergroup","int",3)?GETPOST("search_usergroup","int",3):GETPOST("usergroup","int",3);
+$showbirthday = empty($conf->use_javascript_ajax)?(GETPOST("search_showbirthday","int")?GETPOST("search_showbirthday","int"):GETPOST("showbirthday","int")):1;
 
 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
 $object = new ActionComm($db);
@@ -108,7 +109,7 @@ if (! $sortfield)
 }
 
 // Security check
-$socid = GETPOST("socid",'int');
+$socid = GETPOST("search_socid",'int')?GETPOST("search_socid",'int'):GETPOST("socid",'int');
 if ($user->societe_id) $socid=$user->societe_id;
 $result = restrictedArea($user, 'agenda', 0, '', 'myactions');
 if ($socid < 0) $socid='';
@@ -126,20 +127,22 @@ $arrayfields=array(
 	'owner'=>array('label'=>"Owner", 'checked'=>1),
 	'c.libelle'=>array('label'=>"Type", 'checked'=>1),
 	'a.label'=>array('label'=>"Title", 'checked'=>1),
+	'a.note'=>array('label'=>'Description', 'checked'=>0),
 	'a.datep'=>array('label'=>"DateStart", 'checked'=>1),
 	'a.datep2'=>array('label'=>"DateEnd", 'checked'=>1),
 	's.nom'=>array('label'=>"ThirdParty", 'checked'=>1),
 	'a.fk_contact'=>array('label'=>"Contact", 'checked'=>1),
 	'a.fk_element'=>array('label'=>"LinkedObject", 'checked'=>0, 'enabled'=>(! empty($conf->global->AGENDA_SHOW_LINKED_OBJECT))),
 	'a.percent'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000),
-
+	'a.datec'=>array('label'=>'DateCreation', 'checked'=>0),
+	'a.tms'=>array('label'=>'DateModification', 'checked'=>0)
 );
 // Extra fields
 if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
 {
    foreach($extrafields->attribute_label as $key => $val)
    {
-		 $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]);
+		if (! empty($extrafields->attribute_list[$key])) $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]);
    }
 }
 
@@ -175,6 +178,7 @@ if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x',
     //$actioncode='';
     $search_id='';
 	$search_title='';
+    $search_note='';
     $datestart='';
     $dateend='';
     $status='';
@@ -207,41 +211,49 @@ if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&con
 if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit);
 if ($actioncode != '') {
 	if(is_array($actioncode)) {
-		foreach($actioncode as $str_action) $param.="&actioncode[]=".urlencode($str_action);
-	} else $param.="&actioncode=".urlencode($actioncode);
+		foreach($actioncode as $str_action) $param.="&search_actioncode[]=".urlencode($str_action);
+	} else $param.="&search_actioncode=".urlencode($actioncode);
 }
-if ($resourceid > 0) $param.="&resourceid=".urlencode($resourceid);
-if ($status != '' && $status > -1) $param.="&status=".urlencode($status);
-if ($filter) $param.="&filter=".urlencode($filter);
-if ($filtert) $param.="&filtert=".urlencode($filtert);
-if ($socid) $param.="&socid=".urlencode($socid);
-if ($showbirthday) $param.="&showbirthday=1";
-if ($pid) $param.="&projectid=".urlencode($pid);
-if ($type) $param.="&type=".urlencode($type);
-if ($usergroup) $param.="&usergroup=".urlencode($usergroup);
-if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss);
+if ($resourceid > 0) $param.="&search_resourceid=".urlencode($resourceid);
+if ($status != '' && $status > -1) $param.="&search_status=".urlencode($status);
+if ($filter) $param.="&search_filter=".urlencode($filter);
+if ($filtert) $param.="&search_filtert=".urlencode($filtert);
+if ($socid) $param.="&search_socid=".urlencode($socid);
+if ($showbirthday) $param.="&search_showbirthday=1";
+if ($pid) $param.="&search_projectid=".urlencode($pid);
+if ($type) $param.="&search_type=".urlencode($type);
+if ($usergroup) $param.="&search_usergroup=".urlencode($usergroup);
 if ($search_id != '') $param.='&search_title='.urlencode($search_id);
 if ($search_title != '') $param.='&search_title='.urlencode($search_title);
+if ($search_note != '') $param.='&search_note='.$search_note;
 if (GETPOST('datestartday','int')) $param.='&datestartday='.GETPOST('datestartday','int');
 if (GETPOST('datestartmonth','int')) $param.='&datestartmonth='.GETPOST('datestartmonth','int');
 if (GETPOST('datestartyear','int')) $param.='&datestartyear='.GETPOST('datestartyear','int');
 if (GETPOST('dateendday','int')) $param.='&dateendday='.GETPOST('dateendday','int');
 if (GETPOST('dateendmonth','int')) $param.='&dateendmonth='.GETPOST('dateendmonth','int');
 if (GETPOST('dateendyear','int')) $param.='&dateendyear='.GETPOST('dateendyear','int');
+if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss);
 // Add $param from extra fields
 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
 
 $sql = "SELECT";
 if ($usergroup > 0) $sql.=" DISTINCT";
-$sql.= " s.nom as societe, s.rowid as socid, s.client,";
-$sql.= " a.id, a.label, a.datep as dp, a.datep2 as dp2,";
+$sql.= " s.nom as societe, s.rowid as socid, s.client, s.email as socemail,";
+$sql.= " a.id, a.label, a.note, a.datep as dp, a.datep2 as dp2,";
 $sql.= ' a.fk_user_author,a.fk_user_action,';
 $sql.= " a.fk_contact, a.note, a.percent as percent,";
-$sql.= " a.fk_element, a.elementtype,";
+$sql.= " a.fk_element, a.elementtype, a.datec, a.tms as datem,";
 $sql.= " c.code as type_code, c.libelle as type_label,";
 $sql.= " sp.lastname, sp.firstname, sp.email, sp.phone, sp.address, sp.phone as phone_pro, sp.phone_mobile, sp.phone_perso, sp.fk_pays as country_id";
+
 // Add fields from extrafields
 foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
+
+// Add fields from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+
 $sql.= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
 $sql.=" LEFT JOIN ".MAIN_DB_PREFIX."actioncomm_extrafields as ef ON (a.id = ef.fk_object) ";
 if (! $user->rights->societe->client->voir && ! $socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON a.fk_soc = sc.fk_soc";
@@ -300,6 +312,7 @@ if ($status == 'done') { $sql.= " AND (a.percent = 100)"; }
 if ($status == 'todo') { $sql.= " AND (a.percent >= 0 AND a.percent < 100)"; }
 if ($search_id) $sql.=natural_search("a.id", $search_id, 1);
 if ($search_title) $sql.=natural_search("a.label", $search_title);
+if ($search_note) $sql.=natural_search('a.note', $search_note);
 // We must filter on assignement table
 if ($filtert > 0 || $usergroup > 0)
 {
@@ -313,9 +326,15 @@ if ($filtert > 0 || $usergroup > 0)
 if ($dateselect > 0) $sql.= " AND ((a.datep2 >= '".$db->idate($dateselect)."' AND a.datep <= '".$db->idate($dateselect+3600*24-1)."') OR (a.datep2 IS NULL AND a.datep > '".$db->idate($dateselect-3600)."' AND a.datep <= '".$db->idate($dateselect+3600*24-1)."'))";
 if ($datestart > 0) $sql.= " AND a.datep BETWEEN '".$db->idate($datestart)."' AND '".$db->idate($datestart+3600*24-1)."'";
 if ($dateend > 0) $sql.= " AND a.datep2 BETWEEN '".$db->idate($dateend)."' AND '".$db->idate($dateend+3600*24-1)."'";
+
 // Add where from extra fields
 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
 
+// Add where from hooks
+$parameters=array();
+$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters);    // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+
 $sql.= $db->order($sortfield,$sortorder);
 
 $nbtotalofrecords = '';
@@ -364,10 +383,10 @@ if ($resql)
 
 	//if ($actioncode)    $nav.='<input type="hidden" name="actioncode" value="'.$actioncode.'">';
 	//if ($resourceid)      $nav.='<input type="hidden" name="resourceid" value="'.$resourceid.'">';
-	if ($filter)          $nav.='<input type="hidden" name="filter" value="'.$filter.'">';
+	if ($filter)          $nav.='<input type="hidden" name="search_filter" value="'.$filter.'">';
 	//if ($filtert)         $nav.='<input type="hidden" name="filtert" value="'.$filtert.'">';
 	//if ($socid)           $nav.='<input type="hidden" name="socid" value="'.$socid.'">';
-	if ($showbirthday)    $nav.='<input type="hidden" name="showbirthday" value="1">';
+	if ($showbirthday)    $nav.='<input type="hidden" name="search_showbirthday" value="1">';
 	//if ($pid)             $nav.='<input type="hidden" name="projectid" value="'.$pid.'">';
 	//if ($usergroup)       $nav.='<input type="hidden" name="usergroup" value="'.$usergroup.'">';
 	print $nav;
@@ -461,8 +480,9 @@ if ($resql)
 	$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters);    // Note that $action and $object may have been modified by hook
 	print $hookmanager->resPrint;
 
-
-    if (! empty($arrayfields['a.percent']['checked']))	{
+	if (! empty($arrayfields['a.datec']['checked']))	print '<td class="liste_titre"></td>';
+	if (! empty($arrayfields['a.tms']['checked']))		print '<td class="liste_titre"></td>';
+	if (! empty($arrayfields['a.percent']['checked']))	{
 		print '<td class="liste_titre center">';
     	print $formactions->form_select_status_action('formaction',$status,1,'status',1,2);
     	print ajax_combobox('selectstatus');
@@ -480,6 +500,7 @@ if ($resql)
 	if (! empty($arrayfields['owner']['checked']))        print_liste_field_titre($arrayfields['owner']['label'], $_SERVER["PHP_SELF"],"",$param,"","",$sortfield,$sortorder);
 	if (! empty($arrayfields['c.libelle']['checked']))	  print_liste_field_titre($arrayfields['c.libelle']['label'], $_SERVER["PHP_SELF"],"c.libelle",$param,"","",$sortfield,$sortorder);
 	if (! empty($arrayfields['a.label']['checked']))	  print_liste_field_titre($arrayfields['a.label']['label'], $_SERVER["PHP_SELF"],"a.label",$param,"","",$sortfield,$sortorder);
+	if (! empty($arrayfields['a.note']['checked']))		  print_liste_field_titre($arrayfields['a.note']['label'], $_SERVER["PHP_SELF"],"a.note",$param,"","",$sortfield,$sortorder);
 	//if (! empty($conf->global->AGENDA_USE_EVENT_TYPE))
 	if (! empty($arrayfields['a.datep']['checked']))	  print_liste_field_titre($arrayfields['a.datep']['label'], $_SERVER["PHP_SELF"],"a.datep",$param,'','align="center"',$sortfield,$sortorder);
 	if (! empty($arrayfields['a.datep2']['checked']))	  print_liste_field_titre($arrayfields['a.datep2']['label'], $_SERVER["PHP_SELF"],"a.datep2",$param,'','align="center"',$sortfield,$sortorder);
@@ -494,6 +515,10 @@ if ($resql)
 	$parameters=array('arrayfields'=>$arrayfields,'param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder);
 	$reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters);    // Note that $action and $object may have been modified by hook
 	print $hookmanager->resPrint;
+
+	if (! empty($arrayfields['a.datec']['checked'])) print_liste_field_titre($arrayfields['a.datec']['label'], $_SERVER["PHP_SELF"],"a.datec,a.id",$param,"",'align="center"',$sortfield,$sortorder);
+	if (! empty($arrayfields['a.tms']['checked'])) print_liste_field_titre($arrayfields['a.tms']['label'], $_SERVER["PHP_SELF"],"a.tms,a.id",$param,"",'align="center"',$sortfield,$sortorder);
+
 	if (! empty($arrayfields['a.percent']['checked']))print_liste_field_titre("Status",$_SERVER["PHP_SELF"],"a.percent",$param,"",'align="center"',$sortfield,$sortorder);
 	print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ');
 	print "</tr>\n";
@@ -523,6 +548,7 @@ if ($resql)
 		$actionstatic->type_label=$obj->type_label;
 		$actionstatic->type_picto=$obj->type_picto;
 		$actionstatic->label=$obj->label;
+		$actionstatic->note=dol_htmlentitiesbr($obj->note);
 
 		print '<tr class="oddeven">';
 
@@ -576,6 +602,14 @@ if ($resql)
 			print '</td>';
 		}
 
+		// Description
+		if (! empty($arrayfields['a.note']['checked'])) {
+			print '<td class="tdoverflowonsmartphone">';
+			$text = dolGetFirstLineOfText(dol_string_nohtmltag($actionstatic->note, 0));
+			print $form->textwithtooltip(dol_trunc($text,40), $actionstatic->note);
+			print '</td>';
+		}
+
 		// Start date
 		if (! empty($arrayfields['a.datep']['checked'])) {
 			print '<td align="center">';
@@ -599,11 +633,13 @@ if ($resql)
 		// Third party
 		if (! empty($arrayfields['s.nom']['checked'])) {
 			print '<td class="tdoverflowmax100">';
-			if ($obj->socid)
+			if ($obj->socid > 0)
 			{
 				$societestatic->id=$obj->socid;
 				$societestatic->client=$obj->client;
 				$societestatic->name=$obj->societe;
+				$societestatic->email=$obj->socemail;
+
 				print $societestatic->getNomUrl(1,'',28);
 			}
 			else print '&nbsp;';
@@ -652,6 +688,15 @@ if ($resql)
 		$reshook=$hookmanager->executeHooks('printFieldListValue',$parameters);    // Note that $action and $object may have been modified by hook
 		print $hookmanager->resPrint;
 
+		// Date creation
+		if (! empty($arrayfields['a.datec']['checked'])) {
+			// Status/Percent
+			print '<td align="center" class="nowrap">'.dol_print_date($obj->datec, 'dayhour').'</td>';
+		}
+		// Date update
+		if (! empty($arrayfields['a.tms']['checked'])) {
+			print '<td align="center" class="nowrap">'.dol_print_date($obj->datem, 'dayhour').'</td>';
+		}
 		if (! empty($arrayfields['a.percent']['checked'])) {
 			// Status/Percent
 			$datep=$db->jdate($obj->datep);

+ 40 - 26
htdocs/comm/action/peruser.php

@@ -41,9 +41,9 @@ require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
 
 if (! isset($conf->global->AGENDA_MAX_EVENTS_DAY_VIEW)) $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW=3;
 
-$filter = GETPOST("filter",'alpha',3);
-$filtert = GETPOST("filtert","int",3);
-$usergroup = GETPOST("usergroup","int",3);
+$filter = GETPOST("search_filter",'alpha',3)?GETPOST("search_filter",'alpha',3):GETPOST("filter",'alpha',3);
+$filtert = GETPOST("search_filtert","int",3)?GETPOST("search_filtert","int",3):GETPOST("filtert","int",3);
+$usergroup = GETPOST("search_usergroup","int",3)?GETPOST("search_usergroup","int",3):GETPOST("usergroup","int",3);
 //if (! ($usergroup > 0) && ! ($filtert > 0)) $filtert = $user->id;
 //$showbirthday = empty($conf->use_javascript_ajax)?GETPOST("showbirthday","int"):1;
 $showbirthday = 0;
@@ -64,7 +64,7 @@ if (! $sortorder) $sortorder="ASC";
 if (! $sortfield) $sortfield="a.datec";
 
 // Security check
-$socid = GETPOST("socid","int");
+$socid = GETPOST("search_socid","int")?GETPOST("search_socid","int"):GETPOST("socid","int");
 if ($user->societe_id) $socid=$user->societe_id;
 $result = restrictedArea($user, 'agenda', 0, '', 'myactions');
 if ($socid < 0) $socid='';
@@ -79,24 +79,24 @@ if (! $user->rights->agenda->allactions->read || $filter =='mine')  // If no per
 
 //$action=GETPOST('action','alpha');
 $action='show_peruser'; //We use 'show_week' mode
-$resourceid=GETPOST("resourceid","int");
+$resourceid=GETPOST("search_resourceid","int")?GETPOST("search_resourceid","int"):GETPOST("resourceid","int");
 $year=GETPOST("year","int")?GETPOST("year","int"):date("Y");
 $month=GETPOST("month","int")?GETPOST("month","int"):date("m");
 $week=GETPOST("week","int")?GETPOST("week","int"):date("W");
 $day=GETPOST("day","int")?GETPOST("day","int"):date("d");
-$pid=GETPOST("projectid","int",3);
-$status=GETPOST("status",'alpha');
-$type=GETPOST("type",'alpha');
+$pid=GETPOST("search_projectid","int",3)?GETPOST("search_projectid","int",3):GETPOST("projectid","int",3);
+$status=GETPOST("search_status",'alpha')?GETPOST("search_status",'alpha'):GETPOST("status",'alpha');
+$type=GETPOST("search_type",'alpha')?GETPOST("search_type",'alpha'):GETPOST("type",'alpha');
 $maxprint=((GETPOST("maxprint",'int')!='')?GETPOST("maxprint",'int'):$conf->global->AGENDA_MAX_EVENTS_DAY_VIEW);
 // Set actioncode (this code must be same for setting actioncode into peruser, listacton and index)
-if (GETPOST('actioncode','array'))
+if (GETPOST('search_actioncode','array'))
 {
-    $actioncode=GETPOST('actioncode','array',3);
+    $actioncode=GETPOST('search_actioncode','array',3);
     if (! count($actioncode)) $actioncode='0';
 }
 else
 {
-    $actioncode=GETPOST("actioncode","alpha",3)?GETPOST("actioncode","alpha",3):(GETPOST("actioncode","alpha")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE));
+    $actioncode=GETPOST("search_actioncode","alpha",3)?GETPOST("search_actioncode","alpha",3):(GETPOST("search_actioncode","alpha")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE));
 }
 if ($actioncode == '' && empty($actioncodearray)) $actioncode=(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE);
 
@@ -201,25 +201,25 @@ if ($status == 'done') $title=$langs->trans("DoneActions");
 if ($status == 'todo') $title=$langs->trans("ToDoActions");
 
 $param='';
-if ($actioncode || isset($_GET['actioncode']) || isset($_POST['actioncode'])) {
+if ($actioncode || isset($_GET['search_actioncode']) || isset($_POST['search_actioncode'])) {
 	if(is_array($actioncode)) {
-		foreach($actioncode as $str_action) $param.="&actioncode[]=".urlencode($str_action);
-	} else $param.="&actioncode=".urlencode($actioncode);
+		foreach($actioncode as $str_action) $param.="&search_actioncode[]=".urlencode($str_action);
+	} else $param.="&search_actioncode=".urlencode($actioncode);
 }
-if ($resourceid > 0) $param.="&resourceid=".urlencode($resourceid);
-if ($status || isset($_GET['status']) || isset($_POST['status'])) $param.="&status=".urlencode($status);
-if ($filter)  $param.="&filter=".urlencode($filter);
-if ($filtert) $param.="&filtert=".urlencode($filtert);
-if ($usergroup) $param.="&usergroup=".urlencode($usergroup);
-if ($socid)   $param.="&socid=".urlencode($socid);
-if ($showbirthday) $param.="&showbirthday=1";
-if ($pid)     $param.="&projectid=".urlencode($pid);
-if ($type)   $param.="&type=".urlencode($type);
+if ($resourceid > 0) $param.="&search_resourceid=".urlencode($resourceid);
+if ($status || isset($_GET['status']) || isset($_POST['status'])) $param.="&search_status=".urlencode($status);
+if ($filter)        $param.="&search_filter=".urlencode($filter);
+if ($filtert)       $param.="&search_filtert=".urlencode($filtert);
+if ($usergroup)     $param.="&search_usergroup=".urlencode($usergroup);
+if ($socid)         $param.="&search_socid=".urlencode($socid);
+if ($showbirthday)  $param.="&search_showbirthday=1";
+if ($pid)           $param.="&search_projectid=".urlencode($pid);
+if ($type)          $param.="&search_type=".urlencode($type);
 if ($action == 'show_day' || $action == 'show_week' || $action == 'show_month' || $action != 'show_peruser') $param.='&action='.urlencode($action);
 if ($begin_h != '') $param.='&begin_h='.urlencode($begin_h);
-if ($end_h != '') $param.='&end_h='.urlencode($end_h);
+if ($end_h != '')   $param.='&end_h='.urlencode($end_h);
 if ($begin_d != '') $param.='&begin_d='.urlencode($begin_d);
-if ($end_d != '') $param.='&end_d='.urlencode($end_d);
+if ($end_d != '')   $param.='&end_d='.urlencode($end_d);
 $param.="&maxprint=".urlencode($maxprint);
 
 
@@ -358,9 +358,23 @@ if ($conf->use_javascript_ajax)
 }
 
 
+$newcardbutton='';
+if ($user->rights->agenda->myactions->create || $user->rights->agenda->allactions->create)
+{
+	$tmpforcreatebutton=dol_getdate(dol_now(), true);
+
+	$newparam.='&month='.str_pad($month, 2, "0", STR_PAD_LEFT).'&year='.$tmpforcreatebutton['year'];
+
+	//$param='month='.$monthshown.'&year='.$year;
+	$hourminsec='100000';
+	$newcardbutton = '<a class="butActionNew" href="'.DOL_URL_ROOT.'/comm/action/card.php?action=create&datep='.sprintf("%04d%02d%02d",$tmpforcreatebutton['year'],$tmpforcreatebutton['mon'],$tmpforcreatebutton['mday']).$hourminsec.'&backtopage='.urlencode($_SERVER["PHP_SELF"].($newparam?'?'.$newparam:'')).'"><span class="valignmiddle">'.$langs->trans("AddAction").'</span>';
+	$newcardbutton.= '<span class="fa fa-plus-circle valignmiddle"></span>';
+	$newcardbutton.= '</a>';
+}
 
 $link='';
-print load_fiche_titre($s, $link.' &nbsp; &nbsp; '.$nav, '');
+print load_fiche_titre($s, $link.' &nbsp; &nbsp; '.$nav.' '.$newcardbutton, '');
+
 
 
 // Get event in an array

+ 10 - 10
htdocs/comm/card.php

@@ -327,7 +327,7 @@ if ($object->id > 0)
 	print '</td><td>';
 	if ($action == 'editconditions')
 	{
-		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id',1);
+		$form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1);
 	}
 	else
 	{
@@ -346,7 +346,7 @@ if ($object->id > 0)
 	print '</td><td>';
 	if ($action == 'editmode')
 	{
-		$form->form_modes_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id,$object->mode_reglement_id,'mode_reglement_id');
+		$form->form_modes_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
 	}
 	else
 	{
@@ -1136,7 +1136,7 @@ if ($object->id > 0)
 	 */
 	if (! empty($conf->facture->enabled) && $user->rights->facture->lire)
 	{
-        $sql = 'SELECT f.rowid as facid, f.facnumber, f.type, f.amount';
+        $sql = 'SELECT f.rowid as facid, f.ref, f.type, f.amount';
         $sql.= ', f.total as total_ht';
         $sql.= ', f.tva as total_tva';
         $sql.= ', f.total_ttc';
@@ -1147,7 +1147,7 @@ if ($object->id > 0)
 		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON f.rowid=pf.fk_facture';
 		$sql.= " WHERE f.fk_soc = s.rowid AND s.rowid = ".$object->id;
 		$sql.= " AND f.entity IN (".getEntity('invoice').")";
-		$sql.= ' GROUP BY f.rowid, f.facnumber, f.type, f.amount, f.total, f.tva, f.total_ttc,';
+		$sql.= ' GROUP BY f.rowid, f.ref, f.type, f.amount, f.total, f.tva, f.total_ttc,';
 		$sql.= ' f.datef, f.datec, f.paye, f.fk_statut,';
 		$sql.= ' s.nom, s.rowid';
 		$sql.= " ORDER BY f.datef DESC, f.datec DESC";
@@ -1176,7 +1176,7 @@ if ($object->id > 0)
 				$objp = $db->fetch_object($resql);
 
 				$facturestatic->id = $objp->facid;
-				$facturestatic->ref = $objp->facnumber;
+				$facturestatic->ref = $objp->ref;
 				$facturestatic->type = $objp->type;
 				$facturestatic->total_ht = $objp->total_ht;
 				$facturestatic->total_tva = $objp->total_tva;
@@ -1242,7 +1242,7 @@ if ($object->id > 0)
     {
         if ($object->status != 1)
         {
-            print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyIsClosed")).'" href="#">'.$langs->trans("ThirdPartyIsClosed").'</a></div>';
+            print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("ThirdPartyIsClosed")).'" href="#">'.$langs->trans("ThirdPartyIsClosed").'</a></div>';
         }
 
     	if (! empty($conf->propal->enabled) && $user->rights->propal->creer && $object->status==1)
@@ -1282,7 +1282,7 @@ if ($object->id > 0)
     		{
     			if (empty($user->rights->facture->creer))
     			{
-    			    print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("NotAllowed")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
+    			    print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("NotAllowed")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     			}
     			else
     			{
@@ -1294,13 +1294,13 @@ if ($object->id > 0)
     				    if ($object->client != 0 && $object->client != 2)
     				    {
     					   if (! empty($orders2invoice) && $orders2invoice > 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/orderstoinvoice.php?socid='.$object->id.'">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
-    					   else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("NoOrdersToInvoice")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
+    					   else print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("NoOrdersToInvoice")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
     				    }
-    				    else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
+    				    else print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     				}
 
     				if ($object->client != 0 && $object->client != 2) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&socid='.$object->id.'">'.$langs->trans("AddBill").'</a></div>';
-    				else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
+    				else print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     			}
     		}
     	}

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

@@ -995,7 +995,7 @@ else
 
 				if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! $user->rights->mailing->mailing_advance->send)
 				{
-					print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("TestMailing").'</a>';
+					print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("TestMailing").'</a>';
 				}
 				else
 				{
@@ -1006,11 +1006,11 @@ else
 				{
 					if ($object->nbemail <= 0)
 					{
-						print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NoTargetYet")).'">'.$langs->trans("ValidMailing").'</a>';
+						print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NoTargetYet")).'">'.$langs->trans("ValidMailing").'</a>';
 					}
 					else if (empty($user->rights->mailing->valider))
 					{
-						print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("ValidMailing").'</a>';
+						print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("ValidMailing").'</a>';
 					}
 					else
 					{
@@ -1022,11 +1022,11 @@ else
 				{
 					if ($conf->global->MAILING_LIMIT_SENDBYWEB < 0)
 					{
-						print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("SendingFromWebInterfaceIsNotAllowed")).'">'.$langs->trans("SendMailing").'</a>';
+						print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("SendingFromWebInterfaceIsNotAllowed")).'">'.$langs->trans("SendMailing").'</a>';
 					}
 					else if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! $user->rights->mailing->mailing_advance->send)
 					{
-						print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("SendMailing").'</a>';
+						print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("SendMailing").'</a>';
 					}
 					else
 					{
@@ -1043,7 +1043,7 @@ else
 				{
 					if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! $user->rights->mailing->mailing_advance->send)
 					{
-						print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("ResetMailing").'</a>';
+						print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("ResetMailing").'</a>';
 					}
 					else
 					{
@@ -1055,7 +1055,7 @@ else
 				{
 					if ($object->statut > 0 && (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! $user->rights->mailing->mailing_advance->delete))
 					{
-						print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("DeleteMailing").'</a>';
+						print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("DeleteMailing").'</a>';
 					}
 					else
 					{

+ 6 - 8
htdocs/comm/mailing/cibles.php

@@ -72,7 +72,7 @@ $object = new Mailing($db);
 
 if ($action == 'add')
 {
-	$module=GETPOST("module");
+	$module=GETPOST("module",'alpha');
 	$result=-1;
 
 	foreach ($modulesdir as $dir)
@@ -89,14 +89,10 @@ if ($action == 'add')
 		{
 			require_once $file;
 
-			// We fill $filtersarray. Using this variable is now deprecated. Kept for backward compatibility.
-			$filtersarray=array();
-			if (isset($_POST["filter"])) $filtersarray[0]=$_POST["filter"];
-
 			// Add targets into database
 			$obj = new $classname($db);
 			dol_syslog("Call add_to_target on class ".$classname);
-			$result=$obj->add_to_target($id,$filtersarray);
+			$result=$obj->add_to_target($id);
 		}
 	}
 	if ($result > 0)
@@ -329,14 +325,16 @@ if ($object->fetch($id) >= 0)
 				// Si le module mailing est qualifie
 				if ($qualified)
 				{
+					$var = ! $var;
+
 					if ($allowaddtarget)
 					{
-						print '<form class="oddeven tagtr" 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 class="oddeven tagtr">';
+					    print '<div '.$bctag[$var].'>';
 					}
 
 					print '<div class="tagtd">';

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

@@ -745,7 +745,16 @@ class AdvanceTargetingMailing extends CommonObject
 				$sqlwhere[]= " (t.civility IN ('".$this->db->escape(implode("','",$arrayquery['contact_civility']))."'))";
 			}
 			if ($arrayquery['contact_no_email']!='') {
-				$sqlwhere[]= " (t.no_email='".$this->db->escape($arrayquery['contact_no_email'])."')";
+				$tmpwhere = '';
+				if (! empty($arrayquery['contact_no_email']))
+				{
+					$tmpwhere.= "(t.email IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE t.entity IN (".getEntity('mailing').") AND email = '".$this->db->escape($arrayquery['contact_no_email'])."'))";
+				}
+				else
+				{
+					$tmpwhere.= "(t.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE t.entity IN (".getEntity('mailing').") AND email = '".$this->db->escape($arrayquery['contact_no_email'])."'))";
+				}
+				$sqlwhere[]= $tmpwhere;
 			}
 			if ($arrayquery['contact_update_st_dt']!='') {
 				$sqlwhere[]= " (t.tms >= '".$this->db->idate($arrayquery['contact_update_st_dt'])."' AND t.tms <= '".$this->db->idate($arrayquery['contact_update_end_dt'])."')";

+ 101 - 13
htdocs/comm/propal/card.php

@@ -10,8 +10,8 @@
  * Copyright (C) 2012-2013 Christophe Battarel   <christophe.battarel@altairis.fr>
  * Copyright (C) 2012      Cedric Salvador       <csalvador@gpcsolutions.fr>
  * Copyright (C) 2013-2014 Florian Henry		 <florian.henry@open-concept.pro>
- * Copyright (C) 2014	   Ferran Marcet		 <fmarcet@2byte.es>
- * Copyright (C) 2016      Marcos García         <marcosgdf@gmail.com>
+ * Copyright (C) 2014       Ferran Marcet		 <fmarcet@2byte.es>
+ * Copyright (C) 2016       Marcos García         <marcosgdf@gmail.com>
  * Copyright (C) 2018       Frédéric France         <frederic.france@netlogic.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -696,6 +696,88 @@ if (empty($reshook))
 			}
 		}
 	}
+	
+	// add lines from objectlinked
+	elseif($action == 'import_lines_from_object'
+	    && $user->rights->propal->creer
+	    && $object->statut == Propal::STATUS_DRAFT
+	    )
+	{
+	    $fromElement = GETPOST('fromelement');
+	    $fromElementid = GETPOST('fromelementid');
+	    $importLines = GETPOST('line_checkbox');
+	    
+	    if(!empty($importLines) && is_array($importLines) && !empty($fromElement) && ctype_alpha($fromElement) && !empty($fromElementid))
+	    {
+	        if($fromElement == 'commande')
+	        {
+	            dol_include_once('/'.$fromElement.'/class/'.$fromElement.'.class.php');
+	            $lineClassName = 'OrderLine';
+	        }
+	        elseif($fromElement == 'propal')
+	        {
+	            dol_include_once('/comm/'.$fromElement.'/class/'.$fromElement.'.class.php');
+	            $lineClassName = 'PropaleLigne';
+	        }
+	        $nextRang = count($object->lines) + 1;
+	        $importCount = 0;
+	        $error = 0;
+	        foreach($importLines as $lineId)
+	        {
+	            $lineId = intval($lineId);
+	            $originLine = new $lineClassName($db);
+	            if(intval($fromElementid) > 0 && $originLine->fetch( $lineId ) > 0)
+	            {
+	                $originLine->fetch_optionals($lineId);
+	                $desc = $originLine->desc;
+	                $pu_ht = $originLine->subprice;
+	                $qty = $originLine->qty;
+	                $txtva = $originLine->tva_tx;
+	                $txlocaltax1 = $originLine->localtax1_tx;
+	                $txlocaltax2 = $originLine->localtax2_tx;
+	                $fk_product = $originLine->fk_product;
+	                $remise_percent = $originLine->remise_percent;
+	                $date_start = $originLine->date_start;
+	                $date_end = $originLine->date_end;
+	                $ventil = 0;
+	                $info_bits = $originLine->info_bits;
+	                $fk_remise_except = $originLine->fk_remise_except;
+	                $price_base_type='HT';
+	                $pu_ttc=0;
+	                $type = $originLine->product_type;
+	                $rang=$nextRang++;
+	                $special_code = $originLine->special_code;
+	                $origin = $originLine->element;
+	                $origin_id = $originLine->id;
+	                $fk_parent_line=0;
+	                $fk_fournprice=$originLine->fk_fournprice;
+	                $pa_ht = $originLine->pa_ht;
+	                $label = $originLine->label;
+	                $array_options = $originLine->array_options;
+	                $situation_percent = 100;
+	                $fk_prev_id = '';
+	                $fk_unit = $originLine->fk_unit;
+	                $pu_ht_devise = $originLine->multicurrency_subprice;
+	                
+	                $res = $object->addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $price_base_type, $pu_ttc, $info_bits, $type, $rang, $special_code, $fk_parent_line, $fk_fournprice, $pa_ht, $label,$date_start, $date_end,$array_options, $fk_unit, $origin, $origin_id, $pu_ht_devise, $fk_remise_except);
+	                
+	                if($res > 0){
+	                    $importCount++;
+	                }else{
+	                    $error++;
+	                }
+	            }
+	            else{
+	                $error++;
+	            }
+	        }
+	        
+	        if($error)
+	        {
+	            setEventMessages($langs->trans('ErrorsOnXLines',$error), null, 'errors');
+	        }
+	    }
+	}
 
 	include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
 
@@ -959,7 +1041,7 @@ if (empty($reshook))
 					$desc = $prod->description;
 				}
 
-				$desc = dol_concatdesc($desc, $product_desc);
+				$desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->CHANGE_ORDER_CONCAT_DESCRIPTION));
 
 				// Add dimensions into product description
 				/*if (empty($conf->global->MAIN_PRODUCT_DISABLE_AUTOADD_DIM))
@@ -1627,7 +1709,7 @@ if ($action == 'create')
 	if (! empty($conf->multicurrency->enabled))
 	{
 		print '<tr>';
-		print '<td>'.fieldLabel('Currency','multicurrency_code').'</td>';
+		print '<td>'.$form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0).'</td>';
 		print '<td class="maxwidthonsmartphone">';
 		print $form->selectMultiCurrency($currency_code, 'multicurrency_code', 0);
 		print '</td></tr>';
@@ -2105,7 +2187,7 @@ if ($action == 'create')
 	print '</tr></table>';
 	print '</td><td>';
 	if (! empty($object->brouillon) && $action == 'editmode' && $usercancreate) {
-		$form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id');
+		$form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
 	} else {
 		$form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'none');
 	}
@@ -2118,7 +2200,7 @@ if ($action == 'create')
 		print '<tr>';
 		print '<td>';
 		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print fieldLabel('Currency','multicurrency_code');
+		print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
 		print '</td>';
 		if ($action != 'editmulticurrencycode' && ! empty($object->brouillon) && $usercancreate)
 			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencycode&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
@@ -2135,7 +2217,7 @@ if ($action == 'create')
 		print '<tr>';
 		print '<td>';
 		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print fieldLabel('CurrencyRate','multicurrency_tx');
+		print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
 		print '</td>';
 		if ($action != 'editmulticurrencyrate' && ! empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency && $usercancreate)
 			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencyrate&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
@@ -2243,17 +2325,17 @@ if ($action == 'create')
 	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 '<tr><td class="titlefieldmiddle">' . $form->editfieldkey('MulticurrencyAmountHT', 'multicurrency_total_ht', '', $object, 0) . '</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 '<tr><td>' . $form->editfieldkey('MulticurrencyAmountVAT', 'multicurrency_total_tva', '', $object, 0) . '</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 '<tr><td>' . $form->editfieldkey('MulticurrencyAmountTTC', 'multicurrency_total_ttc', '', $object, 0) . '</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>';
 	}
@@ -2381,7 +2463,7 @@ if ($action == 'create')
 						print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=validate">' . $langs->trans('Validate') . '</a></div>';
 					}
 					else
-						print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">' . $langs->trans('Validate') . '</a></div>';
+						print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans('Validate') . '</a></div>';
 				}
 				// Create event
 				/*if ($conf->agenda->enabled && ! empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD)) 	// Add hidden condition because this is not a "workflow" action so should appears somewhere else on page.
@@ -2404,7 +2486,7 @@ if ($action == 'create')
 					if ($usercansend) {
 						print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=presend&mode=init#formmailbeforetitle">' . $langs->trans('SendMail') . '</a></div>';
 					} else
-						print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">' . $langs->trans('SendMail') . '</a></div>';
+						print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans('SendMail') . '</a></div>';
 				}
 
 				// Create an order
@@ -2488,7 +2570,13 @@ if ($action == 'create')
 
 		// Show links to link elements
 		$linktoelem = $form->showLinkToObjectBlock($object, null, array('propal'));
-		$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
+		
+		$compatibleImportElementsList = false;
+		if($user->rights->propal->creer && $object->statut == Propal::STATUS_DRAFT)
+		{
+		    $compatibleImportElementsList = array('commande','propal'); // import from linked elements
+		}
+		$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
 
 		// Show online signature link
 		$useonlinesignature = $conf->global->MAIN_FEATURES_LEVEL;	// Replace this with 1 when feature to make online signature is ok

+ 34 - 31
htdocs/comm/propal/class/propal.class.php

@@ -14,6 +14,7 @@
  * Copyright (C) 2014-2015 Marcos García            <marcosgdf@gmail.com>
  * Copyright (C) 2018      Nicolas ZABOURI			<info@inovea-conseil.com>
  * Copyright (C) 2018      Frédéric France          <frederic.france@netlogic.fr>
+ * Copyright (C) 2018      Ferran Marcet         	<fmarcet@2byte.es>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -438,38 +439,40 @@ class Propal extends CommonObject
 		global $mysoc, $conf, $langs;
 
 		dol_syslog(get_class($this)."::addline propalid=$this->id, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, fk_product=$fk_product, remise_except=$remise_percent, price_base_type=$price_base_type, pu_ttc=$pu_ttc, info_bits=$info_bits, type=$type, fk_remise_except=".$fk_remise_except);
-		include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
-
-		// Clean parameters
-		if (empty($remise_percent)) $remise_percent=0;
-		if (empty($qty)) $qty=0;
-		if (empty($info_bits)) $info_bits=0;
-		if (empty($rang)) $rang=0;
-		if (empty($fk_parent_line) || $fk_parent_line < 0) $fk_parent_line=0;
-
-		$remise_percent=price2num($remise_percent);
-		$qty=price2num($qty);
-		$pu_ht=price2num($pu_ht);
-		$pu_ht_devise=price2num($pu_ht_devise);
-		$pu_ttc=price2num($pu_ttc);
-		$txtva=price2num($txtva);               // $txtva can have format '5.0(XXX)' or '5'
-		$txlocaltax1=price2num($txlocaltax1);
-		$txlocaltax2=price2num($txlocaltax2);
-		$pa_ht=price2num($pa_ht);
-		if ($price_base_type=='HT')
-		{
-			$pu=$pu_ht;
-		}
-		else
+		if ($this->statut == self::STATUS_DRAFT)
 		{
-			$pu=$pu_ttc;
-		}
+			include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
+
+			// Clean parameters
+			if (empty($remise_percent)) $remise_percent=0;
+			if (empty($qty)) $qty=0;
+			if (empty($info_bits)) $info_bits=0;
+			if (empty($rang)) $rang=0;
+			if (empty($fk_parent_line) || $fk_parent_line < 0) $fk_parent_line=0;
+
+			$remise_percent=price2num($remise_percent);
+			$qty=price2num($qty);
+			$pu_ht=price2num($pu_ht);
+			$pu_ht_devise=price2num($pu_ht_devise);
+			$pu_ttc=price2num($pu_ttc);
+			if (!preg_match('/\((.*)\)/', $txtva)) {
+				$txtva = price2num($txtva);               // $txtva can have format '5,1' or '5.1' or '5.1(XXX)', we must clean only if '5,1'
+			}
+			$txlocaltax1=price2num($txlocaltax1);
+			$txlocaltax2=price2num($txlocaltax2);
+			$pa_ht=price2num($pa_ht);
+			if ($price_base_type=='HT')
+			{
+				$pu=$pu_ht;
+			}
+			else
+			{
+				$pu=$pu_ttc;
+			}
 
-		// Check parameters
-		if ($type < 0) return -1;
+			// Check parameters
+			if ($type < 0) return -1;
 
-		if ($this->statut == self::STATUS_DRAFT)
-		{
 			$this->db->begin();
 
 			$product_type=$type;
@@ -2432,7 +2435,7 @@ class Propal extends CommonObject
 	 *  @param		int		$notrigger	1=Does not execute triggers, 0=Execute triggers
 	 *	@return     int         		<0 if KO, >0 if OK
 	 */
-	function cloture($user, $statut, $note, $notrigger=0)
+	function cloture($user, $statut, $note="", $notrigger=0)
 	{
 		global $langs,$conf;
 
@@ -2775,7 +2778,7 @@ class Propal extends CommonObject
 
 		if (count($linkedInvoices) > 0)
 		{
-			$sql= "SELECT rowid as facid, facnumber, total, datef as df, fk_user_author, fk_statut, paye";
+			$sql= "SELECT rowid as facid, ref, total, datef as df, fk_user_author, fk_statut, paye";
 			$sql.= " FROM ".MAIN_DB_PREFIX."facture";
 			$sql.= " WHERE rowid IN (".implode(',',$linkedInvoices).")";
 

+ 21 - 46
htdocs/comm/propal/list.php

@@ -11,7 +11,7 @@
  * Copyright (C) 2013      Cédric Salvador       <csalvador@gpcsolutions.fr>
  * Copyright (C) 2015      Jean-François Ferry     <jfefe@aternatik.fr>
  * Copyright (C) 2016-2018 Ferran Marcet	 <fmarcet@2byte.es>
- * Copyright (C) 2017      Charlene Benke	 <charlie@patas-monkey.com>
+ * Copyright (C) 2017-2018 Charlene Benke	 <charlie@patas-monkey.com>
  * Copyright (C) 2018	   Nicolas ZABOURI	 <info@inovea-conseil.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -45,7 +45,7 @@ require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
 
 // Load translation files required by the page
-$langs->loadLangs(array('companies','propal','compta','bills','orders','products','deliveries'));
+$langs->loadLangs(array('companies', 'propal', 'compta', 'bills', 'orders', 'products', 'deliveries', 'categories'));
 
 $socid=GETPOST('socid','int');
 
@@ -175,9 +175,6 @@ if (is_array($extrafields->attribute_label) && count($extrafields->attribute_lab
 	}
 }
 
-$object = new Propal($db);	// To be passed as parameter of executeHooks that need
-
-
 /*
  * Actions
  */
@@ -258,7 +255,7 @@ $projectstatic=new Project($db);
 $formcompany=new FormCompany($db);
 
 $help_url='EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos';
-llxHeader('',$langs->trans('Proposal'),$help_url);
+//llxHeader('',$langs->trans('Proposal'),$help_url);
 
 $sql = 'SELECT';
 if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT';
@@ -332,45 +329,9 @@ if ($viewstatut != '' && $viewstatut != '-1')
 {
 	$sql.= ' AND p.fk_statut IN ('.$db->escape($viewstatut).')';
 }
-if ($search_month > 0)
-{
-	if ($search_year > 0 && empty($search_day))
-	$sql.= " AND p.datep BETWEEN '".$db->idate(dol_get_first_day($search_year,$search_month,false))."' AND '".$db->idate(dol_get_last_day($search_year,$search_month,false))."'";
-	else if ($search_year > 0 && ! empty($search_day))
-	$sql.= " AND p.datep BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $search_month, $search_day, $search_year))."' AND '".$db->idate(dol_mktime(23, 59, 59, $search_month, $search_day, $search_year))."'";
-	else
-	$sql.= " AND date_format(p.datep, '%m') = '".$db->escape($search_month)."'";
-}
-else if ($search_year > 0)
-{
-	$sql.= " AND p.datep BETWEEN '".$db->idate(dol_get_first_day($search_year,1,false))."' AND '".$db->idate(dol_get_last_day($search_year,12,false))."'";
-}
-if ($search_month_end > 0)
-{
-	if ($search_yearfin > 0 && empty($search_dayfin))
-		$sql.= " AND p.fin_validite BETWEEN '".$db->idate(dol_get_first_day($search_yearfin,$search_month_end,false))."' AND '".$db->idate(dol_get_last_day($search_yearfin,$search_month_end,false))."'";
-	else if ($search_yearfin > 0 && ! empty($search_dayfin))
-		$sql.= " AND p.fin_validite BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $search_month_end, $search_dayfin, $search_yearfin))."' AND '".$db->idate(dol_mktime(23, 59, 59, $search_month_end, $search_dayfin, $search_yearfin))."'";
-	else
-		$sql.= " AND date_format(p.fin_validite, '%m') = '".$db->escape($search_month_end)."'";
-}
-else if ($search_yearfin > 0)
-{
-	$sql.= " AND p.fin_validite BETWEEN '".$db->idate(dol_get_first_day($search_yearfin,1,false))."' AND '".$db->idate(dol_get_last_day($search_yearfin,12,false))."'";
-}
-if ($search_monthdelivery > 0)
-{
-	if ($search_yeardelivery > 0 && empty($search_daydelivery))
-		$sql.= " AND p.date_livraison BETWEEN '".$db->idate(dol_get_first_day($search_yeardelivery,$search_monthdelivery,false))."' AND '".$db->idate(dol_get_last_day($search_yeardelivery,$search_monthdelivery,false))."'";
-	else if ($search_yeardelivery > 0 && ! empty($search_daydelivery))
-		$sql.= " AND p.date_livraison BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $search_monthdelivery, $search_daydelivery, $search_yeardelivery))."' AND '".$db->idate(dol_mktime(23, 59, 59, $search_monthdelivery, $search_daydelivery, $search_yeardelivery))."'";
-	else
-		$sql.= " AND date_format(p.date_livraison, '%m') = '".$db->escape($search_monthdelivery)."'";
-}
-else if ($search_yeardelivery > 0)
-{
-	$sql.= " AND p.date_livraison BETWEEN '".$db->idate(dol_get_first_day($search_yeardelivery,1,false))."' AND '".$db->idate(dol_get_last_day($search_yeardelivery,12,false))."'";
-}
+$sql.= dolSqlDateFilter("p.datep", $search_day, $search_month, $search_year);
+$sql.= dolSqlDateFilter("p.fin_validite", $search_dayfin, $search_month_end, $search_yearfin);
+$sql.= dolSqlDateFilter("p.date_livraison", $search_daydelivery, $search_monthdelivery, $search_yeardelivery);
 if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$db->escape($search_sale);
 if ($search_user > 0)
 {
@@ -404,6 +365,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
 $sql.= $db->plimit($limit+1, $offset);
 
 $resql=$db->query($sql);
+
 if ($resql)
 {
 	$objectstatic=new Propal($db);
@@ -425,6 +387,18 @@ if ($resql)
 
 	$arrayofselected=is_array($toselect)?$toselect:array();
 
+	if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall)
+	{
+		$obj = $db->fetch_object($resql);
+
+		$id = $obj->rowid;
+
+		header("Location: ".DOL_URL_ROOT.'/comm/propal/card.php?id='.$id);
+		exit;
+	}
+
+	llxHeader('',$langs->trans('Proposal'),$help_url);
+
 	$param='&viewstatut='.urlencode($viewstatut);
 	if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage);
 	if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit);
@@ -452,11 +426,12 @@ if ($resql)
 
 	// List of mass actions available
 	$arrayofmassactions =  array(
+		'generate_doc'=>$langs->trans("Generate"),
 		'presend'=>$langs->trans("SendByMail"),
 		'builddoc'=>$langs->trans("PDFMerge"),
 	);
 	if ($user->rights->propal->supprimer) $arrayofmassactions['predelete']=$langs->trans("Delete");
-	if ($user->rights->propal->cloturer) $arrayofmassactions['closed']=$langs->trans("Closed");
+	if ($user->rights->propal->cloturer) $arrayofmassactions['closed']=$langs->trans("Close");
 	if (in_array($massaction, array('presend','predelete','closed'))) $arrayofmassactions=array();
 	$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
 

+ 13 - 13
htdocs/comm/remx.php

@@ -407,7 +407,7 @@ if ($socid > 0)
 	if($isCustomer) {
 		if($isSupplier) {
 			print '<div class="fichecenter">';
-			print '<div class="fichehalfleft">';
+			print '<div class="fichehalfleft fichehalfleft-lg">';
 			print load_fiche_titre($langs->trans("CustomerDiscounts"), '', '');
 		}
 
@@ -415,7 +415,7 @@ if ($socid > 0)
 		$sql.= " rc.datec as dc, rc.description,";
 		$sql.= " rc.fk_facture_source,";
 		$sql.= " u.login, u.rowid as user_id,";
-		$sql.= " fa.facnumber as ref, fa.type as type";
+		$sql.= " fa.ref as ref, fa.type as type";
 		$sql.= " FROM  ".MAIN_DB_PREFIX."user as u, ".MAIN_DB_PREFIX."societe_remise_except as rc";
 		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."facture as fa ON rc.fk_facture_source = fa.rowid";
 		$sql.= " WHERE rc.fk_soc = " . $object->id;
@@ -542,7 +542,7 @@ if ($socid > 0)
 	if($isSupplier) {
 		if($isCustomer) {
 			print '</div>'; // class="fichehalfleft"
-			print '<div class="fichehalfright">';
+			print '<div class="fichehalfright fichehalfright-lg">';
 			print '<div class="ficheaddleft">';
 			print load_fiche_titre($langs->trans("SupplierDiscounts"), '', '');
 		}
@@ -695,7 +695,7 @@ if ($socid > 0)
 	if($isCustomer) {
 		if($isSupplier) {
 			print '<div class="fichecenter">';
-			print '<div class="fichehalfleft">';
+			print '<div class="fichehalfleft fichehalfleft-lg">';
 			print load_fiche_titre($langs->trans("CustomerDiscounts"), '', '');
 		}
 
@@ -704,8 +704,8 @@ if ($socid > 0)
 		$sql.= " rc.datec as dc, rc.description, rc.fk_facture_line, rc.fk_facture,";
 		$sql.= " rc.fk_facture_source,";
 		$sql.= " u.login, u.rowid as user_id,";
-		$sql.= " f.rowid, f.facnumber,";
-		$sql.= " fa.facnumber as ref, fa.type as type";
+		$sql.= " f.rowid, f.ref,";
+		$sql.= " fa.ref as ref, fa.type as type";
 		$sql.= " FROM ".MAIN_DB_PREFIX."facture as f";
 		$sql.= " , ".MAIN_DB_PREFIX."user as u";
 		$sql.= " , ".MAIN_DB_PREFIX."facturedet as fc";
@@ -723,8 +723,8 @@ if ($socid > 0)
 		$sql2.= " rc.datec as dc, rc.description, rc.fk_facture_line, rc.fk_facture,";
 		$sql2.= " rc.fk_facture_source,";
 		$sql2.= " u.login, u.rowid as user_id,";
-		$sql2.= " f.rowid, f.facnumber,";
-		$sql2.= " fa.facnumber as ref, fa.type as type";
+		$sql2.= " f.rowid, f.ref,";
+		$sql2.= " fa.ref as ref, fa.type as type";
 		$sql2.= " FROM ".MAIN_DB_PREFIX."facture as f";
 		$sql2.= " , ".MAIN_DB_PREFIX."user as u";
 		$sql2.= " , ".MAIN_DB_PREFIX."societe_remise_except as rc";
@@ -819,7 +819,7 @@ if ($socid > 0)
 	    				print $obj->description;
 	    				print '</td>';
 	    			}
-	    			print '<td align="left" class="nowrap"><a href="'.DOL_URL_ROOT.'/compta/facture/card.php?facid='.$obj->rowid.'">'.img_object($langs->trans("ShowBill"),'bill').' '.$obj->facnumber.'</a></td>';
+	    			print '<td align="left" class="nowrap"><a href="'.DOL_URL_ROOT.'/compta/facture/card.php?facid='.$obj->rowid.'">'.img_object($langs->trans("ShowBill"),'bill').' '.$obj->ref.'</a></td>';
 	    			print '<td align="right">'.price($obj->amount_ht).'</td>';
 	    			print '<td align="right">'.price2num($obj->tva_tx,'MU').'%</td>';
 	    			print '<td align="right">'.price($obj->amount_ttc).'</td>';
@@ -848,7 +848,7 @@ if ($socid > 0)
 	if($isSupplier) {
 		if($isCustomer) {
 			print '</div>'; // class="fichehalfleft"
-			print '<div class="fichehalfright">';
+			print '<div class="fichehalfright fichehalfright-lg">';
 			print '<div class="ficheaddleft">';
 			print load_fiche_titre($langs->trans("SupplierDiscounts"), '', '');
 		}
@@ -858,7 +858,7 @@ if ($socid > 0)
 		$sql.= " rc.datec as dc, rc.description, rc.fk_invoice_supplier_line, rc.fk_invoice_supplier,";
 		$sql.= " rc.fk_invoice_supplier_source,";
 		$sql.= " u.login, u.rowid as user_id,";
-		$sql.= " f.rowid, f.ref as facnumber,";
+		$sql.= " f.rowid, f.ref as ref,";
 		$sql.= " fa.ref, fa.type as type";
 		$sql.= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
 		$sql.= " , ".MAIN_DB_PREFIX."user as u";
@@ -877,7 +877,7 @@ if ($socid > 0)
 		$sql2.= " rc.datec as dc, rc.description, rc.fk_invoice_supplier_line, rc.fk_invoice_supplier,";
 		$sql2.= " rc.fk_invoice_supplier_source,";
 		$sql2.= " u.login, u.rowid as user_id,";
-		$sql2.= " f.rowid, f.ref as facnumber,";
+		$sql2.= " f.rowid, f.ref as ref,";
 		$sql2.= " fa.ref, fa.type as type";
 		$sql2.= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
 		$sql2.= " , ".MAIN_DB_PREFIX."user as u";
@@ -973,7 +973,7 @@ if ($socid > 0)
 						print $obj->description;
 						print '</td>';
 					}
-					print '<td align="left" class="nowrap"><a href="'.DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$obj->rowid.'">'.img_object($langs->trans("ShowBill"),'bill').' '.$obj->facnumber.'</a></td>';
+					print '<td align="left" class="nowrap"><a href="'.DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$obj->rowid.'">'.img_object($langs->trans("ShowBill"),'bill').' '.$obj->ref.'</a></td>';
 					print '<td align="right">'.price($obj->amount_ht).'</td>';
 					print '<td align="right">'.price2num($obj->tva_tx,'MU').'%</td>';
 					print '<td align="right">'.price($obj->amount_ttc).'</td>';

+ 157 - 119
htdocs/commande/card.php

@@ -106,7 +106,8 @@ $permissionedit = $user->rights->commande->creer; 		// Used by the include of ac
  */
 
 $parameters = array('socid' => $socid);
-$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
+// Note that $action and $object may be modified by some hooks
+$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
 
 if (empty($reshook))
@@ -419,10 +420,11 @@ if (empty($reshook))
 
 						// Hooks
 						$parameters = array('objFrom' => $srcobject);
-						$reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
-						// modified by hook
-						if ($reshook < 0)
+						// Note that $action and $object may be modified by hook
+						$reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action);
+						if ($reshook < 0) {
 							$error++;
+						}
 					} else {
 						setEventMessages($object->error, $object->errors, 'errors');
 						$error++;
@@ -866,7 +868,7 @@ if (empty($reshook))
 					$desc = $prod->description;
 				}
 
-				$desc = dol_concatdesc($desc, $product_desc);
+				$desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->CHANGE_ORDER_CONCAT_DESCRIPTION));
 
 				// Add custom code and origin country into description
 				if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
@@ -1318,6 +1320,88 @@ if (empty($reshook))
 		exit();
 	}
 
+	// add lines from objectlinked
+	if($action == 'import_lines_from_object'
+	    && $user->rights->commande->creer
+	    && $object->statut == Commande::STATUS_DRAFT
+	  )
+	{
+	    $fromElement = GETPOST('fromelement');
+	    $fromElementid = GETPOST('fromelementid');
+	    $importLines = GETPOST('line_checkbox');
+	    
+	    if(!empty($importLines) && is_array($importLines) && !empty($fromElement) && ctype_alpha($fromElement) && !empty($fromElementid))
+	    {
+	        if($fromElement == 'commande')
+	        {
+	            dol_include_once('/'.$fromElement.'/class/'.$fromElement.'.class.php');
+	            $lineClassName = 'OrderLine';
+	        }
+	        elseif($fromElement == 'propal')
+	        {
+	            dol_include_once('/comm/'.$fromElement.'/class/'.$fromElement.'.class.php');
+	            $lineClassName = 'PropaleLigne';
+	        }
+	        $nextRang = count($object->lines) + 1;
+	        $importCount = 0;
+	        $error = 0;
+	        foreach($importLines as $lineId)
+	        {
+	            $lineId = intval($lineId);
+	            $originLine = new $lineClassName($db);
+	            if(intval($fromElementid) > 0 && $originLine->fetch( $lineId ) > 0)
+	            {
+	                $originLine->fetch_optionals($lineId);
+	                $desc = $originLine->desc;
+	                $pu_ht = $originLine->subprice;
+	                $qty = $originLine->qty;
+	                $txtva = $originLine->tva_tx;
+	                $txlocaltax1 = $originLine->localtax1_tx;
+	                $txlocaltax2 = $originLine->localtax2_tx;
+	                $fk_product = $originLine->fk_product;
+	                $remise_percent = $originLine->remise_percent;
+	                $date_start = $originLine->date_start;
+	                $date_end = $originLine->date_end;
+	                $ventil = 0;
+	                $info_bits = $originLine->info_bits;
+	                $fk_remise_except = $originLine->fk_remise_except;
+	                $price_base_type='HT';
+	                $pu_ttc=0;
+	                $type = $originLine->product_type;
+	                $rang=$nextRang++;
+	                $special_code = $originLine->special_code;
+	                $origin = $originLine->element;
+	                $origin_id = $originLine->id;
+	                $fk_parent_line=0;
+	                $fk_fournprice=$originLine->fk_fournprice;
+	                $pa_ht = $originLine->pa_ht;
+	                $label = $originLine->label;
+	                $array_options = $originLine->array_options;
+	                $situation_percent = 100;
+	                $fk_prev_id = '';
+	                $fk_unit = $originLine->fk_unit;
+	                $pu_ht_devise = $originLine->multicurrency_subprice;
+	                
+	                $res = $object->addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $info_bits, $fk_remise_except, $price_base_type, $pu_ttc, $date_start, $date_end, $type, $rang, $special_code, $fk_parent_line, $fk_fournprice, $pa_ht, $label,$array_options, $fk_unit, $origin, $origin_id, $pu_ht_devise);
+	                
+	                if($res > 0){
+	                    $importCount++;
+	                }else{
+	                    $error++;
+	                }
+	            }
+	            else{
+	                $error++;
+	            }
+	        }
+	        
+	        if($error)
+	        {
+	            setEventMessages($langs->trans('ErrorsOnXLines',$error), null, 'errors');
+	        }
+	    }
+	}
+	
 	// Actions when printing a doc from card
 	include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
 
@@ -1669,7 +1753,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 	// Other attributes
 	$parameters = array('objectsrc' => $objectsrc, 'socid'=>$socid);
-	$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by
+	// Note that $action and $object may be modified by hook
+	$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
 	print $hookmanager->resPrint;
 	if (empty($reshook)) {
 		print $object->showOptionals($extrafields, 'edit');
@@ -1687,7 +1772,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 	if (! empty($conf->multicurrency->enabled))
 	{
 		print '<tr>';
-		print '<td>'.fieldLabel('Currency','multicurrency_code').'</td>';
+		print '<td>'.$form->editfieldkey("Currency", 'multicurrency_code', '', $object, 0).'</td>';
 		print '<td class="maxwidthonsmartphone">';
 		print $form->selectMultiCurrency($currency_code, 'multicurrency_code');
 		print '</td></tr>';
@@ -1969,7 +2054,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Call Hook formConfirm
 		$parameters = array('lineid' => $lineid);
-		$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
+		// Note that $action and $object may be modified by hook
+		$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
 		if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
 		elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
 
@@ -2074,13 +2160,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Date
 		print '<tr><td>';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans('Date');
-		print '</td>';
-
-		if ($action != 'editdate' && $object->brouillon)
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdate&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
-		print '</tr></table>';
+		$editenable = $user->rights->commande->creer && $object->statut == Commande::STATUS_DRAFT;
+		print $form->editfieldkey("Date", 'date', '', $object, $editenable);
 		print '</td><td>';
 		if ($action == 'editdate') {
 			print '<form name="setdate" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
@@ -2100,12 +2181,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Delivery date planed
 		print '<tr><td>';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans('DateDeliveryPlanned');
-		print '</td>';
-		if ($action != 'editdate_livraison')
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdate_livraison&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetDeliveryDate'), 1) . '</a></td>';
-		print '</tr></table>';
+		$editenable = $user->rights->commande->creer;
+		print $form->editfieldkey("DateDeliveryPlanned", 'date_livraison', '', $object, $editenable);
 		print '</td><td>';
 		if ($action == 'editdate_livraison') {
 			print '<form name="setdate_livraison" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
@@ -2125,13 +2202,9 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Shipping Method
 		if (! empty($conf->expedition->enabled)) {
-			print '<tr><td height="10">';
-			print '<table width="100%" class="nobordernopadding"><tr><td>';
-			print $langs->trans('SendingMethod');
-			print '</td>';
-			if ($action != 'editshippingmethod' && $user->rights->commande->creer)
-				print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editshippingmethod&amp;id='.$object->id.'">'.img_edit($langs->trans('SetShippingMode'),1).'</a></td>';
-			print '</tr></table>';
+			print '<tr><td>';
+			$editenable = $user->rights->commande->creer;
+			print $form->editfieldkey("SendingMethod", 'shippingmethod', '', $object, $editenable);
 			print '</td><td>';
 			if ($action == 'editshippingmethod') {
 				$form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
@@ -2144,15 +2217,12 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Warehouse
 		if (! empty($conf->expedition->enabled) && ! empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
+			$langs->load('stocks');
 			require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
 			$formproduct=new FormProduct($db);
 			print '<tr><td>';
-			print '<table width="100%" class="nobordernopadding"><tr><td>';
-			print $langs->trans('Warehouse');
-			print '</td>';
-			if ($action != 'editwarehouse' && $user->rights->commande->creer)
-				print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editwarehouse&amp;id='.$object->id.'">'.img_edit($langs->trans('SetWarehouse'),1).'</a></td>';
-			print '</tr></table>';
+			$editenable = $user->rights->commande->creer;
+			print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $editenable);
 			print '</td><td>';
 			if ($action == 'editwarehouse') {
 				$formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1);
@@ -2165,12 +2235,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Terms of payment
 		print '<tr><td>';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans('PaymentConditionsShort');
-		print '</td>';
-		if ($action != 'editconditions')
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editconditions&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetConditions'), 1) . '</a></td>';
-		print '</tr></table>';
+		$editenable = $user->rights->commande->creer;
+		print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, $editenable);
 		print '</td><td>';
 		if ($action == 'editconditions') {
 			$form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->cond_reglement_id, 'cond_reglement_id', 1);
@@ -2183,15 +2249,11 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// Mode of payment
 		print '<tr><td>';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans('PaymentMode');
-		print '</td>';
-		if ($action != 'editmode')
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmode&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetMode'), 1) . '</a></td>';
-		print '</tr></table>';
+		$editenable = $user->rights->commande->creer;
+		print $form->editfieldkey("PaymentMode", 'mode', '', $object, $editenable);
 		print '</td><td>';
 		if ($action == 'editmode') {
-			$form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id');
+			$form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
 		} else {
 			$form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'none');
 		}
@@ -2203,12 +2265,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 			// Multicurrency code
 			print '<tr>';
 			print '<td>';
-			print '<table class="nobordernopadding" width="100%"><tr><td>';
-			print fieldLabel('Currency','multicurrency_code');
-			print '</td>';
-			if ($action != 'editmulticurrencycode' && ! empty($object->brouillon))
-				print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencycode&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
-			print '</tr></table>';
+			$editenable = $user->rights->commande->creer && $object->statut == Commande::STATUS_DRAFT;
+			print $form->editfieldkey("Currency", 'multicurrencycode', '', $object, $editenable);
 			print '</td><td>';
 			if ($action == 'editmulticurrencycode') {
 				$form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, 'multicurrency_code');
@@ -2220,12 +2278,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 			// Multicurrency rate
 			print '<tr>';
 			print '<td>';
-			print '<table class="nobordernopadding" width="100%"><tr><td>';
-			print fieldLabel('CurrencyRate','multicurrency_tx');
-			print '</td>';
-			if ($action != 'editmulticurrencyrate' && ! empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency)
-				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>';
+			$editenable = $user->rights->commande->creer && $object->multicurrency_code && $object->multicurrency_code != $conf->currency && $object->statut == Commande::STATUS_DRAFT;
+			print $form->editfieldkey("CurrencyRate", 'multicurrencyrate', '', $object, $editenable);
 			print '</td><td>';
 			if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
 				if($action == 'actualizemulticurrencyrate') {
@@ -2244,13 +2298,9 @@ if ($action == 'create' && $user->rights->commande->creer)
 		}
 
 		// Delivery delay
-		print '<tr class="fielddeliverydelay"><td height="10">';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans('AvailabilityPeriod');
-		print '</td>';
-		if ($action != 'editavailability')
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editavailability&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetAvailability'), 1) . '</a></td>';
-		print '</tr></table>';
+		print '<tr class="fielddeliverydelay"><td>';
+		$editenable = $user->rights->commande->creer;
+		print $form->editfieldkey("AvailabilityPeriod", 'availability', '', $object, $editenable);
 		print '</td><td>';
 		if ($action == 'editavailability') {
 			$form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'availability_id', 1);
@@ -2260,13 +2310,9 @@ if ($action == 'create' && $user->rights->commande->creer)
 		print '</td></tr>';
 
 		// Source reason (why we have an ordrer)
-		print '<tr><td height="10">';
-		print '<table class="nobordernopadding" width="100%"><tr><td>';
-		print $langs->trans('Channel');
-		print '</td>';
-		if ($action != 'editdemandreason')
-			print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdemandreason&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetDemandReason'), 1) . '</a></td>';
-		print '</tr></table>';
+		print '<tr><td>';
+		$editenable = $user->rights->commande->creer;
+		print $form->editfieldkey("Channel", 'demandreason', '', $object, $editenable);
 		print '</td><td>';
 		if ($action == 'editdemandreason') {
 			$form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'demand_reason_id', 1);
@@ -2277,13 +2323,9 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 		// 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 '<tr><td>';
+		$editenable = $user->rights->commande->creer;
+		print $form->editfieldkey("SourceMode", 'inputmode', '', $object, $editenable);
 		print '</td><td>';
 		if ($action == 'editinputmode') {
 			$form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'input_mode_id', 1);
@@ -2296,15 +2338,13 @@ if ($action == 'create' && $user->rights->commande->creer)
 		$tmparray=$object->getTotalWeightVolume();
 		$totalWeight=$tmparray['weight'];
 		$totalVolume=$tmparray['volume'];
-		if ($totalWeight)
-		{
+		if ($totalWeight) {
 			print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
 			print '<td>';
 			print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
 			print '</td></tr>';
 		}
-		if ($totalVolume)
-		{
+		if ($totalVolume) {
 			print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
 			print '<td>';
 			print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
@@ -2314,15 +2354,10 @@ if ($action == 'create' && $user->rights->commande->creer)
 		// TODO How record was recorded OrderMode (llx_c_input_method)
 
 		// Incoterms
-		if (!empty($conf->incoterm->enabled))
-		{
+		if (!empty($conf->incoterm->enabled)) {
 			print '<tr><td>';
-			print '<table width="100%" class="nobordernopadding"><tr><td>';
-			print $langs->trans('IncotermLabel');
-			print '<td><td align="right">';
-			if ($user->rights->commande->creer) print '<a href="'.DOL_URL_ROOT.'/commande/card.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
-			else print '&nbsp;';
-			print '</td></tr></table>';
+			$editenable = $user->rights->commande->creer;
+			print $form->editfieldkey("IncotermLabel", 'incoterm', '', $object, $editenable);
 			print '</td>';
 			print '<td>';
 			if ($action != 'editincoterm')
@@ -2337,15 +2372,10 @@ if ($action == 'create' && $user->rights->commande->creer)
 		}
 
 		// Bank Account
-		if (! empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && ! empty($conf->banque->enabled))
-		{
-			print '<tr><td class="nowrap">';
-			print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
-			print $langs->trans('BankAccount');
-			print '<td>';
-			if ($action != 'editbankaccount' && $user->rights->commande->creer)
-				print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editbankaccount&amp;id='.$object->id.'">'.img_edit($langs->trans('SetBankAccount'),1).'</a></td>';
-			print '</tr></table>';
+		if (! empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && ! empty($conf->banque->enabled)) {
+			print '<tr><td>';
+			$editenable = $user->rights->commande->creer;
+			print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, $editenable);
 			print '</td><td>';
 			if ($action == 'editbankaccount') {
 				$form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
@@ -2371,17 +2401,17 @@ if ($action == 'create' && $user->rights->commande->creer)
 		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 '<tr><td class="titlefieldmiddle">' . $form->editfieldkey('MulticurrencyAmountHT', 'multicurrency_total_ht', '', $object, 0) . '</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 '<tr><td>' . $form->editfieldkey('MulticurrencyAmountVAT', 'multicurrency_total_tva', '', $object, 0) . '</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 '<tr><td>' . $form->editfieldkey('MulticurrencyAmountTTC', 'multicurrency_total_ttc', '', $object, 0) . '</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>';
 		}
@@ -2446,12 +2476,11 @@ if ($action == 'create' && $user->rights->commande->creer)
 		 */
 		$result = $object->getLinesArray();
 
-		print '	<form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '#addline' : '#line_' . GETPOST('lineid')) . '" method="POST">
+		print '<form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '#addline' : '#line_' . GETPOST('lineid')) . '" method="POST">
 		<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">
 		<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline') . '">
 		<input type="hidden" name="mode" value="">
-		<input type="hidden" name="id" value="' . $object->id . '">
-		';
+		<input type="hidden" name="id" value="' . $object->id . '">';
 
 		if (! empty($conf->use_javascript_ajax) && $object->statut == Commande::STATUS_DRAFT) {
 			include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
@@ -2477,7 +2506,8 @@ if ($action == 'create' && $user->rights->commande->creer)
 				$object->formAddObjectLine(1, $mysoc, $soc);
 
 				$parameters = array();
-				$reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
+				// Note that $action and $object may be modified by hook
+				$reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action);
 			}
 		}
 		print '</table>';
@@ -2494,15 +2524,15 @@ if ($action == 'create' && $user->rights->commande->creer)
 			print '<div class="tabsAction">';
 
 			$parameters = array();
-			$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
-																									  // modified by hook
+			// Note that $action and $object may be modified by hook
+			$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
 			if (empty($reshook)) {
 				// Send
 				if ($object->statut > Commande::STATUS_DRAFT) {
 					if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->commande->order_advance->send)) {
 						print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=presend&mode=init#formmailbeforetitle">' . $langs->trans('SendMail') . '</a></div>';
 					} else
-						print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">' . $langs->trans('SendMail') . '</a></div>';
+						print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans('SendMail') . '</a></div>';
 				}
 
 				// Valid
@@ -2518,10 +2548,11 @@ if ($action == 'create' && $user->rights->commande->creer)
 					print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id=' . $object->id . '&amp;action=modif">' . $langs->trans('Modify') . '</a></div>';
 				}
 				// Create event
-				/*if ($conf->agenda->enabled && ! empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD)) 				// Add hidden condition because this is not a
-																									  // "workflow" action so should appears somewhere else on
-																									  // page.
+				/*if ($conf->agenda->enabled && ! empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD))
 				{
+					// Add hidden condition because this is not a
+					// "workflow" action so should appears somewhere else on
+					// page.
 					print '<a class="butAction" href="' . DOL_URL_ROOT . '/comm/action/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans("AddAction") . '</a>';
 				}*/
 
@@ -2533,7 +2564,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 						if ($user->rights->ficheinter->creer) {
 							print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/fichinter/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans('AddIntervention') . '</a></div>';
 						} else {
-							print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('AddIntervention') . '</a></div>';
+							print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('AddIntervention') . '</a></div>';
 						}
 					}
 				}
@@ -2557,11 +2588,11 @@ if ($action == 'create' && $user->rights->commande->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('CreateShipment') . '</a></div>';
 							} else {
-								print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . dol_escape_htmltag($langs->trans("NotAllowed")) . '">' . $langs->trans('CreateShipment') . '</a></div>';
+								print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" 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('CreateShipment') . '</a></div>';
+							print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("ErrorModuleSetupNotComplete")) . '">' . $langs->trans('CreateShipment') . '</a></div>';
 						}
 					}
 				}
@@ -2610,7 +2641,7 @@ if ($action == 'create' && $user->rights->commande->creer)
 					if ($numshipping == 0) {
 						print '<div class="inline-block divButAction"><a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=delete">' . $langs->trans('Delete') . '</a></div>';
 					} else {
-						print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("ShippingExist") . '">' . $langs->trans("Delete") . '</a></div>';
+						print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . $langs->trans("ShippingExist") . '">' . $langs->trans("Delete") . '</a></div>';
 					}
 				}
 			}
@@ -2638,7 +2669,14 @@ if ($action == 'create' && $user->rights->commande->creer)
 
 			// Show links to link elements
 			$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
-			$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
+			
+			$compatibleImportElementsList = false;
+			if($user->rights->commande->creer
+			    && $object->statut == Commande::STATUS_DRAFT)
+			{
+			    $compatibleImportElementsList = array('commande','propal'); // import from linked elements
+			}
+			$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem,$compatibleImportElementsList);
 
 			// Show online payment link
 			$useonlinepayment = (! empty($conf->paypal->enabled) || ! empty($conf->stripe->enabled) || ! empty($conf->paybox->enabled));

+ 41 - 39
htdocs/commande/class/commande.class.php

@@ -9,8 +9,8 @@
  * Copyright (C) 2012      Cedric Salvador      <csalvador@gpcsolutions.fr>
  * Copyright (C) 2013      Florian Henry		<florian.henry@open-concept.pro>
  * Copyright (C) 2014-2015 Marcos García        <marcosgdf@gmail.com>
- * Copyright (C) 2016-2017 Ferran Marcet        <fmarcet@2byte.es>
  * Copyright (C) 2018      Nicolas ZABOURI	<info@inovea-conseil.com>
+ * Copyright (C) 2016-2018 Ferran Marcet        <fmarcet@2byte.es>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -1312,45 +1312,47 @@ class Commande extends CommonOrder
 		$logtext.= ", date_end=$date_end, type=$type special_code=$special_code, fk_unit=$fk_unit, origin=$origin, origin_id=$origin_id, pu_ht_devise=$pu_ht_devise";
 		dol_syslog(get_class($this).$logtext, LOG_DEBUG);
 
-		include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
-
-		// Clean parameters
-		if (empty($remise_percent)) $remise_percent=0;
-		if (empty($qty)) $qty=0;
-		if (empty($info_bits)) $info_bits=0;
-		if (empty($rang)) $rang=0;
-		if (empty($txtva)) $txtva=0;
-		if (empty($txlocaltax1)) $txlocaltax1=0;
-		if (empty($txlocaltax2)) $txlocaltax2=0;
-		if (empty($fk_parent_line) || $fk_parent_line < 0) $fk_parent_line=0;
-		if (empty($this->fk_multicurrency)) $this->fk_multicurrency=0;
-
-		$remise_percent=price2num($remise_percent);
-		$qty=price2num($qty);
-		$pu_ht=price2num($pu_ht);
-		$pu_ht_devise=price2num($pu_ht_devise);
-		$pu_ttc=price2num($pu_ttc);
-		$pa_ht=price2num($pa_ht);
-		$txtva = price2num($txtva);
-		$txlocaltax1 = price2num($txlocaltax1);
-		$txlocaltax2 = price2num($txlocaltax2);
-		if ($price_base_type=='HT')
-		{
-			$pu=$pu_ht;
-		}
-		else
+		if ($this->statut == self::STATUS_DRAFT)
 		{
-			$pu=$pu_ttc;
-		}
-		$label=trim($label);
-		$desc=trim($desc);
+			include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
 
-		// Check parameters
-		if ($type < 0) return -1;
+			// Clean parameters
+			if (empty($remise_percent)) $remise_percent=0;
+			if (empty($qty)) $qty=0;
+			if (empty($info_bits)) $info_bits=0;
+			if (empty($rang)) $rang=0;
+			if (empty($txtva)) $txtva=0;
+			if (empty($txlocaltax1)) $txlocaltax1=0;
+			if (empty($txlocaltax2)) $txlocaltax2=0;
+			if (empty($fk_parent_line) || $fk_parent_line < 0) $fk_parent_line=0;
+			if (empty($this->fk_multicurrency)) $this->fk_multicurrency=0;
 
-		if ($this->statut == self::STATUS_DRAFT)
-		{
-			$this->db->begin();
+			$remise_percent=price2num($remise_percent);
+			$qty=price2num($qty);
+			$pu_ht=price2num($pu_ht);
+			$pu_ht_devise=price2num($pu_ht_devise);
+			$pu_ttc=price2num($pu_ttc);
+			$pa_ht=price2num($pa_ht);
+			if (!preg_match('/\((.*)\)/', $txtva)) {
+				$txtva = price2num($txtva);               // $txtva can have format '5,1' or '5.1' or '5.1(XXX)', we must clean only if '5,1'
+			}
+			$txlocaltax1 = price2num($txlocaltax1);
+			$txlocaltax2 = price2num($txlocaltax2);
+			if ($price_base_type=='HT')
+			{
+				$pu=$pu_ht;
+			}
+			else
+			{
+				$pu=$pu_ttc;
+			}
+			$label=trim($label);
+			$desc=trim($desc);
+
+			// Check parameters
+			if ($type < 0) return -1;
+
+            $this->db->begin();
 
 			$product_type=$type;
 			if (!empty($fk_product))
@@ -4021,9 +4023,9 @@ class OrderLine extends CommonOrderLine
 	 *  @param      int		$notrigger	    0=launch triggers after, 1=disable triggers
 	 *	@return	 int  <0 si ko, >0 si ok
 	 */
-	function delete($user=null, $notrigger=0)
+	function delete(User $user, $notrigger=0)
 	{
-		global $conf, $user, $langs;
+		global $conf, $langs;
 
 		$error=0;
 

+ 20 - 29
htdocs/commande/list.php

@@ -10,6 +10,8 @@
  * Copyright (C) 2015       Marcos García           <marcosgdf@gmail.com>
  * Copyright (C) 2015       Jean-François Ferry     <jfefe@aternatik.fr>
  * Copyright (C) 2016       Ferran Marcet           <fmarcet@2byte.es>
+ * Copyright (C) 2018       Charlene Benke	    <charlie@patas-monkey.com>
+
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -74,6 +76,7 @@ $socid=GETPOST('socid','int');
 $search_user=GETPOST('search_user','int');
 $search_sale=GETPOST('search_sale','int');
 $search_total_ht=GETPOST('search_total_ht','alpha');
+$search_total_ttc=GETPOST('search_total_ttc','alpha');
 $search_categ_cus=trim(GETPOST("search_categ_cus",'int'));
 $optioncss = GETPOST('optioncss','alpha');
 $billed = GETPOST('billed','int');
@@ -232,7 +235,7 @@ $projectstatic=new Project($db);
 
 $title=$langs->trans("Orders");
 $help_url="EN:Module_Customers_Orders|FR:Module_Commandes_Clients|ES:Módulo_Pedidos_de_clientes";
-llxHeader('',$title,$help_url);
+// llxHeader('',$title,$help_url);
 
 $sql = 'SELECT';
 if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT';
@@ -300,32 +303,8 @@ if ($viewstatut <> '')
 		$sql .= ' AND ((c.fk_statut IN (1,2)) OR (c.fk_statut = 3 AND c.facture = 0))'; // validated, in process or closed but not billed
 	}
 }
-if ($search_ordermonth > 0)
-{
-	if ($search_orderyear > 0 && empty($search_orderday))
-	$sql.= " AND c.date_commande BETWEEN '".$db->idate(dol_get_first_day($search_orderyear,$search_ordermonth,false))."' AND '".$db->idate(dol_get_last_day($search_orderyear,$search_ordermonth,false))."'";
-	else if ($search_orderyear > 0 && ! empty($search_orderday))
-	$sql.= " AND c.date_commande BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $search_ordermonth, $search_orderday, $search_orderyear))."' AND '".$db->idate(dol_mktime(23, 59, 59, $search_ordermonth, $search_orderday, $search_orderyear))."'";
-	else
-	$sql.= " AND date_format(c.date_commande, '%m') = '".$search_ordermonth."'";
-}
-else if ($search_orderyear > 0)
-{
-	$sql.= " AND c.date_commande BETWEEN '".$db->idate(dol_get_first_day($search_orderyear,1,false))."' AND '".$db->idate(dol_get_last_day($search_orderyear,12,false))."'";
-}
-if ($search_deliverymonth > 0)
-{
-	if ($search_deliveryyear > 0 && empty($search_deliveryday))
-	$sql.= " AND c.date_livraison BETWEEN '".$db->idate(dol_get_first_day($search_deliveryyear,$search_deliverymonth,false))."' AND '".$db->idate(dol_get_last_day($search_deliveryyear,$search_deliverymonth,false))."'";
-	else if ($search_deliveryyear > 0 && ! empty($search_deliveryday))
-	$sql.= " AND c.date_livraison BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $search_deliverymonth, $search_deliveryday, $search_deliveryyear))."' AND '".$db->idate(dol_mktime(23, 59, 59, $search_deliverymonth, $search_deliveryday, $search_deliveryyear))."'";
-	else
-	$sql.= " AND date_format(c.date_livraison, '%m') = '".$search_deliverymonth."'";
-}
-else if ($search_deliveryyear > 0)
-{
-	$sql.= " AND c.date_livraison BETWEEN '".$db->idate(dol_get_first_day($search_deliveryyear,1,false))."' AND '".$db->idate(dol_get_last_day($search_deliveryyear,12,false))."'";
-}
+$sql.= dolSqlDateFilter("c.date_commande", $search_orderday, $search_ordermonth, $search_orderyear);
+$sql.= dolSqlDateFilter("c.date_livraison", $search_deliveryday, $search_deliverymonth, $search_deliveryyear);
 if ($search_town)  $sql.= natural_search('s.town', $search_town);
 if ($search_zip)   $sql.= natural_search("s.zip",$search_zip);
 if ($search_state) $sql.= natural_search("state.nom",$search_state);
@@ -335,6 +314,7 @@ if ($search_company) $sql .= natural_search('s.nom', $search_company);
 if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$search_sale;
 if ($search_user > 0) $sql.= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='commande' AND tc.source='internal' AND ec.element_id = c.rowid AND ec.fk_socpeople = ".$search_user;
 if ($search_total_ht != '') $sql.= natural_search('c.total_ht', $search_total_ht, 1);
+if ($search_total_ttc != '') $sql.= natural_search('c.total_ttc', $search_total_ttc, 1);
 if ($search_project_ref != '') $sql.= natural_search("p.ref",$search_project_ref);
 if ($search_categ_cus > 0) $sql.= " AND cc.fk_categorie = ".$db->escape($search_categ_cus);
 if ($search_categ_cus == -2)   $sql.= " AND cc.fk_categorie IS NULL";
@@ -399,6 +379,16 @@ if ($resql)
 
 	$arrayofselected=is_array($toselect)?$toselect:array();
 
+	if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall)
+	{
+		$obj = $db->fetch_object($resql);
+		$id = $obj->rowid;
+		header("Location: ".DOL_URL_ROOT.'/commande/card.php?id='.$id);
+		exit;
+	}
+
+	llxHeader('',$title,$help_url);
+
 	$param='';
 
 	if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage);
@@ -437,6 +427,7 @@ if ($resql)
 
 	// List of mass actions available
 	$arrayofmassactions =  array(
+		'generate_doc'=>$langs->trans("Generate"),
 		'presend'=>$langs->trans("SendByMail"),
 		'builddoc'=>$langs->trans("PDFMerge"),
 		'cancelorders'=>$langs->trans("Cancel"),
@@ -467,8 +458,8 @@ if ($resql)
 	print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
 	print '<input type="hidden" name="viewstatut" value="'.$viewstatut.'">';
 	print '<input type="hidden" name="socid" value="'.$socid.'">';
-	
-	
+
+
 	print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_commercial.png', 0, $newcardbutton, '', $limit);
 
 	$topicmail="SendOrderRef";

+ 3 - 3
htdocs/commande/orderstoinvoice.php

@@ -136,7 +136,7 @@ if (($action == 'create' || $action == 'add') && !$error)
 	$closeOrders	= GETPOST('autocloseorders') ? true : false;
 
 	// Security check
-	$fieldid = GETPOST('ref','alpha')?'facnumber':'rowid';
+	$fieldid = GETPOST('ref','alpha')?'ref':'rowid';
 	if ($user->societe_id) $socid=$user->societe_id;
 	$result = restrictedArea($user, 'facture', $id,'','','fk_soc',$fieldid);
 
@@ -163,7 +163,7 @@ if (($action == 'create' || $action == 'add') && !$error)
 				// Si facture standard
 				$object->socid				= $_POST['socid'];
 				$object->type				= $_POST['type'];
-				$object->number				= $_POST['facnumber'];
+				$object->number				= $_POST['ref'];
 				$object->date				= $datefacture;
 				$object->note_public		= trim($_POST['note_public']);
 				$object->note				= trim($_POST['note']);
@@ -405,7 +405,7 @@ if ($action == 'create' && !$error)
 	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 	print '<input type="hidden" name="action" value="add">';
 	print '<input type="hidden" name="socid" value="'.$soc->id.'">' ."\n";
-	print '<input name="facnumber" type="hidden" value="provisoire">';
+	print '<input name="ref" type="hidden" value="provisoire">';
 	print '<input name="ref_client" type="hidden" value="'.$ref_client.'">';
 	print '<input name="ref_int" type="hidden" value="'.$ref_int.'">';
 	print '<input type="hidden" name="origin" value="'.GETPOST('origin').'">';

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