diff --git a/ChangeLog b/ChangeLog index 7f210c6fab1..2f9bbcc45c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,20 +26,20 @@ Dolibarr better: - The old driver of "mysql" has been removed. Dolibarr use the new one (mysqli) by default. - Remove not used function calculate_byte(). Use dol_print_size() instead. - Function pdf_getTotalQty is now deprecated. Not used by Dolibarr core. +- Method commande->deleteline($lineid) has been replaced with commande->deleteline($user, $lineid). - Method expensereport->delete(id, user) has been replaced with ->delete(user) Method warehouse->delete(id) has been replace with ->delete(user) This is to follow good practice to make a fetch on object before deleting it. -- The form to add a product to a draft proposal/order/invoice from the product card is hidden by default. +- The form to add a product to a draft proposal/order/invoice, from the product card, is hidden by default. It was not commonly used and usage generates some problems (cost price for margin calculation not entered, vat setting). Set constant PRODUCT_ADD_FORM_ADD_TO to retrieve it. -- The javascript "datatables" library was used to be provided into Dolibarr sources, but it was not used by application. +- The javascript "datatables" library was previously provided into Dolibarr sources, but it was not used by application. So there is no reason to maintain its compatibility with other dolibarr components. If an external module need this - library, this external module must embed hte library in his own sources/packages. -- Trigger name SUPPLIER_PROPOSAL_CREATE has been renamed into PROPOSAL_SUPPLIER_CREATE -- A new paramater sqlfilters was introduced to allow filter on any fields int the REST API. Few old parameters - no more required were also removed. Use this new one if you ware using one of them. -- Method commande->deleteline($lindeid) has been replaced with commande->deleteline($user, $lineid). - + library, this external module must embed the library in his own sources/packages. +- Trigger name SUPPLIER_PROPOSAL_CREATE has been renamed into PROPOSAL_SUPPLIER_CREATE. +- A new paramater sqlfilters was introduced to allow filter on any fields int the REST API. Few old parameters, + no more required, were also removed. Use this new one if you were using one of them. +- The trigger that activate or close a contract line is run on a contract line, not on contract. ***** ChangeLog for 4.0.2 compared to 4.0.1 ***** diff --git a/build/composer/README b/build/composer/README index d58359defec..e6846f2f09b 100644 --- a/build/composer/README +++ b/build/composer/README @@ -1,10 +1,19 @@ -To test upgrade of a lib with composer: +* To list packages -composer update --no-dev --no-autoloader --dry-run ccampbell/chromephp +composer show -i -To upgrade a lib with composer: +* To test upgrade of a lib with composer: + +Remove entry in composer.lock +Edit composer.json to change version to "x.y.z" +composer -v update --root-reqs --no-dev --no-autoloader --dry-run ccampbell/chromephp + +* To upgrade a lib with composer: + +Remove entry in composer.lock +Edit composer.json to change version to "x.y.z" +composer -v update --root-reqs --no-dev --no-autoloader ccampbell/chromephp -composer update --no-dev --no-autoloader ccampbell/chromephp diff --git a/build/debian/README.howto b/build/debian/README.howto index cd7cd93c24e..1b64380cc26 100644 --- a/build/debian/README.howto +++ b/build/debian/README.howto @@ -73,7 +73,8 @@ Ex: https://alioth.debian.org/users/eldy-guest # msgfmt -v -c -o /dev/null XX.po To have status of translation for language XX # To check package integrity -# lintian --pedantic -E -I package.deb To test a package +# lintian --pedantic -E -I package.deb To test a binary package +# lintian --pedantic -E -I package.dsc To test a source package # To manipulate packages # dpkg -l List all packages @@ -181,8 +182,8 @@ To test a package > cp ../build-area/* /srv/chroot/unstable/tmp > sudo schroot -c name_of_chroot > cd /tmp -> lintian --pedantic -E -I dolibarr*.deb -> lintian --pedantic -E -I dolibarr*.dsc +> lintian --no-tag-display-limit --pedantic -E -I dolibarr*.deb +> lintian --no-tag-display-limit --pedantic -E -I dolibarr*.dsc > dpkg -i dolibarr*.deb ou pour avoir des traces: dpkg -D77777 -i dolibarr*.deb > apt-get install -f @@ -295,12 +296,16 @@ If script fails with error Bad certificate, you can set "export PERL_LWP_SSL_VER * Edit orig.tar.gz file to remove - debian - htdocs/includes/ckeditor -- htdocs/includes/jszip +- htdocs/includes/jquery/css +- htdocs/includes/jquery/js +- htdocs/includes/jquery/plugins/flot +- htdocs/includes/jquery/plugins/multiselect - htdocs/includes/jquery/plugins/datatables +- htdocs/includes/jszip - htdocs/includes/mike42 - htdocs/includes/phpexcel or htdocs/includes/phpoffice -- htdocs/includes/swiftmailer - htdocs/includes/restler/framework/Luracast/Restler/explorer +- htdocs/includes/swiftmailer - htdocs/includes/tcpdf or htdocs/includes/tecnickcom And rename file into dolibarr-x.y.z+dfsgw.tgz diff --git a/build/debian/source/lintian-overrides b/build/debian/source/lintian-overrides index 603c27ef4cd..b4c0956e90f 100644 --- a/build/debian/source/lintian-overrides +++ b/build/debian/source/lintian-overrides @@ -1,5 +1,10 @@ # Remove warning, we want to keep both standard and minified sources. -dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jsgantt/* dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jquery/* -# This is a textual data file -source-is-missing htdocs/includes/mobiledetect/mobiledetectlib/Mobile_Detect.json \ No newline at end of file +dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jsgantt/* +dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jstz/* +# Those are false positives, the files are their own sources since +# they are not minified +source-is-missing htdocs/includes/jsgantt/jsgantt.js * +source-is-missing htdocs/includes/jquery/plugins/colorpicker/jquery.colorpicker.js * +source-is-missing htdocs/includes/jquery/plugins/select2/select2.js * +source-is-missing htdocs/includes/jquery/plugins/select2/select2_locale_ar.js * diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index fb3b39feca3..c06d8f0730f 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -1145,6 +1145,9 @@ if ($nboftargetok) { "$DESTI/package_rpm_generic/$FILENAMERPM"=>'Dolibarr installer for Fedora-Redhat-Mandriva-Opensuse (DoliRpm)', "$DESTI/package_rpm_generic/$FILENAMERPMSRC"=>'none', # none means it won't be published on SF "$DESTI/package_debian-ubuntu/${FILENAMEDEB}_all.deb"=>'Dolibarr installer for Debian-Ubuntu (DoliDeb)', + "$DESTI/package_debian-ubuntu/${FILENAMEDEB}_amd64.changes"=>'none', # none means it won't be published on SF + "$DESTI/package_debian-ubuntu/${FILENAMEDEB}.dsc"=>'none', # none means it won't be published on SF + "$DESTI/package_debian-ubuntu/${FILENAMEDEB}.debian.tar.gz"=>'none', # none means it won't be published on SF "$DESTI/package_debian-ubuntu/${FILENAMEDEBSHORT}.orig.tar.gz"=>'none', # none means it won't be published on SF "$DESTI/package_windows/$FILENAMEEXEDOLIWAMP.exe"=>'Dolibarr installer for Windows (DoliWamp)', "$DESTI/standard/$FILENAMETGZ.tgz"=>'Dolibarr ERP-CRM', @@ -1155,6 +1158,10 @@ if ($nboftargetok) { "$DESTI/package_rpm_generic/$FILENAMERPM"=>'package_rpm_generic', "$DESTI/package_rpm_generic/$FILENAMERPMSRC"=>'package_rpm_generic', "$DESTI/package_debian-ubuntu/${FILENAMEDEB}_all.deb"=>'package_debian-ubuntu', + "$DESTI/package_debian-ubuntu/${FILENAMEDEB}_amd64.changes"=>'package_debian-ubuntu', + "$DESTI/package_debian-ubuntu/${FILENAMEDEB}.dsc"=>'package_debian-ubuntu', + "$DESTI/package_debian-ubuntu/${FILENAMEDEB}.debian.tar.gz"=>'package_debian-ubuntu', + "$DESTI/package_debian-ubuntu/${FILENAMEDEBSHORT}.orig.tar.gz"=>'package_debian-ubuntu', "$DESTI/package_debian-ubuntu/${FILENAMEDEBSHORT}.orig.tar.gz"=>'package_debian-ubuntu', "$DESTI/package_windows/$FILENAMEEXEDOLIWAMP.exe"=>'package_windows', "$DESTI/standard/$FILENAMETGZ.tgz"=>'standard', diff --git a/composer.json b/composer.json index 2aa9dd216d6..a8d6b9ee5ff 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "php": ">=5.3.0", "ext-curl": "*", "ccampbell/chromephp": "4.1.0", - "ckeditor/ckeditor": "dev-full/stable", + "ckeditor/ckeditor": "4.5.9", "mike42/escpos-php": "1.2.1", "mobiledetect/mobiledetectlib": "2.8.17", "phpoffice/phpexcel": "1.8.1", diff --git a/composer.lock b/composer.lock index 2e30ef6bd01..b6433991a15 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f666a32d1a59518b8ecc55899e829e79", - "content-hash": "8d110e7d8fca6eca1aa814ee35d0032b", + "hash": "c586663818e933f26657871d86d01dc6", + "content-hash": "09e891bb978d35a48902a5f57760aee9", "packages": [ { "name": "ccampbell/chromephp", @@ -52,16 +52,16 @@ }, { "name": "ckeditor/ckeditor", - "version": "dev-full/stable", + "version": "4.5.11", "source": { "type": "git", "url": "https://github.com/ckeditor/ckeditor-releases.git", - "reference": "4a7a6d717f9a408fa8f9ea53ef2dba4d64b83e91" + "reference": "48155a1e1c7e84736b5a166ad3f33acea2a51255" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/4a7a6d717f9a408fa8f9ea53ef2dba4d64b83e91", - "reference": "4a7a6d717f9a408fa8f9ea53ef2dba4d64b83e91", + "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/48155a1e1c7e84736b5a166ad3f33acea2a51255", + "reference": "48155a1e1c7e84736b5a166ad3f33acea2a51255", "shasum": "" }, "type": "library", @@ -89,7 +89,7 @@ "text", "wysiwyg" ], - "time": "2016-05-12 15:36:04" + "time": "2016-09-07 13:32:39" }, { "name": "mike42/escpos-php", @@ -273,12 +273,12 @@ "source": { "type": "git", "url": "https://github.com/Luracast/Restler-Framework.git", - "reference": "bfe1139b233852b745c6a0ec14d7244ceb3b3fc6" + "reference": "3388d76e73a81f871ce5baa906271071b12cd17f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Luracast/Restler-Framework/zipball/bfe1139b233852b745c6a0ec14d7244ceb3b3fc6", - "reference": "bfe1139b233852b745c6a0ec14d7244ceb3b3fc6", + "url": "https://api.github.com/repos/Luracast/Restler-Framework/zipball/3388d76e73a81f871ce5baa906271071b12cd17f", + "reference": "3388d76e73a81f871ce5baa906271071b12cd17f", "shasum": "" }, "require": { @@ -325,7 +325,7 @@ "rest", "server" ], - "time": "2016-02-28 15:57:37" + "time": "2016-06-21 12:42:18" }, { "name": "tecnickcom/tcpdf", @@ -391,11 +391,1391 @@ "time": "2015-09-12 10:08:34" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "jakub-onderka/php-console-color", + "version": "0.1", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "jakub-onderka/php-code-style": "1.0", + "jakub-onderka/php-parallel-lint": "0.*", + "jakub-onderka/php-var-dump-check": "0.*", + "phpunit/phpunit": "3.7.*", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleColor": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com", + "homepage": "http://www.acci.cz" + } + ], + "time": "2014-04-08 15:00:19" + }, + { + "name": "jakub-onderka/php-console-highlighter", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "shasum": "" + }, + "require": { + "jakub-onderka/php-console-color": "~0.1", + "php": ">=5.3.0" + }, + "require-dev": { + "jakub-onderka/php-code-style": "~1.0", + "jakub-onderka/php-parallel-lint": "~0.5", + "jakub-onderka/php-var-dump-check": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleHighlighter": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "acci@acci.cz", + "homepage": "http://www.acci.cz/" + } + ], + "time": "2015-04-20 18:58:01" + }, + { + "name": "jakub-onderka/php-parallel-lint", + "version": "v0.9.2", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git", + "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa", + "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "jakub-onderka/php-console-highlighter": "~0.3", + "nette/tester": "~1.3" + }, + "suggest": { + "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet" + }, + "bin": [ + "parallel-lint" + ], + "type": "library", + "autoload": { + "classmap": [ + "./" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com" + } + ], + "description": "This tool check syntax of PHP files about 20x faster than serial check.", + "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint", + "time": "2015-12-15 10:42:16" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30 07:12:33" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-06-10 07:14:17" + }, + { + "name": "phpspec/prophecy", + "version": "v1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2016-06-07 08:13:47" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-10-06 15:47:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-06-21 13:08:43" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2016-05-12 18:03:57" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-09-15 10:49:45" + }, + { + "name": "phpunit/phpunit", + "version": "4.8.27", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90", + "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2016-07-21 06:48:14" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-10-02 06:51:40" + }, + { + "name": "phpunit/phpunit-selenium", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/giorgiosironi/phpunit-selenium.git", + "reference": "2bad798ec0daf20d2854400e3bc5329ee0a7b2d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/giorgiosironi/phpunit-selenium/zipball/2bad798ec0daf20d2854400e3bc5329ee0a7b2d1", + "reference": "2bad798ec0daf20d2854400e3bc5329ee0a7b2d1", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-dom": "*", + "php": ">=5.3.3", + "phpunit/phpunit": "~4.8", + "sebastian/comparator": "~1.0" + }, + "require-dev": { + "phing/phing": "2.*" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Giorgio Sironi", + "email": "info@giorgiosironi.com", + "role": "developer" + }, + { + "name": "Ivan Kurnosov", + "email": "zerkms@zerkms.com", + "role": "developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "original developer" + } + ], + "description": "Selenium Server integration for PHPUnit", + "homepage": "http://www.phpunit.de/", + "keywords": [ + "phpunit", + "selenium", + "testing", + "xunit" + ], + "time": "2016-03-01 10:33:56" + }, + { + "name": "sebastian/comparator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-08-18 05:49:44" + }, + { + "name": "sebastian/exporter", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-06-17 09:04:28" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-11-11 19:50:13" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21 13:59:46" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2016-09-01 23:53:02" + }, + { + "name": "symfony/yaml", + "version": "v3.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-10-24 18:41:13" + }, + { + "name": "webmozart/assert", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-08-09 15:02:57" + } + ], "aliases": [], "minimum-stability": "stable", "stability-flags": { - "ckeditor/ckeditor": 20, "restler/framework": 5 }, "prefer-stable": false, diff --git a/dev/skeletons/skeleton_card.php b/dev/skeletons/skeleton_card.php index 9adcdba87de..f0a9dd23c26 100644 --- a/dev/skeletons/skeleton_card.php +++ b/dev/skeletons/skeleton_card.php @@ -53,6 +53,7 @@ $langs->load("other"); // Get parameters $id = GETPOST('id','int'); $action = GETPOST('action','alpha'); +$cancel = GETPOST('cancel'); $backtopage = GETPOST('backtopage'); $myparam = GETPOST('myparam','alpha'); @@ -95,6 +96,18 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e if (empty($reshook)) { + if ($cancel) + { + if ($action != 'addlink') + { + $urltogo=$backtopage?$backtopage:dol_buildpath('/mymodule/list.php',1); + header("Location: ".$urltogo); + exit; + } + if ($id > 0 || ! empty($ref)) $ret = $object->fetch($id,$ref); + $action=''; + } + // Action to add record if ($action == 'add') { @@ -140,11 +153,8 @@ if (empty($reshook)) } } - // Cancel - if ($action == 'update' && GETPOST('cancel')) $action='view'; - // Action to update record - if ($action == 'update' && ! GETPOST('cancel')) + if ($action == 'update') { $error=0; diff --git a/dev/skeletons/skeleton_list.php b/dev/skeletons/skeleton_list.php index c47a87a8033..f571af9873e 100644 --- a/dev/skeletons/skeleton_list.php +++ b/dev/skeletons/skeleton_list.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2007-2016 Laurent Destailleur * Copyright (C) 2014-2016 Juanjo Menent * * This program is free software; you can redistribute it and/or modify @@ -52,9 +52,13 @@ dol_include_once('/mymodule/class/skeleton_class.class.php'); $langs->load("mymodule"); $langs->load("other"); -// Get parameters +$action=GETPOST('action','alpha'); +$massaction=GETPOST('massaction','alpha'); +$show_files=GETPOST('show_files','int'); +$confirm=GETPOST('confirm','alpha'); +$toselect = GETPOST('toselect', 'array'); + $id = GETPOST('id','int'); -$action = GETPOST('action','alpha'); $backtopage = GETPOST('backtopage'); $myparam = GETPOST('myparam','alpha'); @@ -212,7 +216,7 @@ $parameters=array(); $reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook $sql.=$hookmanager->resPrint; $sql.= " FROM ".MAIN_DB_PREFIX."mytable as t"; -if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."mytable_extrafields as ef on (u.rowid = ef.fk_object)"; +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."mytable_extrafields as ef on (t.rowid = ef.fk_object)"; $sql.= " WHERE 1 = 1"; //$sql.= " WHERE u.entity IN (".getEntity('mytable',1).")"; if ($search_field1) $sql.= natural_search("field1",$search_field1); @@ -329,6 +333,7 @@ if (! empty($moreforfilter)) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +print '
'; print ''."\n"; // Fields title @@ -531,6 +536,7 @@ $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters); // N print $hookmanager->resPrint; print '
'."\n"; +print '
'."\n"; print ''."\n"; diff --git a/htdocs/.gitignore b/htdocs/.gitignore index 608ef55d106..1650ea7e5ae 100644 --- a/htdocs/.gitignore +++ b/htdocs/.gitignore @@ -22,3 +22,4 @@ /cabinetmed* /webmail* /conf/conf.php +/subtotal/ diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index cb3255f981d..3edda4f8587 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -155,19 +155,19 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as a2 ON aa.account_par $sql .= " WHERE asy.rowid = " . $pcgver; if (strlen(trim($search_account))) { - $sql .= " AND aa.account_number like '%" . $search_account . "%'"; + $sql .= natural_search("aa.account_number", $search_account); } if (strlen(trim($search_label))) { - $sql .= " AND aa.label like '%" . $search_label . "%'"; + $sql .= natural_search("aa.label", $search_label); } if (strlen(trim($search_accountparent))) { - $sql .= " AND aa.account_parent like '%" . $search_accountparent . "%'"; + $sql .= natural_search("aa.account_parent", $search_accountparent); } if (strlen(trim($search_pcgtype))) { - $sql .= " AND aa.pcg_type like '%" . $search_pcgtype . "%'"; + $sql .= natural_search("aa.pcg_type", $search_pcgtype); } if (strlen(trim($search_pcgsubtype))) { - $sql .= " AND aa.pcg_subtype like '%" . $search_pcgsubtype . "%'"; + $sql .= natural_search("aa.pcg_subtype", $search_pcgsubtype); } $sql .= $db->order($sortfield, $sortorder); @@ -198,11 +198,9 @@ if ($resql) { print_barre_liste($langs->trans('ListAccounts'), $page, $_SERVER["PHP_SELF"], $params, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy'); - $i = 0; - print '
'; - // Box to select active chart of accoun + // Box to select active chart of account $var = ! $var; print $langs->trans("Selectchartofaccounts") . " : "; print ''; - print ''; + print ''; if (! empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) print ''; // On sell print ''; diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index f925bf4e4eb..a650100918e 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -307,6 +307,8 @@ if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } +$num=count($object->lines); + if ($action == 'delmouv') { $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?mvt_num=' . GETPOST('mvt_num'), $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1); print $formconfirm; @@ -448,7 +450,9 @@ foreach ($object->lines as $line ) { } print ''; -print ''; +if ($num < $limit) print ''.$langs->trans("Total").''; +else print ''.$langs->trans("Totalforthispage").''; +print ''; print ''; print price($total_debit); print ''; diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 3a6a428abed..9d8c7429964 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -1,7 +1,6 @@ - * largely based on the great work of : + * Copyright (C) 2016 Neil Orley largely based on the great work of : * - Copyright (C) 2013-2016 Olivier Geffroy * - Copyright (C) 2013-2016 Florian Henry * - Copyright (C) 2013-2016 Alexandre Spangaro @@ -18,7 +17,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * */ /** @@ -72,11 +70,8 @@ $pagenext = $page + 1; if ($sortorder == "") $sortorder = "ASC"; if ($sortfield == "") $sortfield = "t.rowid"; -if (empty($search_date_start)) { - $search_date_start = dol_mktime(0, 0, 0, 1, 1, dol_print_date(dol_now(), '%Y')); - $search_date_end = dol_mktime(0, 0, 0, 12, 31, dol_print_date(dol_now(), '%Y')); -} - +if (empty($search_date_start)) $search_date_start = dol_mktime(0, 0, 0, 1, 1, dol_print_date(dol_now(), '%Y')); +if (empty($search_date_end)) $search_date_end = dol_mktime(0, 0, 0, 12, 31, dol_print_date(dol_now(), '%Y')); $object = new BookKeeping($db); @@ -126,16 +121,17 @@ if (!GETPOST("button_removefilter_x") && !GETPOST("button_removefilter")) // Bot } } + /* * Action */ -if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers +if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers { $search_doc_date = ''; $search_accountancy_code = ''; $search_accountancy_code_start = ''; - $search_label_account = ''; + $search_label_account = ''; $search_mvt_label = ''; $search_direction = ''; $search_ledger_code = ''; diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index d40d8147ef0..268b5fa69c2 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -402,7 +402,7 @@ class AccountancyExport print length_accountg($line->numero_compte) . $this->separator; print substr(length_accountg($line->numero_compte),0,2) . $this->separator; print '"'.dol_trunc($line->label_compte,40,'right','UTF-8',1).'"' . $this->separator; - print '"'.dol_trunc($line->piece_num,15,'right','UTF-8',1)."'".$this->separator; + print '"'.dol_trunc($line->piece_num,15,'right','UTF-8',1).'"'.$this->separator; print price2num($line->montant).$this->separator; print $line->sens.$this->separator; print $date . $this->separator; diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index a6f487c1211..85fccbc543b 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -73,7 +73,7 @@ class BookKeeping extends CommonObject public $id; /** */ - public $doc_date = ''; + public $doc_date; public $doc_type; public $doc_ref; public $fk_doc; @@ -184,9 +184,7 @@ class BookKeeping extends CommonObject $sql .= " WHERE doc_type = '" . $this->doc_type . "'"; $sql .= " AND fk_docdet = " . $this->fk_docdet; $sql .= " AND numero_compte = '" . $this->numero_compte . "'"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; $resql = $this->db->query($sql); @@ -200,9 +198,7 @@ class BookKeeping extends CommonObject $sqlnum .= " WHERE doc_type = '" . $this->doc_type . "'"; $sqlnum .= " AND fk_docdet = '" . $this->fk_docdet . "'"; $sqlnum .= " AND doc_ref = '" . $this->doc_ref . "'"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sqlnum .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . ":: create sqlnum=" . $sqlnum, LOG_DEBUG); $resqlnum = $this->db->query($sqlnum); @@ -214,9 +210,7 @@ class BookKeeping extends CommonObject if (empty($this->piece_num)) { $sqlnum = "SELECT MAX(piece_num)+1 as maxpiecenum"; $sqlnum .= " FROM " . MAIN_DB_PREFIX . $this->table_element; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sqlnum .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . ":: create sqlnum=" . $sqlnum, LOG_DEBUG); $resqlnum = $this->db->query($sqlnum); @@ -503,9 +497,7 @@ class BookKeeping extends CommonObject $sql .= " t.piece_num"; $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; $sql .= ' WHERE 1 = 1'; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; if (null !== $ref) { $sql .= ' AND t.ref = ' . '\'' . $ref . '\''; } else { @@ -608,10 +600,9 @@ class BookKeeping extends CommonObject } } } - $sql.= ' WHERE 1 = 1'; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; + $sql .= ' WHERE 1 = 1'; + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; if (count($sqlwhere) > 0) { $sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere); } @@ -721,9 +712,7 @@ class BookKeeping extends CommonObject } } $sql.= ' WHERE 1 = 1'; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; if (count($sqlwhere) > 0) { $sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere); } @@ -817,9 +806,7 @@ class BookKeeping extends CommonObject } } $sql.= ' WHERE 1 = 1'; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; if (count($sqlwhere) > 0) { $sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere); } @@ -1073,9 +1060,7 @@ class BookKeeping extends CommonObject $sql.= " WHERE 1 = 1"; if (! empty($delyear)) $sql.= " AND YEAR(doc_date) = " . $delyear; // FIXME Must use between if (! empty($journal)) $sql.= " AND code_journal = '".$journal."'"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; $resql = $this->db->query($sql); if (! $resql) { @@ -1107,9 +1092,7 @@ class BookKeeping extends CommonObject $sql = "DELETE"; $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; $sql .= " WHERE piece_num = " . $piecenum; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; $resql = $this->db->query($sql); @@ -1180,9 +1163,12 @@ class BookKeeping extends CommonObject * @return void */ public function initAsSpecimen() { - $this->id = 0; + global $user; - $this->doc_date = ''; + $now=dol_now(); + + $this->id = 0; + $this->doc_date = $now; $this->doc_type = ''; $this->doc_ref = ''; $this->fk_doc = ''; @@ -1190,11 +1176,11 @@ class BookKeeping extends CommonObject $this->code_tiers = ''; $this->numero_compte = ''; $this->label_compte = ''; - $this->debit = ''; + $this->debit = 99.9; $this->credit = ''; $this->montant = ''; $this->sens = ''; - $this->fk_user_author = ''; + $this->fk_user_author = $user->id; $this->import_key = ''; $this->code_journal = ''; $this->piece_num = ''; @@ -1212,9 +1198,7 @@ class BookKeeping extends CommonObject $sql = "SELECT piece_num,doc_date,code_journal,doc_ref,doc_type"; $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; $sql .= " WHERE piece_num = " . $piecenum; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG); $result = $this->db->query($sql); @@ -1245,9 +1229,7 @@ class BookKeeping extends CommonObject global $conf; $sql = "SELECT MAX(piece_num)+1 as max FROM " . MAIN_DB_PREFIX . $this->table_element; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . "getNextNumMvt sql=" . $sql, LOG_DEBUG); $result = $this->db->query($sql); @@ -1279,9 +1261,7 @@ class BookKeeping extends CommonObject $sql .= " montant, sens, fk_user_author, import_key, code_journal, piece_num"; $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; $sql .= " WHERE piece_num = " . $piecenum; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG); $result = $this->db->query($sql); @@ -1333,9 +1313,7 @@ class BookKeeping extends CommonObject $sql .= " numero_compte, label_compte, debit, credit,"; $sql .= " montant, sens, fk_user_author, import_key, code_journal, piece_num"; $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . "::export_bookkeping", LOG_DEBUG); @@ -1404,9 +1382,7 @@ class BookKeeping extends CommonObject $sql .= " AND aa.active = 1"; $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; $sql .= " AND asy.rowid = " . $pcgver; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND ab.entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND ab.entity IN (" . getEntity("accountancy", 1) . ")"; $sql .= " ORDER BY account_number ASC"; dol_syslog(get_class($this) . "::select_account", LOG_DEBUG); @@ -1472,9 +1448,7 @@ class BookKeeping extends CommonObject $sql .= " WHERE aa.account_number = '" . $account . "'"; $sql .= " AND parent.active = 1"; $sql .= " AND root.active = 1"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " AND aa.entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " AND aa.entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); @@ -1513,9 +1487,7 @@ class BookKeeping extends CommonObject $sql .= " AND asy.rowid = " . $pcgver; $sql .= " AND aa.active = 1"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE aa.entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " WHERE aa.entity IN (" . getEntity("accountancy", 1) . ")"; dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/accountancy/class/html.formventilation.class.php b/htdocs/accountancy/class/html.formventilation.class.php index fab9e81031d..069e0ea3df3 100644 --- a/htdocs/accountancy/class/html.formventilation.class.php +++ b/htdocs/accountancy/class/html.formventilation.class.php @@ -30,6 +30,10 @@ */ class FormVentilation extends Form { + + private $options_cache = array(); + + /** * Return select filter with date of transaction * @@ -41,9 +45,7 @@ class FormVentilation extends Form $options = array(); $sql = 'SELECT DISTINCT import_key from ' . MAIN_DB_PREFIX . 'accounting_bookkeeping'; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; $sql .= ' ORDER BY import_key DESC'; dol_syslog(get_class($this) . "::select_bookkeeping_importkey", LOG_DEBUG); @@ -72,63 +74,76 @@ class FormVentilation extends Form * @param int $select_in selectid value is a aa.rowid (0 default) or aa.account_number (1) * @param int $select_out set value returned by select 0=rowid (default), 1=account_number * @param string $morecss More css non HTML object - * @return string String with HTML select + * @param string $usecache Key to use to store result into a cache. Next call with same key will reuse the cache. + * @return string String with HTML select */ - function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $morecss='maxwidth300 maxwidthonsmartphone') { + function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $morecss='maxwidth300 maxwidthonsmartphone', $usecache='') + { global $conf; require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; - $trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT') ? $conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT : 50; - - $sql = "SELECT DISTINCT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version"; - $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa"; - $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = " . $conf->global->CHARTOFACCOUNTS; - $sql .= " AND aa.active = 1"; - $sql .= " ORDER BY aa.account_number"; - - dol_syslog(get_class($this) . "::select_account", LOG_DEBUG); - $resql = $this->db->query($sql); - - if (!$resql) { - $this->error = "Error " . $this->db->lasterror(); - dol_syslog(get_class($this) . "::select_account " . $this->error, LOG_ERR); - return -1; - } - - $out = ajax_combobox($htmlname, $event); - - // TODO Add $options in cache so next call will not execute the request - $selected = 0; - $options = array(); - while ($obj = $this->db->fetch_object($resql)) + $options = array(); + if ($usecache && ! empty($this->options_cache[$usecache])) { - $label = length_accountg($obj->account_number) . ' - ' . $obj->label; - $label = dol_trunc($label, $trunclength); - - $select_value_in = $obj->rowid; - $select_value_out = $obj->rowid; - - // Try to guess if we have found default value - if ($select_in == 1) { - $select_value_in = $obj->account_number; - } - if ($select_out == 1) { - $select_value_out = $obj->account_number; - } - // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number - // Because same account_number can be share between different accounting_system and do have the same meaning - if ($selectid != '' && $selectid == $select_value_in) { - //var_dump("Found ".$selectid." ".$select_value_in); - $selected = $select_value_out; - } - - $options[$select_value_out] = $label; + $options = $this->options_cache[$usecache]; } + else + { + $trunclength = defined('ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT') ? $conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT : 50; + + $sql = "SELECT DISTINCT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa"; + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; + $sql .= " AND asy.rowid = " . $conf->global->CHARTOFACCOUNTS; + $sql .= " AND aa.active = 1"; + $sql .= " ORDER BY aa.account_number"; + + dol_syslog(get_class($this) . "::select_account", LOG_DEBUG); + $resql = $this->db->query($sql); + + if (!$resql) { + $this->error = "Error " . $this->db->lasterror(); + dol_syslog(get_class($this) . "::select_account " . $this->error, LOG_ERR); + return -1; + } + $out = ajax_combobox($htmlname, $event); + + $selected = 0; + while ($obj = $this->db->fetch_object($resql)) + { + $label = length_accountg($obj->account_number) . ' - ' . $obj->label; + $label = dol_trunc($label, $trunclength); + + $select_value_in = $obj->rowid; + $select_value_out = $obj->rowid; + + // Try to guess if we have found default value + if ($select_in == 1) { + $select_value_in = $obj->account_number; + } + if ($select_out == 1) { + $select_value_out = $obj->account_number; + } + // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number + // Because same account_number can be share between different accounting_system and do have the same meaning + if ($selectid != '' && $selectid == $select_value_in) { + //var_dump("Found ".$selectid." ".$select_value_in); + $selected = $select_value_out; + } + + $options[$select_value_out] = $label; + } + $this->db->free($resql); + + if ($usecache) + { + $this->options_cache[$usecache] = $options; + } + } + $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1); - $this->db->free($resql); return $out; } @@ -232,9 +247,7 @@ class FormVentilation extends Form // Auxiliary customer account $sql = "SELECT DISTINCT code_compta, nom "; $sql .= " FROM ".MAIN_DB_PREFIX."societe"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")"; - } + $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")"; $sql .= " ORDER BY code_compta"; dol_syslog(get_class($this)."::select_auxaccount", LOG_DEBUG); $resql = $this->db->query($sql); @@ -254,9 +267,7 @@ class FormVentilation extends Form // Auxiliary supplier account $sql = "SELECT DISTINCT code_compta_fournisseur, nom "; $sql .= " FROM ".MAIN_DB_PREFIX."societe"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")"; - } + $sql .= " WHERE entity IN (" . getEntity("societe", 1) . ")"; $sql .= " ORDER BY code_compta_fournisseur"; dol_syslog(get_class($this)."::select_auxaccount", LOG_DEBUG); $resql = $this->db->query($sql); @@ -297,9 +308,7 @@ class FormVentilation extends Form $sql = "SELECT DISTINCT date_format(doc_date,'%Y') as dtyear"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; $sql .= " ORDER BY date_format(doc_date,'%Y')"; dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); @@ -338,9 +347,7 @@ class FormVentilation extends Form $sql = "SELECT DISTINCT code_journal"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping"; - if (! empty($conf->multicompany->enabled)) { - $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; - } + $sql .= " WHERE entity IN (" . getEntity("accountancy", 1) . ")"; $sql .= " ORDER BY code_journal"; dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 08677974a6d..fea8281935f 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -80,7 +80,7 @@ if ($action == 'validatehistory') { $sqlclean .= ' ON accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=' . $conf->global->CHARTOFACCOUNTS . ')'; $resql = $db->query($sqlclean); - // Now make the binding + // Now make the binding. Bind automatically only for product with a dedicated account that exists into chart of account, others need a manual bind if ($db->type == 'pgsql') { $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet"; $sql1 .= " SET fk_code_ventilation = accnt.rowid"; @@ -136,11 +136,13 @@ if ($action == 'validatehistory') { // Now clean $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet as fd"; - $sql1 .= " SET fd.fk_code_ventilation = 0"; - $sql1 .= " WHERE fd.fk_facture IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture as f"; - $sql1 .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'"; - $sql1 .= " AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "')"; - + $sql1.= " SET fd.fk_code_ventilation = 0"; + $sql1.= " WHERE fd.fk_facture IN ( SELECT f.rowid FROM " . MAIN_DB_PREFIX . "facture as f"; + $sql1.= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($year_current, 1, false)) . "'"; + $sql1.= " AND f.datef <= '" . $db->idate(dol_get_last_day($year_current, 12, false)) . "'"; + $sql1.= " AND f.entity IN (" . getEntity("accountancy", 1) . ")"; + $sql1.=")"; + dol_syslog("htdocs/accountancy/customer/index.php fixaccountancycode", LOG_DEBUG); $resql1 = $db->query($sql1); @@ -169,12 +171,10 @@ print load_fiche_titre($langs->trans("CustomersVentilation") . " " . $textprevye print $langs->trans("DescVentilCustomer") . '
'; print $langs->trans("DescVentilMore", $langs->transnoentitiesnoconv("ValidateHistory"), $langs->transnoentitiesnoconv("ToBind")) . '
'; print '
'; -print '
'; -print '' . $langs->trans("ValidateHistory") . ''; -print '' . $langs->trans("CleanHistory", $year_current) . ''; +//print '
'; // TODO Remove this. Should be done into the repair.php script -if ($conf->global->MAIN_FEATURES_LEVEL > 0) print '' . $langs->trans("CleanFixHistory", $year_current) . ''; -print '
'; +if ($conf->global->MAIN_FEATURES_LEVEL > 1) print '' . $langs->trans("CleanFixHistory", $year_current) . ''; +//print '
'; $sql = "SELECT count(*) FROM " . MAIN_DB_PREFIX . "facturedet as fd"; $sql .= " , " . MAIN_DB_PREFIX . "facture as f"; @@ -191,8 +191,16 @@ if ($result) { $y = $year_current; +$buttonbind = '' . $langs->trans("ValidateHistory") . ''; +$buttonreset = '' . $langs->trans("CleanHistory", $year_current) . ''; + + + + $var = true; +print_fiche_titre($langs->trans("OverviewOfAmountOfLinesNotBound"), $buttonbind, ''); + print ''; print ''; print ''; @@ -213,7 +221,7 @@ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid $sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; $sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; $sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy - +$sql .= " AND aa.account_number IS NULL"; $sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label"; dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG); @@ -239,6 +247,69 @@ if ($resql) { } print "
' . $langs->trans("Account") . '' . $langs->trans("Label") . '
\n"; + +print '
'; + + +print_fiche_titre($langs->trans("OverviewOfAmountOfLinesBound"), $buttonreset, ''); + +print ''; +print ''; +print ''; +for($i = 1; $i <= 12; $i ++) { + print ''; +} +print ''; + +$sql = "SELECT " . $db->ifsql('aa.account_number IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.account_number') . " AS codecomptable,"; +$sql .= " " . $db->ifsql('aa.label IS NULL', "'".$langs->trans('NotMatch')."'", 'aa.label') . " AS intitule,"; +for($i = 1; $i <= 12; $i ++) { + $sql .= " SUM(" . $db->ifsql('MONTH(f.datef)=' . $i, 'fd.total_ht', '0') . ") AS month" . str_pad($i, 2, '0', STR_PAD_LEFT) . ","; +} +$sql .= " SUM(fd.total_ht) as total"; +$sql .= " FROM " . MAIN_DB_PREFIX . "facturedet as fd"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid = fd.fk_code_ventilation"; +$sql .= " WHERE f.datef >= '" . $db->idate(dol_get_first_day($y, 1, false)) . "'"; +$sql .= " AND f.datef <= '" . $db->idate(dol_get_last_day($y, 12, false)) . "'"; +$sql .= " AND f.entity IN (" . getEntity("facture", 0) . ")"; // We don't share object for accountancy +$sql .= " AND aa.account_number IS NOT NULL"; +$sql .= " GROUP BY fd.fk_code_ventilation,aa.account_number,aa.label"; + +dol_syslog("htdocs/accountancy/customer/index.php sql=" . $sql, LOG_DEBUG); +$resql = $db->query($sql); +if ($resql) { + $num = $db->num_rows($resql); + + while ( $row = $db->fetch_row($resql)) { + + $var = ! $var; + print ''; + print ''; + for($i = 2; $i <= 12; $i ++) { + print ''; + } + print ''; + print ''; + print ''; + } + $db->free($resql); +} else { + print $db->lasterror(); // Show last sql error +} +print "
' . $langs->trans("Account") . '' . $langs->trans("Label") . '' . $langs->trans('MonthShort' . str_pad($i, 2, '0', STR_PAD_LEFT)) . '' . $langs->trans("Total") . '
' . length_accountg($row[0]) . '' . $row[1] . '' . price($row[$i]) . '' . price($row[13]) . '' . price($row[14]) . '
\n"; + + + + + +print '
'; +print '
'; + + +print_fiche_titre($langs->trans("OtherInfo"), '', ''); + + print "
\n"; print ''; print ''; diff --git a/htdocs/accountancy/customer/lines.php b/htdocs/accountancy/customer/lines.php index d33fc82f3bc..b133e505d5c 100644 --- a/htdocs/accountancy/customer/lines.php +++ b/htdocs/accountancy/customer/lines.php @@ -38,6 +38,7 @@ $langs->load("bills"); $langs->load("compta"); $langs->load("main"); $langs->load("accountancy"); +$langs->load("productbatch"); $account_parent = GETPOST('account_parent'); $changeaccount = GETPOST('changeaccount'); @@ -83,7 +84,7 @@ $formventilation = new FormVentilation($db); */ // Purge search criteria -if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers +if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers { $search_ref = ''; $search_invoice = ''; @@ -122,6 +123,7 @@ if (is_array($changeaccount) && count($changeaccount) > 0) { $account_parent = ''; // Protection to avoid to mass apply it a second time } + /* * View */ @@ -148,7 +150,7 @@ print ' - '; + if (! empty($conf->use_javascript_ajax)) + { + $ret.=' + + '; + } return $ret; } @@ -734,7 +748,7 @@ class Form } $out.= ''; - $out .= ''; + $out .= ''; if (!empty($page)) { @@ -1445,7 +1459,8 @@ class Form $nodatarole=($comboenhancement?' data-role="none"':''); } - $out.= ''; if ($show_empty) $out.= ''."\n"; if ($show_every) $out.= ''."\n"; @@ -2877,7 +2892,9 @@ class Form /** - * Return list of payment modes + * Return list of payment modes. + * Constant MAIN_DEFAULT_PAYMENT_TERM_ID can used to set default value but scope is all application, probably not what you want. + * See instead to force the default value by the caller. * * @param int $selected Id of payment term to preselect by default * @param string $htmlname Nom de la zone select @@ -3419,7 +3436,7 @@ class Form } // Now add questions - $more.='
' . $langs->trans("TotalVente") . '
'."\n"; + $more.='
'."\n"; $more.=''."\n"; foreach ($formquestion as $key => $input) { @@ -3995,15 +4012,16 @@ class Form * * @param string $page Page URL where form is shown * @param int $selected Value pre-selected - * @param string $htmlname Nom du formulaire select. Si 'none', non modifiable. Example 'remise_id'. + * @param string $htmlname Name of SELECT component. If 'none', not changeable. Example 'remise_id'. * @param int $socid Third party id * @param float $amount Total amount available * @param string $filter SQL filter on discounts * @param int $maxvalue Max value for lines that can be selected * @param string $more More string to add + * @param int $hidelist 1=Hide list * @return void */ - function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter='', $maxvalue=0, $more='') + function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter='', $maxvalue=0, $more='', $hidelist=0) { global $conf,$langs; if ($htmlname != "none") @@ -4014,26 +4032,31 @@ class Form print '
'; if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { - if (! $filter || $filter=="fk_facture_source IS NULL") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency)).': '; // If we want deposit to be substracted to payments only and not to total of final invoice - else print $langs->trans("CompanyHasCreditNote",price($amount,0,$langs,0,0,-1,$conf->currency)).': '; + if (! $filter || $filter=="fk_facture_source IS NULL") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency)); // If we want deposit to be substracted to payments only and not to total of final invoice + else print $langs->trans("CompanyHasCreditNote",price($amount,0,$langs,0,0,-1,$conf->currency)); } else { - if (! $filter || $filter=="fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description LIKE '(DEPOSIT)%')") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency)).': '; - else print $langs->trans("CompanyHasCreditNote",price($amount,0,$langs,0,0,-1,$conf->currency)).': '; - } - print '
'; - $newfilter='fk_facture IS NULL AND fk_facture_line IS NULL'; // Remises disponibles - if ($filter) $newfilter.=' AND ('.$filter.')'; - $nbqualifiedlines=$this->select_remises($selected,$htmlname,$newfilter,$socid,$maxvalue); - if ($nbqualifiedlines > 0) - { - print '   '; + if (! $filter || $filter=="fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description LIKE '(DEPOSIT)%')") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency)); + else print $langs->trans("CompanyHasCreditNote",price($amount,0,$langs,0,0,-1,$conf->currency)); } + if (empty($hidelist)) print ': '; print '
'; - if ($more) + if (empty($hidelist)) + { + print '
'; + $newfilter='fk_facture IS NULL AND fk_facture_line IS NULL'; // Remises disponibles + if ($filter) $newfilter.=' AND ('.$filter.')'; + $nbqualifiedlines=$this->select_remises($selected,$htmlname,$newfilter,$socid,$maxvalue); + if ($nbqualifiedlines > 0) + { + print '   '; + } + print '
'; + } + if ($more) { print '
'; print $more; @@ -4564,7 +4587,7 @@ class Form if ($usecalendar == "eldy") { // Zone de saisie manuelle de la date - $retstring.='trans("FormatDateShortJavaInput").'\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript $retstring.='>'; @@ -4592,7 +4615,7 @@ class Form { //$retstring.='
'; // Day - $retstring.=''; + $retstring.=''; if ($emptydate || $set_time == -1) { @@ -4606,7 +4629,7 @@ class Form $retstring.=""; - $retstring.=''; + $retstring.=''; if ($emptydate || $set_time == -1) { $retstring.=''; @@ -4624,11 +4647,11 @@ class Form // Year if ($emptydate || $set_time == -1) { - $retstring.=''; + $retstring.=''; } else { - $retstring.=''; + $retstring.=''; for ($year = $syear - 5; $year < $syear + 10 ; $year++) { @@ -4645,7 +4668,7 @@ class Form if ($h) { // Show hour - $retstring.=''; + $retstring.=''; if ($emptyhours) $retstring.=''; for ($hour = 0; $hour < 24; $hour++) { @@ -4659,7 +4682,7 @@ class Form if ($m) { // Show minutes - $retstring.=''; + $retstring.=''; if ($emptyhours) $retstring.=''; for ($min = 0; $min < 60 ; $min++) { @@ -5294,7 +5317,7 @@ class Form if (empty($reshook)) { - $num = count($object->linkedObjects); + $nbofdifferenttypes = count($object->linkedObjects); print '
'; print load_fiche_titre($langs->trans('RelatedObjects'), $morehtmlright, ''); @@ -5311,7 +5334,7 @@ class Form print '
'; print ''; - $numoutput=0; + $nboftypesoutput=0; foreach($object->linkedObjects as $objecttype => $objects) { @@ -5371,23 +5394,28 @@ class Form $dirtpls=array_merge($conf->modules_parts['tpl'],array('/'.$tplpath.'/tpl')); foreach($dirtpls as $reldir) { + if ($nboftypesoutput == ($nbofdifferenttypes - 1)) // No more type to show after + { + global $noMoreLinkedObjectBlockAfter; + $noMoreLinkedObjectBlockAfter=1; + } $res=@include dol_buildpath($reldir.'/'.$tplname.'.tpl.php'); if ($res) { - $numoutput++; + $nboftypesoutput++; break; } } } - if (! $numoutput) + if (! $nboftypesoutput) { print ''; } print '
'.(! empty($formquestion['text'])?$formquestion['text']:'').'
'.$langs->trans("None").'
'; - return $num; + return $nbofdifferenttypes; } } @@ -5644,32 +5672,9 @@ class Form $next_ref = $object->ref_next?''.(($conf->dol_use_jmobile != 4)?'>':' ').'':''.(($conf->dol_use_jmobile != 4)?'>':' ').''; //print "xx".$previous_ref."x".$next_ref; - $ret.='
'; - - if ($morehtmlleft) - { - if ($conf->browser->layout == 'phone') $ret.='
'.$morehtmlleft.'
'; - else $ret.='
'.$morehtmlleft.'
'; - } - - $ret.='
'; - - // For thirdparty, contact, user, member, the ref is the id, so we show something else - if ($object->element == 'societe') - { - $ret.=dol_htmlentities($object->name); - } - else if (in_array($object->element, array('contact', 'user', 'member'))) - { - $ret.=dol_htmlentities($object->getFullName($langs)); - } - else if ($fieldref != 'none') $ret.=dol_htmlentities($object->$fieldref); - if ($morehtmlref) - { - $ret.=' '.$morehtmlref; - } - $ret.='
'; + $ret.='
'; + // Right part of banner if ($morehtmlright) $ret.='
'.$morehtmlright.'
'; if ($previous_ref || $next_ref || $morehtml) @@ -5690,7 +5695,34 @@ class Form $ret.='
'; } if ($morehtmlstatus) $ret.='
'.$morehtmlstatus.'
'; - $ret.='
'; + + // Left part of banner + if ($morehtmlleft) + { + if ($conf->browser->layout == 'phone') $ret.='
'.$morehtmlleft.'
'; // class="center" to have photo in middle + else $ret.='
'.$morehtmlleft.'
'; + } + + //if ($conf->browser->layout == 'phone') $ret.='
'; + $ret.='
'; + + // For thirdparty, contact, user, member, the ref is the id, so we show something else + if ($object->element == 'societe') + { + $ret.=dol_htmlentities($object->name); + } + else if (in_array($object->element, array('contact', 'user', 'member'))) + { + $ret.=dol_htmlentities($object->getFullName($langs)); + } + else if ($fieldref != 'none') $ret.=dol_htmlentities($object->$fieldref); + if ($morehtmlref) + { + $ret.=' '.$morehtmlref; + } + $ret.='
'; + + $ret.=''; return $ret; } @@ -5757,6 +5789,7 @@ class Form else $file=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.$object->logo; $originalfile=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.$object->logo; } + $email=$object->email; } else if ($modulepart=='contact') { @@ -5768,6 +5801,7 @@ class Form else $file=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.$object->photo; $originalfile=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.$object->photo; } + $email=$object->email; } else if ($modulepart=='userphoto') { @@ -5864,10 +5898,10 @@ class Form if ($caneditfield) { if ($object->photo) $ret.="
\n"; - $ret.=''; - if ($object->photo) $ret.=''; + $ret.='
'.$langs->trans("Delete").'

'; + if ($object->photo) $ret.=''; $ret.=''; - $ret.=''; + $ret.=''; $ret.='
'.$langs->trans("Delete").'

'.$langs->trans("PhotoFile").'
'; } diff --git a/htdocs/core/class/html.formactions.class.php b/htdocs/core/class/html.formactions.class.php index 503c1fbb739..16b63c16601 100644 --- a/htdocs/core/class/html.formactions.class.php +++ b/htdocs/core/class/html.formactions.class.php @@ -180,7 +180,10 @@ class FormActions elseif ($typeelement == 'fichinter') $title=$langs->trans('ActionsOnFicheInter'); else $title=$langs->trans("Actions"); - print load_fiche_titre($title,'',''); + $buttontoaddnewevent = ''; + $buttontoaddnewevent.= $langs->trans("AddEvent"); + $buttontoaddnewevent.= ''; + print load_fiche_titre($title, $buttontoaddnewevent, ''); $page=0; $param=''; $sortfield='a.datep'; @@ -250,13 +253,13 @@ class FormActions * @param array|string $selected Type pre-selected (can be 'manual', 'auto' or 'AC_xxx'). Can be an array too. * @param string $htmlname Name of select field * @param string $excludetype A type to exclude ('systemauto', 'system', '') - * @param integer $onlyautoornot 1=Group all type AC_XXX into 1 line AC_MANUAL. 0=Keep details of type + * @param integer $onlyautoornot 1=Group all type AC_XXX into 1 line AC_MANUAL. 0=Keep details of type, -1=Keep details and add a combined line "All manual" * @param int $hideinfohelp 1=Do not show info help, 0=Show, -1=Show+Add info to tell how to set default value * @param int $multiselect 1=Allow multiselect of action type * @param int $nooutput 1=No output * @return string */ - function select_type_actions($selected='',$htmlname='actioncode',$excludetype='',$onlyautoornot=0, $hideinfohelp=0, $multiselect=0, $nooutput=0) + function select_type_actions($selected='', $htmlname='actioncode', $excludetype='', $onlyautoornot=0, $hideinfohelp=0, $multiselect=0, $nooutput=0) { global $langs,$user,$form,$conf; diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index ac800d480fc..35fcfb4c25b 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -702,7 +702,7 @@ class FormCompany if (is_object($object) && method_exists($object, 'liste_type_contact')) { $lesTypes = $object->liste_type_contact($source, $sortorder, 0, 1); - print ''; if ($showempty) print ''; foreach($lesTypes as $key=>$value) { diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 109d2c5d23d..dadc470e273 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -62,7 +62,7 @@ class FormFile * @param int $addcancel 1=Add 'Cancel' button * @param int $sectionid If upload must be done inside a particular ECM section * @param int $perm Value of permission to allow upload - * @param int $size Length of input file area + * @param int $size Length of input file area. Deprecated. * @param Object $object Object to use (when attachment is done on an element) * @param string $options Add an option column * @param integer $useajax Use fileupload ajax (0=never, 1=if enabled, 2=always whatever is option). 2 should never be used. @@ -106,7 +106,7 @@ class FormFile if (! empty($options)) $out .= ''.$options.''; - $out .= ''; + $out .= ''; $max=$conf->global->MAIN_UPLOAD_DOC; // En Kb $maxphp=@ini_get('upload_max_filesize'); // En inconnu @@ -121,10 +121,10 @@ class FormFile { $out .= ''; } - $out .= 'global->MAIN_UPLOAD_DOC) || empty($perm)?' disabled':''); $out .= '>'; - $out .= ' '; + $out .= ' '; $out .= 'global->MAIN_UPLOAD_DOC) || empty($perm)?' disabled':''); $out .= '>'; @@ -183,11 +183,11 @@ class FormFile $out .= '
'; $out .= '
'; if (! empty($conf->global->OPTIMIZEFORTEXTBROWSER)) $out .= ' '; - $out .= ''; + $out .= ''; $out .= '
'; $out .= '
'; if (! empty($conf->global->OPTIMIZEFORTEXTBROWSER)) $out .= ' '; - $out .= ''; + $out .= ''; $out .= ''; $out .= ''; $out .= '
'; @@ -549,6 +549,7 @@ class FormFile $buttonlabeltoshow=$buttonlabel; if (empty($buttonlabel)) $buttonlabel=$langs->trans('Generate'); + if ($conf->browser->layout == 'phone') $urlsource.='#'.$forname.'_form'; # So we switch to form after a generation if (empty($noform)) $out.= ''; $out.= ''; $out.= ''; @@ -776,6 +777,8 @@ class FormFile /** * Show a Document icon with link(s) + * You may want to call this into a div like this: + * print '
'.$formfile->getDocumentsLink($element_doc, $filename, $filedir).'
'; * * @param string $modulepart propal, facture, facture_fourn, ... * @param string $modulesubdir Sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into subdir of module. @@ -800,7 +803,7 @@ class FormFile $out.= ''."\n"; if (! empty($file_list)) { - $out='
'; print ''; /*if ($user_id == $user->id) diff --git a/htdocs/holiday/view_log.php b/htdocs/holiday/view_log.php index 8ee69dc54ad..a04ef05c69b 100644 --- a/htdocs/holiday/view_log.php +++ b/htdocs/holiday/view_log.php @@ -71,7 +71,11 @@ if ($lastUpdate) else print $langs->trans('None'); print "
\n"; -print ''; +$moreforfilter=''; + +print '
'; +print '
'."\n"; + print ''; print ''; @@ -122,7 +126,7 @@ if ($log_holiday == '2') print ''."\n"; print '
'."\n"; - +print ''; llxFooter(); diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index 89d69974577..c4c14ff8d5f 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2005-2016 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2012 Christophe Battarel * @@ -342,8 +342,6 @@ if ($step == 1 || ! $datatoimport) dol_fiche_head($head, 'step1', $langs->trans("NewImport")); - print ''; - print $langs->trans("SelectImportDataSet").'
'; // Affiche les modules d'imports @@ -387,10 +385,7 @@ if ($step == 1 || ! $datatoimport) } print '
'; - print ''; - dol_fiche_end(); - } @@ -413,7 +408,7 @@ if ($step == 2 && $datatoimport) print ''; // Module - print ''; + print ''; print ''; // Lot de donnees a importer - print ''; + print ''; print ''; print '
'.$langs->trans("Module").'
'.$langs->trans("Module").''; $titleofmodule=$objimport->array_import_module[0]->getName(); // Special cas for import common to module/services @@ -422,15 +417,16 @@ if ($step == 2 && $datatoimport) print '
'.$langs->trans("DatasetToImport").'
'.$langs->trans("DatasetToImport").''; print img_object($objimport->array_import_module[0]->getName(),$objimport->array_import_icon[0]).' '; print $objimport->array_import_label[0]; print '
'; - print '
'."\n"; + dol_fiche_end(); + print '
'; print ''; @@ -463,9 +459,6 @@ if ($step == 2 && $datatoimport) } print '
'; - - dol_fiche_end(); - } @@ -498,7 +491,7 @@ if ($step == 3 && $datatoimport) print ''; // Module - print ''; + print ''; print ''; // Lot de donnees a importer - print ''; + print ''; print ''; // Source file format - print ''; + print ''; print ''; print '
'.$langs->trans("Module").'
'.$langs->trans("Module").''; $titleofmodule=$objimport->array_import_module[0]->getName(); // Special cas for import common to module/services @@ -507,7 +500,7 @@ if ($step == 3 && $datatoimport) print '
'.$langs->trans("DatasetToImport").'
'.$langs->trans("DatasetToImport").''; print img_object($objimport->array_import_module[0]->getName(),$objimport->array_import_icon[0]).' '; print $objimport->array_import_label[0]; @@ -519,7 +512,7 @@ if ($step == 3 && $datatoimport) //print '
'.$langs->trans("InformationOnSourceFile").'
'.$langs->trans("SourceFileFormat").'
'.$langs->trans("SourceFileFormat").''; $text=$objmodelimport->getDriverDescForKey($format); print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format),$text); @@ -528,9 +521,11 @@ if ($step == 3 && $datatoimport) print '
'; - print '
'."\n"; - + + dol_fiche_end(); + print '
'; + print '
'; print ''; print ''; @@ -542,7 +537,7 @@ if ($step == 3 && $datatoimport) print ''.$langs->trans("ChooseFileToImport",img_picto('','filenew')).''; - print ''.$langs->trans("FileWithDataToImport").''; + //print ''.$langs->trans("FileWithDataToImport").''; // Input file name box $var=false; @@ -602,8 +597,6 @@ if ($step == 3 && $datatoimport) } print '
'; - - dol_fiche_end(); } @@ -719,7 +712,7 @@ if ($step == 4 && $datatoimport) print ''; // Module - print ''; + print ''; print ''; // Lot de donnees a importer - print ''; + print ''; print ''; // Source file format - print ''; + print ''; print ''; + print ''; print ''; + print ''; print ''; print '
'.$langs->trans("Module").'
'.$langs->trans("Module").''; $titleofmodule=$objimport->array_import_module[0]->getName(); // Special cas for import common to module/services @@ -728,7 +721,7 @@ if ($step == 4 && $datatoimport) print '
'.$langs->trans("DatasetToImport").'
'.$langs->trans("DatasetToImport").''; print img_object($objimport->array_import_module[0]->getName(),$objimport->array_import_icon[0]).' '; print $objimport->array_import_label[0]; @@ -740,7 +733,7 @@ if ($step == 4 && $datatoimport) //print '
'.$langs->trans("InformationOnSourceFile").'
'.$langs->trans("SourceFileFormat").'
'.$langs->trans("SourceFileFormat").''; $text=$objmodelimport->getDriverDescForKey($format); print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format),$text); @@ -748,7 +741,7 @@ if ($step == 4 && $datatoimport) // Separator and enclosure if ($model == 'csv') { - print '
'.$langs->trans("CsvOptions").'
'.$langs->trans("CsvOptions").''; print '
'; print ''; @@ -767,7 +760,7 @@ if ($step == 4 && $datatoimport) } // File to import - print '
'.$langs->trans("FileToImport").'
'.$langs->trans("FileToImport").''; $modulepart='import'; $relativepath=GETPOST('filetoimport'); @@ -777,6 +770,9 @@ if ($step == 4 && $datatoimport) print '
'; + + dol_fiche_end(); + print '
'."\n"; @@ -801,7 +797,7 @@ if ($step == 4 && $datatoimport) print ''; // Title of array with fields - print ''; + print '
'; print ''; print ''; print ''; @@ -999,8 +995,6 @@ if ($step == 4 && $datatoimport) print '
'.$langs->trans("FieldsInSourceFile").''.$langs->trans("FieldsInTargetDatabase").'
'; - dol_fiche_end(); - if ($conf->use_javascript_ajax) { @@ -1183,7 +1177,7 @@ if ($step == 5 && $datatoimport) print ''; // Module - print ''; + print ''; print ''; // Source file format - print ''; + print ''; print ''; + print ''; print ''; print ''; @@ -254,7 +254,7 @@ if ($action == 'create') print ''; print ''; print ''; diff --git a/htdocs/loan/index.php b/htdocs/loan/index.php index b0c65b90cbf..0d79913f10e 100644 --- a/htdocs/loan/index.php +++ b/htdocs/loan/index.php @@ -121,7 +121,9 @@ if ($resql) print_barre_liste($langs->trans("Loans"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy.png', 0, '', '', $limit); - print '
'.$langs->trans("Module").'
'.$langs->trans("Module").''; $titleofmodule=$objimport->array_import_module[0]->getName(); // Special cas for import common to module/services @@ -1204,7 +1198,7 @@ if ($step == 5 && $datatoimport) //print '
'.$langs->trans("InformationOnSourceFile").'
'.$langs->trans("SourceFileFormat").'
'.$langs->trans("SourceFileFormat").''; $text=$objmodelimport->getDriverDescForKey($format); print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format),$text); @@ -1212,7 +1206,7 @@ if ($step == 5 && $datatoimport) // Separator and enclosure if ($model == 'csv') { - print '
'.$langs->trans("CsvOptions").'
'.$langs->trans("CsvOptions").''; print $langs->trans("Separator").' : '; print htmlentities($separator); @@ -1441,9 +1435,9 @@ if ($step == 5 && $datatoimport) $db->rollback(); // We force rollback because this was just a simulation. // Show OK - if (! count($arrayoferrors) && ! count($arrayofwarnings)) print img_picto($langs->trans("OK"),'tick').' '.$langs->trans("NoError").'

'; - else print $langs->trans("NbOfLinesOK",$nbok).'

'; - + if (! count($arrayoferrors) && ! count($arrayofwarnings)) print '
'.img_picto($langs->trans("OK"),'tick').' '.$langs->trans("NoError").'


'; + else print ''.$langs->trans("NbOfLinesOK",$nbok).'

'; + // Show Errors //var_dump($arrayoferrors); if (count($arrayoferrors)) @@ -1585,7 +1579,7 @@ if ($step == 6 && $datatoimport) print ''; // Module - print ''; + print ''; print ''; // Source file format - print ''; + print ''; print ''; + // Separator and enclosure + if ($model == 'csv') { + print ''; + print ''; + } + // File to import print ''; print '
'.$langs->trans("Module").'
'.$langs->trans("Module").''; $titleofmodule=$objimport->array_import_module[0]->getName(); // Special cas for import common to module/services @@ -1606,12 +1600,23 @@ if ($step == 6 && $datatoimport) //print '
'.$langs->trans("InformationOnSourceFile").'
'.$langs->trans("SourceFileFormat").'
'.$langs->trans("SourceFileFormat").''; $text=$objmodelimport->getDriverDescForKey($format); print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format),$text); print '
'.$langs->trans("CsvOptions").''; + print $langs->trans("Separator").' : '; + print htmlentities($separator); + print '    '.$langs->trans("Enclosure").' : '; + print htmlentities($enclosure); + print '
'.$langs->trans("FileToImport").''; diff --git a/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php b/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php index e8248a385fa..8a3023cab20 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php @@ -505,7 +505,7 @@ class CommentParser $data = explode('|', $data); $r['type'] = count($data) == 1 ? $data[0] : $data; } - if (isset($r['type']) && Text::endsWith($r['type'], '[]')) { + if (isset($r['type']) && is_string($r['type']) && Text::endsWith($r['type'], '[]')) { $r[static::$embeddedDataName]['type'] = substr($r['type'], 0, -2); $r['type'] = 'array'; } diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index b999eefe6a4..eb7e77cfc24 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -151,7 +151,7 @@ define('DOL_URL_ROOT', $suburi); // URL relative root ('', '/dolibarr', ...) if (empty($conf->file->character_set_client)) $conf->file->character_set_client="UTF-8"; if (empty($conf->db->character_set)) $conf->db->character_set='utf8'; -if (empty($conf->db->dolibarr_main_db_collation)) $conf->db->dolibarr_main_db_collation='utf8_general_ci'; +if (empty($conf->db->dolibarr_main_db_collation)) $conf->db->dolibarr_main_db_collation='utf8_unicode_ci'; if (empty($conf->db->dolibarr_main_db_encryption)) $conf->db->dolibarr_main_db_encryption=0; if (empty($conf->db->dolibarr_main_db_cryptkey)) $conf->db->dolibarr_main_db_cryptkey=''; if (empty($conf->db->user)) $conf->db->user=''; @@ -300,11 +300,13 @@ function conf($dolibarr_main_document_root) $conf->db->user = trim($dolibarr_main_db_user); $conf->db->pass = trim($dolibarr_main_db_pass); + // Mysql driver support has been removed in favor of mysqli + if ($conf->db->type == 'mysql') $conf->db->type = 'mysqli'; if (empty($character_set_client)) $character_set_client="UTF-8"; $conf->file->character_set_client=strtoupper($character_set_client); - if (empty($dolibarr_main_db_character_set)) $dolibarr_main_db_character_set=($conf->db->type=='mysql'?'latin1':''); // Old installation + if (empty($dolibarr_main_db_character_set)) $dolibarr_main_db_character_set=($conf->db->type=='mysqli'?'utf8':''); $conf->db->character_set=$dolibarr_main_db_character_set; - if (empty($dolibarr_main_db_collation)) $dolibarr_main_db_collation=($conf->db->type=='mysql'?'latin1_swedish_ci':''); // Old installation + if (empty($dolibarr_main_db_collation)) $dolibarr_main_db_collation=($conf->db->type=='mysqli'?'utf8_unicode_ci':''); $conf->db->dolibarr_main_db_collation=$dolibarr_main_db_collation; if (empty($dolibarr_main_db_encryption)) $dolibarr_main_db_encryption=0; $conf->db->dolibarr_main_db_encryption = $dolibarr_main_db_encryption; diff --git a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql index d5f7f636946..d747d5098f5 100644 --- a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql +++ b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql @@ -22,7 +22,7 @@ -- -- VMYSQL4.1 DELETE FROM llx_usergroup_user WHERE fk_usergroup NOT IN (SELECT rowid from llx_usergroup); -insert into llx_const (name, value, type, note, visible, entity) values ('MAIN_ENABLE_LOG_TO_HTML','0','chaine','If this option is set to 1, it is possible to see log output at end of HTML sources by adding paramater logtohtml=1 on URL',1,0); +insert into llx_const (name, value, type, note, visible, entity) values (__ENCRYPT('MAIN_ENABLE_LOG_TO_HTML')__,__ENCRYPT('0')__,'chaine','If this option is set to 1, it is possible to see log output at end of HTML sources by adding paramater logtohtml=1 on URL',1,0); -- Was done into a 3.8 fix, so we must do it also in 3.9 @@ -61,7 +61,7 @@ update llx_opensurvey_sondage set format = 'D' where format = 'D+'; update llx_opensurvey_sondage set format = 'A' where format = 'A+'; INSERT INTO llx_const (name, value, type, note, visible) values (__ENCRYPT('MAIN_DELAY_EXPENSEREPORTS_TO_PAY')__,__ENCRYPT('31')__,'chaine','Tolérance de retard avant alerte (en jours) sur les notes de frais impayées',0); -INSERT INTO llx_const (name, value, type, note, visible) values ('MAIN_SIZE_SHORTLIST_LIMIT','3','chaine','Max length for small lists (tabs)',0); +INSERT INTO llx_const (name, value, type, note, visible) values (__ENCRYPT('MAIN_SIZE_SHORTLISTE_LIMIT')__,__ENCRYPT('3')__,'chaine','Max length for small lists (tabs)',0); ALTER TABLE llx_accounting_system MODIFY COLUMN pcg_version varchar(32); ALTER TABLE llx_accountingaccount MODIFY COLUMN fk_pcg_version varchar(32); diff --git a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql index ea82a187694..ab60df659d6 100644 --- a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql +++ b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql @@ -24,6 +24,9 @@ -- -- VPGSQL8.2 DELETE FROM llx_usergroup_user WHERE fk_user NOT IN (SELECT rowid from llx_user); -- -- VMYSQL4.1 DELETE FROM llx_usergroup_user WHERE fk_usergroup NOT IN (SELECT rowid from llx_usergroup); +-- after changing const name, please insure that old constant was rename +UPDATE llx_const SET name = __ENCRYPT('THIRDPARTY_DEFAULT_CREATE_CONTACT')__ WHERE name = __ENCRYPT('MAIN_THIRPARTY_CREATION_INDIVIDUAL')__; -- under 3.9.0 +UPDATE llx_const SET name = __ENCRYPT('THIRDPARTY_DEFAULT_CREATE_CONTACT')__ WHERE name = __ENCRYPT('MAIN_THIRDPARTY_CREATION_INDIVIDUAL')__; -- under 4.0.1 -- VPGSQL8.2 ALTER TABLE llx_product_lot ALTER COLUMN entity SET DEFAULT 1; ALTER TABLE llx_product_lot MODIFY COLUMN entity integer DEFAULT 1; @@ -45,6 +48,9 @@ ALTER TABLE llx_don ADD COLUMN date_valid datetime; DELETE FROM llx_menu where module='expensereport'; +ALTER TABLE llx_facturedet ADD COLUMN fk_user_author integer after fk_unit; +ALTER TABLE llx_facturedet ADD COLUMN fk_user_modif integer after fk_unit; + ALTER TABLE llx_user DROP COLUMN phenix_login; ALTER TABLE llx_user DROP COLUMN phenix_pass; ALTER TABLE llx_user ADD COLUMN dateemployment datetime; @@ -105,8 +111,10 @@ ALTER TABLE llx_expensereport_extrafields ADD INDEX idx_expensereport_extrafield ALTER TABLE llx_cotisation RENAME TO llx_subscription; ALTER TABLE llx_subscription ADD UNIQUE INDEX uk_subscription (fk_adherent,dateadh); ALTER TABLE llx_subscription CHANGE COLUMN cotisation subscription real; -ALTER TABLE llx_adherent_type CHANGE COLUMN cotisation subscription varchar(3) NOT NULL DEFAULT 'yes'; - +ALTER TABLE llx_adherent_type CHANGE COLUMN cotisation subscription varchar(3) NOT NULL DEFAULT '1'; + +UPDATE llx_adherent_type SET subscription = '1' WHERE subscription = 'yes'; + CREATE TABLE llx_product_lot_extrafields ( rowid integer AUTO_INCREMENT PRIMARY KEY, @@ -168,15 +176,58 @@ create table llx_resource_extrafields ALTER TABLE llx_resource_extrafields ADD INDEX idx_resource_extrafields (fk_object); -INSERT INTO llx_const (name, value, type, note, visible) values ('MAIN_SIZE_SHORTLIST_LIMIT','3','chaine','Max length for small lists (tabs)',0); +INSERT INTO llx_const (name, value, type, note, visible) values (__ENCRYPT('MAIN_SIZE_SHORTLIST_LIMIT')__,__ENCRYPT('3')__,'chaine','Max length for small lists (tabs)',0); ALTER TABLE llx_bank_account ADD COLUMN note_public text; ALTER TABLE llx_bank_account ADD COLUMN model_pdf varchar(255); ALTER TABLE llx_bank_account ADD COLUMN import_key varchar(14); +ALTER TABLE llx_projet ADD COLUMN import_key varchar(14); +ALTER TABLE llx_projet_task ADD COLUMN import_key varchar(14); +ALTER TABLE llx_projet_task_time ADD COLUMN import_key varchar(14); + + ALTER TABLE llx_overwrite_trans ADD COLUMN entity integer DEFAULT 1 NOT NULL AFTER rowid; +ALTER TABLE llx_mailing_cibles ADD COLUMN error_text varchar(255); + +ALTER TABLE llx_c_actioncomm MODIFY COLUMN type varchar(50) DEFAULT 'system' NOT NULL; + +create table llx_user_employment +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + entity integer DEFAULT 1 NOT NULL, -- multi company id + ref varchar(50), -- reference + ref_ext varchar(50), -- reference into an external system (not used by dolibarr) + fk_user integer, + datec datetime, + tms timestamp, + fk_user_creat integer, + fk_user_modif integer, + job varchar(128), -- job position. may be a dictionnary + status integer NOT NULL, -- draft, active, closed + salary double(24,8), -- last and current value stored into llx_user + salaryextra double(24,8), -- last and current value stored into llx_user + weeklyhours double(16,8), -- last and current value stored into llx_user + dateemployment date, -- last and current value stored into llx_user + dateemploymentend date -- last and current value stored into llx_user +)ENGINE=innodb; + + + +-- Sequence to removed duplicated values of llx_links. Use serveral times if you still have duplicate. +drop table tmp_links_double; +--select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2; +create table tmp_links_double as (select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2); +--select * from tmp_links_double; +delete from llx_links where (rowid, label) in (select max_rowid, label from tmp_links_double); --update to avoid duplicate, delete to delete +drop table tmp_links_double; + +ALTER TABLE llx_links ADD UNIQUE INDEX uk_links (objectid,label); + +UPDATE llx_projet_task SET ref = NULL WHERE ref = ''; +ALTER TABLE llx_projet_task ADD UNIQUE INDEX uk_projet_task_ref (ref, entity); -- Product attributes CREATE TABLE llx_product_attribute diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index da5eab83e9b..3ba06daabce 100755 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -13,6 +13,13 @@ -- flush privileges; +-- Requests to change character set and collation of a column + +-- ALTER TABLE llx_accountingaccount MODIFY account_number VARCHAR(20) CHARACTER SET utf8; +-- ALTER TABLE llx_accountingaccount MODIFY account_number VARCHAR(20) COLLATE utf8_unicode_ci; +-- You can check with show full columns from llx_accountingaccount; + + -- Requests to clean corrupted database @@ -169,6 +176,7 @@ update llx_opensurvey_sondage set format = 'D' where format = 'D+'; update llx_opensurvey_sondage set format = 'A' where format = 'A+'; update llx_opensurvey_sondage set tms = now(); + -- ALTER TABLE llx_facture_fourn ALTER COLUMN fk_cond_reglement DROP NOT NULL; @@ -176,12 +184,21 @@ update llx_product set barcode = null where barcode in ('', '-1', '0'); update llx_societe set barcode = null where barcode in ('', '-1', '0'); +-- Sequence to removed duplicated values of llx_links. Use serveral times if you still have duplicate. +drop table tmp_links_double; +--select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2; +create table tmp_links_double as (select objectid, label, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_links where label is not null group by objectid, label having count(rowid) >= 2); +--select * from tmp_links_double; +delete from llx_links where (rowid, label) in (select max_rowid, label from tmp_links_double); --update to avoid duplicate, delete to delete +drop table tmp_links_double; + + -- Sequence to removed duplicated values of barcode in llx_product. Use serveral times if you still have duplicate. drop table tmp_product_double; --select barcode, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_product where barcode is not null group by barcode having count(rowid) >= 2; create table tmp_product_double as (select barcode, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_product where barcode is not null group by barcode having count(rowid) >= 2); --select * from tmp_product_double; -update llx_product set barcode = null where (rowid, barcode) in (select max_rowid, barcode from tmp_product_double); +update llx_product set barcode = null where (rowid, barcode) in (select max_rowid, barcode from tmp_product_double); --update to avoid duplicate, delete to delete drop table tmp_product_double; diff --git a/htdocs/install/mysql/tables/llx_c_actioncomm.sql b/htdocs/install/mysql/tables/llx_c_actioncomm.sql index d29cd2f8df3..a2b2d0cb069 100644 --- a/htdocs/install/mysql/tables/llx_c_actioncomm.sql +++ b/htdocs/install/mysql/tables/llx_c_actioncomm.sql @@ -22,7 +22,7 @@ create table llx_c_actioncomm ( id integer PRIMARY KEY, code varchar(12) NOT NULL, - type varchar(10) DEFAULT 'system' NOT NULL, + type varchar(50) DEFAULT 'system' NOT NULL, libelle varchar(48) NOT NULL, module varchar(16) DEFAULT NULL, active tinyint DEFAULT 1 NOT NULL, diff --git a/htdocs/install/mysql/tables/llx_expensereport.sql b/htdocs/install/mysql/tables/llx_expensereport.sql index a6f93d9cb37..a6b45daddf4 100755 --- a/htdocs/install/mysql/tables/llx_expensereport.sql +++ b/htdocs/install/mysql/tables/llx_expensereport.sql @@ -24,8 +24,8 @@ CREATE TABLE llx_expensereport ( ref_ext integer, total_ht double(24,8) DEFAULT 0, total_tva double(24,8) DEFAULT 0, - localtax1 double(24,8) DEFAULT 0, -- amount total localtax1 - localtax2 double(24,8) DEFAULT 0, -- amount total localtax2 + localtax1 double(24,8) DEFAULT 0, -- amount total localtax1 + localtax2 double(24,8) DEFAULT 0, -- amount total localtax2 total_ttc double(24,8) DEFAULT 0, date_debut date NOT NULL, date_fin date NOT NULL, @@ -42,14 +42,14 @@ CREATE TABLE llx_expensereport ( fk_user_approve integer DEFAULT NULL, fk_user_refuse integer DEFAULT NULL, fk_user_cancel integer DEFAULT NULL, - fk_statut integer NOT NULL, -- 1=brouillon, 2=validated (waiting approval), 4=canceled, 5=approved, 6=payed, 99=refused - fk_c_paiement integer DEFAULT NULL, -- deprecated - paid smallint default 0 NOT NULL, -- deprecated + fk_statut integer NOT NULL, -- 1=brouillon, 2=validated (waiting approval), 4=canceled, 5=approved, 6=payed, 99=refused + fk_c_paiement integer DEFAULT NULL, -- deprecated + paid smallint default 0 NOT NULL, -- deprecated note_public text, note_private text, detail_refuse varchar(255) DEFAULT NULL, detail_cancel varchar(255) DEFAULT NULL, - integration_compta integer DEFAULT NULL, -- not used + integration_compta integer DEFAULT NULL, -- not used fk_bank_account integer DEFAULT NULL, model_pdf varchar(50) DEFAULT NULL, @@ -61,6 +61,6 @@ CREATE TABLE llx_expensereport ( multicurrency_total_ttc double(24,8) DEFAULT 0, import_key varchar(14), - extraparams varchar(255) -- for other parameters with json format + extraparams varchar(255) -- for other parameters with json format ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_facturedet.sql b/htdocs/install/mysql/tables/llx_facturedet.sql index 0bf124975ab..28c07e6d508 100644 --- a/htdocs/install/mysql/tables/llx_facturedet.sql +++ b/htdocs/install/mysql/tables/llx_facturedet.sql @@ -65,6 +65,8 @@ create table llx_facturedet situation_percent real, -- % progression of lines invoicing fk_prev_id integer, -- id of the line in the previous situation, fk_unit integer DEFAULT NULL, -- id of the unit code¡ + fk_user_author integer, -- user making creation + fk_user_modif integer, -- user making last change fk_multicurrency integer, multicurrency_code varchar(255), diff --git a/htdocs/install/mysql/tables/llx_links.key.sql b/htdocs/install/mysql/tables/llx_links.key.sql new file mode 100644 index 00000000000..7ba509e9d58 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_links.key.sql @@ -0,0 +1,22 @@ +-- ======================================================================== +-- Copyright (C) 2016 Laurent Destailleur +-- +-- 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 . +-- +-- +-- Linked files +-- ======================================================================== + +ALTER TABLE llx_links ADD UNIQUE INDEX uk_links (objectid,label); + diff --git a/htdocs/install/mysql/tables/llx_mailing_cibles.sql b/htdocs/install/mysql/tables/llx_mailing_cibles.sql index 72fdeca2925..f3031069220 100644 --- a/htdocs/install/mysql/tables/llx_mailing_cibles.sql +++ b/htdocs/install/mysql/tables/llx_mailing_cibles.sql @@ -1,6 +1,6 @@ -- ======================================================================== -- Copyright (C) 2005 Rodolphe Quiedeville --- Copyright (C) 2009-2012 Laurent Destailleur +-- Copyright (C) 2009-2016 Laurent Destailleur -- Copyright (C) 2011-2012 Regis Houssin -- -- This program is free software; you can redistribute it and/or modify @@ -33,6 +33,6 @@ create table llx_mailing_cibles source_url varchar(160), source_id integer, source_type varchar(16), - date_envoi datetime - + date_envoi datetime, + error_text varchar(255) -- text with error if statut is -1 )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_projet.sql b/htdocs/install/mysql/tables/llx_projet.sql index ab3bbee222e..d50547b711b 100644 --- a/htdocs/install/mysql/tables/llx_projet.sql +++ b/htdocs/install/mysql/tables/llx_projet.sql @@ -41,5 +41,6 @@ create table llx_projet --budget_days real, -- budget in days is sum of field planned_workload of tasks opp_amount double(24,8), budget_amount double(24,8), - model_pdf varchar(255) + model_pdf varchar(255), + import_key varchar(14) -- Import key )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_projet_task.key.sql b/htdocs/install/mysql/tables/llx_projet_task.key.sql index f25d00d5563..620bbc17eaa 100644 --- a/htdocs/install/mysql/tables/llx_projet_task.key.sql +++ b/htdocs/install/mysql/tables/llx_projet_task.key.sql @@ -17,6 +17,7 @@ -- -- ============================================================================ +ALTER TABLE llx_projet_task ADD UNIQUE INDEX uk_projet_task_ref (ref, entity); ALTER TABLE llx_projet_task ADD INDEX idx_projet_task_fk_projet (fk_projet); ALTER TABLE llx_projet_task ADD INDEX idx_projet_task_fk_user_creat (fk_user_creat); diff --git a/htdocs/install/mysql/tables/llx_projet_task.sql b/htdocs/install/mysql/tables/llx_projet_task.sql index 5b9decd23ef..70ec071be95 100644 --- a/htdocs/install/mysql/tables/llx_projet_task.sql +++ b/htdocs/install/mysql/tables/llx_projet_task.sql @@ -41,5 +41,6 @@ create table llx_projet_task note_private text, note_public text, rang integer DEFAULT 0, - model_pdf varchar(255) + model_pdf varchar(255), + import_key varchar(14) -- Import key )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_projet_task_time.sql b/htdocs/install/mysql/tables/llx_projet_task_time.sql index 3ca161ed07d..9dcc0826f7b 100644 --- a/htdocs/install/mysql/tables/llx_projet_task_time.sql +++ b/htdocs/install/mysql/tables/llx_projet_task_time.sql @@ -28,5 +28,6 @@ create table llx_projet_task_time thm double(24,8), invoice_id integer DEFAULT NULL, -- If we need to invoice each line of timespent, we can save invoice id here invoice_line_id integer DEFAULT NULL, -- If we need to invoice each line of timespent, we can save invoice line id here - note text + import_key varchar(14), -- Import key + note text, )ENGINE=innodb; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 1619884c36f..1dee42cd39d 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -8,7 +8,11 @@ ACCOUNTING_EXPORT_AMOUNT=Export amount ACCOUNTING_EXPORT_DEVISE=Export currency Selectformat=Select the format for the file ACCOUNTING_EXPORT_PREFIX_SPEC=Specify the prefix for the file name - +ThisService=This service +ThisProduct=This product +DefaultForService=Default for service +DefaultForProduct=Default for product +CantSuggest=Can't suggest AccountancySetupDoneFromAccountancyMenu=Most setup of the accountancy is done from the menu %s ConfigAccountingExpert=Configuration of the module accounting expert Journalization=Journalization @@ -18,6 +22,10 @@ BackToChartofaccounts=Return chart of accounts Chartofaccounts=Chart of accounts CurrentDedicatedAccountingAccount=Current dedicated account AssignDedicatedAccountingAccount=New account to assign +InvoiceLabel=Invoice label +OverviewOfAmountOfLinesNotBound=Overview of amount of lines not bound to accounting account +OverviewOfAmountOfLinesBound=Overview of amount of lines already bound to accounting account +OtherInfo=Other information AccountancyArea=Accountancy area AccountancyAreaDescIntro=Usage of the accountancy module is done in several step: @@ -49,7 +57,7 @@ ChangeAndLoad=Change and load Addanaccount=Add an accounting account AccountAccounting=Accounting account AccountAccountingShort=Account -AccountAccountingSuggest=Accounting account suggest +AccountAccountingSuggest=Accounting account suggested MenuDefaultAccounts=Default accounts MenuVatAccounts=Vat accounts MenuTaxAccounts=Tax accounts diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 746d0ec7d77..19f6dfe9d81 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -223,6 +223,16 @@ HelpCenterDesc1=This area can help you to get a Help support service on Dolibarr HelpCenterDesc2=Some part of this service are available in english only. CurrentMenuHandler=Current menu handler MeasuringUnit=Measuring unit +LeftMargin=Left margin +TopMargin=Top margin +PaperSize=Paper type +Orientation=Orientation +SpaceX=Space X +SpaceY=Space Y +FontSize=Font size +Content=Content +NoticePeriod=Notice +NewByMonth=New by month Emails=E-mails EMailsSetup=E-mails setup EMailsDesc=This page allows you to overwrite your PHP parameters for e-mails sending. In most cases on Unix/Linux OS, your PHP setup is correct and these parameters are useless. @@ -354,6 +364,7 @@ Boolean=Boolean (Checkbox) ExtrafieldPhone = Phone ExtrafieldPrice = Price ExtrafieldMail = Email +ExtrafieldUrl = Url ExtrafieldSelect = Select list ExtrafieldSelectList = Select from table ExtrafieldSeparator=Separator @@ -365,8 +376,8 @@ ExtrafieldLink=Link to an object ExtrafieldParamHelpselect=Parameters list have to be like key,value

for example :
1,value1
2,value2
3,value3
...

In order to have the list depending on another :
1,value1|parent_list_code:parent_key
2,value2|parent_list_code:parent_key ExtrafieldParamHelpcheckbox=Parameters list have to be like key,value

for example :
1,value1
2,value2
3,value3
... ExtrafieldParamHelpradio=Parameters list have to be like key,value

for example :
1,value1
2,value2
3,value3
... -ExtrafieldParamHelpsellist=Parameters list comes from a table
Syntax : table_name:label_field:id_field::filter
Example : c_typent:libelle:id::filter

filter can be a simple test (eg active=1) to display only active value
You can also use $ID$ in filter witch is the current id of current object
To do a SELECT in filter use $SEL$
if you want to filter on extrafields use syntaxt extra.fieldcode=... (where field code is the code of extrafield)

In order to have the list depending on another :
c_typent:libelle:id:parent_list_code|parent_column:filter -ExtrafieldParamHelpchkbxlst=Parameters list comes from a table
Syntax : table_name:label_field:id_field::filter
Example : c_typent:libelle:id::filter

filter can be a simple test (eg active=1) to display only active value
You can also use $ID$ in filter witch is the current id of current object
To do a SELECT in filter use $SEL$
if you want to filter on extrafields use syntaxt extra.fieldcode=... (where field code is the code of extrafield)

In order to have the list depending on another :
c_typent:libelle:id:parent_list_code|parent_column:filter +ExtrafieldParamHelpsellist=Parameters list comes from a table
Syntax : table_name:label_field:id_field::filter
Example : c_typent:libelle:id::filter

filter can be a simple test (eg active=1) to display only active value
You can also use $ID$ in filter witch is the current id of current object
To do a SELECT in filter use $SEL$
if you want to filter on extrafields use syntax extra.fieldcode=... (where field code is the code of extrafield)

In order to have the list depending on another :
c_typent:libelle:id:parent_list_code|parent_column:filter +ExtrafieldParamHelpchkbxlst=Parameters list comes from a table
Syntax : table_name:label_field:id_field::filter
Example : c_typent:libelle:id::filter

filter can be a simple test (eg active=1) to display only active value
You can also use $ID$ in filter witch is the current id of current object
To do a SELECT in filter use $SEL$
if you want to filter on extrafields use syntax extra.fieldcode=... (where field code is the code of extrafield)

In order to have the list depending on another :
c_typent:libelle:id:parent_list_code|parent_column:filter ExtrafieldParamHelplink=Parameters must be ObjectName:Classpath
Syntax : ObjectName:Classpath
Example : Societe:societe/class/societe.class.php LibraryToBuildPDF=Library used for PDF generation WarningUsingFPDF=Warning: Your conf.php contains directive dolibarr_pdf_force_fpdf=1. This means you use the FPDF library to generate PDF files. This library is old and does not support a lot of features (Unicode, image transparency, cyrillic, arab and asiatic languages, ...), so you may experience errors during PDF generation.
To solve this and have a full support of PDF generation, please download TCPDF library, then comment or remove the line $dolibarr_pdf_force_fpdf=1, and add instead $dolibarr_lib_TCPDF_PATH='path_to_TCPDF_dir' @@ -398,7 +409,7 @@ EnableAndSetupModuleCron=If you want to have this recurring invoice beeing gener ModuleCompanyCodeAquarium=Return an accountancy code built by:
%s followed by third party supplier code for a supplier accountancy code,
%s followed by third party customer code for a customer accountancy code. ModuleCompanyCodePanicum=Return an empty accountancy code. ModuleCompanyCodeDigitaria=Accountancy code depends on third party code. The code is composed of the character "C" in the first position followed by the first 5 characters of the third party code. -Use3StepsApproval=By default, Purchase Orders need to be created and approved by 2 different users (one step/user to create and one step/user to approve. Note that if user has both permission to create and approve, one step/user will be enough). You can ask with this option to introduce a third step/user approval, if amount is higher than a dedicated value (so 3 steps will be necessary: 1 validation, 2=first approval and 3=second approval if amount is enough).
Set this to empty if one approval (2 steps) is enough, set it to a very low value (0.1) if a second approval is always required. +Use3StepsApproval=By default, Purchase Orders need to be created and approved by 2 different users (one step/user to create and one step/user to approve. Note that if user has both permission to create and approve, one step/user will be enough). You can ask with this option to introduce a third step/user approval, if amount is higher than a dedicated value (so 3 steps will be necessary: 1=validation, 2=first approval and 3=second approval if amount is enough).
Set this to empty if one approval (2 steps) is enough, set it to a very low value (0.1) if a second approval (3 steps) is always required. UseDoubleApproval=Use a 3 steps approval when amount (without tax) is higher than... # Modules @@ -814,6 +825,7 @@ DictionaryPaymentModes=Payment modes DictionaryTypeContact=Contact/Address types DictionaryEcotaxe=Ecotax (WEEE) DictionaryPaperFormat=Paper formats +DictionaryFormatCards=Cards formats DictionaryFees=Types of fees DictionarySendingMethods=Shipping methods DictionaryStaff=Staff @@ -1017,7 +1029,6 @@ SimpleNumRefModelDesc=Returns the reference number with format %syymm-nnnn where ShowProfIdInAddress=Show professionnal id with addresses on documents ShowVATIntaInAddress=Hide VAT Intra num with addresses on documents TranslationUncomplete=Partial translation -SomeTranslationAreUncomplete=Some languages may be partially translated or may contains errors. If you detect some, you can fix language files registering to http://transifex.com/projects/p/dolibarr/. MAIN_DISABLE_METEO=Disable meteo view TestLoginToAPI=Test login to API ProxyDesc=Some features of Dolibarr need to have an Internet access to work. Define here parameters for this. If the Dolibarr server is behind a Proxy server, those parameters tells Dolibarr how to access Internet through it. @@ -1565,7 +1576,7 @@ HighlightLinesOnMouseHover=Highlight table lines when mouse move passes over HighlightLinesColor=Highlight color of the line when the mouse passes over (keep empty for no highlight) TextTitleColor=Color of page title LinkColor=Color of links -PressF5AfterChangingThis=Press F5 on keyboard after changing this value to have it effective +PressF5AfterChangingThis=Press F5 on keyboard or clear your browser cache after changing this value to have it effective NotSupportedByAllThemes=Will works with core themes, may not be supported by external themes BackgroundColor=Background color TopMenuBackgroundColor=Background color for Top menu @@ -1625,13 +1636,13 @@ AddOtherPagesOrServices=Add other pages or services AddModels=Add document or numbering templates AddSubstitutions=Add keys substitutions DetectionNotPossible=Detection not possible -UrlToGetKeyToUseAPIs=Url to get token to use API (once token has been received it is saved on database user table and will be checked on each future access) +UrlToGetKeyToUseAPIs=Url to get token to use API (once token has been received it is saved on database user table and must be provided on each API call) ListOfAvailableAPIs=List of available APIs activateModuleDependNotSatisfied=Module "%s" depends on module "%s" that is missing, so module "%1$s" may not work correclty. Please install module "%2$s" or disable module "%1$s" if you want to be safe from any surprise CommandIsNotInsideAllowedCommands=The command you try to run is not inside list of allowed commands defined into parameter $dolibarr_main_restrict_os_commands into conf.php file. LandingPage=Landing page SamePriceAlsoForSharedCompanies=If you use a multicompany module, with the choice "Single price", price will be also the same for all companies if products are shared between environments -ModuleEnabledAdminMustCheckRights=Module has been activated. Permissions for activated module(s) were given to admin users only. You may need to grant permissions to other users manually if necessary. +ModuleEnabledAdminMustCheckRights=Module has been activated. Permissions for activated module(s) were given to admin users only. You may need to grant permissions to other users or groups manually if necessary. UserHasNoPermissions=This user has no permission defined TypeCdr=Use "None" if the date of payment term is date of invoice plus a delta in days (delta is field "Nb of days")
Use "At end of month", if, after delta, the date must be increased to reach the end of month (+ an optional "Offset" in days)
Use "Current/Next" to have payment term date being the first Nth of the month (N is stored into field "Nb of days") ##### Resource #### diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 3f4898630ba..9ee5510f983 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -75,6 +75,8 @@ PaymentsAlreadyDone=Payments already done PaymentsBackAlreadyDone=Payments back already done PaymentRule=Payment rule PaymentMode=Payment type +PaymentTypeDC=Debit/Credit Card +PaymentTypePP=PayPal IdPaymentMode=Payment type (id) LabelPaymentMode=Payment type (label) PaymentModeShort=Payment type @@ -330,6 +332,7 @@ GeneratedFromRecurringInvoice=Generated from template recurring invoice %s DateIsNotEnough=Date not reached yet InvoiceGeneratedFromTemplate=Invoice %s generated from recurring template invoice %s # PaymentConditions +Statut=Status PaymentConditionShortRECEP=Immediate PaymentConditionRECEP=Immediate PaymentConditionShort30D=30 days @@ -446,6 +449,7 @@ PDFCrevetteDescription=Invoice PDF template Crevette. A complete invoice templat TerreNumRefModelDesc1=Return number with format %syymm-nnnn for standard invoices and %syymm-nnnn for credit notes where yy is year, mm is month and nnnn is a sequence with no break and no return to 0 MarsNumRefModelDesc1=Return number with format %syymm-nnnn for standard invoices, %syymm-nnnn for replacement invoices, %syymm-nnnn for deposit invoices and %syymm-nnnn for credit notes where yy is year, mm is month and nnnn is a sequence with no break and no return to 0 TerreNumRefModelError=A bill starting with $syymm already exists and is not compatible with this model of sequence. Remove it or rename it to activate this module. +CactusNumRefModelDesc1=Return number with format %syymm-nnnn for standard invoices, %syymm-nnnn for credit notes and %syymm-nnnn for deposit invoices where yy is year, mm is month and nnnn is a sequence with no break and no return to 0 ##### Types de contacts ##### TypeContact_facture_internal_SALESREPFOLL=Representative following-up customer invoice TypeContact_facture_external_BILLING=Customer invoice contact @@ -483,5 +487,5 @@ ToCreateARecurringInvoiceGene=To generate future invoices regularly and manually ToCreateARecurringInvoiceGeneAuto=If you need to have such invoices generated automatically, ask you administrator to enable and setup module %s. Note that both method (manual and automatic) can be used together with no risk of duplication. DeleteRepeatableInvoice=Delete template invoice ConfirmDeleteRepeatableInvoice=Are your sure you want to delete the template invoice? -CreateOneBillByThird=Create one invoice per third (otherwise, one invoice per order) -BillCreated=%s bill(s) created \ No newline at end of file +CreateOneBillByThird=Create one invoice per third party (otherwise, one invoice per order) +BillCreated=%s bill(s) created diff --git a/htdocs/langs/en_US/commercial.lang b/htdocs/langs/en_US/commercial.lang index 5e1959d0ecb..16a6611db4a 100644 --- a/htdocs/langs/en_US/commercial.lang +++ b/htdocs/langs/en_US/commercial.lang @@ -28,7 +28,7 @@ ShowCustomer=Show customer ShowProspect=Show prospect ListOfProspects=List of prospects ListOfCustomers=List of customers -LastDoneTasks=Latest %s completed tasks +LastDoneTasks=Latest %s completed actions LastActionsToDo=Oldest %s not completed actions DoneAndToDoActions=Completed and To do events DoneActions=Completed events @@ -62,7 +62,7 @@ ActionAC_SHIP=Send shipping by mail ActionAC_SUP_ORD=Send supplier order by mail ActionAC_SUP_INV=Send supplier invoice by mail ActionAC_OTH=Other -ActionAC_OTH_AUTO=Other (automatically inserted events) +ActionAC_OTH_AUTO=Automatically inserted events ActionAC_MANUAL=Manually inserted events ActionAC_AUTO=Automatically inserted events Stats=Sales statistics diff --git a/htdocs/langs/en_US/compta.lang b/htdocs/langs/en_US/compta.lang index bd410e7b726..c3bfaa08110 100644 --- a/htdocs/langs/en_US/compta.lang +++ b/htdocs/langs/en_US/compta.lang @@ -200,7 +200,7 @@ BasedOnTwoFirstLettersOfVATNumberBeingDifferentFromYourCompanyCountry=Based on t SameCountryCustomersWithVAT=National customers report BasedOnTwoFirstLettersOfVATNumberBeingTheSameAsYourCompanyCountry=Based on the two first letters of the VAT number being the same as your own company's country code LinkedFichinter=Link to an intervention -ImportDataset_tax_contrib=Import social/fiscal taxes -ImportDataset_tax_vat=Import vat payments +ImportDataset_tax_contrib=Social/fiscal taxes +ImportDataset_tax_vat=Vat payments ErrorBankAccountNotFound=Error: Bank account not found FiscalPeriod=Accounting period diff --git a/htdocs/langs/en_US/interventions.lang b/htdocs/langs/en_US/interventions.lang index 1fd7fd56767..0de0d487925 100644 --- a/htdocs/langs/en_US/interventions.lang +++ b/htdocs/langs/en_US/interventions.lang @@ -26,6 +26,7 @@ DocumentModelStandard=Standard document model for interventions InterventionCardsAndInterventionLines=Interventions and lines of interventions InterventionClassifyBilled=Classify "Billed" InterventionClassifyUnBilled=Classify "Unbilled" +InterventionClassifyDone=Classify "Done" StatusInterInvoiced=Billed ShowIntervention=Show intervention SendInterventionRef=Submission of intervention %s diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 45e8246261a..d036a72186b 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -50,7 +50,6 @@ NbOfEMails=Nb of EMails TotalNbOfDistinctRecipients=Number of distinct recipients NoTargetYet=No recipients defined yet (Go on tab 'Recipients') RemoveRecipient=Remove recipient -CommonSubstitutions=Common substitutions YouCanAddYourOwnPredefindedListHere=To create your email selector module, see htdocs/core/modules/mailings/README. EMailTestSubstitutionReplacedByGenericValues=When using test mode, substitutions variables are replaced by generic values MailingAddFile=Attach this file @@ -98,7 +97,7 @@ ToAddRecipientsChooseHere=Add recipients by choosing from the lists NbOfEMailingsReceived=Mass emailings received NbOfEMailingsSend=Mass emailings sent IdRecord=ID record -DeliveryReceipt=Delivery Receipt +DeliveryReceipt=Delivery Ack. YouCanUseCommaSeparatorForSeveralRecipients=You can use the comma separator to specify several recipients. TagCheckMail=Track mail opening TagUnsubscribe=Unsubscribe link @@ -119,6 +118,8 @@ MailSendSetupIs2=You must first go, with an admin account, into menu %sHome - Se MailSendSetupIs3=If you have any questions on how to setup your SMTP server, you can ask to %s. YouCanAlsoUseSupervisorKeyword=You can also add the keyword __SUPERVISOREMAIL__ to have email being sent to the supervisor of user (works only if an email is defined for this supervisor) NbOfTargetedContacts=Current number of targeted contact emails +UseFormatFileEmailToTarget=Imported file must have format email;name;firstname;other +UseFormatInputEmailToTarget=Enter a string with format email;name;firstname;other MailAdvTargetRecipients=Recipients (advanced selection) AdvTgtTitle=Fill input fields to preselect the thirdparties or contacts/addresses to target AdvTgtSearchTextHelp=Use %% as magic caracters. For exemple to find all item like jean, joe, jim, you can input j%%, you can also use ; as separator for value, and use ! for except this value. For exemple jean;joe;jim%%;!jimo;!jima% will target all jean, joe, start with jim but not jimo and not everythnig taht start by jima diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index f12a9216985..f671d4397c5 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -322,6 +322,9 @@ AmountTTCShort=Amount (inc. tax) AmountHT=Amount (net of tax) AmountTTC=Amount (inc. tax) AmountVAT=Amount tax +MulticurrencyAlreadyPaid=Already payed, original currency +MulticurrencyRemainderToPay=Remain to pay, original currency +MulticurrencyPaymentAmount=Payment amount, original currency MulticurrencyAmountHT=Amount (net of tax), original currency MulticurrencyAmountTTC=Amount (inc. of tax), original currency MulticurrencyAmountVAT=Amount tax, original currency @@ -613,6 +616,9 @@ NoFileFound=No documents saved in this directory CurrentUserLanguage=Current language CurrentTheme=Current theme CurrentMenuManager=Current menu manager +Browser=Browser +Layout=Layout +Screen=Screen DisabledModules=Disabled modules For=For ForCustomer=For customer @@ -635,7 +641,7 @@ PrintContentArea=Show page to print main content area MenuManager=Menu manager WarningYouAreInMaintenanceMode=Warning, you are in a maintenance mode, so only login %s is allowed to use application at the moment. CoreErrorTitle=System error -CoreErrorMessage=Sorry, an error occurred. Check the logs or contact your system administrator. +CoreErrorMessage=Sorry, an error occurred. Contact your system administrator to check the logs or disable $dolibarr_main_prod=1 to get more information. CreditCard=Credit card FieldsWithAreMandatory=Fields with %s are mandatory FieldsWithIsForPublic=Fields with %s are shown on public list of members. If you don't want this, check off the "public" box. @@ -743,6 +749,7 @@ Calendar=Calendar GroupBy=Group by... ViewFlatList=View flat list RemoveString=Remove string '%s' +SomeTranslationAreUncomplete=Some languages may be partially translated or may contains errors. If you detect some, you can fix language files registering to http://transifex.com/projects/p/dolibarr/. # Week day Monday=Monday Tuesday=Tuesday diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index c123fed51a5..245f6f3ccc0 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -13,7 +13,7 @@ ListOfValidatedPublicMembers=List of validated public members ErrorThisMemberIsNotPublic=This member is not public ErrorMemberIsAlreadyLinkedToThisThirdParty=Another member (name: %s, login: %s) is already linked to a third party %s. Remove this link first because a third party can't be linked to only a member (and vice versa). ErrorUserPermissionAllowsToLinksToItselfOnly=For security reasons, you must be granted permissions to edit all users to be able to link a member to a user that is not yours. -ThisIsContentOfYourCard=This is details of your card +ThisIsContentOfYourCard=Hi.

This is a remind of the information we get about you. Feel free to contact us if something looks wrong.

CardContent=Content of your member card SetLinkToUser=Link to a Dolibarr user SetLinkToThirdParty=Link to a Dolibarr third party diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index 2f0579394eb..62ffb02bbcf 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -126,29 +126,19 @@ TypeContact_order_supplier_internal_SHIPPING=Representative following-up shippin TypeContact_order_supplier_external_BILLING=Supplier invoice contact TypeContact_order_supplier_external_SHIPPING=Supplier shipping contact TypeContact_order_supplier_external_CUSTOMER=Supplier contact following-up order - Error_COMMANDE_SUPPLIER_ADDON_NotDefined=Constant COMMANDE_SUPPLIER_ADDON not defined Error_COMMANDE_ADDON_NotDefined=Constant COMMANDE_ADDON not defined Error_OrderNotChecked=No orders to invoice selected -# Sources -OrderSource0=Commercial proposal -OrderSource1=Internet -OrderSource2=Mail campaign -OrderSource3=Phone compaign -OrderSource4=Fax campaign -OrderSource5=Commercial -OrderSource6=Store -QtyOrdered=Qty ordered -# Documents models -PDFEinsteinDescription=A complete order model (logo...) -PDFEdisonDescription=A simple order model -PDFProformaDescription=A complete proforma invoice (logo…) -# Orders modes +# Order modes (how we receive order). Not the "why" are keys stored into dict.lang OrderByMail=Mail OrderByFax=Fax OrderByEMail=EMail OrderByWWW=Online OrderByPhone=Phone +# Documents models +PDFEinsteinDescription=A complete order model (logo...) +PDFEdisonDescription=A simple order model +PDFProformaDescription=A complete proforma invoice (logo…) CreateInvoiceForThisCustomer=Bill orders NoOrdersToInvoice=No orders billable CloseProcessedOrdersAutomatically=Classify "Processed" all selected orders. @@ -158,4 +148,5 @@ OrderCreated=Your orders have been created OrderFail=An error happened during your orders creation CreateOrders=Create orders ToBillSeveralOrderSelectCustomer=To create an invoice for several orders, click first onto customer, then choose "%s". -CloseReceivedSupplierOrdersAutomatically=Close order to "%s" automatically if all products are received. \ No newline at end of file +CloseReceivedSupplierOrdersAutomatically=Close order to "%s" automatically if all products are received. +SetShippingMode=Set shipping mode \ No newline at end of file diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index 9b9fd13f5cb..e62c925da00 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -17,7 +17,7 @@ printEatby=Eat-by: %s printSellby=Sell-by: %s printQty=Qty: %d AddDispatchBatchLine=Add a line for Shelf Life dispatching -WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, increase/decrease stock mode is forced to last choice and can't be edited. Other options can be defined as you want. +WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, automatic increase/decrease stock mode is forced to shipping validate and manual dispatching for reception and can't be edited. Other options can be defined as you want. ProductDoesNotUseBatchSerial=This product does not use lot/serial number ProductLotSetup=Setup of module lot/serial ShowCurrentStockOfLot=Show current stock for couple product/lot diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 64b2ee995bc..37ccb4a6d10 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -89,7 +89,7 @@ NoteNotVisibleOnBill=Note (not visible on invoices, proposals...) ServiceLimitedDuration=If product is a service with limited duration: MultiPricesAbility=Several segment of prices per product/service (each customer is in one segment) MultiPricesNumPrices=Number of prices -AssociatedProductsAbility=Activate the package feature +AssociatedProductsAbility=Activate the feature to manage virtual products AssociatedProducts=Virtual product AssociatedProductsNumber=Number of products composing this virtual product ParentProductsNumber=Number of parent packaging product diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 7897d57007d..dedd187db6d 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -22,6 +22,7 @@ TasksPublicDesc=This view presents all projects and tasks you are allowed to rea TasksDesc=This view presents all projects and tasks (your user permissions grant you permission to view everything). AllTaskVisibleButEditIfYouAreAssigned=All tasks for such project are visible, but you can enter time only for task you are assigned on. Assign task to you if you want to enter time on it. OnlyYourTaskAreVisible=Only tasks you are assigned on are visible. Assign task to you if you want to enter time on it. +ImportDatasetTasks=Tasks of projects NewProject=New project AddProject=Create project DeleteAProject=Delete a project diff --git a/htdocs/langs/en_US/sendings.lang b/htdocs/langs/en_US/sendings.lang index cbbeb092a1a..1b90020edde 100644 --- a/htdocs/langs/en_US/sendings.lang +++ b/htdocs/langs/en_US/sendings.lang @@ -16,14 +16,15 @@ NbOfSendings=Number of shipments NumberOfShipmentsByMonth=Number of shipments by month SendingCard=Shipment card NewSending=New shipment -CreateASending=Create a shipment +CreateShipment=Create shipment QtyShipped=Qty shipped +QtyPreparedOrShipped=Qty prepared or shipped QtyToShip=Qty to ship QtyReceived=Qty received QtyInOtherShipments=Qty in other shipments KeepToShip=Remain to ship OtherSendingsForSameOrder=Other shipments for this order -SendingsAndReceivingForSameOrder=Shipments and receivings for this order +SendingsAndReceivingForSameOrder=Shipments and receipts for this order SendingsToValidate=Shipments to validate StatusSendingCanceled=Canceled StatusSendingDraft=Draft diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index d5fa618b1e0..90ec9a6fb2c 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -46,7 +46,7 @@ PMPValue=Weighted average price PMPValueShort=WAP EnhancedValueOfWarehouses=Warehouses value UserWarehouseAutoCreate=Create a warehouse automatically when creating a user -AllowAddLimitStockByWarehouse=Allow to add limit and desired stock by product and warehouse +AllowAddLimitStockByWarehouse=Allow to add limit and desired stock per couple (product, warehouse) instead of per product IndependantSubProductStock=Product stock and subproduct stock are independant QtyDispatched=Quantity dispatched QtyDispatchedShort=Qty dispatched @@ -136,7 +136,7 @@ OpenAll=Open for all actions OpenInternal=Open for internal actions OpenShipping=Open for shippings OpenDispatch=Open for dispatch -UseDispatchStatus=Use dispatch status (aprouve/refuse) +UseDispatchStatus=Use a dispatch status (approve/refuse) for product lines on supplier order reception OptionMULTIPRICESIsOn=Option "several prices per segment" is on. It means a product has several selling price so value for sell can't be calculated ProductStockWarehouseCreated=Stock limit for alert and desired optimal stock correctly created ProductStockWarehouseUpdated=Stock limit for alert and desired optimal stock correctly updated diff --git a/htdocs/langs/en_US/trips.lang b/htdocs/langs/en_US/trips.lang index 6a12588139d..900b424f3e7 100644 --- a/htdocs/langs/en_US/trips.lang +++ b/htdocs/langs/en_US/trips.lang @@ -1,6 +1,7 @@ # Dolibarr language file - Source file is en_US - trips ExpenseReport=Expense report ExpenseReports=Expense reports +ShowExpenseReport=Show expense report Trips=Expense reports TripsAndExpenses=Expenses reports TripsAndExpensesStatistics=Expense reports statistics diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index 8a09c66989e..4a002fab02c 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -8,7 +8,7 @@ EditPassword=Edit password SendNewPassword=Regenerate and send password ReinitPassword=Regenerate password PasswordChangedTo=Password changed to: %s -SubjectNewPassword=Your new password for Dolibarr +SubjectNewPassword=Your new password for %s GroupRights=Group permissions UserRights=User permissions UserGUISetup=User display setup diff --git a/htdocs/langs/fr_FR/companies.lang b/htdocs/langs/fr_FR/companies.lang index a56e0f27e09..5671adf71aa 100644 --- a/htdocs/langs/fr_FR/companies.lang +++ b/htdocs/langs/fr_FR/companies.lang @@ -173,6 +173,12 @@ ProfId3FR=Id. prof. 3 (NAF-APE) ProfId4FR=Id. prof. 4 (RCS/RM) ProfId5FR=- ProfId6FR=- +ProfId1GA=Id. prof. 1 (NIF) +ProfId2GA=Id. prof. 2 (RCCM) +ProfId3GA=Id. prof. 3 (CAE) +ProfId4GA=Id. prof. 4 +ProfId5GA=- +ProfId6GA=- ProfId1GB=Numéro d'enregistrement ProfId2GB=- ProfId3GB=SIC diff --git a/htdocs/livraison/card.php b/htdocs/livraison/card.php index c1236f239bd..b6097886529 100644 --- a/htdocs/livraison/card.php +++ b/htdocs/livraison/card.php @@ -750,14 +750,6 @@ else // Rien a droite print '
'; - - // List of existing shipment and delivery receipts - /*if ($expedition->origin_id) - { - print '
'; - //show_list_sending_receive($expedition->origin,$expedition->origin_id," AND e.rowid <> ".$expedition->id); - show_list_sending_receive($expedition->origin,$expedition->origin_id); - }*/ } else { diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index 0894447d485..2b31ca856bc 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -245,7 +245,7 @@ if ($action == 'create') print '
'.$langs->trans('NotePrivate').''; - $doleditor = new DolEditor('note_private', GETPOST('note_private', 'alpha'), '', 160, 'dolibarr_notes', 'In', false, true, true, ROWS_6, 100); + $doleditor = new DolEditor('note_private', GETPOST('note_private', 'alpha'), '', 160, 'dolibarr_notes', 'In', false, true, true, ROWS_6, '90%'); print $doleditor->Create(1); print '
'.$langs->trans('NotePublic').''; - $doleditor = new DolEditor('note_public', GETPOST('note_public', 'alpha'), '', 160, 'dolibarr_notes', 'In', false, true, true, ROWS_6, 100); + $doleditor = new DolEditor('note_public', GETPOST('note_public', 'alpha'), '', 160, 'dolibarr_notes', 'In', false, true, true, ROWS_6, '90%'); print $doleditor->Create(1); print '
'; + print '
'; + print '
'."\n"; + print ''; print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"l.rowid","",$param,"",$sortfield,$sortorder); print_liste_field_titre($langs->trans("Label"),$_SERVER["PHP_SELF"],"l.label","",$param,'align="left"',$sortfield,$sortorder); @@ -176,6 +178,7 @@ if ($resql) } print "
"; + print ''; print "\n"; $db->free($resql); } diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index b64da2c0b2d..3a9ef61d7ec 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -849,6 +849,7 @@ if (! defined('NOREQUIRETRAN')) $bc=array(0=>'class="impair"',1=>'class="pair"'); $bcdd=array(0=>'class="impair drag drop"',1=>'class="pair drag drop"'); $bcnd=array(0=>'class="impair nodrag nodrop nohover"',1=>'class="pair nodrag nodrop nohoverpair"'); // Used for tr to add new lines +$bctag=array(0=>'class="impair tagtr"',1=>'class="pair tagtr"'); // Define messages variables $mesg=''; $warning=''; $error=0; @@ -1887,7 +1888,7 @@ if (! function_exists("llxFooter")) print '
'.$msg.'
'; } - define("MAIN_CORE_ERROR",0); + //define("MAIN_CORE_ERROR",0); // Constant was defined and we can't change value of a constant } print "\n\n"; diff --git a/htdocs/margin/checkMargins.php b/htdocs/margin/checkMargins.php index 66ade35e09e..24451e39d77 100644 --- a/htdocs/margin/checkMargins.php +++ b/htdocs/margin/checkMargins.php @@ -179,7 +179,10 @@ if ($result) { print '
'; print_barre_liste($langs->trans("MarginDetails"), $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, '', $num, $nbtotalofrecords, ''); - print ""; + $moreforfilter=''; + + print '
'; + print '
'."\n"; print ''; @@ -244,6 +247,8 @@ if ($result) { } } print "
"; + + print ""; } else { dol_print_error($db); } diff --git a/htdocs/margin/productMargins.php b/htdocs/margin/productMargins.php index 24150a1050c..88570d1c1d4 100644 --- a/htdocs/margin/productMargins.php +++ b/htdocs/margin/productMargins.php @@ -203,8 +203,11 @@ if ($result) print '
'; print_barre_liste($langs->trans("MarginDetails"),$page,$_SERVER["PHP_SELF"],"&id=".$id,$sortfield,$sortorder,'',0,0,''); + $moreforfilter=''; + $i = 0; - print ""; + print '
'; + print '
'."\n"; print ''; if ($id > 0) { @@ -324,6 +327,7 @@ if ($result) print "\n"; print "
"; + print ''; } else { diff --git a/htdocs/opensurvey/card.php b/htdocs/opensurvey/card.php index dc0acb48d96..133f1554b49 100644 --- a/htdocs/opensurvey/card.php +++ b/htdocs/opensurvey/card.php @@ -252,7 +252,7 @@ print ''; print ''.$langs->trans("Description") .''; if ($action == 'edit') { - $doleditor=new DolEditor('nouveauxcommentaires', dol_htmlentities($object->commentaires),'',120,'dolibarr_notes','In',1,1,1,ROWS_7,120); + $doleditor=new DolEditor('nouveauxcommentaires', dol_htmlentities($object->commentaires),'',120,'dolibarr_notes','In',1,1,1,ROWS_7,'90%'); $doleditor->Create(0,''); } else diff --git a/htdocs/opensurvey/list.php b/htdocs/opensurvey/list.php index aed5610bee0..584685ead51 100644 --- a/htdocs/opensurvey/list.php +++ b/htdocs/opensurvey/list.php @@ -78,8 +78,6 @@ llxHeader(); $param=''; $fieldtosortuser=empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION)?'firstname':'lastname'; -print '
'."\n"; - print load_fiche_titre($langs->trans("OpenSurveyArea")); // List of surveys into database @@ -90,7 +88,11 @@ print ''; print ''; print ''; -print ''."\n"; +$moreforfilter = ''; + +print '
'; +print '
'."\n"; + print ''; print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "p.id_sondage",$param,"","",$sortfield,$sortorder); print_liste_field_titre($langs->trans("Title"), $_SERVER["PHP_SELF"], "p.titre",$param,"","",$sortfield,$sortorder); @@ -104,7 +106,7 @@ print ''."\n"; print ''; print ''; -print ''; +print ''; print ''; print ''; print ''; @@ -197,11 +199,9 @@ while ($i < min($num,$limit)) } print '
'."\n"; - +print '
'; print ''; -print ''."\n"; - llxFooter(); $db->close(); diff --git a/htdocs/opensurvey/wizard/create_survey.php b/htdocs/opensurvey/wizard/create_survey.php index 94ec2a7c247..787bb7969fa 100644 --- a/htdocs/opensurvey/wizard/create_survey.php +++ b/htdocs/opensurvey/wizard/create_survey.php @@ -149,7 +149,7 @@ if (! $_SESSION["titre"] && (GETPOST('creation_sondage_date') || GETPOST('creati print ''."\n"; print ''. $langs->trans("Description") .''; -$doleditor=new DolEditor('commentaires', $_SESSION["commentaires"],'',120,'dolibarr_notes','In',1,1,1,ROWS_7,120); +$doleditor=new DolEditor('commentaires', $_SESSION["commentaires"],'',120,'dolibarr_notes','In',1,1,1,ROWS_7,'90%'); $doleditor->Create(0,''); print ''."\n"; print ''."\n"; diff --git a/htdocs/paybox/admin/paybox.php b/htdocs/paybox/admin/paybox.php index 98645575a13..8abcac5a6f1 100644 --- a/htdocs/paybox/admin/paybox.php +++ b/htdocs/paybox/admin/paybox.php @@ -179,14 +179,14 @@ print ''; $var=!$var; print ''; print $langs->trans("MessageOK").''; -$doleditor=new DolEditor('PAYBOX_MESSAGE_OK',$conf->global->PAYBOX_MESSAGE_OK,'',100,'dolibarr_details','In',false,true,true,ROWS_2,60); +$doleditor=new DolEditor('PAYBOX_MESSAGE_OK',$conf->global->PAYBOX_MESSAGE_OK,'',100,'dolibarr_details','In',false,true,true,ROWS_2,'90%'); $doleditor->Create(); print ''; $var=!$var; print ''; print $langs->trans("MessageKO").''; -$doleditor=new DolEditor('PAYBOX_MESSAGE_KO',$conf->global->PAYBOX_MESSAGE_KO,'',100,'dolibarr_details','In',false,true,true,ROWS_2,60); +$doleditor=new DolEditor('PAYBOX_MESSAGE_KO',$conf->global->PAYBOX_MESSAGE_KO,'',100,'dolibarr_details','In',false,true,true,ROWS_2,'90%'); $doleditor->Create(); print ''; diff --git a/htdocs/paypal/admin/paypal.php b/htdocs/paypal/admin/paypal.php index f794989c59e..e63fb3e85c7 100644 --- a/htdocs/paypal/admin/paypal.php +++ b/htdocs/paypal/admin/paypal.php @@ -203,14 +203,14 @@ print ''; $var=!$var; print ''; print $langs->trans("MessageOK").''; -$doleditor=new DolEditor('PAYPAL_MESSAGE_OK',$conf->global->PAYPAL_MESSAGE_OK,'',100,'dolibarr_details','In',false,true,true,ROWS_4,60); +$doleditor=new DolEditor('PAYPAL_MESSAGE_OK',$conf->global->PAYPAL_MESSAGE_OK,'',100,'dolibarr_details','In',false,true,true,ROWS_4,'90%'); $doleditor->Create(); print ''; $var=!$var; print ''; print $langs->trans("MessageKO").''; -$doleditor=new DolEditor('PAYPAL_MESSAGE_KO',$conf->global->PAYPAL_MESSAGE_KO,'',100,'dolibarr_details','In',false,true,true,ROWS_4,60); +$doleditor=new DolEditor('PAYPAL_MESSAGE_KO',$conf->global->PAYPAL_MESSAGE_KO,'',100,'dolibarr_details','In',false,true,true,ROWS_4,'90%'); $doleditor->Create(); print ''; diff --git a/htdocs/product/admin/dynamic_prices.php b/htdocs/product/admin/dynamic_prices.php index 7c9a46d8972..7949b47c346 100644 --- a/htdocs/product/admin/dynamic_prices.php +++ b/htdocs/product/admin/dynamic_prices.php @@ -322,7 +322,7 @@ if ($action == 'create_updater' || $action == 'edit_updater') { $help = $langs->trans("GlobalVariableUpdaterHelp".$type).'
'.$langs->trans("GlobalVariableUpdaterHelpFormat".$type).''; print ''.$form->textwithpicto($langs->trans("Parameters"),$help,1).''; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('parameters',empty($price_updaters->parameters)?'':$price_updaters->parameters,'',300,'','',false,false,false,10,80); + $doleditor=new DolEditor('parameters',empty($price_updaters->parameters)?'':$price_updaters->parameters,'',300,'','',false,false,false,ROWS_8,'90%'); $doleditor->Create(); print ''; print ''; diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index c399d222177..e6d2c6524b7 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -63,7 +63,7 @@ dol_syslog(join(',', $_GET)); if (! empty($action) && $action == 'fetch' && ! empty($id)) { - require DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; $outjson = array(); diff --git a/htdocs/product/card.php b/htdocs/product/card.php index fbf199f8edd..1465510f9b8 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -636,7 +636,7 @@ if (empty($reshook)) $pu_ht = price($prodcustprice->lines [0]->price); $pu_ttc = price($prodcustprice->lines [0]->price_ttc); $price_base_type = $prodcustprice->lines [0]->price_base_type; - $prod->tva_tx = $prodcustprice->lines [0]->tva_tx; + $tva_tx = $prodcustprice->lines [0]->tva_tx; } } } @@ -953,7 +953,7 @@ else // Description (used in invoice, propal...) print ''.$langs->trans("Description").''; - $doleditor = new DolEditor('desc', GETPOST('desc'), '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, '80%'); + $doleditor = new DolEditor('desc', GETPOST('desc'), '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '80%'); $doleditor->Create(); print ""; @@ -1065,7 +1065,7 @@ else print ''.$langs->trans("NoteNotVisibleOnBill").''; // We use dolibarr_details as type of DolEditor here, because we must not accept images as description is included into PDF and not accepted by TCPDF. - $doleditor = new DolEditor('note_private', GETPOST('note_private'), '', 140, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 8, '80%'); + $doleditor = new DolEditor('note_private', GETPOST('note_private'), '', 140, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_8, '80%'); $doleditor->Create(); print ""; @@ -1260,7 +1260,7 @@ else print ''.$langs->trans("Description").''; // We use dolibarr_details as type of DolEditor here, because we must not accept images as description is included into PDF and not accepted by TCPDF. - $doleditor = new DolEditor('desc', $object->description, '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, 80); + $doleditor = new DolEditor('desc', $object->description, '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '90%'); $doleditor->Create(); print ""; @@ -1391,7 +1391,7 @@ else { print ''.$langs->trans("NoteNotVisibleOnBill").''; - $doleditor = new DolEditor('note_private', $object->note_private, '', 140, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, 80); + $doleditor = new DolEditor('note_private', $object->note_private, '', 140, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '90%'); $doleditor->Create(); print ""; @@ -1764,8 +1764,11 @@ $formquestionclone=array( array('type' => 'text', 'name' => 'clone_ref','label' => $langs->trans("NewRefForClone"), 'value' => empty($tmpcode) ? $langs->trans("CopyOf").' '.$object->ref : $tmpcode, 'size'=>24), array('type' => 'checkbox', 'name' => 'clone_content','label' => $langs->trans("CloneContentProduct"), 'value' => 1), array('type' => 'checkbox', 'name' => 'clone_prices', 'label' => $langs->trans("ClonePricesProduct").' ('.$langs->trans("FeatureNotYetAvailable").')', 'value' => 0, 'disabled' => true), - array('type' => 'checkbox', 'name' => 'clone_composition', 'label' => $langs->trans('CloneCompositionProduct'), 'value' => 1) ); +if (! empty($conf->global->PRODUIT_SOUSPRODUITS)) +{ + $formquestionclone[]=array('type' => 'checkbox', 'name' => 'clone_composition', 'label' => $langs->trans('CloneCompositionProduct'), 'value' => 1); +} // Confirm delete product if (($action == 'delete' && (empty($conf->use_javascript_ajax) || ! empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js diff --git a/htdocs/product/class/api_deprecated_product.class.php b/htdocs/product/class/api_deprecated_product.class.php index d4ad8335f54..66f34fbd9c3 100644 --- a/htdocs/product/class/api_deprecated_product.class.php +++ b/htdocs/product/class/api_deprecated_product.class.php @@ -307,6 +307,7 @@ class ProductApi extends DolibarrApi } foreach($request_data as $field => $value) { + if ($field == 'id') continue; $this->product->$field = $value; } diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 290d011d09c..0c08fb0dc35 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -213,6 +213,7 @@ class Products extends DolibarrApi } foreach($request_data as $field => $value) { + if ($field == 'id') continue; $this->product->$field = $value; } diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 23f590c3533..e450a3d5931 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -935,7 +935,23 @@ class Product extends CommonObject if ($result < 0) { $error++; } // End call triggers } - + + // Delete from product_batch on product delete + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX.'product_batch'; + $sql.= " WHERE fk_product_stock IN ("; + $sql.= "SELECT rowid FROM ".MAIN_DB_PREFIX.'product_stock'; + $sql.= " WHERE fk_product = ".$id.")"; + dol_syslog(get_class($this).'::delete', LOG_DEBUG); + $result = $this->db->query($sql); + if (! $result) + { + $error++; + $this->errors[] = $this->db->lasterror(); + } + } + // Delete all child tables if (! $error) { @@ -2016,6 +2032,30 @@ class Product extends CommonObject $this->stats_commande['nb']=$obj->nb; $this->stats_commande['rows']=$obj->nb_rows; $this->stats_commande['qty']=$obj->qty?$obj->qty:0; + + // if it's a virtual product, maybe it is in order by extension + if (! empty($conf->global->ORDER_ADD_ORDERS_WITH_PARENT_PROD_IF_INCDEC)) + { + $TFather = $this->getFather(); + if (is_array($TFather) && !empty($TFather)) { + foreach($TFather as &$fatherData) { + $pFather = new Product($this->db); + $pFather->id = $fatherData['id']; + $qtyCoef = $fatherData['qty']; + + if ($fatherData['incdec']) { + $pFather->load_stats_commande($socid, $filtrestatut); + + $this->stats_commande['customers']+=$pFather->stats_commande['customers']; + $this->stats_commande['nb']+=$pFather->stats_commande['nb']; + $this->stats_commande['rows']+=$pFather->stats_commande['rows']; + $this->stats_commande['qty']+=$pFather->stats_commande['qty'] * $qtyCoef; + + } + } + } + } + return 1; } else @@ -2174,7 +2214,7 @@ class Product extends CommonObject if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE c.rowid = cd.fk_contrat"; $sql.= " AND c.fk_soc = s.rowid"; - $sql.= " AND c.entity IN (".getEntity('contrat', 1).")"; + $sql.= " AND c.entity IN (".getEntity('contract', 1).")"; $sql.= " AND cd.fk_product = ".$this->id; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; //$sql.= " AND c.statut != 0"; @@ -2800,7 +2840,7 @@ class Product extends CommonObject $list = array(); - $sql = "SELECT p.fk_soc"; + $sql = "SELECT DISTINCT p.fk_soc"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as p"; $sql.= " WHERE p.fk_product = ".$this->id; $sql.= " AND p.entity = ".$conf->entity; @@ -2852,17 +2892,17 @@ class Product extends CommonObject /** * Clone links between products * - * @param int $fromId Product id - * @param int $toId Product id - * @return number + * @param int $fromId Product id + * @param int $toId Product id + * @return int <0 if KO, >0 if OK */ function clone_associations($fromId, $toId) { $this->db->begin(); - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_association (rowid, fk_product_pere, fk_product_fils, qty)'; - $sql.= " SELECT null, $toId, fk_product_fils, qty FROM ".MAIN_DB_PREFIX."product_association"; - $sql.= " WHERE fk_product_pere = '".$fromId."'"; + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'product_association (fk_product_pere, fk_product_fils, qty)'; + $sql.= " SELECT ".$toId.", fk_product_fils, qty FROM ".MAIN_DB_PREFIX."product_association"; + $sql.= " WHERE fk_product_pere = ".$fromId; dol_syslog(get_class($this).'::clone_association', LOG_DEBUG); if (! $this->db->query($sql)) @@ -3204,7 +3244,11 @@ class Product extends CommonObject { // } - if (! empty($this->entity)) $label .= '
' . $this->show_photos($conf->product->multidir_output[$this->entity],1,1,0,0,0,80); + if (! empty($this->entity)) + { + $tmpphoto = $this->show_photos($conf->product->multidir_output[$this->entity],1,1,0,0,0,80); + if ($this->nbphoto > 0) $label .= '
' . $tmpphoto; + } $linkclose=''; diff --git a/htdocs/product/dynamic_price/editor.php b/htdocs/product/dynamic_price/editor.php index 9b20371ea5b..0b93d17749a 100644 --- a/htdocs/product/dynamic_price/editor.php +++ b/htdocs/product/dynamic_price/editor.php @@ -199,7 +199,7 @@ foreach ($price_globals->listGlobalVariables() as $entry) { //Price expression editor print ''.$form->textwithpicto($langs->trans("PriceExpressionEditor"),$help_text,1).''; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; -$doleditor=new DolEditor('expression',isset($price_expression->expression)?$price_expression->expression:'','',300,'','',false,false,false,4,80); +$doleditor=new DolEditor('expression',isset($price_expression->expression)?$price_expression->expression:'','',300,'','',false,false,false,ROWS_4,'90%'); $doleditor->Create(); print ''; print ''; diff --git a/htdocs/product/list.php b/htdocs/product/list.php index e130f2d3d7d..d54adaadd9e 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -471,7 +471,8 @@ else $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - print ''; + print '
'; + print '
'."\n"; print ''; if (! empty($arrayfields['p.ref']['checked'])) print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"],"p.ref","",$param,"",$sortfield,$sortorder); if (! empty($arrayfields['pfp.ref_fourn']['checked'])) print_liste_field_titre($arrayfields['pfp.ref_fourn']['label'], $_SERVER["PHP_SELF"],"pfp.ref_fourn","",$param,"",$sortfield,$sortorder); @@ -871,6 +872,7 @@ else $db->free($resql); print "
"; + print ""; } print ''; } diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index b193e553b61..13bc0fef186 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -86,7 +86,7 @@ if (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || ! empty($conf->global * Actions */ -if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers +if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers { $sref=""; $snom=""; @@ -261,6 +261,7 @@ if ($resql) $colspan_warehouse = 1; if (! empty($conf->global->STOCK_DETAIL_ON_WAREHOUSE)) { $colspan_warehouse = $nb_warehouse > 1 ? $nb_warehouse+1 : 1; } + print '
'; print ''; // Lignes des titres @@ -381,6 +382,7 @@ if ($resql) } print "
"; + print '
'; print ''; if ($num > $conf->liste_limit) diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index c9619124389..471aa7e3e6d 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -83,7 +83,7 @@ if (! empty($canvas)) * Actions */ -if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers +if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers { $sref=""; $snom=""; @@ -249,7 +249,8 @@ if ($resql) /*if ($eatby) $param.="&eatby=".$eatby; if ($sellby) $param.="&sellby=".$sellby;*/ - print ''; + print '
'; + print '
'; // Lignes des titres print ""; @@ -381,6 +382,7 @@ if ($resql) } print "
"; + print ''; print ''; if ($num > $conf->liste_limit) diff --git a/htdocs/product/stats/commande.php b/htdocs/product/stats/commande.php index f9b9d14d794..192017af2a5 100644 --- a/htdocs/product/stats/commande.php +++ b/htdocs/product/stats/commande.php @@ -193,7 +193,8 @@ if ($id > 0 || ! empty($ref)) print ''; $i = 0; - print ''; + print '
'; + print '
'; print ''; print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"c.rowid","",$option,'',$sortfield,$sortorder); print_liste_field_titre($langs->trans("Company"),$_SERVER["PHP_SELF"],"s.nom","",$option,'',$sortfield,$sortorder); @@ -243,8 +244,8 @@ if ($id > 0 || ! empty($ref)) print ''; print ''; print "
'.price($total_ht).'
"; + print ""; print ''; - print '
'; } else { dol_print_error($db); } diff --git a/htdocs/product/stats/commande_fournisseur.php b/htdocs/product/stats/commande_fournisseur.php index 4bdfdcc5c81..bed3be1892f 100644 --- a/htdocs/product/stats/commande_fournisseur.php +++ b/htdocs/product/stats/commande_fournisseur.php @@ -72,6 +72,7 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) { $search_year = ''; } + /* * View */ @@ -203,6 +204,7 @@ if ($id > 0 || ! empty($ref)) { print ''; $i = 0; + print '
'; print ''; print ''; print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "c.rowid", "", $option, '', $sortfield, $sortorder); @@ -251,8 +253,8 @@ if ($id > 0 || ! empty($ref)) { print ''; print ''; print "
' . price($total_ht) . '
"; + print '
'; print ''; - print '
'; } else { dol_print_error($db); } diff --git a/htdocs/product/stats/contrat.php b/htdocs/product/stats/contrat.php index ff91fbf299e..8c5f1a3ba86 100644 --- a/htdocs/product/stats/contrat.php +++ b/htdocs/product/stats/contrat.php @@ -123,7 +123,7 @@ if ($id > 0 || ! empty($ref)) $sql.= ", ".MAIN_DB_PREFIX."contratdet as cd"; $sql.= " WHERE c.rowid = cd.fk_contrat"; $sql.= " AND c.fk_soc = s.rowid"; - $sql.= " AND c.entity IN (".getEntity('contrat', 1).")"; + $sql.= " AND c.entity IN (".getEntity('contract', 1).")"; $sql.= " AND cd.fk_product =".$product->id; if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; if ($socid) $sql.= " AND s.rowid = ".$socid; @@ -135,10 +135,27 @@ if ($id > 0 || ! empty($ref)) if ($result) { $num = $db->num_rows($result); - + if (! empty($id)) + $option .= '&id=' . $product->id; + if (! empty($search_month)) + $option .= '&search_month=' . $search_month; + if (! empty($search_year)) + $option .= '&search_year=' . $search_year; + + print '
' . "\n"; + if (! empty($sortfield)) + print ''; + if (! empty($sortorder)) + print ''; + if (! empty($page)) { + print ''; + $option .= '&page=' . $page; + } + print_barre_liste($langs->trans("Contrats"),$page,$_SERVER["PHP_SELF"],"&id=$product->id",$sortfield,$sortorder,'',$num,0,''); $i = 0; + print '
'; print ''; print ''; @@ -180,13 +197,15 @@ if ($id > 0 || ! empty($ref)) $i++; } } + + print '
'; + print '
'; + print '
'; } else { dol_print_error($db); } - print ""; - print '
'; $db->free($result); } } diff --git a/htdocs/product/stats/facture.php b/htdocs/product/stats/facture.php index e9eb3d41859..53e5b0ab0a6 100644 --- a/htdocs/product/stats/facture.php +++ b/htdocs/product/stats/facture.php @@ -216,6 +216,7 @@ if ($id > 0 || ! empty($ref)) print ''; $i = 0; + print '
'; print ''; print ''; print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"s.rowid","",$option,'',$sortfield,$sortorder); @@ -265,8 +266,8 @@ if ($id > 0 || ! empty($ref)) print ''; print ''; print "
'.price($total_ht).'
"; + print '
'; print ''; - print '
'; } else { dol_print_error($db); } diff --git a/htdocs/product/stats/facture_fournisseur.php b/htdocs/product/stats/facture_fournisseur.php index 77bd4b73887..6fe189c7700 100644 --- a/htdocs/product/stats/facture_fournisseur.php +++ b/htdocs/product/stats/facture_fournisseur.php @@ -195,6 +195,7 @@ if ($id > 0 || ! empty($ref)) print ''; $i = 0; + print '
'; print ''; print ''; print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "s.rowid", "", $option, '', $sortfield, $sortorder); @@ -244,8 +245,8 @@ if ($id > 0 || ! empty($ref)) print ''; print ''; print "
' . price($total_ht) . '
"; + print '
'; print ''; - print '
'; } else { dol_print_error($db); } diff --git a/htdocs/product/stats/propal.php b/htdocs/product/stats/propal.php index d23853c174f..289cf3d3578 100644 --- a/htdocs/product/stats/propal.php +++ b/htdocs/product/stats/propal.php @@ -197,6 +197,7 @@ if ($id > 0 || ! empty($ref)) print ''; $i = 0; + print '
'; print ''; print ''; print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "p.rowid", "", $option, '', $sortfield, $sortorder); @@ -238,19 +239,20 @@ if ($id > 0 || ! empty($ref)) } } } - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print "
' . $langs->trans('Total') . '' . $total_qty . '' . price($total_ht) . '
"; - print ''; - print '
'; - } else { - dol_print_error($db); - } - $db->free($result); + + print ''; + print '' . $langs->trans('Total') . ''; + print ''; + print '' . $total_qty . ''; + print '' . price($total_ht) . ''; + print ''; + print ""; + print '
'; + print ''; + } else { + dol_print_error($db); + } + $db->free($result); } } } else { diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php index f1097b331b9..ad6ea9d6560 100644 --- a/htdocs/product/stock/card.php +++ b/htdocs/product/stock/card.php @@ -204,7 +204,7 @@ if ($action == 'create') print ''.$langs->trans("Description").''; // Editeur wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('desc',(!empty($object->description)?$object->description:''),'',180,'dolibarr_notes','In',false,true,$conf->fckeditor->enabled,5,70); + $doleditor=new DolEditor('desc',(!empty($object->description)?$object->description:''),'',180,'dolibarr_notes','In',false,true,$conf->fckeditor->enabled,ROWS_5,'90%'); $doleditor->Create(); print ''; @@ -332,7 +332,8 @@ else // Nb of products print ''.$langs->trans("NumberOfProducts").''; - print empty($calcproducts['nb'])?'0':$calcproducts['nb']; + $valtoshow=price2num($calcproducts['nb'], 'MS'); + print empty($valtoshow)?'0':$valtoshow; print ""; print ''; @@ -485,13 +486,19 @@ else $productstatic->entity=$objp->entity; print $productstatic->getNomUrl(1,'stock',16); print ''; + + // Label print ''.$objp->produit.''; - print ''.$objp->value.''; + print ''; + $valtoshow=price2num($objp->value, 'MS'); + print empty($valtoshow)?'0':$valtoshow; + print ''; $totalunit+=$objp->value; // Price buy PMP print ''.price(price2num($objp->ppmp,'MU')).''; + // Total PMP print ''.price(price2num($objp->ppmp*$objp->value,'MT')).''; $totalvalue+=price2num($objp->ppmp*$objp->value,'MT'); @@ -530,7 +537,10 @@ else $db->free($resql); print ''.$langs->trans("Total").''; - print ''.$totalunit.''; + print ''; + $valtoshow=price2num($totalunit, 'MS'); + print empty($valtoshow)?'0':$valtoshow; + print ''; print ' '; print ''.price(price2num($totalvalue,'MT')).''; if (empty($conf->global->PRODUIT_MULTIPRICES)) @@ -583,7 +593,7 @@ else print ''.$langs->trans("Description").''; // Editeur wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('desc',$object->description,'',180,'dolibarr_notes','In',false,true,$conf->fckeditor->enabled,5,70); + $doleditor=new DolEditor('desc',$object->description,'',180,'dolibarr_notes','In',false,true,$conf->fckeditor->enabled,ROWS_5,'90%'); $doleditor->Create(); print ''; diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php new file mode 100644 index 00000000000..a246e7fc135 --- /dev/null +++ b/htdocs/product/stock/class/api_stockmovements.class.php @@ -0,0 +1,350 @@ + + * + * 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 . + */ + +use Luracast\Restler\RestException; + +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; + + +/** + * API class for stock movements + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class StockMovements extends DolibarrApi +{ + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'product_id', + 'warehouse_id', + 'qty' + ); + + /** + * @var MouvmeentStock $stockmovement {@type MouvementStock} + */ + public $stockmovement; + + /** + * Constructor + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->stockmovement = new MouvementStock($this->db); + } + + /** + * Get properties of a stock movement object + * + * Return an array with stock movement informations + * + * @param int $id ID of movement + * @return array|mixed data without useless information + * + * @throws RestException + */ + /* + function get($id) + { + if(! DolibarrApiAccess::$user->rights->stock->lire) { + throw new RestException(401); + } + + $result = $this->stockmovement->fetch($id); + if( ! $result ) { + throw new RestException(404, 'warehouse not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('warehouse',$this->stockmovement->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->stockmovement); + }*/ + + /** + * Get a list of stock movement + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.product_id:=:1) and (t.date_creation:<:'20160101')" + * @return array Array of warehouse objects + * + * @throws RestException + */ + function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $sqlfilters = '') { + global $db, $conf; + + $obj_ret = array(); + + if(! DolibarrApiAccess::$user->rights->stock->lire) { + throw new RestException(401); + } + + $sql = "SELECT t.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."stock_mouvement as t"; + //$sql.= ' WHERE t.entity IN ('.getEntity('stock', 1).')'; + $sql.= ' WHERE 1 = 1'; + // Add sql filters + if ($sqlfilters) + { + if (! DolibarrApi::_checkFilters($sqlfilters)) + { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $i=0; + $num = $db->num_rows($result); + while ($i < min($num, ($limit <= 0 ? $num : $limit))) + { + $obj = $db->fetch_object($result); + $stockmovement_static = new MouvementStock($db); + if($stockmovement_static->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($stockmovement_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve stock movement list : '.$stockmovement_static->error); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No stock movement found'); + } + return $obj_ret; + } + +/* + * @param int $product_id Id product id {@min 1} + * @param int $warehouse_id Id warehouse {@min 1} + * @param float $qty Qty to add (Use negative value for a stock decrease) {@min 0} {@message qty must be higher than 0} + * @param string $lot Lot + * @param string $movementcode Movement code {@example INV123} + * @param string $movementlabel Movement label {@example Inventory number 123} + * @param string $price To update AWP (Average Weighted Price) when you make a stock increase (qty must be higher then 0). + */ + + + /** + * Create stock movement object. + * You can use the following message to test this RES API: + * { "product_id": 1, "warehouse_id": 1, "qty": 1, "lot": "", "movementcode": "INV123", "movementlabel": "Inventory 123", "price": 0 } + * + * @param array $request_data Request data + * @return int ID of stock movement + */ + //function post($product_id, $warehouse_id, $qty, $lot='', $movementcode='', $movementlabel='', $price=0) + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->stock->creer) { + throw new RestException(401); + } + + // Check mandatory fields + //$result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + //$this->stockmovement->$field = $value; + if ($field == 'product_id') $product_id = $value; + if ($field == 'warehouse_id') $warehouse_id = $value; + if ($field == 'qty') $qty = $value; + if ($field == 'lot') $lot = $value; + if ($field == 'movementcode') $movementcode = $value; + if ($field == 'movementlabel') $movementlabel = $value; + if ($field == 'price') $price = $value; + } + + // Type increase or decrease + if ($qty >= 0) $type = 3; + else $type = 2; + + if($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, $price, $movementlabel, $movementcode, '', '', '', $lot) <= 0) { + throw new RestException(503, 'Error when create stock movement : '.$this->stockmovement->error); + } + + return $this->stockmovement->id; + } + + /** + * Update stock movement + * + * @param int $id Id of warehouse to update + * @param array $request_data Datas + * @return int + */ + /* + function put($id, $request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->stock->creer) { + throw new RestException(401); + } + + $result = $this->stockmovement->fetch($id); + if( ! $result ) { + throw new RestException(404, 'stock movement not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('stock',$this->stockmovement->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + if ($field == 'id') continue; + $this->stockmovement->$field = $value; + } + + if($this->stockmovement->update($id, DolibarrApiAccess::$user)) + return $this->get ($id); + + return false; + }*/ + + /** + * Delete stock movement + * + * @param int $id Stock movement ID + * @return array + */ + /* + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->stock->supprimer) { + throw new RestException(401); + } + $result = $this->stockmovement->fetch($id); + if( ! $result ) { + throw new RestException(404, 'stock movement not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('stock',$this->stockmovement->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (! $this->stockmovement->delete(DolibarrApiAccess::$user)) { + throw new RestException(401,'error when delete stock movement'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Warehouse deleted' + ) + ); + }*/ + + + + /** + * Clean sensible object datas + * + * @param MouvementStock $object Object to clean + * @return array Array of cleaned object properties + * + * @todo use an array for properties to clean + * + */ + function _cleanObjectDatas($object) { + + $object = parent::_cleanObjectDatas($object); + + // Remove useless data + unset($object->civility_id); + unset($object->firstname); + unset($object->lastname); + unset($object->name); + unset($object->location_incoterms); + unset($object->libelle_incoterms); + unset($object->fk_incoterms); + unset($object->lines); + unset($object->total_ht); + unset($object->total_ttc); + unset($object->total_tva); + unset($object->total_localtax1); + unset($object->total_localtax2); + unset($object->note); + unset($object->note_private); + unset($object->note_public); + unset($object->shipping_method_id); + unset($object->fk_account); + unset($object->modelpdf); + unset($object->fk_delivery_address); + unset($object->cond_reglement); + unset($object->cond_reglement_id); + unset($object->mode_reglement_id); + unset($object->barcode_type_coder); + unset($object->barcode_type_label); + unset($object->barcode_type_code); + unset($object->barcode_type); + unset($object->country_code); + unset($object->country_id); + unset($object->country); + unset($object->thirdparty); + unset($object->contact); + unset($object->contact_id); + unset($object->user); + unset($object->fk_project); + unset($object->project); + + //unset($object->eatby); Filled correctly in read mode + //unset($object->sellby); Filled correctly in read mode + + return $object; + } + + /** + * Validate fields before create or update object + * + * @param array|null $data Data to validate + * @return array + * + * @throws RestException + */ + function _validate($data) + { + $stockmovement = array(); + foreach (Warehouses::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $stockmovement[$field] = $data[$field]; + } + return $stockmovement; + } +} diff --git a/htdocs/product/stock/class/api_warehouses.class.php b/htdocs/product/stock/class/api_warehouses.class.php new file mode 100644 index 00000000000..79eefc821c3 --- /dev/null +++ b/htdocs/product/stock/class/api_warehouses.class.php @@ -0,0 +1,282 @@ + + * + * 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 . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + +/** + * API class for warehouses + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class Warehouses extends DolibarrApi +{ + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'label', + ); + + /** + * @var Entrepot $warehouse {@type Entrepot} + */ + public $warehouse; + + /** + * Constructor + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->warehouse = new Entrepot($this->db); + } + + /** + * Get properties of a warehouse object + * + * Return an array with warehouse informations + * + * @param int $id ID of warehouse + * @return array|mixed data without useless information + * + * @throws RestException + */ + function get($id) + { + if(! DolibarrApiAccess::$user->rights->stock->lire) { + throw new RestException(401); + } + + $result = $this->warehouse->fetch($id); + if( ! $result ) { + throw new RestException(404, 'warehouse not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('warehouse',$this->warehouse->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->warehouse); + } + + /** + * List warehouses + * + * Get a list of warehouses + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'WH-%') and (t.date_creation:<:'20160101')" + * @return array Array of warehouse objects + * + * @throws RestException + */ + function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $sqlfilters = '') { + global $db, $conf; + + $obj_ret = array(); + + if(! DolibarrApiAccess::$user->rights->stock->lire) { + throw new RestException(401); + } + + $sql = "SELECT t.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."entrepot as t"; + $sql.= ' WHERE t.entity IN ('.getEntity('stock', 1).')'; + // Add sql filters + if ($sqlfilters) + { + if (! DolibarrApi::_checkFilters($sqlfilters)) + { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $i=0; + $num = $db->num_rows($result); + while ($i < min($num, ($limit <= 0 ? $num : $limit))) + { + $obj = $db->fetch_object($result); + $warehouse_static = new Entrepot($db); + if($warehouse_static->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($warehouse_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve warehouse list : '.$warehouse_static->error); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No warehouse found'); + } + return $obj_ret; + } + + + /** + * Create warehouse object + * + * @param array $request_data Request data + * @return int ID of warehouse + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->stock->creer) { + throw new RestException(401); + } + + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->warehouse->$field = $value; + } + if($this->warehouse->create(DolibarrApiAccess::$user) <= 0) { + throw new RestException(503, 'Error when create warehouse : '.$this->warehouse->error); + } + return $this->warehouse->id; + } + + /** + * Update warehouse + * + * @param int $id Id of warehouse to update + * @param array $request_data Datas + * @return int + */ + function put($id, $request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->stock->creer) { + throw new RestException(401); + } + + $result = $this->warehouse->fetch($id); + if( ! $result ) { + throw new RestException(404, 'warehouse not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('stock',$this->warehouse->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + if ($field == 'id') continue; + $this->warehouse->$field = $value; + } + + if($this->warehouse->update($id, DolibarrApiAccess::$user)) + return $this->get ($id); + + return false; + } + + /** + * Delete warehouse + * + * @param int $id Warehouse ID + * @return array + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->stock->supprimer) { + throw new RestException(401); + } + $result = $this->warehouse->fetch($id); + if( ! $result ) { + throw new RestException(404, 'warehouse not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('stock',$this->warehouse->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (! $this->warehouse->delete(DolibarrApiAccess::$user)) { + throw new RestException(401,'error when delete warehouse'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Warehouse deleted' + ) + ); + } + + + /** + * Clean sensible object datas + * + * @param Entrepot $object Object to clean + * @return array Array of cleaned object properties + * + * @todo use an array for properties to clean + * + */ + function _cleanObjectDatas($object) { + + $object = parent::_cleanObjectDatas($object); + + // Remove the subscriptions because they are handled as a subresource. + //unset($object->subscriptions); + + return $object; + } + + + /** + * Validate fields before create or update object + * + * @param array|null $data Data to validate + * @return array + * + * @throws RestException + */ + function _validate($data) + { + $warehouse = array(); + foreach (Warehouses::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $warehouse[$field] = $data[$field]; + } + return $warehouse; + } +} diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index 2f5af64da96..36599833c2d 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -173,11 +173,15 @@ class Entrepot extends CommonObject */ function update($id, $user) { + if (empty($id)) $id = $this->id; + // Check if new parent is already a child of current warehouse - if(!empty($this->fk_parent)) { + if(!empty($this->fk_parent)) + { $TChildWarehouses = array($id); $TChildWarehouses = $this->get_children_warehouses($this->id, $TChildWarehouses); - if(in_array($this->fk_parent, $TChildWarehouses)) { + if(in_array($this->fk_parent, $TChildWarehouses)) + { $this->error = 'ErrorCannotAddThisParentWarehouse'; return -2; } @@ -189,13 +193,13 @@ class Entrepot extends CommonObject $this->lieu=trim($this->lieu); $this->address=trim($this->address); - $this->zip=trim($this->zip); - $this->town=trim($this->town); - $this->country_id=($this->country_id > 0 ? $this->country_id : $this->country_id); + $this->zip=trim($this->zip); + $this->town=trim($this->town); + $this->country_id=($this->country_id > 0 ? $this->country_id : 0); $sql = "UPDATE ".MAIN_DB_PREFIX."entrepot "; $sql .= " SET label = '" . $this->db->escape($this->libelle) ."'"; - $sql .= ", fk_parent = '" . (($this->fk_parent > 0) ? $this->fk_parent : 'NULL') ."'"; + $sql .= ", fk_parent = " . (($this->fk_parent > 0) ? $this->fk_parent : 'NULL'); $sql .= ", description = '" . $this->db->escape($this->description) ."'"; $sql .= ", statut = " . $this->statut; $sql .= ", lieu = '" . $this->db->escape($this->lieu) ."'"; diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 1532f62aa22..dee344b6a5b 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -30,11 +30,32 @@ */ class MouvementStock extends CommonObject { - var $product_id; - var $entrepot_id; - var $qty; - var $type; + /** + * @var string Id to identify managed objects + */ + public $element = 'stockmouvement'; + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element = 'stock_mouvement'; + + public $product_id; + public $warehouse_id; + public $qty; + public $type; + + public $tms = ''; + public $datem = ''; + public $price; + public $fk_user_author; + public $label; + public $fk_origin; + public $origintype; + public $inventorycode; + public $batch; + + /** * Constructor @@ -46,6 +67,7 @@ class MouvementStock extends CommonObject $this->db = $db; } + /** * Add a movement of stock (in one direction only) * @@ -54,18 +76,18 @@ class MouvementStock extends CommonObject * @param int $entrepot_id Id of warehouse * @param int $qty Qty of movement (can be <0 or >0 depending on parameter type) * @param int $type Direction of movement: - * 0=input (stock increase after stock transfert), 1=output (stock decrease after stock transfer), + * 0=input (stock increase by a stock transfer), 1=output (stock decrease after by a stock transfer), * 2=output (stock decrease), 3=input (stock increase) * Note that qty should be > 0 with 0 or 3, < 0 with 1 or 2. * @param int $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed. * @param string $label Label of stock movement * @param string $inventorycode Inventory code * @param string $datem Force date of movement - * @param date $eatby eat-by date - * @param date $sellby sell-by date + * @param date $eatby eat-by date. Will be used if lot does not exists yet and will be created. + * @param date $sellby sell-by date. Will be used if lot does not exists yet and will be created. * @param string $batch batch number * @param boolean $skip_batch If set to true, stock movement is done without impacting batch record - * @param int $id_product_batch Id product_batch (when skip_batch is flase and we already know which record of product_batch to use) + * @param int $id_product_batch Id product_batch (when skip_batch is false and we already know which record of product_batch to use) * @return int <0 if KO, 0 if fk_product is null, >0 if OK */ function _create($user, $fk_product, $entrepot_id, $qty, $type, $price=0, $label='', $inventorycode='', $datem='',$eatby='',$sellby='',$batch='',$skip_batch=false, $id_product_batch=0) @@ -75,7 +97,7 @@ class MouvementStock extends CommonObject require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; $error = 0; - dol_syslog(get_class($this)."::_create start userid=$user->id, fk_product=$fk_product, warehouse=$entrepot_id, qty=$qty, type=$type, price=$price, label=$label, inventorycode=$inventorycode, datem=".$datem.", eatby=".$eatby.", sellby=".$sellby.", batch=".$batch.", skip_batch=".$skip_batch); + dol_syslog(get_class($this)."::_create start userid=$user->id, fk_product=$fk_product, warehouse_id=$entrepot_id, qty=$qty, type=$type, price=$price, label=$label, inventorycode=$inventorycode, datem=".$datem.", eatby=".$eatby.", sellby=".$sellby.", batch=".$batch.", skip_batch=".$skip_batch); // Clean parameters if (empty($price)) $price=0; @@ -90,7 +112,7 @@ class MouvementStock extends CommonObject } if ($sellby < 0) { - $this->errors[]='ErrorBadValueForParameterEatBy'; + $this->errors[]='ErrorBadValueForParameterSellBy'; return -1; } @@ -315,7 +337,7 @@ class MouvementStock extends CommonObject $sql.= " '".$origintype."'"; $sql.= ")"; - dol_syslog(get_class($this)."::_create", LOG_DEBUG); + dol_syslog(get_class($this)."::_create insert record into stock_mouvement", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { @@ -340,7 +362,7 @@ class MouvementStock extends CommonObject $sql = "SELECT rowid, reel FROM ".MAIN_DB_PREFIX."product_stock"; $sql.= " WHERE fk_entrepot = ".$entrepot_id." AND fk_product = ".$fk_product; // This is a unique key - dol_syslog(get_class($this)."::_create", LOG_DEBUG); + dol_syslog(get_class($this)."::_create check if a record already exists in product_stock", LOG_DEBUG); $resql=$this->db->query($sql); if ($resql) { @@ -405,7 +427,7 @@ class MouvementStock extends CommonObject $sql.= " (".$qty.", ".$entrepot_id.", ".$fk_product.")"; } - dol_syslog(get_class($this)."::_create", LOG_DEBUG); + dol_syslog(get_class($this)."::_create update stock value", LOG_DEBUG); $resql=$this->db->query($sql); if (! $resql) { @@ -444,7 +466,7 @@ class MouvementStock extends CommonObject $sql.= " stock=(SELECT SUM(ps.reel) FROM ".MAIN_DB_PREFIX."product_stock as ps WHERE ps.fk_product = p.rowid)"; $sql.= " WHERE rowid = ".$fk_product; - dol_syslog(get_class($this)."::_create", LOG_DEBUG); + dol_syslog(get_class($this)."::_create update AWP", LOG_DEBUG); $resql=$this->db->query($sql); if (! $resql) { @@ -487,6 +509,96 @@ class MouvementStock extends CommonObject } } + + + /** + * Load object in memory from the database + * + * @param int $id Id object + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id) + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $sql = 'SELECT'; + $sql .= ' t.rowid,'; + $sql .= " t.tms,"; + $sql .= " t.datem,"; + $sql .= " t.fk_product,"; + $sql .= " t.fk_entrepot,"; + $sql .= " t.value,"; + $sql .= " t.price,"; + $sql .= " t.type_mouvement,"; + $sql .= " t.fk_user_author,"; + $sql .= " t.label,"; + $sql .= " t.fk_origin,"; + $sql .= " t.origintype,"; + $sql .= " t.inventorycode,"; + $sql .= " t.batch,"; + $sql .= " t.eatby,"; + $sql .= " t.sellby"; + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; + $sql.= ' WHERE 1 = 1'; + //if (null !== $ref) { + //$sql .= ' AND t.ref = ' . '\'' . $ref . '\''; + //} else { + $sql .= ' AND t.rowid = ' . $id; + //} + + $resql = $this->db->query($sql); + if ($resql) { + $numrows = $this->db->num_rows($resql); + if ($numrows) { + $obj = $this->db->fetch_object($resql); + + $this->id = $obj->rowid; + + $this->product_id = $obj->fk_product; + $this->warehouse_id = $obj->fk_entrepot; + $this->qty = $obj->value; + $this->type = $obj->type_mouvement; + + $this->tms = $this->db->jdate($obj->tms); + $this->datem = $this->db->jdate($obj->datem); + $this->price = $obj->price; + $this->fk_user_author = $obj->fk_user_author; + $this->label = $obj->label; + $this->fk_origin = $obj->fk_origin; + $this->origintype = $obj->origintype; + $this->inventorycode = $obj->inventorycode; + $this->batch = $obj->batch; + $this->eatby = $this->db->jdate($obj->eatby); + $this->sellby = $this->db->jdate($obj->sellby); + } + + // Retrieve all extrafields for invoice + // fetch optionals attributes and labels + require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + $extrafields=new ExtraFields($this->db); + $extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true); + $this->fetch_optionals($this->id,$extralabels); + + // $this->fetch_lines(); + + $this->db->free($resql); + + if ($numrows) { + return 1; + } else { + return 0; + } + } else { + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + + return - 1; + } + } + + + /** * Create movement in database for all subproducts @@ -545,18 +657,18 @@ class MouvementStock extends CommonObject /** * Decrease stock for product and subproducts * - * @param User $user Object user - * @param int $fk_product Id product - * @param int $entrepot_id Warehouse id - * @param int $qty Quantity - * @param int $price Price - * @param string $label Label of stock movement - * @param string $datem Force date of movement - * @param date $eatby eat-by date - * @param date $sellby sell-by date - * @param string $batch batch number + * @param User $user Object user + * @param int $fk_product Id product + * @param int $entrepot_id Warehouse id + * @param int $qty Quantity + * @param int $price Price + * @param string $label Label of stock movement + * @param string $datem Force date of movement + * @param date $eatby eat-by date + * @param date $sellby sell-by date + * @param string $batch batch number * @param int $id_product_batch Id product_batch - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, >0 if OK */ function livraison($user, $fk_product, $entrepot_id, $qty, $price=0, $label='', $datem='', $eatby='', $sellby='', $batch='', $id_product_batch=0) { @@ -592,8 +704,10 @@ class MouvementStock extends CommonObject * * @param int $id Id of product * @return int <0 if KO, nb of subproducts if OK + * @deprecated A count($product->getChildsArbo($id,1)) is same. No reason to have this in this class. */ - function nbOfSubProdcuts($id) + /* + function nbOfSubProducts($id) { $nbSP=0; @@ -605,7 +719,7 @@ class MouvementStock extends CommonObject $nbSP=$obj->nb; } return $nbSP; - } + }*/ /** * Count number of product in stock before a specific date diff --git a/htdocs/product/stock/class/productlot.class.php b/htdocs/product/stock/class/productlot.class.php index 01da38fae31..6128f8dcf17 100644 --- a/htdocs/product/stock/class/productlot.class.php +++ b/htdocs/product/stock/class/productlot.class.php @@ -547,7 +547,15 @@ class Productlot extends CommonObject $label = '' . $langs->trans("Batch") . ''; $label.= '
'; $label.= '' . $langs->trans('Batch') . ': ' . $this->batch; - + if ($this->eatby) + { + $label.= '
' . $langs->trans('EatByDate') . ': ' . dol_print_date($this->eatby, 'day'); + } + if ($this->sellby) + { + $label.= '
' . $langs->trans('SellByDate') . ': ' . dol_print_date($this->sellby, 'day'); + } + $link = ''; + print '
'; + print ''."\n"; print ""; print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"], "e.label","",$param,"",$sortfield,$sortorder); @@ -250,7 +251,8 @@ if ($result) $db->free($result); print "
"; - + print ""; + print ''; } else diff --git a/htdocs/product/stock/mouvement.php b/htdocs/product/stock/mouvement.php index 7d80032e1d9..21444984d65 100644 --- a/htdocs/product/stock/mouvement.php +++ b/htdocs/product/stock/mouvement.php @@ -162,8 +162,8 @@ if ($action == "correct_stock") //$eatby=GETPOST('eatby'); //$sellby=GETPOST('sellby'); - $eatby=dol_mktime(12, 0, 0, GETPOST('eatbymonth'), GETPOST('eatbyday'), GETPOST('eatbyyear')); - $sellby=dol_mktime(12, 0, 0, GETPOST('sellbymonth'), GETPOST('sellbyday'), GETPOST('sellbyyear')); + $eatby=dol_mktime(0, 0, 0, GETPOST('eatbymonth'), GETPOST('eatbyday'), GETPOST('eatbyyear')); + $sellby=dol_mktime(0, 0, 0, GETPOST('sellbymonth'), GETPOST('sellbyday'), GETPOST('sellbyyear')); $result=$product->correct_stock_batch( $user, @@ -534,7 +534,8 @@ if ($resql) // Nb of products print ''.$langs->trans("NumberOfProducts").''; - print empty($calcproducts['nb'])?'0':$calcproducts['nb']; + $valtoshow=price2num($calcproducts['nb'], 'MS'); + print empty($valtoshow)?'0':$valtoshow; print ""; print ''; @@ -698,7 +699,9 @@ if ($resql) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - print ''."\n"; + print '
'; + print '
'."\n"; + print ""; if (! empty($arrayfields['m.rowid']['checked'])) print_liste_field_titre($arrayfields['m.rowid']['label'],$_SERVER["PHP_SELF"],'m.rowid','',$param,'',$sortfield,$sortorder); if (! empty($arrayfields['m.datem']['checked'])) print_liste_field_titre($arrayfields['m.datem']['label'],$_SERVER["PHP_SELF"],'m.datem','',$param,'',$sortfield,$sortorder); @@ -740,7 +743,7 @@ if ($resql) { // Ref print ''; } if (! empty($arrayfields['m.datem']['checked'])) @@ -1000,12 +1003,16 @@ if ($resql) } $db->free($resql); - print "
'; - print ''; + print ''; print '

"; + print ""; + print '
'; + print ""; // Add number of product when there is a filter on period if (count($arrayofuniqueproduct) == 1 && is_numeric($year)) { - $productidselected=0; + print "
"; + + $productidselected=0; foreach ($arrayofuniqueproduct as $key => $val) { $productidselected=$key; @@ -1031,8 +1038,6 @@ if ($resql) print "
\n"; //print ''; } - - } else { diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 4482e249410..4c00a2b9675 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -55,8 +55,8 @@ $stocklimit = GETPOST('seuil_stock_alerte'); $desiredstock = GETPOST('desiredstock'); $cancel = GETPOST('cancel'); $fieldid = isset($_GET["ref"])?'ref':'rowid'; -$d_eatby=dol_mktime(12, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']); -$d_sellby=dol_mktime(12, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']); +$d_eatby=dol_mktime(0, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']); +$d_sellby=dol_mktime(0, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']); $pdluoid=GETPOST('pdluoid','int'); // Security check @@ -453,8 +453,8 @@ if ($action == 'updateline' && GETPOST('save') == $langs->trans('Save')) } else { - $d_eatby=dol_mktime(12, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']); - $d_sellby=dol_mktime(12, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']); + $d_eatby=dol_mktime(0, 0, 0, $_POST['eatbymonth'], $_POST['eatbyday'], $_POST['eatbyyear']); + $d_sellby=dol_mktime(0, 0, 0, $_POST['sellbymonth'], $_POST['sellbyday'], $_POST['sellbyyear']); $pdluo->batch=GETPOST("batch_number",'san_alpha'); $pdluo->eatby=$d_eatby; $pdluo->sellby=$d_sellby; diff --git a/htdocs/product/stock/productlot_list.php b/htdocs/product/stock/productlot_list.php index 1843506bd79..dfcda620a8c 100644 --- a/htdocs/product/stock/productlot_list.php +++ b/htdocs/product/stock/productlot_list.php @@ -142,7 +142,7 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; // Purge search criteria -if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") ||GETPOST("button_removefilter")) // All test are required to be compatible with all browsers +if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") ||GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers { $search_entity=''; $search_product=''; @@ -227,7 +227,7 @@ $sql.= " FROM ".MAIN_DB_PREFIX."product_lot as t"; if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot_extrafields as ef on (t.rowid = ef.fk_object)"; $sql.= ", ".MAIN_DB_PREFIX."product as p"; $sql.= " WHERE p.rowid = t.fk_product"; -//$sql.= " WHERE u.entity IN (".getEntity('mytable',1).")"; +//$sql.= " WHERE u.entity IN (".getEntity('productlot',1).")"; if ($search_entity) $sql.= natural_search("entity",$search_entity); if ($search_product) $sql.= natural_search("p.ref",$search_product); @@ -339,7 +339,8 @@ if ($resql) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - print ''."\n"; + print '
'; + print '
'."\n"; // Fields title print ''; @@ -587,7 +588,8 @@ if ($resql) print $hookmanager->resPrint; print '
'."\n"; - + print '
'; + print ''."\n"; /* diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index a9b2dc57b1b..5281d913d95 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -120,7 +120,7 @@ if ($action == 'order' && isset($_POST['valid'])) $qty = GETPOST('tobuy'.$i, 'int'); //$desc = GETPOST('desc'.$i, 'alpha'); $sql = 'SELECT fk_product, fk_soc, ref_fourn'; - $sql .= ', tva_tx, unitprice FROM '; + $sql .= ', tva_tx, unitprice, remise_percent FROM '; $sql .= MAIN_DB_PREFIX . 'product_fournisseur_price'; $sql .= ' WHERE rowid = ' . $supplierpriceid; $resql = $db->query($sql); @@ -152,6 +152,7 @@ if ($action == 'order' && isset($_POST['valid'])) $tva = $line->tva_tx / 100; $line->total_tva = $line->total_ht * $tva; $line->total_ttc = $line->total_ht + $line->total_tva; + $line->remise_percent = $obj->remise_percent; $line->ref_fourn = $obj->ref_fourn; $suppliers[$obj->fk_soc]['lines'][] = $line; } @@ -334,7 +335,7 @@ if ($usevirtualstock) $sqlCommandesCli = "(SELECT ".$db->ifsql("SUM(cd.qty) IS NULL", "0", "SUM(cd.qty)")." as qty"; $sqlCommandesCli.= " FROM ".MAIN_DB_PREFIX."commandedet as cd"; $sqlCommandesCli.= " LEFT JOIN ".MAIN_DB_PREFIX."commande as c ON (c.rowid = cd.fk_commande)"; - $sqlCommandesCli.= " WHERE c.entity IN (".getEntity('order', 1).")"; + $sqlCommandesCli.= " WHERE c.entity IN (".getEntity('commande', 1).")"; $sqlCommandesCli.= " AND cd.fk_product = p.rowid"; $sqlCommandesCli.= " AND c.fk_statut IN (1,2))"; diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index 9277de5b498..0b48be2b0d5 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -110,7 +110,7 @@ print ''; print ''; print ''; - print ''.$langs->trans("InventoryCode").''; + print ''.$langs->trans("InventoryCode").''; print ''; print ''; diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index 98fe80f7c90..dfddd1e19f1 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -117,7 +117,7 @@ print ''; print ''; print ''; - print ''.$langs->trans("InventoryCode").''; + print ''.$langs->trans("InventoryCode").''; print ''; print ''; diff --git a/htdocs/product/traduction.php b/htdocs/product/traduction.php index b609e96661a..1f6ae678a81 100644 --- a/htdocs/product/traduction.php +++ b/htdocs/product/traduction.php @@ -213,13 +213,13 @@ if ($action == 'edit') print ''; print ''; print ''; if (! empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) { print ''; @@ -313,14 +313,14 @@ if ($action == 'add' && ($user->rights->produit->creer || $user->rights->service print ''; print ''; print ''; // Other field (not used) if (! empty($conf->global->PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION)) { print ''; } diff --git a/htdocs/projet/activity/perday.php b/htdocs/projet/activity/perday.php index 012a71f21a0..d803b55c875 100644 --- a/htdocs/projet/activity/perday.php +++ b/htdocs/projet/activity/perday.php @@ -347,8 +347,9 @@ else { print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'
'; } -print '
'; -print "\n"; + +dol_fiche_end(); + // Filter on user /* dol_fiche_head(''); @@ -382,18 +383,20 @@ print "\n"; print '
'.$nav.'
'; // We move this before the assign to components so, the default submit button is not the assign to. -print '
'; +print '
'; print $langs->trans("AssignTaskToMe").'
'; $formproject->selectTasks($socid?$socid:-1, $taskid, 'taskid', 32, 0, 1, 1); print $formcompany->selectTypeContact($object, '', 'type','internal','rowid', 0); -print ''; +print ''; //print ''; print '
'; print '
'; -print '
'.$langs->trans('Label').'
'.$langs->trans('Description').''; - $doleditor = new DolEditor("desc-$key", $object->multilangs[$key]["description"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); + $doleditor = new DolEditor("desc-$key", $object->multilangs[$key]["description"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_3, '90%'); $doleditor->Create(); print '
'.$langs->trans('Other').' ('.$langs->trans("NotUsed").')'; - $doleditor = new DolEditor("other-$key", $object->multilangs[$key]["other"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); + $doleditor = new DolEditor("other-$key", $object->multilangs[$key]["other"], '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_3, '90%'); $doleditor->Create(); } print '
'.$langs->trans('Label').'
'.$langs->trans('Description').''; - $doleditor = new DolEditor('desc', '', '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); + $doleditor = new DolEditor('desc', '', '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_3, '90%'); $doleditor->Create(); print '
'.$langs->trans('Other').' ('.$langs->trans("NotUsed").''; - $doleditor = new DolEditor('other', '', '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 3, 80); + $doleditor = new DolEditor('other', '', '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_3, '90%'); $doleditor->Create(); print '
'; +print '
'; +print '
'."\n"; + print ''; print ''; print ''; @@ -444,8 +447,7 @@ else print ''; } print "
'.$langs->trans("RefTask").''.$langs->trans("LabelTask").'
'.$langs->trans("NoTasks").'
"; - -dol_fiche_end(); +print ''; print '
'; print ''; diff --git a/htdocs/projet/activity/perweek.php b/htdocs/projet/activity/perweek.php index 396eb352d3b..c64105bca62 100644 --- a/htdocs/projet/activity/perweek.php +++ b/htdocs/projet/activity/perweek.php @@ -342,8 +342,8 @@ else { print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'
'; } -print '
'; -print "\n"; + +dol_fiche_end(); // Filter on user /* dol_fiche_head(''); @@ -377,18 +377,19 @@ print "\n"; print '
'.$nav.'
'; // We move this before the assign to components so, the default submit button is not the assign to. -print '
'; +print '
'; print $langs->trans("AssignTaskToMe").'
'; $formproject->selectTasks($socid?$socid:-1, $taskid, 'taskid', 32, 0, 1, 1); print $formcompany->selectTypeContact($object, '', 'type','internal','rowid', 0); -print ''; +print ''; //print ''; print '
'; print '
'; -print ''; +print '
'; +print '
'."\n"; print ''; print ''; @@ -465,12 +466,11 @@ else print ''; } print "
'.$langs->trans("RefTask").'
'.$langs->trans("NoTasks").'
"; +print '
'; print ''."\n"; print ''."\n"; -dol_fiche_end(); - print '
'; print ''; print '
'; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index f4c5d871fc6..9aae20a6300 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -615,12 +615,12 @@ if ($action == 'create' && $user->rights->projet->creer) }); '; } -else +elseif ($object->id > 0) { /* * Show or edit */ - + $res=$object->fetch_optionals($object->id,$extralabels); // To verify role of users @@ -698,7 +698,7 @@ else // Label print ''.$langs->trans("Label").''; - print ''; + print ''; // Thirdparty if ($conf->societe->enabled) @@ -752,7 +752,7 @@ else // Date start print ''.$langs->trans("DateStart").''; print $form->select_date($object->date_start?$object->date_start:-1,'projectstart',0,0,0,'',1,0,1); - print '     '. $langs->trans("ProjectReportDate"); print ''; @@ -829,33 +829,12 @@ else print ''; - // Ref - /* - print ''; - */ - - // Label - //print ''; - - // Third party - /* - print ''; - */ - // Visibility print ''; - // Statut - //print ''; - if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { // Opportunity status @@ -879,7 +858,11 @@ else print ''; // Budget @@ -1144,6 +1127,10 @@ else $parameters=array(); $reshook=$hookmanager->executeHooks('mainCardTabAddMore',$parameters,$object,$action); // Note that $action and $object may have been modified by hook } +else +{ + print $langs->trans("RecordNotFound"); +} llxFooter(); diff --git a/htdocs/projet/class/api_projects.class.php b/htdocs/projet/class/api_projects.class.php new file mode 100644 index 00000000000..f36df0773eb --- /dev/null +++ b/htdocs/projet/class/api_projects.class.php @@ -0,0 +1,600 @@ + + * Copyright (C) 2016 Laurent Destailleur + * + * 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 . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + +/** + * API class for projects + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class Projects extends DolibarrApi +{ + + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'ref', + 'title' + ); + + /** + * @var Project $project {@type Project} + */ + public $project; + + /** + * Constructor + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->project = new Project($this->db); + $this->task = new Task($this->db); + } + + /** + * Get properties of a project object + * + * Return an array with project informations + * + * @param int $id ID of project + * @return array|mixed data without useless information + * + * @throws RestException + */ + function get($id) + { + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $this->project->fetchObjectLinked(); + return $this->_cleanObjectDatas($this->project); + } + + + + /** + * List projects + * + * Get a list of projects + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $thirdparty_ids Thirdparty ids to filter projects of. {@example '1' or '1,2,3'} {@pattern /^[0-9,]*$/i} + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @return array Array of project objects + */ + function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '') { + global $db, $conf; + + $obj_ret = array(); + // case of external user, $thirdpartyid param is ignored and replaced by user's socid + $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids; + + // If the internal user must only see his customers, force searching by him + if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id; + + $sql = "SELECT t.rowid"; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX."projet as t"; + + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + + $sql.= ' WHERE t.entity IN ('.getEntity('project', 1).')'; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")"; + if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + // Insert sale filter + if ($search_sale > 0) + { + $sql .= " AND sc.fk_user = ".$search_sale; + } + // Add sql filters + if ($sqlfilters) + { + if (! DolibarrApi::_checkFilters($sqlfilters)) + { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + dol_syslog("API Rest request"); + $result = $db->query($sql); + + if ($result) + { + $num = $db->num_rows($result); + while ($i < min($num, ($limit <= 0 ? $num : $limit))) + { + $obj = $db->fetch_object($result); + $project_static = new Project($db); + if($project_static->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($project_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve project list'); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No project found'); + } + return $obj_ret; + } + + /** + * Create project object + * + * @param array $request_data Request data + * @return int ID of project + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401, "Insuffisant rights"); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->project->$field = $value; + } + /*if (isset($request_data["lines"])) { + $lines = array(); + foreach ($request_data["lines"] as $line) { + array_push($lines, (object) $line); + } + $this->project->lines = $lines; + }*/ + if ($this->project->create(DolibarrApiAccess::$user) <= 0) { + $errormsg = $this->project->error; + throw new RestException(500, $errormsg ? $errormsg : "Error while creating project"); + } + + return $this->project->id; + } + + /** + * Get tasks of a project + * + * @param int $id Id of project + * @param int $includetimespent 0=Return only list of tasks. 1=Include a summary of time spent, 2=Include details of time spent lines (2 is no implemented yet) + * @return int + * + * @url GET {id}/tasks + */ + function getLines($id, $includetimespent=0) { + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $this->project->getLinesArray(DolibarrApiAccess::$user); + $result = array(); + foreach ($this->project->lines as $line) // $line is a task + { + if ($includetimespent == 1) + { + $timespent = $line->getSummaryOfTimeSpent(0); + } + if ($includetimespent == 1) + { + // TODO + // Add class for timespent records and loop and fill $line->lines with records of timespent + } + array_push($result,$this->_cleanObjectDatas($line)); + } + return $result; + } + + + /** + * Get roles a user is assigned to a project with + * + * @param int $id Id of project + * @param int $userid Id of user (0 = connected user) + * + * @url GET {id}/roles + * + * @return int + */ + function getRoles($id, $userid=0) { + global $db; + + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + $taskstatic=new Task($this->db); + $userp = DolibarrApiAccess::$user; + if ($userid > 0) + { + $userp = new User($this->db); + $userp->fetch($userid); + } + $this->project->roles = $taskstatic->getUserRolesForProjectsOrTasks($userp, 0, $id, 0); + $result = array(); + foreach ($this->project->roles as $line) { + array_push($result,$this->_cleanObjectDatas($line)); + } + return $result; + } + + + /** + * Add a task to given project + * + * @param int $id Id of project to update + * @param array $request_data Projectline data + * + * @url POST {id}/tasks + * + * @return int + */ + /* + function postLine($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->project->addline( + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + $request_data->fk_product, + $request_data->remise_percent, + $request_data->info_bits, + $request_data->fk_remise_except, + 'HT', + 0, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->rang, + $request_data->special_code, + $fk_parent_line, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->array_options, + $request_data->fk_unit, + $this->element, + $request_data->id + ); + + if ($updateRes > 0) { + return $this->get($id)->line->rowid; + + } + return false; + } + */ + + /** + * Update a task to given project + * + * @param int $id Id of project to update + * @param int $taskid Id of task to update + * @param array $request_data Projectline data + * + * @url PUT {id}/tasks/{taskid} + * + * @return object + */ + /* + function putLine($id, $lineid, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->project->updateline( + $lineid, + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->remise_percent, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + 'HT', + $request_data->info_bits, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->fk_parent_line, + 0, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->special_code, + $request_data->array_options, + $request_data->fk_unit + ); + + if ($updateRes > 0) { + $result = $this->get($id); + unset($result->line); + return $this->_cleanObjectDatas($result); + } + return false; + }*/ + + + + /** + * Update project general fields (won't touch lines of project) + * + * @param int $id Id of project to update + * @param array $request_data Datas + * + * @return int + */ + function put($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if ($result <= 0) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + foreach($request_data as $field => $value) { + if ($field == 'id') continue; + $this->project->$field = $value; + } + + if($this->project->update(DolibarrApiAccess::$user, 0) > 0) + { + return $this->get($id); + } + else + { + throw new RestException(500, $this->project->error); + } + } + + /** + * Delete project + * + * @param int $id Project ID + * + * @return array + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->projet->supprimer) { + throw new RestException(401); + } + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if( ! $this->project->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when delete project : '.$this->project->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Project deleted' + ) + ); + + } + + /** + * Validate a project. + * You can test this API with the following input message + * { "notrigger": 0 } + * + * @param int $id Project ID + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * + * @url POST {id}/validate + * + * @return array + * FIXME An error 403 is returned if the request has an empty body. + * Error message: "Forbidden: Content type `text/plain` is not supported." + * Workaround: send this in the body + * { + * "notrigger": 0 + * } + */ + function validate($id, $notrigger=0) + { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $result = $this->project->setValid(DolibarrApiAccess::$user, $notrigger); + if ($result == 0) { + throw new RestException(500, 'Error nothing done. May be object is already validated'); + } + if ($result < 0) { + throw new RestException(500, 'Error when validating Project: '.$this->project->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Project validated' + ) + ); + } + + + /** + * Clean sensible object datas + * + * @param object $object Object to clean + * @return array Array of cleaned object properties + * + * @todo use an array for properties to clean + * + */ + function _cleanObjectDatas($object) { + + $object = parent::_cleanObjectDatas($object); + + unset($object->barcode_type); + unset($object->barcode_type_code); + unset($object->barcode_type_label); + unset($object->barcode_type_coder); + unset($object->cond_reglement_id); + unset($object->cond_reglement); + unset($object->fk_delivery_address); + unset($object->shipping_method_id); + unset($object->fk_account); + unset($object->note); + unset($object->fk_incoterms); + unset($object->libelle_incoterms); + unset($object->location_incoterms); + unset($object->name); + unset($object->lastname); + unset($object->firstname); + unset($object->civility_id); + unset($object->mode_reglement_id); + unset($object->country); + unset($object->country_id); + unset($object->country_code); + + unset($object->weekWorkLoad); + unset($object->weekWorkLoad); + + //unset($object->lines); // for task we use timespent_lines, but for project we use lines + + unset($object->total_ht); + unset($object->total_tva); + unset($object->total_localtax1); + unset($object->total_localtax2); + unset($object->total_ttc); + + return $object; + } + + /** + * Validate fields before create or update object + * + * @param array $data Array with data to verify + * @return array + * @throws RestException + */ + function _validate($data) + { + $object = array(); + foreach (self::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $object[$field] = $data[$field]; + + } + return $object; + } + + + // TODO + // getSummaryOfTimeSpent +} diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php new file mode 100644 index 00000000000..a5bab614a4a --- /dev/null +++ b/htdocs/projet/class/api_tasks.class.php @@ -0,0 +1,613 @@ + + * Copyright (C) 2016 Laurent Destailleur + * + * 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 . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + +/** + * API class for projects + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class Tasks extends DolibarrApi +{ + + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'ref', + 'label' + ); + + /** + * @var Task $task {@type Task} + */ + public $task; + + /** + * Constructor + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->task = new Task($this->db); + } + + /** + * Get properties of a task object + * + * Return an array with task informations + * + * @param int $id ID of task + * @param int $includetimespent 0=Return only task. 1=Include a summary of time spent, 2=Include details of time spent lines (2 is no implemented yet) + * @return array|mixed data without useless information + * + * @throws RestException + */ + function get($id, $includetimespent=0) + { + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->task->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Task not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('task',$this->task->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if ($includetimespent == 1) + { + $timespent = $this->task->getSummaryOfTimeSpent(0); + } + if ($includetimespent == 1) + { + // TODO + // Add class for timespent records and loop and fill $line->lines with records of timespent + } + + return $this->_cleanObjectDatas($this->task); + } + + + + /** + * List tasks + * + * Get a list of tasks + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @return array Array of project objects + */ + function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') { + global $db, $conf; + + $obj_ret = array(); + // case of external user, $thirdpartyid param is ignored and replaced by user's socid + $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids; + + // If the internal user must only see his customers, force searching by him + if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id; + + $sql = "SELECT t.rowid"; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX."projet_task as t"; + + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + + $sql.= ' WHERE t.entity IN ('.getEntity('project', 1).')'; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")"; + if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + // Insert sale filter + if ($search_sale > 0) + { + $sql .= " AND sc.fk_user = ".$search_sale; + } + // Add sql filters + if ($sqlfilters) + { + if (! DolibarrApi::_checkFilters($sqlfilters)) + { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + dol_syslog("API Rest request"); + $result = $db->query($sql); + + if ($result) + { + $num = $db->num_rows($result); + while ($i < min($num, ($limit <= 0 ? $num : $limit))) + { + $obj = $db->fetch_object($result); + $task_static = new Task($db); + if($task_static->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($task_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve task list'); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No task found'); + } + return $obj_ret; + } + + /** + * Create task object + * + * @param array $request_data Request data + * @return int ID of project + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401, "Insuffisant rights"); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->task->$field = $value; + } + /*if (isset($request_data["lines"])) { + $lines = array(); + foreach ($request_data["lines"] as $line) { + array_push($lines, (object) $line); + } + $this->project->lines = $lines; + }*/ + if ($this->task->create(DolibarrApiAccess::$user) <= 0) { + $errormsg = $this->task->error; + throw new RestException(500, $errormsg ? $errormsg : "Error while creating task"); + } + + return $this->task->id; + } + + /** + * Get time spent of a task + * + * @param int $id Id of task + * @return int + * + * @url GET {id}/tasks + */ + /* + function getLines($id, $includetimespent=0) { + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $this->project->getLinesArray(DolibarrApiAccess::$user); + $result = array(); + foreach ($this->project->lines as $line) // $line is a task + { + if ($includetimespent == 1) + { + $timespent = $line->getSummaryOfTimeSpent(0); + } + if ($includetimespent == 1) + { + // TODO + // Add class for timespent records and loop and fill $line->lines with records of timespent + } + array_push($result,$this->_cleanObjectDatas($line)); + } + return $result; + } + */ + + /** + * Get roles a user is assigned to a task with + * + * @param int $id Id of task + * @param int $userid Id of user (0 = connected user) + * + * @url GET {id}/roles + * + * @return int + */ + function getRoles($id, $userid=0) { + global $db; + + if(! DolibarrApiAccess::$user->rights->projet->lire) { + throw new RestException(401); + } + + $result = $this->task->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Task not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('task',$this->task->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $usert = DolibarrApiAccess::$user; + if ($userid > 0) + { + $usert = new User($this->db); + $usert->fetch($userid); + } + $this->task->roles = $this->task->getUserRolesForProjectsOrTasks(0, $usert, 0, $id); + $result = array(); + foreach ($this->task->roles as $line) { + array_push($result,$this->_cleanObjectDatas($line)); + } + return $result; + } + + + /** + * Add a task to given project + * + * @param int $id Id of project to update + * @param array $request_data Projectline data + * + * @url POST {id}/tasks + * + * @return int + */ + /* + function postLine($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->project->addline( + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + $request_data->fk_product, + $request_data->remise_percent, + $request_data->info_bits, + $request_data->fk_remise_except, + 'HT', + 0, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->rang, + $request_data->special_code, + $fk_parent_line, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->array_options, + $request_data->fk_unit, + $this->element, + $request_data->id + ); + + if ($updateRes > 0) { + return $this->get($id)->line->rowid; + + } + return false; + } + */ + + /** + * Update a task to given project + * + * @param int $id Id of project to update + * @param int $taskid Id of task to update + * @param array $request_data Projectline data + * + * @url PUT {id}/tasks/{taskid} + * + * @return object + */ + /* + function putLine($id, $lineid, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->project->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Project not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->project->updateline( + $lineid, + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->remise_percent, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + 'HT', + $request_data->info_bits, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->fk_parent_line, + 0, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->special_code, + $request_data->array_options, + $request_data->fk_unit + ); + + if ($updateRes > 0) { + $result = $this->get($id); + unset($result->line); + return $this->_cleanObjectDatas($result); + } + return false; + }*/ + + + /** + * Update task general fields (won't touch time spent of task) + * + * @param int $id Id of task to update + * @param array $request_data Datas + * + * @return int + */ + function put($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + + $result = $this->task->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Task not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('task',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + foreach($request_data as $field => $value) { + if ($field == 'id') continue; + $this->task->$field = $value; + } + + if($this->task->update(DolibarrApiAccess::$user, 0) > 0) + { + return $this->get($id); + } + else + { + throw new RestException(500, $this->task->error); + } + } + + /** + * Delete task + * + * @param int $id Task ID + * + * @return array + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->projet->supprimer) { + throw new RestException(401); + } + $result = $this->task->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Task not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('task',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if( ! $this->task->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when delete task : '.$this->task->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Task deleted' + ) + ); + + } + + + /** + * Add time spent to a task of a project. + * You can test this API with the following input message + * { "date": "2016-12-31 23:15:00", "duration": 1800, "user_id": 1, "note": "My time test" } + * + * @param int $id Task ID + * @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT) + * @param int $duration Duration in seconds (3600 = 1h) + * @param int $user_id User (Use 0 for connected user) + * @param string $note Note + * + * @url POST {id}/addtimespent + * + * @return array + */ + function addTimeSpent($id, $date, $duration, $user_id=0, $note='') + { + if(! DolibarrApiAccess::$user->rights->projet->creer) { + throw new RestException(401); + } + $result = $this->task->fetch($id); + if ($result <= 0) { + throw new RestException(404, 'Task not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('project',$this->project->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $uid = $user_id; + if (empty($uid)) $uid = DolibarrApiAccess::$user->id; + + $newdate = dol_stringtotime($date, 1); + $this->task->timespent_date = $newdate; + $this->task->timespent_datehour = $newdate; + $this->task->timespent_withhour = 1; + $this->task->timespent_duration = $duration; + $this->task->timespent_fk_user = $user_id; + $this->task->timespent_note = $note; + + $result = $this->task->addTimeSpent(DolibarrApiAccess::$user, 0); + if ($result == 0) { + throw new RestException(500, 'Error nothing done. May be object is already validated'); + } + if ($result < 0) { + throw new RestException(500, 'Error when adding time: '.$this->task->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Time spent added' + ) + ); + } + + + /** + * Clean sensible object datas + * + * @param object $object Object to clean + * @return array Array of cleaned object properties + * + * @todo use an array for properties to clean + * + */ + function _cleanObjectDatas($object) { + + $object = parent::_cleanObjectDatas($object); + + unset($object->barcode_type); + unset($object->barcode_type_code); + unset($object->barcode_type_label); + unset($object->barcode_type_coder); + unset($object->cond_reglement_id); + unset($object->cond_reglement); + unset($object->fk_delivery_address); + unset($object->shipping_method_id); + unset($object->fk_account); + unset($object->note); + unset($object->fk_incoterms); + unset($object->libelle_incoterms); + unset($object->location_incoterms); + unset($object->name); + unset($object->lastname); + unset($object->firstname); + unset($object->civility_id); + unset($object->mode_reglement_id); + unset($object->country); + unset($object->country_id); + unset($object->country_code); + + unset($object->weekWorkLoad); + unset($object->weekWorkLoad); + + //unset($object->lines); // for task we use timespent_lines, but for project we use lines + + unset($object->total_ht); + unset($object->total_tva); + unset($object->total_localtax1); + unset($object->total_localtax2); + unset($object->total_ttc); + + return $object; + } + + /** + * Validate fields before create or update object + * + * @param array $data Array with data to verify + * @return array + * @throws RestException + */ + function _validate($data) + { + $object = array(); + foreach (self::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $object[$field] = $data[$field]; + + } + return $object; + } + + + // TODO + // getSummaryOfTimeSpent +} diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 4ac568182de..7a88fc3112c 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -97,6 +97,11 @@ class Project extends CommonObject */ public $date_m; + /** + * @var Task[] + */ + public $lines; + /** * Constructor @@ -228,7 +233,7 @@ class Project extends CommonObject * * @param User $user User object of making update * @param int $notrigger 1=Disable all triggers - * @return int + * @return int <=0 if KO, >0 if OK */ function update($user, $notrigger=0) { @@ -241,7 +246,15 @@ class Project extends CommonObject $this->description = trim($this->description); if ($this->opp_amount < 0) $this->opp_amount=''; if ($this->opp_percent < 0) $this->opp_percent=''; - + if ($this->date_end && $this->date_end < $this->date_start) + { + $this->error = $langs->trans("ErrorDateEndLowerThanDateStart"); + $this->errors[] = $this->error; + $this->db->rollback(); + dol_syslog(get_class($this)."::update error -3 " . $this->error, LOG_ERR); + return -3; + } + if (dol_strlen(trim($this->ref)) > 0) { $this->db->begin(); @@ -338,7 +351,7 @@ class Project extends CommonObject } /** - * Get object and lines from database + * Get object from database * * @param int $id Id of object to load * @param string $ref Ref of project @@ -695,10 +708,11 @@ class Project extends CommonObject /** * Validate a project * - * @param User $user User that validate - * @return int <0 if KO, >0 if OK + * @param User $user User that validate + * @param int $notrigger 1=Disable triggers + * @return int <0 if KO, >0 if OK */ - function setValid($user) + function setValid($user, $notrigger=0) { global $langs, $conf; @@ -725,10 +739,13 @@ class Project extends CommonObject if ($resql) { // Call trigger - $result=$this->call_trigger('PROJECT_VALIDATE',$user); - if ($result < 0) { $error++; } - // End call triggers - + if (empty($notrigger)) + { + $result=$this->call_trigger('PROJECT_VALIDATE',$user); + if ($result < 0) { $error++; } + // End call triggers + } + if (!$error) { $this->statut=1; @@ -1750,12 +1767,12 @@ class Project extends CommonObject global $conf; if (! ($this->statut == 1)) return false; - if (! $this->datee) return false; + if (! $this->datee && ! $this->date_end) return false; $now = dol_now(); - return $this->datee < ($now - $conf->projet->warning_delay); - } + return ($this->datee ? $this->datee : $this->date_end) < ($now - $conf->projet->warning_delay); + } /** @@ -1866,5 +1883,20 @@ class Project extends CommonObject return 1; } + + /** + * Create an array of tasks of current project + * + * @param User $user Object user we want project allowed to + * @return int >0 if OK, <0 if KO + */ + function getLinesArray($user) + { + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + $taskstatic = new Task($this->db); + + $this->lines = $taskstatic->getTasksArray(0, $user, $this->id, 0, 0); + } + } diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index ad2f5faecbe..27099ef4d91 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -33,7 +33,9 @@ class Task extends CommonObject { public $element='project_task'; //!< Id that identify managed objects public $table_element='projet_task'; //!< Name of table without prefix where object is stored + public $fk_element='fk_task'; public $picto = 'task'; + protected $childtables=array('projet_task_time'); // To test if we can delete object var $fk_task_parent; var $label; @@ -50,6 +52,15 @@ class Task extends CommonObject var $fk_user_valid; var $rang; + var $timespent_min_date; + var $timespent_max_date; + var $timespent_total_duration; + var $timespent_total_amount; + var $timespent_nblinesnull; + var $timespent_nblines; + // For detail of lines of timespent record, there is the property ->lines in common + + // Var used to call method addTimeSpent(). Bad practice. var $timespent_id; var $timespent_duration; var $timespent_old_duration; @@ -176,7 +187,7 @@ class Task extends CommonObject * * @param int $id Id object * @param int $ref ref object - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, 0 if not found, >0 if OK */ function fetch($id,$ref='') { @@ -214,7 +225,9 @@ class Task extends CommonObject $resql=$this->db->query($sql); if ($resql) { - if ($this->db->num_rows($resql)) + $num_rows = $this->db->num_rows($resql); + + if ($num_rows) { $obj = $this->db->fetch_object($resql); @@ -241,7 +254,8 @@ class Task extends CommonObject $this->db->free($resql); - return 1; + if ($num_rows) return 1; + else return 0; } else { @@ -256,7 +270,7 @@ class Task extends CommonObject * * @param User $user User that modify * @param int $notrigger 0=launch triggers after, 1=disable triggers - * @return int <0 if KO, >0 if OK + * @return int <=0 if KO, >0 if OK */ function update($user=null, $notrigger=0) { @@ -380,13 +394,22 @@ class Task extends CommonObject $this->db->begin(); if ($this->hasChildren() > 0) + { + dol_syslog(get_class($this)."::delete Can't delete record as it has some sub tasks", LOG_WARNING); + $this->error='ErrorRecordHasSubTasks'; + $this->db->rollback(); + return 0; + } + + $objectisused = $this->isObjectUsed($this->id); + if (! empty($objectisused)) { dol_syslog(get_class($this)."::delete Can't delete record as it has some child", LOG_WARNING); $this->error='ErrorRecordHasChildren'; $this->db->rollback(); return 0; } - + if (! $error) { // Delete linked contacts @@ -581,7 +604,7 @@ class Task extends CommonObject $this->fk_projet=''; $this->ref='TK01'; $this->fk_task_parent=''; - $this->title='Specimen task TK01'; + $this->label='Specimen task TK01'; $this->duration_effective=''; $this->fk_user_creat=''; $this->progress='25'; @@ -754,10 +777,10 @@ class Task extends CommonObject * Return list of roles for a user for each projects or each tasks (or a particular project or a particular task). * * @param User $userp Return roles on project for this internal user. If set, usert and taskid must not be defined. - * @param User $usert Return roles on task for this internal user. If set userp must not be defined. + * @param User $usert Return roles on task for this internal user. If set userp must NOT be defined. -1 means no filter. * @param int $projectid Project id list separated with , to filter on project * @param int $taskid Task id to filter on a task - * @param string $filteronprojstatus Filter on project status if userp is set. Not used if userp not defined. + * @param integer $filteronprojstatus Filter on project status if userp is set. Not used if userp not defined. * @return array Array (projectid => 'list of roles for project' or taskid => 'list of roles for task') */ function getUserRolesForProjectsOrTasks($userp, $usert, $projectid='', $taskid=0, $filteronprojstatus=-1) @@ -781,7 +804,8 @@ class Task extends CommonObject /* Liste des taches et role sur les projets ou taches */ $sql = "SELECT pt.rowid as pid, ec.element_id, ctc.code, ctc.source"; if ($userp) $sql.= " FROM ".MAIN_DB_PREFIX."projet as pt"; - if ($usert) $sql.= " FROM ".MAIN_DB_PREFIX."projet as p, ".MAIN_DB_PREFIX."projet_task as pt"; + if ($usert && $filteronprojstatus > -1) $sql.= " FROM ".MAIN_DB_PREFIX."projet as p, ".MAIN_DB_PREFIX."projet_task as pt"; + if ($usert && $filteronprojstatus <= -1) $sql.= " FROM ".MAIN_DB_PREFIX."projet_task as pt"; $sql.= ", ".MAIN_DB_PREFIX."element_contact as ec"; $sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc"; $sql.= " WHERE pt.rowid = ec.element_id"; @@ -806,7 +830,7 @@ class Task extends CommonObject } //print $sql; - dol_syslog(get_class($this)."::getUserRolesForProjectsOrTasks", LOG_DEBUG); + dol_syslog(get_class($this)."::getUserRolesForProjectsOrTasks execute request", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { @@ -858,7 +882,7 @@ class Task extends CommonObject * * @param User $user User object * @param int $notrigger 0=launch triggers after, 1=disable triggers - * @return void + * @return int <=0 if KO, >0 if OK */ function addTimeSpent($user, $notrigger=0) { @@ -920,7 +944,7 @@ class Task extends CommonObject $ret = -1; } - if ($ret >= 0) + if ($ret > 0) { // Recalculate amount of time spent for task and update denormalized field $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task"; @@ -947,7 +971,7 @@ class Task extends CommonObject } } - if ($ret >=0) + if ($ret >0) { $this->db->commit(); } @@ -962,7 +986,7 @@ class Task extends CommonObject * Calculate total of time spent for task * * @param int $userid Filter on user id. 0=No filter - * @return array Array of info for task array('min_date', 'max_date', 'total_duration') + * @return array Array of info for task array('min_date', 'max_date', 'total_duration', 'total_amount', 'nblines', 'nblinesnull') */ function getSummaryOfTimeSpent($userid=0) { @@ -980,7 +1004,10 @@ class Task extends CommonObject $sql = "SELECT"; $sql.= " MIN(t.task_datehour) as min_date,"; $sql.= " MAX(t.task_datehour) as max_date,"; - $sql.= " SUM(t.task_duration) as total_duration"; + $sql.= " SUM(t.task_duration) as total_duration,"; + $sql.= " SUM(t.task_duration / 3600 * ".$this->db->ifsql("t.thm IS NULL", 0, "t.thm").") as total_amount,"; + $sql.= " COUNT(t.rowid) as nblines,"; + $sql.= " SUM(".$this->db->ifsql("t.thm IS NULL", 1, 0).") as nblinesnull"; $sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time as t"; $sql.= " WHERE t.fk_task = ".$id; if ($userid > 0) $sql.=" AND t.fk_user = ".$userid; @@ -991,22 +1018,28 @@ class Task extends CommonObject { $obj = $this->db->fetch_object($resql); - $result['min_date'] = $obj->min_date; - $result['max_date'] = $obj->max_date; - $result['total_duration'] = $obj->total_duration; - + $result['min_date'] = $obj->min_date; // deprecated. use the ->timespent_xxx instead + $result['max_date'] = $obj->max_date; // deprecated. use the ->timespent_xxx instead + $result['total_duration'] = $obj->total_duration; // deprecated. use the ->timespent_xxx instead + + $this->timespent_min_date=$this->db->jdate($obj->min_date); + $this->timespent_max_date=$this->db->jdate($obj->max_date); + $this->timespent_total_duration=$obj->total_duration; + $this->timespent_total_amount=$obj->total_amount; + $this->timespent_nblinesnull=($obj->nblinesnull?$obj->nblinesnull:0); + $this->timespent_nblines=($obj->nblines?$obj->nblines:0); + $this->db->free($resql); - return $result; } else { dol_print_error($this->db); - return $result; } + return $result; } /** - * Calculate vamue of time consumed using the thm (hourly amount value of work for user entering time) + * Calculate value of time consumed using the thm (hourly amount value of work for user entering time) * * @param User $fuser Filter on a dedicated user * @param string $dates Start date (ex 00:00:00) @@ -1061,7 +1094,7 @@ class Task extends CommonObject } /** - * Load object in memory from database + * Load one record of time spent * * @param int $id Id object * @return int <0 if KO, >0 if OK diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index e94042f43d3..6d1e9cb2828 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -390,7 +390,7 @@ $listofreferent=array( 'table'=>'projet_task', 'datefieldname'=>'task_date', 'disableamount'=>0, - 'test'=>$conf->projet->enabled && $user->rights->projet->lire && $conf->salaries->enabled && empty($conf->global->PROJECT_HIDE_TASKS)), + 'test'=>$conf->projet->enabled && $user->rights->projet->lire && empty($conf->global->PROJECT_HIDE_TASKS)), ); $parameters=array('listofreferent'=>$listofreferent); @@ -506,8 +506,8 @@ foreach ($listofreferent as $key => $value) $element->fetch($idofelement); if ($idofelementuser) $elementuser->fetch($idofelementuser); + // Special cases if ($tablename != 'expensereport_det' && method_exists($element, 'fetch_thirdparty')) $element->fetch_thirdparty(); - if ($tablename == 'don') $total_ht_by_line=$element->amount; elseif ($tablename == 'projet_task') { @@ -737,6 +737,7 @@ foreach ($listofreferent as $key => $value) $element->fetch($idofelement); if ($idofelementuser) $elementuser->fetch($idofelementuser); + // Special cases if ($tablename != 'expensereport_det') { if(method_exists($element, 'fetch_thirdparty')) $element->fetch_thirdparty(); @@ -787,28 +788,34 @@ foreach ($listofreferent as $key => $value) } else { + // Show ref with link if ($element instanceof Task) { print $element->getNomUrl(1,'withproject','time'); print ' - '.dol_trunc($element->label, 48); } else print $element->getNomUrl(1); - + $element_doc = $element->element; $filename=dol_sanitizeFileName($element->ref); $filedir=$conf->{$element_doc}->dir_output . '/' . dol_sanitizeFileName($element->ref); - if($element_doc === 'order_supplier') { + if ($element_doc === 'order_supplier') { $element_doc='commande_fournisseur'; $filedir = $conf->fournisseur->commande->dir_output.'/'.dol_sanitizeFileName($element->ref); } - else if($element_doc === 'invoice_supplier') { + else if ($element_doc === 'invoice_supplier') { $element_doc='facture_fournisseur'; $filename = get_exdir($element->id,2,0,0,$this,'product').dol_sanitizeFileName($element->ref); $filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($element->id,2,0,0,null,'invoice_supplier').dol_sanitizeFileName($element->ref); } - print $formfile->getDocumentsLink($element_doc, $filename, $filedir); + print '
'.$formfile->getDocumentsLink($element_doc, $filename, $filedir).'
'; + + // Show supplier ref + if (! empty($element->ref_supplier)) print ' - '.$element->ref_supplier; + // Show customer ref + if (! empty($element->ref_customer)) print ' - '.$element->ref_customer; } print "\n"; @@ -873,13 +880,21 @@ foreach ($listofreferent as $key => $value) if ($tablename == 'don') $total_ht_by_line=$element->amount; elseif ($tablename == 'projet_task') { - $tmp = $element->getSumOfAmount($elementuser, $dates, $datee); // $element is a task. $elementuser may be empty - $total_ht_by_line = price2num($tmp['amount'],'MT'); - if ($tmp['nblinesnull'] > 0) - { - $langs->load("errors"); - $warning=$langs->trans("WarningSomeLinesWithNullHourlyRate", $conf->currency); - } + if (! empty($conf->salaries->enabled)) + { + // TODO Permission to read daily rate + $tmp = $element->getSumOfAmount($elementuser, $dates, $datee); // $element is a task. $elementuser may be empty + $total_ht_by_line = price2num($tmp['amount'],'MT'); + if ($tmp['nblinesnull'] > 0) + { + $langs->load("errors"); + $warning=$langs->trans("WarningSomeLinesWithNullHourlyRate", $conf->currency); + } + } + else + { + print $langs->trans("ModuleDisabled"); + } } else { diff --git a/htdocs/projet/graph_opportunities.inc.php b/htdocs/projet/graph_opportunities.inc.php index 673fbc973ad..b763240500f 100644 --- a/htdocs/projet/graph_opportunities.inc.php +++ b/htdocs/projet/graph_opportunities.inc.php @@ -83,8 +83,8 @@ if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) } //if ($totalinprocess != $total) //print '
'; - print ''; - print ''; + print ''; diff --git a/htdocs/projet/index.php b/htdocs/projet/index.php index 752e3615464..96f98111c2e 100644 --- a/htdocs/projet/index.php +++ b/htdocs/projet/index.php @@ -140,7 +140,7 @@ print '
'; print '
'.$langs->trans("Ref").''; - print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref'); - print '
'.$langs->trans("Label").''.$object->title.'
'.$langs->trans("ThirdParty").''; - if ($object->thirdparty->id > 0) print $object->thirdparty->getNomUrl(1, 'project'); - else print' '; - print '
'.$langs->trans("Visibility").''; if ($object->public) print $langs->trans('SharedProject'); else print $langs->trans('PrivateProject'); print '
'.$langs->trans("Status").''.$object->getLibStatut(4).'
'.$langs->trans("DateStart").' - '.$langs->trans("DateEnd").''; print dol_print_date($object->date_start,'day'); $end=dol_print_date($object->date_end,'day'); - if ($end) print ' - '.$end; + if ($end) + { + print ' - '.$end; + if ($object->hasDelay()) print img_warning($langs->trans('Late')); + } print '
'.$langs->trans("Total").' ('.$langs->trans("CustomersOrdersRunning").')'.$totalinprocess.'
'.$langs->trans("OpportunityTotalAmount").' ('.$langs->trans("WonLostExcluded").')'.price($totalamount, 0, '', 1, -1, -1, $conf->currency).'
'; + print '
'.$langs->trans("OpportunityTotalAmount").' ('.$langs->trans("WonLostExcluded").')'.price($totalamount, 0, '', 1, -1, -1, $conf->currency).'
'; //print $langs->trans("OpportunityPonderatedAmount").' ('.$langs->trans("WonLostExcluded").')'; print $form->textwithpicto($langs->trans("OpportunityPonderatedAmount").' ('.$langs->trans("WonLostExcluded").')', $langs->trans("OpportunityPonderatedAmountDesc"), 1); print ''.price(price2num($ponderated_opp_amount,'MT'), 0, '', 1, -1, -1, $conf->currency).'
'; print ''; -print_liste_field_titre($langs->trans("OpenedProjectsByThirdparties"),$_SERVER["PHP_SELF"],"s.nom","","","",$sortfield,$sortorder); +print_liste_field_titre($langs->trans("OpenedProjectsByThirdparties"),$_SERVER["PHP_SELF"],"s.nom","","",'',$sortfield,$sortorder); print_liste_field_titre($langs->trans("NbOfProjects"),"","","","",'align="right"',$sortfield,$sortorder); print "\n"; diff --git a/htdocs/projet/info.php b/htdocs/projet/info.php index 5a975b4ec1e..8b6bf3c0288 100644 --- a/htdocs/projet/info.php +++ b/htdocs/projet/info.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2005-2016 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,11 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; $langs->load("projects"); +$id = GETPOST('id','int'); +$ref = GETPOST('ref','alpha'); +$socid = GETPOST('socid','int'); +$action = GETPOST('action','alpha'); + if (GETPOST('actioncode','array')) { $actioncode=GETPOST('actioncode','array',3); @@ -73,16 +78,19 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP */ $form = new Form($db); +$object = new Project($db); $title=$langs->trans("Project").' - '.$object->ref.' '.$object->name; if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->ref.' '.$object->name.' - '.$langs->trans("Info"); $help_url="EN:Module_Projects|FR:Module_Projets|ES:Módulo_Proyectos"; llxHeader("",$title,$help_url); -$object = new Project($db); -$object->fetch($id); -$object->fetch_thirdparty(); -$object->info($id); +if ($id > 0 || ! empty($ref)) +{ + $object->fetch($id, $ref); + $object->fetch_thirdparty(); + $object->info($object->id); +} $head = project_prepare_head($object); @@ -141,7 +149,7 @@ if (! empty($conf->agenda->enabled)) { if (! empty($user->rights->agenda->myactions->create) || ! empty($user->rights->agenda->allactions->create)) { - print ''.$langs->trans("AddAction").''; + print ''.$langs->trans("AddAction").''; } else { diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 787d902768d..c6a44f32c9b 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -450,7 +450,8 @@ if (! empty($moreforfilter)) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields -print '
'; +print '
'; +print '
'."\n"; print ''; if (! empty($arrayfields['p.ref']['checked'])) print_liste_field_titre($arrayfields['p.ref']['label'],$_SERVER["PHP_SELF"],"p.ref","",$param,"",$sortfield,$sortorder); @@ -626,7 +627,7 @@ while ($i < min($num,$limit)) $projectstatic->user_author_id = $obj->fk_user_creat; $projectstatic->public = $obj->public; $projectstatic->ref = $obj->ref; - $projectstatic->datee = $obj->date_end; + $projectstatic->datee = $db->jdate($obj->date_end); $projectstatic->statut = $obj->fk_statut; $projectstatic->opp_status = $obj->fk_opp_status; @@ -867,6 +868,7 @@ $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters); // N print $hookmanager->resPrint; print "
\n"; +print '
'; print "\n"; diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index 986c0537bc5..8a98b99221b 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -339,7 +339,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third { require_once DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.'.php'; $modTask = new $obj; - $defaultref = $modTask->getNextValue($soc,$object); + $defaultref = $modTask->getNextValue($object->thirdparty,null); } if (is_numeric($defaultref) && $defaultref <= 0) $defaultref=''; @@ -351,7 +351,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third print ''; print ''.$langs->trans("Label").''; - print ''; + print ''; print ''; // List of projects diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index 1179ca7546e..5526aa91efb 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -424,7 +424,8 @@ if (! empty($moreforfilter)) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields -print ''; +print '
'; +print '
'."\n"; print ''; if (! empty($arrayfields['t.ref']['checked'])) print_liste_field_titre($arrayfields['t.ref']['label'],$_SERVER["PHP_SELF"],"t.ref","",$param,"",$sortfield,$sortorder); @@ -826,6 +827,7 @@ $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters); // N print $hookmanager->resPrint; print "
"; +print ''; print ''; diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 276fc1cd722..5a9a6704566 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -704,6 +704,7 @@ if (($id > 0 || ! empty($ref)) || $projectidforalltimes > 0) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + print '
'; print ''."\n"; print ''; @@ -975,6 +976,7 @@ if (($id > 0 || ! empty($ref)) || $projectidforalltimes > 0) print ''; print "
"; + print '
'; print ""; } } diff --git a/htdocs/public/paypal/paymentko.php b/htdocs/public/paypal/paymentko.php index f21b2d2409c..4bad572ed8b 100644 --- a/htdocs/public/paypal/paymentko.php +++ b/htdocs/public/paypal/paymentko.php @@ -51,6 +51,13 @@ $langs->load("companies"); $langs->load("paybox"); $langs->load("paypal"); +$PAYPALTOKEN=GETPOST('TOKEN'); +if (empty($PAYPALTOKEN)) $PAYPALTOKEN=GETPOST('token'); +$PAYPALPAYERID=GETPOST('PAYERID'); +if (empty($PAYPALPAYERID)) $PAYPALPAYERID=GETPOST('PayerID'); +$PAYPALFULLTAG=GETPOST('FULLTAG'); +if (empty($PAYPALFULLTAG)) $PAYPALFULLTAG=GETPOST('fulltag'); + /* * Actions @@ -73,6 +80,18 @@ dol_syslog("POST=".$tracepost, LOG_DEBUG, 0, '_paypal'); // Send an email if (! empty($conf->global->PAYPAL_PAYONLINE_SENDEMAIL)) { + // Get on url call + $token = $PAYPALTOKEN; + $fulltag = $PAYPALFULLTAG; + $payerID = $PAYPALPAYERID; + // Set by newpayment.php + $paymentType = $_SESSION['PaymentType']; + $currencyCodeType = $_SESSION['currencyCodeType']; + $FinalPaymentAmt = $_SESSION["Payment_Amount"]; + // From env + $ipaddress = $_SESSION['ipaddress']; + + $sendto=$conf->global->PAYPAL_PAYONLINE_SENDEMAIL; $from=$conf->global->MAILING_EMAIL_FROM; @@ -102,11 +121,6 @@ print ''."\n"; print '
'."\n"; print $langs->trans("YourPaymentHasNotBeenRecorded")."

"; -$PAYPALTOKEN=GETPOST('TOKEN'); -if (empty($PAYPALTOKEN)) $PAYPALTOKEN=GETPOST('token'); -$PAYPALFULLTAG=GETPOST('FULLTAG'); -if (empty($PAYPALFULLTAG)) $PAYPALFULLTAG=GETPOST('fulltag'); - if (! empty($conf->global->PAYPAL_MESSAGE_KO)) print $conf->global->PAYPAL_MESSAGE_KO; print "\n
\n"; diff --git a/htdocs/public/test/test_arrays.php b/htdocs/public/test/test_arrays.php index 05eaafc3e09..175352f404b 100644 --- a/htdocs/public/test/test_arrays.php +++ b/htdocs/public/test/test_arrays.php @@ -31,6 +31,7 @@ if (empty($usedolheader)) Test page + @@ -38,6 +39,7 @@ if (empty($usedolheader)) + @@ -52,9 +54,26 @@ if (empty($usedolheader)) } else { - $arraycss=array(); - $arrayjs=array(); - + $arraycss=array(); + $arrayjs=array(); + /* + $arraycss=array('/includes/jquery/plugins/datatables/media/css/jquery.dataTables.css', + '/includes/jquery/plugins/datatables/extensions/Buttons/css/buttons.dataTables.min.css', + '/includes/jquery/plugins/datatables/extensions/ColReorder/css/colReorder.dataTables.min.css' + ); + $arrayjs=array('/includes/jquery/plugins/datatables/media/js/jquery.dataTables.js', + '/includes/jquery/plugins/datatables/extensions/Buttons/js/dataTables.buttons.js', + '/includes/jquery/plugins/datatables/extensions/Buttons/js/buttons.colVis.min.js', + '/includes/jquery/plugins/datatables/extensions/Buttons/js/buttons.html5.min.js', + '/includes/jquery/plugins/datatables/extensions/Buttons/js/buttons.flash.min.js', + '/includes/jquery/plugins/datatables/extensions/Buttons/js/buttons.print.min.js', + '/includes/jquery/plugins/datatables/extensions/ColReorder/js/dataTables.colReorder.min.js', + '/includes/jszip/jszip.min.js', + '/includes/pdfmake/pdfmake.min.js', + '/includes/pdfmake/vfs_fonts.js' + ); + */ + llxHeader('','','','',0,0,$arrayjs,$arraycss); } @@ -66,9 +85,9 @@ else

This page is a sample of page using tables. It is designed to make test with
- css (add parameter &theme=newtheme to test another theme or edit css of current theme)
-- jmobile (add parameter ">dol_use_jmobile=1&dol_optimize_smallscreen=1 and switch to small screen < 960 to enable view with jmobile)
+- jmobile (add parameter ">dol_use_jmobile=4&dol_optimize_smallscreen=1 and switch to small screen < 1000 to enable view with jmobile)
+- jmobile (add parameter ">dol_use_jmobile=1&dol_optimize_smallscreen=1 and switch to small screen < 570 to enable with emulated jmobile)
- no javascript / usage for bind people (add parameter ">nojs=1 to force disable javascript)
-- dataTables
- tablednd

@@ -79,10 +98,10 @@ This page is a sample of page using tables. It is designed to make test with
- +
- +
@@ -92,10 +111,10 @@ This page is a sample of page using tables. It is designed to make test with
- +
- +
@@ -105,10 +124,10 @@ This page is a sample of page using tables. It is designed to make test with
- + - +
@@ -223,8 +242,8 @@ if (! empty($moreforfilter))
- -


Example 2 : Table using tags: table/thead/tbody/tr/th-td + dataTable => Use this for short result tables
+ -


Example 3 : Table using tags: div.tagtable+div.tagtr+div or div.tagtable+div.tagtr+div.tagtd => Use this for tables that need to have a different form for each line, but AVOID IT if possible (drag and drop of lines does not work for this case, also height of title can't be forced to a minimum)

+


Example 2 : Table using tags: div.tagtable+(div|form).tagtr+div[.tagtd] => Use this for tables that need to have a different form for each line, but AVOID IT if possible (drag and drop of lines does not work for this case, also height of title can't be forced to a minimum)

use_javascript_ajax)) include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php'; ?> -
+
Title A
title B
diff --git a/htdocs/public/test/test_forms.php b/htdocs/public/test/test_forms.php index a697b371438..a53f812611a 100644 --- a/htdocs/public/test/test_forms.php +++ b/htdocs/public/test/test_forms.php @@ -17,7 +17,8 @@ llxHeader();

This page is a sample of page using Dolibarr HTML widget methods. It is designed to make test with
- css (add parameter &theme=newtheme to test another theme or edit css of current theme)
-- jmobile (add parameter ">dol_use_jmobile=1&dol_optimize_smallscreen=1 to enable view with jmobile)
+- jmobile (add parameter ">dol_use_jmobile=4&dol_optimize_smallscreen=1 and switch to small screen < 1000 to enable view with jmobile)
+- jmobile (add parameter ">dol_use_jmobile=1&dol_optimize_smallscreen=1 and switch to small screen < 570 to enable with emulated jmobile)
- no javascript / usage for bind people (add parameter ">nojs=1 to force disable javascript)


diff --git a/htdocs/resource/list.php b/htdocs/resource/list.php index 3b6338f0fce..b2ef82cf8c1 100644 --- a/htdocs/resource/list.php +++ b/htdocs/resource/list.php @@ -186,7 +186,11 @@ print ''; print ''; print ''; -print ''."\n"; +$moreforfilter = ''; + +print '
'; +print '
'."\n"; + print ''; if (! empty($arrayfields['t.ref']['checked'])) print_liste_field_titre($arrayfields['t.ref']['label'],$_SERVER["PHP_SELF"],"t.ref","",$param,"",$sortfield,$sortorder); if (! empty($arrayfields['ty.label']['checked'])) print_liste_field_titre($arrayfields['ty.label']['label'],$_SERVER["PHP_SELF"],"t.code","",$param,"",$sortfield,$sortorder); @@ -250,62 +254,62 @@ print "\n"; if ($ret) { - foreach ($object->lines as $resource) - { - $var=!$var; + foreach ($object->lines as $resource) + { + $var=!$var; - $style=''; - if ($resource->id == GETPOST('lineid')) $style='style="background: orange;"'; + $style=''; + if ($resource->id == GETPOST('lineid')) $style='style="background: orange;"'; - print ''; + print ''; - if (! empty($arrayfields['t.ref']['checked'])) - { - print ''; - } + if (! empty($arrayfields['t.ref']['checked'])) + { + print ''; + } - if (! empty($arrayfields['ty.label']['checked'])) - { - print ''; - } - // Extra fields - if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) - { - foreach($extrafields->attribute_label as $key => $val) - { - if (! empty($arrayfields["ef.".$key]['checked'])) - { - print 'getAlignFlag($key); - if ($align) print ' align="'.$align.'"'; - print '>'; - $tmpkey='options_'.$key; - print $extrafields->showOutputField($key, $resource->array_options[$tmpkey], '', 1); - print ''; - } - } - if (! $i) $totalarray['nbfield']++; - } + if (! empty($arrayfields['ty.label']['checked'])) + { + print ''; + } + // Extra fields + if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) + { + foreach($extrafields->attribute_label as $key => $val) + { + if (! empty($arrayfields["ef.".$key]['checked'])) + { + print 'getAlignFlag($key); + if ($align) print ' align="'.$align.'"'; + print '>'; + $tmpkey='options_'.$key; + print $extrafields->showOutputField($key, $resource->array_options[$tmpkey], '', 1); + print ''; + } + } + if (! $i) $totalarray['nbfield']++; + } - print ''; + print ''; - print ''; - } + print ''; + } - print '
'; - print $resource->getNomUrl(5); - print ''; + print $resource->getNomUrl(5); + print ''; - print $resource->type_label; - print ''; + print $resource->type_label; + print ''; - print ''; - print img_edit(); - print ''; - print ' '; - print ''; - print img_delete(); - print ''; - print ''; + print ''; + print img_edit(); + print ''; + print ' '; + print ''; + print img_delete(); + print ''; + print '
'; - print "\n"; + print ''; + print "\n"; } else { diff --git a/htdocs/societe/ajax/company.php b/htdocs/societe/ajax/company.php index 96ac9f0154b..d2a244f9444 100644 --- a/htdocs/societe/ajax/company.php +++ b/htdocs/societe/ajax/company.php @@ -54,7 +54,7 @@ dol_syslog(join(',',$_GET)); if (! empty($action) && $action == 'fetch' && ! empty($id)) { - require DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; + require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; $outjson=array(); diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index 11cd1fee919..775d9d48cf4 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -115,7 +115,7 @@ class Contacts extends DolibarrApi $sql.= ", " . MAIN_DB_PREFIX . "societe_commerciaux as sc"; } $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON t.fk_soc = s.rowid"; - $sql.= ' WHERE t.entity IN (' . getEntity('contact', 1) . ')'; + $sql.= ' WHERE t.entity IN (' . getEntity('socpeople', 1) . ')'; if ($socid) $sql.= " AND t.fk_soc = " . $socid; if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) @@ -222,7 +222,8 @@ class Contacts extends DolibarrApi foreach ($request_data as $field => $value) { - $this->contact->$field = $value; + if ($field == 'id') continue; + $this->contact->$field = $value; } if ($this->contact->update($id, DolibarrApiAccess::$user, 1, '', '', 'update')) diff --git a/htdocs/societe/class/api_deprecated_contact.class.php b/htdocs/societe/class/api_deprecated_contact.class.php index 56ef1eec19a..65f361de23a 100644 --- a/htdocs/societe/class/api_deprecated_contact.class.php +++ b/htdocs/societe/class/api_deprecated_contact.class.php @@ -126,7 +126,7 @@ class ContactApi extends DolibarrApi $sql.= ", " . MAIN_DB_PREFIX . "societe_commerciaux as sc"; } $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON c.fk_soc = s.rowid"; - $sql.= ' WHERE c.entity IN (' . getEntity('contact', 1) . ')'; + $sql.= ' WHERE c.entity IN (' . getEntity('socpeople', 1) . ')'; if ($socid) $sql.= " AND c.fk_soc = " . $socid; @@ -239,7 +239,8 @@ class ContactApi extends DolibarrApi foreach ($request_data as $field => $value) { - $this->contact->$field = $value; + if ($field == 'id') continue; + $this->contact->$field = $value; } if ($this->contact->update($id, DolibarrApiAccess::$user, 1, '', '', 'update')) diff --git a/htdocs/societe/class/api_deprecated_thirdparty.class.php b/htdocs/societe/class/api_deprecated_thirdparty.class.php index 3179cb697ce..61c9c1cc013 100644 --- a/htdocs/societe/class/api_deprecated_thirdparty.class.php +++ b/htdocs/societe/class/api_deprecated_thirdparty.class.php @@ -328,6 +328,7 @@ class ThirdpartyApi extends DolibarrApi } foreach($request_data as $field => $value) { + if ($field == 'id') continue; $this->company->$field = $value; } diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index de21e4fbbe0..13f28aea705 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -216,6 +216,7 @@ class Thirdparties extends DolibarrApi } foreach($request_data as $field => $value) { + if ($field == 'id') continue; $this->company->$field = $value; } diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 6acae492c33..032df5b45d8 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2013 Laurent Destailleur + * Copyright (C) 2004-2016 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2012 Marcos García * Copyright (C) 2013-2015 Raphaël Doursenaud @@ -57,6 +57,9 @@ $search_account_supplier_code=trim(GETPOST('search_account_supplier_code')); $search_town=trim(GETPOST("search_town")); $search_zip=trim(GETPOST("search_zip")); $search_state=trim(GETPOST("search_state")); +$search_email=trim(GETPOST('search_email')); +$search_phone=trim(GETPOST('search_phone')); +$search_url=trim(GETPOST('search_url')); $search_idprof1=trim(GETPOST('search_idprof1')); $search_idprof2=trim(GETPOST('search_idprof2')); $search_idprof3=trim(GETPOST('search_idprof3')); @@ -153,6 +156,9 @@ $arrayfields=array( 's.zip'=>array('label'=>$langs->trans("Zip"), 'checked'=>1), 'state.nom'=>array('label'=>$langs->trans("State"), 'checked'=>0), 'country.code_iso'=>array('label'=>$langs->trans("Country"), 'checked'=>0), + 's.email'=>array('label'=>$langs->trans("Email"), 'checked'=>0), + 's.url'=>array('label'=>$langs->trans("Url"), 'checked'=>0), + 's.phone'=>array('label'=>$langs->trans("Phone"), 'checked'=>1), 'typent.code'=>array('label'=>$langs->trans("ThirdPartyType"), 'checked'=>$checkedtypetiers), 's.siren'=>array('label'=>$langs->trans("ProfId1Short"), 'checked'=>$checkedprofid1), 's.siret'=>array('label'=>$langs->trans("ProfId2Short"), 'checked'=>$checkedprofid2), @@ -208,6 +214,9 @@ if (empty($reshook)) $search_zip=""; $search_state=""; $search_country=''; + $search_email=''; + $search_phone=''; + $search_url=''; $search_idprof1=''; $search_idprof2=''; $search_idprof3=''; @@ -345,7 +354,7 @@ else dol_print_error($db); $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.barcode, s.town, s.zip, s.datec, s.code_client, s.code_fournisseur, "; $sql.= " st.libelle as stcomm, s.fk_stcomm as stcomm_id, s.fk_prospectlevel, s.prefix_comm, s.client, s.fournisseur, s.canvas, s.status as status,"; -$sql.= " s.siren as idprof1, s.siret as idprof2, s.ape as idprof3, s.idprof4 as idprof4, s.fk_pays,"; +$sql.= " s.email, s.phone, s.url, s.siren as idprof1, s.siret as idprof2, s.ape as idprof3, s.idprof4 as idprof4, s.fk_pays,"; $sql.= " s.tms as date_update, s.datec as date_creation,"; $sql.= " s.code_compta,s.code_compta_fournisseur,"; $sql.= " typent.code as typent_code,"; @@ -389,7 +398,10 @@ if ($search_account_supplier_code) $sql.= natural_search("s.code_compta_fourniss if ($search_town) $sql.= natural_search("s.town",$search_town); if ($search_zip) $sql.= natural_search("s.zip",$search_zip); if ($search_state) $sql.= natural_search("state.nom",$search_state); -if ($search_country) $sql .= " AND s.fk_pays IN (".$search_country.')'; +if ($search_country) $sql .= " AND s.fk_pays IN (".$search_country.')'; +if ($search_email) $sql.= natural_search("s.email",$search_email); +if ($search_phone) $sql.= natural_search("s.phone",$search_phone); +if ($search_url) $sql.= natural_search("s.url",$search_url); if ($search_idprof1) $sql.= natural_search("s.siren",$search_idprof1); if ($search_idprof2) $sql.= natural_search("s.siret",$search_idprof2); if ($search_idprof3) $sql.= natural_search("s.ape",$search_idprof3); @@ -576,29 +588,33 @@ $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfiel if (empty($arrayfields['customerorsupplier']['checked'])) print ''; -print ''; +print '
'; +print '
'."\n"; print ''; -if (! empty($arrayfields['s.nom']['checked'])) print_liste_field_titre($langs->trans("Company"), $_SERVER["PHP_SELF"],"s.nom","",$param,"",$sortfield,$sortorder); -if (! empty($arrayfields['s.barcode']['checked'])) print_liste_field_titre($langs->trans("Gencod"), $_SERVER["PHP_SELF"], "s.barcode",$param,'','',$sortfield,$sortorder); +if (! empty($arrayfields['s.nom']['checked'])) print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"],"s.nom","",$param,"",$sortfield,$sortorder); +if (! empty($arrayfields['s.barcode']['checked'])) print_liste_field_titre($arrayfields['s.barcode']['label'], $_SERVER["PHP_SELF"], "s.barcode",$param,'','',$sortfield,$sortorder); if (! empty($arrayfields['s.code_client']['checked'])) print_liste_field_titre($arrayfields['s.code_client']['label'],$_SERVER["PHP_SELF"],"s.code_client","",$param,'',$sortfield,$sortorder); if (! empty($arrayfields['s.code_fournisseur']['checked'])) print_liste_field_titre($arrayfields['s.code_fournisseur']['label'],$_SERVER["PHP_SELF"],"s.code_fournisseur","",$param,'',$sortfield,$sortorder); if (! empty($arrayfields['s.code_compta']['checked'])) print_liste_field_titre($arrayfields['s.code_compta']['label'],$_SERVER["PHP_SELF"],"s.code_compta","",$param,'',$sortfield,$sortorder); if (! empty($arrayfields['s.code_compta_fournisseur']['checked'])) print_liste_field_titre($arrayfields['s.code_compta_fournisseur']['label'],$_SERVER["PHP_SELF"],"s.code_compta_fournisseur","",$param,'',$sortfield,$sortorder); -if (! empty($arrayfields['s.town']['checked'])) print_liste_field_titre($langs->trans("Town"),$_SERVER["PHP_SELF"],"s.town","",$param,'',$sortfield,$sortorder); -if (! empty($arrayfields['s.zip']['checked'])) print_liste_field_titre($langs->trans("Zip"),$_SERVER["PHP_SELF"],"s.zip","",$param,'',$sortfield,$sortorder); -if (! empty($arrayfields['state.nom']['checked'])) print_liste_field_titre($langs->trans("StateShort"),$_SERVER["PHP_SELF"],"state.nom","",$param,'',$sortfield,$sortorder); -if (! empty($arrayfields['country.code_iso']['checked'])) print_liste_field_titre($langs->trans("Country"),$_SERVER["PHP_SELF"],"country.code_iso","",$param,'align="center"',$sortfield,$sortorder); -if (! empty($arrayfields['typent.code']['checked'])) print_liste_field_titre($langs->trans("ThirdPartyType"),$_SERVER["PHP_SELF"],"typent.code","",$param,'align="center"',$sortfield,$sortorder); +if (! empty($arrayfields['s.town']['checked'])) print_liste_field_titre($arrayfields['s.nom']['label'],$_SERVER["PHP_SELF"],"s.town","",$param,'',$sortfield,$sortorder); +if (! empty($arrayfields['s.zip']['checked'])) print_liste_field_titre($arrayfields['s.zip']['label'],$_SERVER["PHP_SELF"],"s.zip","",$param,'',$sortfield,$sortorder); +if (! empty($arrayfields['state.nom']['checked'])) print_liste_field_titre($arrayfields['state.nom']['label'],$_SERVER["PHP_SELF"],"state.nom","",$param,'',$sortfield,$sortorder); +if (! empty($arrayfields['country.code_iso']['checked'])) print_liste_field_titre($arrayfields['country.code_iso']['label'],$_SERVER["PHP_SELF"],"country.code_iso","",$param,'align="center"',$sortfield,$sortorder); +if (! empty($arrayfields['typent.code']['checked'])) print_liste_field_titre($arrayfields['typent.code']['label'],$_SERVER["PHP_SELF"],"typent.code","",$param,'align="center"',$sortfield,$sortorder); +if (! empty($arrayfields['s.email']['checked'])) print_liste_field_titre($arrayfields['s.email']['label'],$_SERVER["PHP_SELF"],"s.zip","",$param,'',$sortfield,$sortorder); +if (! empty($arrayfields['s.phone']['checked'])) print_liste_field_titre($arrayfields['s.phone']['label'],$_SERVER["PHP_SELF"],"s.zip","",$param,'',$sortfield,$sortorder); +if (! empty($arrayfields['s.url']['checked'])) print_liste_field_titre($arrayfields['s.url']['label'],$_SERVER["PHP_SELF"],"s.zip","",$param,'',$sortfield,$sortorder); if (! empty($arrayfields['s.siren']['checked'])) print_liste_field_titre($form->textwithpicto($langs->trans("ProfId1Short"),$textprofid[1],1,0),$_SERVER["PHP_SELF"],"s.siren","",$param,'class="nowrap"',$sortfield,$sortorder); if (! empty($arrayfields['s.siret']['checked'])) print_liste_field_titre($form->textwithpicto($langs->trans("ProfId2Short"),$textprofid[2],1,0),$_SERVER["PHP_SELF"],"s.siret","",$param,'class="nowrap"',$sortfield,$sortorder); if (! empty($arrayfields['s.ape']['checked'])) print_liste_field_titre($form->textwithpicto($langs->trans("ProfId3Short"),$textprofid[3],1,0),$_SERVER["PHP_SELF"],"s.ape","",$param,'class="nowrap"',$sortfield,$sortorder); if (! empty($arrayfields['s.idprof4']['checked'])) print_liste_field_titre($form->textwithpicto($langs->trans("ProfId4Short"),$textprofid[4],1,0),$_SERVER["PHP_SELF"],"s.idprof4","",$param,'class="nowrap"',$sortfield,$sortorder); if (! empty($arrayfields['s.idprof5']['checked'])) print_liste_field_titre($form->textwithpicto($langs->trans("ProfId5Short"),$textprofid[4],1,0),$_SERVER["PHP_SELF"],"s.idprof5","",$param,'class="nowrap"',$sortfield,$sortorder); if (! empty($arrayfields['s.idprof6']['checked'])) print_liste_field_titre($form->textwithpicto($langs->trans("ProfId6Short"),$textprofid[4],1,0),$_SERVER["PHP_SELF"],"s.idprof6","",$param,'class="nowrap"',$sortfield,$sortorder); -if (! empty($arrayfields['customerorsupplier']['checked'])) print_liste_field_titre(''); // type of customer -if (! empty($arrayfields['s.fk_prospectlevel']['checked'])) print_liste_field_titre($arrayfields['s.fk_prospectlevel']['label'],$_SERVER["PHP_SELF"],"s.fk_prospectlevel","",$param,'align="center"',$sortfield,$sortorder); -if (! empty($arrayfields['s.fk_stcomm']['checked'])) print_liste_field_titre($arrayfields['s.fk_stcomm']['label'],$_SERVER["PHP_SELF"],"s.fk_stcomm","",$param,'align="center"',$sortfield,$sortorder); +if (! empty($arrayfields['customerorsupplier']['checked'])) print_liste_field_titre(''); // type of customer +if (! empty($arrayfields['s.fk_prospectlevel']['checked'])) print_liste_field_titre($arrayfields['s.fk_prospectlevel']['label'],$_SERVER["PHP_SELF"],"s.fk_prospectlevel","",$param,'align="center"',$sortfield,$sortorder); +if (! empty($arrayfields['s.fk_stcomm']['checked'])) print_liste_field_titre($arrayfields['s.fk_stcomm']['label'],$_SERVER["PHP_SELF"],"s.fk_stcomm","",$param,'align="center"',$sortfield,$sortorder); // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { @@ -615,9 +631,9 @@ if (is_array($extrafields->attribute_label) && count($extrafields->attribute_lab $parameters=array('arrayfields'=>$arrayfields); $reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; -if (! empty($arrayfields['s.datec']['checked'])) print_liste_field_titre($langs->trans("DateCreationShort"),$_SERVER["PHP_SELF"],"s.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); -if (! empty($arrayfields['s.tms']['checked'])) print_liste_field_titre($langs->trans("DateModificationShort"),$_SERVER["PHP_SELF"],"s.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); -if (! empty($arrayfields['s.status']['checked'])) print_liste_field_titre($langs->trans("Status"),$_SERVER["PHP_SELF"],"s.status","",$param,'align="center"',$sortfield,$sortorder); +if (! empty($arrayfields['s.datec']['checked'])) print_liste_field_titre($arrayfields['s.datec']['label'],$_SERVER["PHP_SELF"],"s.datec","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); +if (! empty($arrayfields['s.tms']['checked'])) print_liste_field_titre($arrayfields['s.tms']['label'],$_SERVER["PHP_SELF"],"s.tms","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); +if (! empty($arrayfields['s.status']['checked'])) print_liste_field_titre($arrayfields['s.status']['label'],$_SERVER["PHP_SELF"],"s.status","",$param,'align="center"',$sortfield,$sortorder); print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"],"",'','','align="right"',$sortfield,$sortorder,'maxwidthsearch '); print "\n"; @@ -700,6 +716,27 @@ if (! empty($arrayfields['typent.code']['checked'])) print $form->selectarray("search_type_thirdparty", $formcompany->typent_array(0), $search_type_thirdparty, 0, 0, 0, '', 0, 0, 0, (empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?'ASC':$conf->global->SOCIETE_SORT_ON_TYPEENT)); print ''; } +if (! empty($arrayfields['s.email']['checked'])) +{ + // Email + print ''; +} +if (! empty($arrayfields['s.phone']['checked'])) +{ + // Phone + print ''; +} +if (! empty($arrayfields['s.url']['checked'])) +{ + // Url + print ''; +} if (! empty($arrayfields['s.siren']['checked'])) { // IdProf1 @@ -932,6 +969,18 @@ while ($i < min($num, $limit)) print $typenArray[$obj->typent_code]; print ''; } + if (! empty($arrayfields['s.email']['checked'])) + { + print "\n"; + } + if (! empty($arrayfields['s.phone']['checked'])) + { + print "\n"; + } + if (! empty($arrayfields['s.url']['checked'])) + { + print "\n"; + } if (! empty($arrayfields['s.siren']['checked'])) { print "\n"; @@ -1061,6 +1110,7 @@ $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters); // N print $hookmanager->resPrint; print "
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print '".$obj->email."".$obj->phone."".$obj->url."".$obj->idprof1."
"; +print "
"; print ''; diff --git a/htdocs/societe/rib.php b/htdocs/societe/rib.php index 1d8e9348f72..f6149690b7e 100644 --- a/htdocs/societe/rib.php +++ b/htdocs/societe/rib.php @@ -62,6 +62,10 @@ $extralabels=$extrafields->fetch_name_optionals_label($object->table_element); $hookmanager->initHooks(array('thirdpartybancard','globalcard')); +// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array +$hookmanager->initHooks(array('thirdpartybancard')); + + /* * Actions diff --git a/htdocs/societe/soc.php b/htdocs/societe/soc.php index 0220f775d7b..cc0465a0b68 100644 --- a/htdocs/societe/soc.php +++ b/htdocs/societe/soc.php @@ -109,7 +109,7 @@ if (empty($reshook)) } } - if ($action == 'confirm_merge' && $confirm == 'yes') + if ($action == 'confirm_merge' && $confirm == 'yes' && $user->rights->societe->creer) { $object->fetch($socid); @@ -1013,7 +1013,7 @@ else print ''; diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index a50e8509ba5..d2649a42a43 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -341,6 +341,7 @@ if ($result) } + print '
'; print ''; print ''; print_liste_field_titre($langs->trans('Ref'),$_SERVER["PHP_SELF"],'p.ref','',$param,'',$sortfield,$sortorder); @@ -514,7 +515,8 @@ if ($result) } print '
'; - + print '
'; + print ''; $db->free($result); diff --git a/htdocs/supplier_proposal/tpl/linkedobjectblock.tpl.php b/htdocs/supplier_proposal/tpl/linkedobjectblock.tpl.php index 8f72744486a..8ba1f958918 100644 --- a/htdocs/supplier_proposal/tpl/linkedobjectblock.tpl.php +++ b/htdocs/supplier_proposal/tpl/linkedobjectblock.tpl.php @@ -28,27 +28,44 @@ global $user; $langs = $GLOBALS['langs']; $linkedObjectBlock = $GLOBALS['linkedObjectBlock']; +$total=0; $ilink=0; $var=true; -$total=0; foreach($linkedObjectBlock as $key => $objectlink) { - $var=!$var; + $ilink++; + $var=!$var; + $trclass=($var?'pair':'impair'); + if ($ilink == count($linkedObjectBlock) && empty($noMoreLinkedObjectBlockAfter) && count($linkedObjectBlock) <= 1) $trclass.=' liste_sub_total'; ?> - > - trans("SupplierProposal"); ?> - trans("ShowSupplierProposal"),"supplier_proposal").' '.$objectlink->ref; ?> - - datec,'day'); ?> - rights->supplier_proposal->lire) { - $total = $total + $objectlink->total_ht; - echo price($objectlink->total_ht); - } ?> - getLibStatut(3); ?> - ">transnoentitiesnoconv("RemoveLink")); ?> - + + trans("SupplierProposal"); ?> + trans("ShowSupplierProposal"),"supplier_proposal").' '.$objectlink->ref; ?> + + datec,'day'); ?> + rights->supplier_proposal->lire) { + $total = $total + $objectlink->total_ht; + echo price($objectlink->total_ht); + } ?> + getLibStatut(3); ?> + ">transnoentitiesnoconv("RemoveLink")); ?> + 1) +{ + ?> + + trans("Total"); ?> + + + + + + + + diff --git a/htdocs/support/inc.php b/htdocs/support/inc.php index 2db312ee630..869dace222d 100644 --- a/htdocs/support/inc.php +++ b/htdocs/support/inc.php @@ -184,7 +184,7 @@ function conf($dolibarr_main_document_root) $conf->db->user = trim($dolibarr_main_db_user); $conf->db->pass = trim($dolibarr_main_db_pass); - if (empty($conf->db->dolibarr_main_db_collation)) $conf->db->dolibarr_main_db_collation='utf8_general_ci'; + if (empty($conf->db->dolibarr_main_db_collation)) $conf->db->dolibarr_main_db_collation='utf8_unicode_ci'; return 1; } diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 6b540b7c2c5..6685b0cc745 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -71,7 +71,6 @@ $dol_hide_topmenu=$conf->dol_hide_topmenu; $dol_hide_leftmenu=$conf->dol_hide_leftmenu; $dol_optimize_smallscreen=$conf->dol_optimize_smallscreen; $dol_no_mouse_hover=$conf->dol_no_mouse_hover; -$dol_use_jmobile=$conf->dol_use_jmobile; //$conf->global->THEME_ELDY_ENABLE_PERSONALIZED=0; @@ -221,7 +220,6 @@ print 'dol_hide_topmenu='.$dol_hide_topmenu."\n"; print 'dol_hide_leftmenu='.$dol_hide_leftmenu."\n"; print 'dol_optimize_smallscreen='.$dol_optimize_smallscreen."\n"; print 'dol_no_mouse_hover='.$dol_no_mouse_hover."\n"; -print 'dol_use_jmobile='.$dol_use_jmobile."\n"; print 'dol_screenwidth='.$_SESSION['dol_screenwidth']."\n"; print 'dol_screenheight='.$_SESSION['dol_screenheight']."\n"; print 'fontsize='.$fontsize."\n"; @@ -261,8 +259,6 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla background-color: #FFF; } - - input:focus, textarea:focus, button:focus, select:focus { box-shadow: 0 0 4px #8091BF; } @@ -306,7 +302,6 @@ span.timesheetalreadyrecorded input { border: none; /*background: transparent;*/ } - select.flat, form.flat select { font-weight: normal; @@ -341,9 +336,9 @@ input[type=checkbox] { background-color: transparent; border: none; box-shadow: input[type=radio] { background-color: transparent; border: none; box-shadow: none; } input[type=image] { background-color: transparent; border: none; box-shadow: none; } input:-webkit-autofill { - background-color: !important; + background-color: #FBFFEA !important; background-image:none !important; - -webkit-box-shadow: 0 0 0 50px inset; + -webkit-box-shadow: 0 0 0 50px #FBFFEA inset; } ::-webkit-input-placeholder { color:#ccc; } :-moz-placeholder { color:#bbb; } /* firefox 18- */ @@ -351,9 +346,6 @@ input:-webkit-autofill { :-ms-input-placeholder { color:#ccc; } /* ie */ input:-moz-placeholder { color:#ccc; } - -legend { margin-bottom: 8px; } - fieldset { border: 1px solid #AAAAAA !important; } @@ -542,7 +534,7 @@ div.myavailability { margin-top: 6px; margin-left: 4px; } -.selectlimit { +.selectlimit, .marginrightonly { margin-right: 10px !important; } .strikefordisabled { @@ -590,15 +582,18 @@ div.myavailability { } /* DOL_XXX for future usage (when left menu has been removed). If we do not use datatable */ -.table-responsive { +/*.table-responsive { width: calc(100% - 330px); margin-bottom: 15px; overflow-y: hidden; -ms-overflow-style: -ms-autohiding-scrollbar; +}*/ +.div-table-responsive { + overflow-x: auto; + min-height: 0.01%; } - /* ============================================================================== */ /* Styles to hide objects */ /* ============================================================================== */ @@ -621,18 +616,22 @@ div.myavailability { .minwidth400imp { min-width: 400px !important; } .minwidth500imp { min-width: 500px !important; } } +.maxwidth25 { max-width: 25px; } .maxwidth50 { max-width: 50px; } +.maxwidth75 { max-width: 75px; } .maxwidth100 { max-width: 100px; } .maxwidth150 { max-width: 150px; } .maxwidth200 { max-width: 200px; } .maxwidth300 { max-width: 300px; } .maxwidth400 { max-width: 400px; } .maxwidth500 { max-width: 500px; } +.maxwidth50imp { max-width: 50px !important; } .minheight20 { min-height: 20px; } .minheight40 { min-height: 40px; } .titlefieldcreate { width: 20%; } .titlefield { width: 25%; } .titlefieldmiddle { width: 50%; } +.imgmaxwidth180 { max-width: 180px; } /* Force values for small screen 1400 */ @media only screen and (max-width: 1400px) @@ -662,25 +661,40 @@ div.myavailability { /* Force values for small screen 570 */ @media only screen and (max-width: 570px) { + .tdoverflowonsmartphone { + max-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + div.titre { line-height: 2em; } + .border tbody tr, .border tbody tr td, div.tabBar table.border tr, div.tabBar table.border tr td, div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar div.border .table-val-border-col { + height: 40px !important; + } - input[type=text], select, textarea { + .quatrevingtpercent, .inputsearch { + width: 95%; + } + + input, input[type=text], input[type=password], select, textarea { min-width: 20px; min-height: 1.4em; line-height: 1.4em; - margin: .5em 0; padding: .4em .1em; border: 1px solid #BBB; + /* max-width: inherit; why this ? */ } .hideonsmartphone { display: none; } .noenlargeonsmartphone { width : 50px !important; display: inline !important; } .maxwidthonsmartphone { max-width: 100px; } - .maxwidth50onsmartphone { max-width: 50px; } - .maxwidth100onsmartphone { max-width: 100px; } - .maxwidth150onsmartphone { max-width: 150px; } + .maxwidth50onsmartphone { max-width: 40px; } + .maxwidth75onsmartphone { max-width: 50px; } + .maxwidth100onsmartphone { max-width: 70px; } + .maxwidth150onsmartphone { max-width: 120px; } .maxwidth200onsmartphone { max-width: 200px; } .maxwidth300onsmartphone { max-width: 300px; } .maxwidth400onsmartphone { max-width: 400px; } @@ -692,6 +706,32 @@ div.myavailability { .minwidth500imp { min-width: 50px !important; } .titlefield { width: auto; } .titlefieldcreate { width: auto; } + + #tooltip { + position: absolute; + width: px; + } + + /* intput, input[type=text], */ + select { + width: 98%; + min-width: 40px; + } + + div.divphotoref { + padding-right: 5px; + } + img.photoref, div.photoref { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + padding: 4px; + height: 20px; + width: 20px; + object-fit: contain; + } + } .linkobject { cursor: pointer; } @@ -809,7 +849,7 @@ div.fiche { margin-: px; margin-: dol_optimize_smallscreen)?'12':'6')); ?>px; dol_hide_leftmenu) && ! empty($conf->dol_hide_topmenu)) print 'margin-top: 4px;'."\n"; ?> - dol_use_jmobile)) print ' margin-bottom: 10px;'."\n"; ?> + dol_hide_leftmenu)) print 'margin-bottom: 12px;'."\n"; ?> } div.fichecenter { width: 100%; @@ -951,6 +991,9 @@ img.photoref, div.photoref { width: 80px; object-fit: contain; } +img.fitcontain { + object-fit: contain; +} div.photoref { display:table-cell; vertical-align:middle; @@ -1905,10 +1948,7 @@ div.tabs { } div.tabsElem { margin-top: 1px; - dol_use_jmobile)) { ?>; - margin-bottom: -1px; - -} /* To avoid overlap of tabs when not browser */ +} /* To avoid overlap of tabs when not browser */ div.tabBar { color: #; @@ -2333,10 +2373,7 @@ table.border, table.dataTable, .table-border, .table-border-col, .table-key-bord table.borderplus { border: 1px solid #BBB; } -.border tbody tr, .border tbody tr td { - height: 20px; -} -div.tabBar table.border tr, div.tabBar table.border tr td, div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar div.border .table-val-border-col { +.border tbody tr, .border tbody tr td, div.tabBar table.border tr, div.tabBar table.border tr td, div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar div.border .table-val-border-col { height: 20px; } div.tabBar div.border .table-border-row, div.tabBar div.border .table-key-border-col, div.tabBar .table-val-border-col { @@ -2368,7 +2405,6 @@ td.border, div.tagtable div div.border { border-bottom: 1px solid #000000; border-left: 1px solid #000000; } - .table-key-border-col { /* width: 25%; */ vertical-align:top; @@ -2377,6 +2413,7 @@ td.border, div.tagtable div div.border { width:auto; } + /* Main boxes */ table.liste, table.noborder, table.formdoc, div.noborder { @@ -2389,27 +2426,15 @@ table.liste, table.noborder, table.formdoc, div.noborder { border-top-color: rgb(); border-top-style: solid; -/* border-right-width: 1px; - border-right-color: #BBB; - border-right-style: solid; - - border-left-width: 1px; - border-left-color: #BBB; - border-left-style: solid; -*/ border-bottom-width: 1px; border-bottom-color: #BBB; border-bottom-style: solid; margin: 0px 0px 5px 0px; - -/* -moz-box-shadow: 2px 2px 4px #CCC; - -webkit-box-shadow: 2px 2px 4px #CCC; - box-shadow: 2px 2px 4px #CCC; - - -moz-border-radius: 0.2em; - -webkit-border-radius: 0.2em; - border-radius: 0.2em;*/ +} +table.paddingtopbottomonly tr td { + padding-top: 1px; + padding-bottom: 2px; } .liste_titre_add td, .liste_titre_add th, .liste_titre_add .tagtd { @@ -2466,7 +2491,7 @@ table.listwithfilterbefore { /* Pagination */ div.refidpadding { - padding-top: dol_use_jmobile != 4)?'3':'7'; ?>px; + padding-top: 3px; } div.refid { font-weight: bold; @@ -2502,10 +2527,8 @@ div.pagination li { display: inline-block; padding-left: 0px; padding-right: 0px; -dol_use_jmobile != 4) { ?> padding-top: 6px; padding-bottom: 5px; - } .pagination { display: inline-block; @@ -2514,22 +2537,12 @@ div.pagination li { } div.pagination li.pagination a, div.pagination li.pagination span { -dol_use_jmobile != 4) { ?> padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; color: #000; text-decoration: none; - /* - border-color: #ccc; - background-color: #f5f5f5; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);*/ - background-repeat: repeat-x; - + background-repeat: repeat-x; } div.pagination li.pagination span.inactive { cursor: default; @@ -2561,13 +2574,6 @@ div.pagination li.litext a:hover { background-color: transparent; background-image: none; } -dol_use_jmobile == 4) { ?> -div.pagination li.litext { - padding-top: 13px; - vertical-align: top; -} - -dol_use_jmobile != 4) { ?> div.pagination li.noborder a:hover { border: none; background-color: transparent; @@ -2627,7 +2633,6 @@ div.pagination .disabled a:focus { background-color: #fff; border-color: #ddd; } - div.pagination li.pagination .active { text-decoration: underline; } @@ -2835,7 +2840,7 @@ form.liste_total div { border-top: 1px solid #DDDDDD; } tr.liste_sub_total, tr.liste_sub_total td { - border-bottom: 2px solid #aaa; + border-bottom: 1px solid #aaa; } .tableforservicepart1 .impair, .tableforservicepart1 .pair, .tableforservicepart2 .impair, .tableforservicepart2 .pair { @@ -4206,11 +4211,7 @@ a.ui-link, a.ui-link:hover, .ui-btn:hover, span.ui-btn-text:hover, span.ui-btn-i min-width: .4em; padding-left: 6px; padding-right: 6px; - - font-size: 13px; - font-size: px; - /* white-space: normal; */ /* Warning, enable this break the truncate feature */ } .ui-btn-icon-right .ui-btn-inner { @@ -4517,7 +4518,7 @@ img.demothumb { } @media only screen and (max-width: 767px) { - .imgopensurveywizard { width:95%; height: auto; } + .imgopensurveywizard, .imgautosize { width:95%; height: auto; } #tooltip { position: absolute; @@ -4640,30 +4641,6 @@ img.demothumb { div.mainmenu { min-width: 20px; } - - #tooltip { - position: absolute; - width: px; - } - select { - width: 98%; - dol_use_jmobile)) { ?>max-width: 100px; - min-width: 40px; - } - div.divphotoref { - padding-right: 5px; - } - img.photoref, div.photoref { - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - padding: 4px; - height: 20px; - width: 20px; - object-fit: contain; - } - } dol_hide_topmenu; $dol_hide_leftmenu=$conf->dol_hide_leftmenu; $dol_optimize_smallscreen=$conf->dol_optimize_smallscreen; $dol_no_mouse_hover=$conf->dol_no_mouse_hover; -$dol_use_jmobile=$conf->dol_use_jmobile; //$conf->global->THEME_ELDY_ENABLE_PERSONALIZED=0; @@ -221,7 +220,6 @@ print 'dol_hide_topmenu='.$dol_hide_topmenu."\n"; print 'dol_hide_leftmenu='.$dol_hide_leftmenu."\n"; print 'dol_optimize_smallscreen='.$dol_optimize_smallscreen."\n"; print 'dol_no_mouse_hover='.$dol_no_mouse_hover."\n"; -print 'dol_use_jmobile='.$dol_use_jmobile."\n"; print 'dol_screenwidth='.$_SESSION['dol_screenwidth']."\n"; print 'dol_screenheight='.$_SESSION['dol_screenheight']."\n"; print 'fontsize='.$fontsize."\n"; @@ -261,8 +259,6 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla background-color: #FDFDFD; } - - input:focus, textarea:focus, button:focus, select:focus { box-shadow: 0 0 4px #8091BF; } @@ -308,8 +304,6 @@ span.timesheetalreadyrecorded input { /*background: transparent;*/ } - - select.flat, form.flat select { font-weight: normal; } @@ -347,9 +341,9 @@ input[type=radio] { background-color: transparent; border: none; box-shadow: input[type=image] { background-color: transparent; border: none; box-shadow: none; } input[type=text] { min-width: 20px; } input:-webkit-autofill { - background-color: !important; + background-color: #FBFFEA !important; background-image:none !important; - -webkit-box-shadow: 0 0 0 50px inset; + -webkit-box-shadow: 0 0 0 50px #FBFFEA inset; } ::-webkit-input-placeholder { color:#ccc; } :-moz-placeholder { color:#bbb; } /* firefox 18- */ @@ -357,9 +351,6 @@ input:-webkit-autofill { :-ms-input-placeholder { color:#ccc; } /* ie */ input:-moz-placeholder { color:#ccc; } - -legend { margin-bottom: 8px; } - fieldset { border: 1px solid #AAAAAA !important; } @@ -549,7 +540,7 @@ div.myavailability { margin-top: 6px; margin-left: 4px; } -.selectlimit { +.selectlimit, .marginrightonly { margin-right: 10px !important; } .strikefordisabled { @@ -602,6 +593,10 @@ div.myavailability { overflow-y: hidden; -ms-overflow-style: -ms-autohiding-scrollbar; } +.div-table-responsive { + overflow-x: auto; + min-height: 0.01%; +} /* ============================================================================== */ @@ -626,18 +621,23 @@ div.myavailability { .minwidth400imp { min-width: 400px !important; } .minwidth500imp { min-width: 500px !important; } } +.maxwidth25 { max-width: 25px; } .maxwidth50 { max-width: 50px; } +.maxwidth75 { max-width: 75px; } .maxwidth100 { max-width: 100px; } .maxwidth150 { max-width: 150px; } .maxwidth200 { max-width: 200px; } .maxwidth300 { max-width: 300px; } .maxwidth400 { max-width: 400px; } .maxwidth500 { max-width: 500px; } +.maxwidth50imp { max-width: 50px !important; } .minheight20 { min-height: 20px; } .minheight40 { min-height: 40px; } .titlefieldcreate { width: 20%; } .titlefield { width: 25%; } .titlefieldmiddle { width: 50%; } +.imgmaxwidth180 { max-width: 180px; } + /* Force values for small screen 1400 */ @media only screen and (max-width: 1400px) @@ -667,25 +667,40 @@ div.myavailability { /* Force values for small screen 570 */ @media only screen and (max-width: 570px) { + .tdoverflowonsmartphone { + max-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + div.titre { line-height: 2em; } + .border tbody tr, .border tbody tr td, div.tabBar table.border tr { + height: 40px !important; + } - input[type=text], select, textarea { + .quatrevingtpercent, .inputsearch { + width: 95%; + } + + input, input[type=text], input[type=password], select, textarea { min-width: 20px; min-height: 1.4em; line-height: 1.4em; - margin: .5em 0; padding: .4em .1em; border: 1px solid #BBB; + /* max-width: inherit; why this */ } .hideonsmartphone { display: none; } .noenlargeonsmartphone { width : 50px !important; display: inline !important; } .maxwidthonsmartphone { max-width: 100px; } - .maxwidth50onsmartphone { max-width: 50px; } - .maxwidth100onsmartphone { max-width: 100px; } - .maxwidth150onsmartphone { max-width: 150px; } + .maxwidth50onsmartphone { max-width: 40px; } + .maxwidth75onsmartphone { max-width: 50px; } + .maxwidth100onsmartphone { max-width: 70px; } + .maxwidth150onsmartphone { max-width: 120px; } .maxwidth200onsmartphone { max-width: 200px; } .maxwidth300onsmartphone { max-width: 300px; } .maxwidth400onsmartphone { max-width: 400px; } @@ -697,6 +712,31 @@ div.myavailability { .minwidth500imp { min-width: 50px !important; } .titlefield { width: auto; } .titlefieldcreate { width: auto; } + + #tooltip { + position: absolute; + width: px; + } + + /* intput, input[type=text], */ + select { + width: 98%; + min-width: 40px; + } + + div.divphotoref { + padding-right: 5px; + } + img.photoref, div.photoref { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + padding: 4px; + height: 20px; + width: 20px; + object-fit: contain; + } } .linkobject { cursor: pointer; } @@ -1000,6 +1040,9 @@ img.photoref, div.photoref { width: 80px; object-fit: contain; } +img.fitcontain { + object-fit: contain; +} div.photoref { display:table-cell; vertical-align:middle; @@ -1013,6 +1056,7 @@ img.photorefnoborder { object-fit: contain; border: 1px solid #CCC; } + .underrefbanner { } .underbanner { @@ -2114,13 +2158,11 @@ span.butAction, span.butActionDelete { color: #ffffff !important; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #006dcc; - dol_use_jmobile != 4)) { ?> background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); background-image: -o-linear-gradient(top, #0088cc, #0044cc); background-image: linear-gradient(to bottom, #0088cc, #0044cc); - background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); border-color: #0044cc #0044cc #002a80; @@ -2245,10 +2287,7 @@ table.borderplus { border: 1px solid #BBB; } -.border tbody tr, .border tbody tr td { - height: 20px; -} -div.tabBar table.border tr { +.border tbody tr, .border tbody tr td, div.tabBar table.border tr { height: 20px; } @@ -2273,6 +2312,7 @@ td.border, div.tagtable div div.border { width:auto; } + /* Main boxes */ table.liste, table.noborder, table.formdoc, div.noborder { @@ -2285,36 +2325,16 @@ table.liste, table.noborder, table.formdoc, div.noborder { border-top-color: rgb(); border-top-style: solid; -/* border-right-width: 1px; - border-right-color: #BBB; - border-right-style: solid; - - border-left-width: 1px; - border-left-color: #BBB; - border-left-style: solid; -*/ border-bottom-width: 1px; border-bottom-color: #BBB; border-bottom-style: solid; margin: 0px 0px 8px 0px; - /* - -moz-box-shadow: 2px 2px 4px #CCC; - -webkit-box-shadow: 2px 2px 4px #CCC; - box-shadow: 2px 2px 4px #CCC; - */ - /* box-shadow: 0 0 3px rgba(0,0,0,0.16); */ -moz-border-radius: 0.1em; -webkit-border-radius: 0.1em; border-radius: 0.1em; } -/* -#tablelines tr.liste_titre:first-child td, form.formnoborder, tr.liste_titre.trnoborder td { - border-top-width: 1px; - border-top-color: rgb(); - border-top-style: solid; -}*/ table.noborder tr, div.noborder form { border-top-color: #FEFEFE; @@ -2327,6 +2347,10 @@ table.noborder tr, div.noborder form { border-left-style: solid; min-height: 26px; } +table.paddingtopbottomonly tr td { + padding-top: 1px; + padding-bottom: 2px; +} .liste_titre_add td, .liste_titre_add th, .liste_titre_add .tagtd { @@ -2382,7 +2406,7 @@ table.listwithfilterbefore { /* Pagination */ div.refidpadding { - padding-top: dol_use_jmobile != 4)?'3':'14'; ?>px; + padding-top: 3px; } div.refid { font-weight: bold; @@ -2418,10 +2442,8 @@ div.pagination li { display: inline-block; padding-left: 0px; padding-right: 0px; -dol_use_jmobile != 4)) { ?> padding-top: 6px; padding-bottom: 5px; - } .pagination { display: inline-block; @@ -2431,7 +2453,6 @@ div.pagination li { div.pagination li.pagination a, div.pagination li.pagination span { -dol_use_jmobile != 4) { ?> padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; @@ -2445,7 +2466,6 @@ div.pagination li.pagination span { background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); background-repeat: repeat-x; - } div.pagination li.pagination span.inactive { cursor: default; @@ -2458,13 +2478,6 @@ border: none; padding-left: 4px; font-weight: bold; } -dol_use_jmobile == 4) { ?> -div.pagination li.litext { - padding-top: 13px; - vertical-align: top; -} - -dol_use_jmobile != 4) { ?> div.pagination li.noborder a:hover { border: none; background-color: transparent; @@ -2516,7 +2529,6 @@ div.pagination .disabled a:focus { background-color: #fff; border-color: #ddd; } - div.pagination li.pagination .active { text-decoration: underline; } @@ -4114,11 +4126,7 @@ a.ui-link, a.ui-link:hover, .ui-btn:hover, span.ui-btn-text:hover, span.ui-btn-i min-width: .4em; padding-left: 6px; padding-right: 6px; - - font-size: 13px; - font-size: px; - /* white-space: normal; */ /* Warning, enable this break the truncate feature */ } .ui-btn-icon-right .ui-btn-inner { @@ -4439,7 +4447,7 @@ img.demothumb { } @media only screen and (max-width: 767px) { - .imgopensurveywizard { width:95%; height: auto; } + .imgopensurveywizard, .imgautosize { width:95%; height: auto; } #tooltip { position: absolute; @@ -4543,7 +4551,6 @@ img.demothumb { } select { width: 98%; - dol_use_jmobile)) { ?>max-width: 100px; min-width: 0 !important; } div.divphotoref { diff --git a/htdocs/user/agenda_extsites.php b/htdocs/user/agenda_extsites.php index 823f5ad307e..ef7ffd9f70b 100644 --- a/htdocs/user/agenda_extsites.php +++ b/htdocs/user/agenda_extsites.php @@ -169,7 +169,7 @@ print ""; print ""; print ""; print ""; -print "'; +print "'; print "'; print ''; print ""; @@ -187,13 +187,13 @@ while ($i <= $MAXAGENDA) $var=!$var; print ""; // Nb - print '"; + print '"; // Name - print ''; + print ''; // URL - print ''; + print ''; // Offset TZ - print ''; + print ''; // Color (Possible colors are limited by Google) print ''; @@ -747,7 +747,7 @@ if (($action == 'create') || ($action == 'adduserldap')) } else { - print ''; + print ''; } print ''; @@ -760,7 +760,7 @@ if (($action == 'create') || ($action == 'adduserldap')) // Position/Job print ''; print ''; // Gender @@ -785,7 +785,7 @@ if (($action == 'create') || ($action == 'adduserldap')) } else { - print ''; + print ''; } print ''; @@ -997,7 +997,7 @@ if (($action == 'create') || ($action == 'adduserldap')) print ''; print ''; @@ -1102,7 +1102,7 @@ if (($action == 'create') || ($action == 'adduserldap')) print $langs->trans("Note"); print '\n"; @@ -1802,7 +1802,7 @@ else print ''; print ''; - print ''; print ''; @@ -1902,7 +1902,7 @@ else if(! empty($conf->api->enabled) && $user->admin) { print ''; print ''; @@ -1992,7 +1992,7 @@ else } // Type - print ''; + print ''; print ''; } @@ -2104,7 +2104,7 @@ else print '".'\n"; @@ -531,7 +531,7 @@ else print ''; print ''; print "\n"; diff --git a/htdocs/user/index.php b/htdocs/user/index.php index f5d9407d2e3..b1aba55a73f 100644 --- a/htdocs/user/index.php +++ b/htdocs/user/index.php @@ -311,7 +311,10 @@ $moreforfilter=''; $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields -print '
".$langs->trans("Parameter")."".$langs->trans("Name")."".$langs->trans("ExtSiteUrlAgenda")." (".$langs->trans("Example").': http://yoursite/agenda/agenda.ics)".$langs->trans("ExtSiteUrlAgenda").'
'." (".$langs->trans("Example").': http://yoursite/agenda/agenda.ics)
".$form->textwithpicto($langs->trans("FixTZ"), $langs->trans("FillFixTZOnlyIfRequired"), 1).''.$langs->trans("Color").'
'.$langs->trans("AgendaExtNb",$key)."'.$langs->trans("AgendaExtNb",$key)."'; //print $formadmin->selectColor($conf->global->$color, "google_agenda_color".$key, $colorlist); diff --git a/htdocs/user/card.php b/htdocs/user/card.php index d2c96ab7950..8fa91cb57a2 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -733,7 +733,7 @@ if (($action == 'create') || ($action == 'adduserldap')) } else { - print ''; + print ''; } print '
'.$langs->trans("PostOrFunction").''; - print ''; + print ''; print '
'.$langs->trans("Signature").''; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('signature',GETPOST('signature'),'',138,'dolibarr_mailings','In',true,true,empty($conf->global->FCKEDITOR_ENABLE_USERSIGN)?0:1,ROWS_4,90); + $doleditor=new DolEditor('signature',GETPOST('signature'),'',138,'dolibarr_mailings','In',true,true,empty($conf->global->FCKEDITOR_ENABLE_USERSIGN)?0:1,ROWS_4,'90%'); print $doleditor->Create(1); print '
'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('note','','',120,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_3,90); + $doleditor=new DolEditor('note','','',120,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_3,'90%'); $doleditor->Create(); print "
'; if ($caneditfield && !$object->ldap_sid) { - print ''; + print ''; } else { @@ -1817,7 +1817,7 @@ else print ''; if ($caneditfield && !$object->ldap_sid) { - print ''; + print ''; } else { @@ -1829,8 +1829,8 @@ else // Photo print '
'.$langs->trans("Photo").''; - print $form->showphoto('userphoto',$object,100,0,$caneditfield,'photowithmargin','small'); + print ''; + print $form->showphoto('userphoto',$object,60,0,$caneditfield,'photowithmargin','small'); print '
'.$langs->trans("ApiKey").''; - print ''; + print ''; if (! empty($conf->use_javascript_ajax)) print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_api_key" class="linkobject"'); print '
'.$langs->trans("Type").'
'.$langs->trans("Type").''; if ($user->id == $object->id || ! $user->admin) { @@ -2035,7 +2035,7 @@ else // State if (empty($conf->global->USER_DISABLE_STATE)) { - print '
'.fieldLabel('State','state_id').''; + print '
'.fieldLabel('State','state_id').''; print $formcompany->select_state($object->state_id,$object->country_code, 'state_id'); print '
'; if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { @@ -2119,7 +2119,7 @@ else if ($caneditfield) { require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('signature',$object->signature,'',138,'dolibarr_mailings','In',false,true,empty($conf->global->FCKEDITOR_ENABLE_USERSIGN)?0:1,ROWS_4,72); + $doleditor=new DolEditor('signature',$object->signature,'',138,'dolibarr_mailings','In',false,true,empty($conf->global->FCKEDITOR_ENABLE_USERSIGN)?0:1,ROWS_4,'90%'); print $doleditor->Create(1); } else @@ -2135,7 +2135,7 @@ else print ''; if ($caneditfield) { - print ''; + print ''; } else { diff --git a/htdocs/user/class/api_deprecated_user.class.php b/htdocs/user/class/api_deprecated_user.class.php index f080e8a3b45..278ce766878 100644 --- a/htdocs/user/class/api_deprecated_user.class.php +++ b/htdocs/user/class/api_deprecated_user.class.php @@ -191,7 +191,8 @@ class UserApi extends DolibarrApi foreach ($request_data as $field => $value) { - $this->useraccount->$field = $value; + if ($field == 'id') continue; + $this->useraccount->$field = $value; } if ($this->useraccount->update($id, DolibarrApiAccess::$user, 1, '', '', 'update')) diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index e177b4d52ec..db18bea229a 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -214,7 +214,8 @@ class Users extends DolibarrApi foreach ($request_data as $field => $value) { - $this->useraccount->$field = $value; + if ($field == 'id') continue; + $this->useraccount->$field = $value; } if ($this->useraccount->update(DolibarrApiAccess::$user, 1)) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 997933e234b..75af1dae8e3 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1659,38 +1659,48 @@ class User extends CommonObject $outputlangs->load("users"); $outputlangs->load("other"); - $subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword"); + $appli=constant('DOL_APPLICATION_TITLE'); + if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE; + + $subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword", $appli); // Define $urlwithroot //$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); - //$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file - $urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file + //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current if (! $changelater) { + $url = $urlwithroot.'/'; + $mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived").".\n"; $mesg.= $outputlangs->transnoentitiesnoconv("NewKeyIs")." :\n\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n"; $mesg.= "\n"; - $url = $urlwithroot.'/'; - $mesg.= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $conf->global->MAIN_APPLICATION_TITLE).': '.$url."\n\n"; + + $mesg.= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $appli).': '.$url."\n\n"; $mesg.= "--\n"; $mesg.= $user->getFullName($outputlangs); // Username that make then sending + + dol_syslog(get_class($this)."::send_password changelater is off, url=".$url); } else { + $url = $urlwithroot.'/user/passwordforgotten.php?action=validatenewpassword&username='.$this->login."&passwordhash=".dol_hash($password); + $mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived")."\n"; $mesg.= $outputlangs->transnoentitiesnoconv("NewKeyWillBe")." :\n\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n"; $mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n"; $mesg.= "\n"; $mesg.= $outputlangs->transnoentitiesnoconv("YouMustClickToChange")." :\n"; - $url = $urlwithroot.'/user/passwordforgotten.php?action=validatenewpassword&username='.$this->login."&passwordhash=".dol_hash($password); $mesg.= $url."\n\n"; $mesg.= $outputlangs->transnoentitiesnoconv("ForgetIfNothing")."\n\n"; - dol_syslog(get_class($this)."::send_password url=".$url); + + dol_syslog(get_class($this)."::send_password changelater is on, url=".$url); } + $mailfile = new CMailFile( $subject, $this->email, diff --git a/htdocs/user/document.php b/htdocs/user/document.php index 36338f03e10..d1922371909 100644 --- a/htdocs/user/document.php +++ b/htdocs/user/document.php @@ -96,6 +96,7 @@ if ($id > 0 || ! empty($ref)) // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array $hookmanager->initHooks(array('usercard','globalcard')); + /* * Actions */ @@ -108,6 +109,7 @@ if (empty($reshook)) { include_once DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; } + /* * View */ @@ -144,20 +146,21 @@ if ($object->id) } - print ''; + print '
'; // Login - print ''; + print ''; - // Nbre fichiers - print ''; + // Nbre files + print ''; //Total taille - print ''; + print ''; print '
'.$langs->trans("Login").''.$object->login.' 
'.$langs->trans("Login").''.$object->login.' 
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; - print ''; + dol_fiche_end(); + $modulepart = 'user'; $permission = $user->rights->user->user->creer; diff --git a/htdocs/user/group/card.php b/htdocs/user/group/card.php index 541d847a45b..936673b1894 100644 --- a/htdocs/user/group/card.php +++ b/htdocs/user/group/card.php @@ -256,7 +256,7 @@ if ($action == 'create') print "
'.$langs->trans("Description").''; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('note','','',240,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_8,90); + $doleditor=new DolEditor('note','','',240,'dolibarr_notes','',false,true,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_8,'90%'); $doleditor->Create(); print "
'.$langs->trans("Description").''; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('note',$object->note,'',240,'dolibarr_notes','',true,false,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_8,90); + $doleditor=new DolEditor('note',$object->note,'',240,'dolibarr_notes','',true,false,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_8,'90%'); $doleditor->Create(); print '
'; + +print '
'; +print '
'."\n"; + print ''; if (! empty($arrayfields['u.login']['checked'])) print_liste_field_titre($langs->trans("Login"),$_SERVER['PHP_SELF'],"u.login",$param,"","",$sortfield,$sortorder); if (! empty($arrayfields['u.lastname']['checked'])) print_liste_field_titre($langs->trans("Lastname"),$_SERVER['PHP_SELF'],"u.lastname",$param,"","",$sortfield,$sortorder); @@ -655,9 +658,10 @@ $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters); // N print $hookmanager->resPrint; print "
"; +print '
'; print "\n"; -$db->free($result); +$db->free($result); llxFooter(); $db->close(); diff --git a/htdocs/user/note.php b/htdocs/user/note.php index ccd7eb153a4..e2feb378f3c 100644 --- a/htdocs/user/note.php +++ b/htdocs/user/note.php @@ -112,7 +112,7 @@ if ($id) print "id."\">"; // Editeur wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('note_private',$object->note,'',280,'dolibarr_notes','In',true,false,$conf->global->FCKEDITOR_ENABLE_SOCIETE,10,80); + $doleditor=new DolEditor('note_private',$object->note,'',280,'dolibarr_notes','In',true,false,$conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_8,'90%'); $doleditor->Create(); } else diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index 3240ae2d5ec..95c3eb6c87f 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -329,8 +329,8 @@ if ($result) { // On affiche ligne pour modifier droits print ''; - print ''.img_object('',$picto).' '.$objMod->getName(); - print ' '; + print ''.img_object('',$picto).' '.$objMod->getName(); + print ''; print ''; print ''.$langs->trans("All").""; print '/'; @@ -344,7 +344,7 @@ if ($result) print ''; // Picto and label of permission - print ''.img_object('',$picto).' '.$objMod->getName().''; + print ''.img_object('',$picto).' '.$objMod->getName().''; // Permission and tick if (! empty($object->admin) && ! empty($objMod->rights_admin_allowed)) // Permission own because admin @@ -403,7 +403,7 @@ if ($result) } $permlabel=($conf->global->MAIN_USE_ADVANCED_PERMS && ($langs->trans("PermissionAdvanced".$obj->id)!=("PermissionAdvanced".$obj->id))?$langs->trans("PermissionAdvanced".$obj->id):(($langs->trans("Permission".$obj->id)!=("Permission".$obj->id))?$langs->trans("Permission".$obj->id):$langs->trans($obj->libelle))); - print ''.$permlabel. ''; + print ''.$permlabel.''; print ''."\n"; diff --git a/htdocs/viewimage.php b/htdocs/viewimage.php index b6d33de99ae..6fa65660df1 100644 --- a/htdocs/viewimage.php +++ b/htdocs/viewimage.php @@ -36,7 +36,13 @@ if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); if (! defined('NOREQUIREHOOK')) define('NOREQUIREHOOK','1'); // Disable "main.inc.php" hooks // Some value of modulepart can be used to get resources that are public so no login are required. if ((isset($_GET["modulepart"]) && $_GET["modulepart"] == 'companylogo') && ! defined("NOLOGIN")) define("NOLOGIN",'1'); -if ((isset($_GET["modulepart"]) && $_GET["modulepart"] == 'medias') && ! defined("NOLOGIN")) define("NOLOGIN",'1'); +if ((isset($_GET["modulepart"]) && $_GET["modulepart"] == 'medias') && ! defined("NOLOGIN")) +{ + define("NOLOGIN",'1'); + // For multicompany + $entity=(! empty($_GET['entity']) ? (int) $_GET['entity'] : (! empty($_POST['entity']) ? (int) $_POST['entity'] : 1)); + if (is_numeric($entity)) define("DOLENTITY", $entity); +} /** * Header empty diff --git a/htdocs/websites/index.php b/htdocs/websites/index.php index d0aa6424787..69143108e66 100644 --- a/htdocs/websites/index.php +++ b/htdocs/websites/index.php @@ -632,7 +632,7 @@ if (count($object->records) > 0) if ($website && $action == 'preview') { $disabled=''; - if (empty($user->rights->websites->create)) $disabled=' disabled="disabled"'; + if (empty($user->rights->websites->write)) $disabled=' disabled="disabled"'; print '   '; @@ -735,7 +735,7 @@ if (count($object->records) > 0) if ($action == 'preview') { $disabled=''; - if (empty($user->rights->websites->create)) $disabled=' disabled="disabled"'; + if (empty($user->rights->websites->write)) $disabled=' disabled="disabled"'; if ($pageid > 0) { @@ -978,7 +978,7 @@ if ($action == 'editcontent') $contentforedit .= $objectpage->content; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor=new DolEditor('PAGE_CONTENT',$contentforedit,'',500,'Full','',true,true,true,5,60); + $doleditor=new DolEditor('PAGE_CONTENT',$contentforedit,'',500,'Full','',true,true,true,ROWS_5,'90%'); $doleditor->Create(0, '', false); } diff --git a/scripts/cron/cron_run_jobs.php b/scripts/cron/cron_run_jobs.php index e10d089c2a8..d60218fba22 100755 --- a/scripts/cron/cron_run_jobs.php +++ b/scripts/cron/cron_run_jobs.php @@ -82,7 +82,7 @@ if ($key != $conf->global->CRON_KEY) // If param userlogin is reserved word 'firstadmin' if ($userlogin == 'firstadmin') { - $sql='SELECT login from '.MAIN_DB_PREFIX.'user WHERE admin = 1 ORDER BY entity LIMIT 1'; + $sql='SELECT login from '.MAIN_DB_PREFIX.'user WHERE admin = 1 and statut = 1 ORDER BY entity LIMIT 1'; $resql=$db->query($sql); if ($resql) { diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index f967b53d9db..786970e2b3a 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -367,6 +367,14 @@ class FunctionsLibTest extends PHPUnit_Framework_TestCase $after=dol_string_nohtmltag($text, 1); $this->assertEquals("A string with tag with < chars",$after,"test3"); + $text="A string
Another string"; + $after=dol_string_nohtmltag($text,0); + $this->assertEquals("A string\nAnother string",$after,"test4"); + + $text="A string
Another string"; + $after=dol_string_nohtmltag($text,1); + $this->assertEquals("A string Another string",$after,"test5"); + return true; }