diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 432f30f2332..00000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: Bug report -about: Create a report to help us fix something that is broken -title: '' -labels: Bug -assignees: '' - ---- - -# Instructions -*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.* -*Please:* -- *replace the bracket enclosed texts with meaningful information* -- *remove any unused sub-section* - - -# Bug -[*Short description*] - -## Environment -- **Version**: [*Affected Dolibarr version(s)*] -- **OS**: [*Server OS type and version*] -- **Web server**: [*Webserver type and version*] -- **PHP**: [*PHP version*] -- **Database**: [*Database type and version*] -- **URL(s)**: [*Affected URL(s)*] - -## Expected and actual behavior -[*Verbose description*] - -## Steps to reproduce the behavior -[*Verbose description*] - -## [Attached files](https://help.github.com/articles/issue-attachments) (Screenshots, screencasts, dolibarr.log, debugging informations…) -[*Files*] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000000..d7dc3d584e3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,71 @@ +name: Bug report +description: Create a report to help us fix something that is broken +labels: ["Bug"] + +body: + - type: markdown + attributes: + value: | + This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report. + + - type: textarea + id: bug + attributes: + label: Bug + description: Please give a short description of the bug + validations: + required: true + + - type: input + id: environment-version + attributes: + label: Environment Version + description: Affected Dolibarr version(s) + + - type: input + id: environment-os + attributes: + label: Environment OS + description: Server OS type and version + + - type: input + id: environment-webserver + attributes: + label: Environment Web server + description: Webserver type and version + + - type: input + id: environment-php + attributes: + label: Environment PHP + description: PHP version + + - type: input + id: environment-database + attributes: + label: Environment Database + description: Database type and version + + - type: input + id: environment-urls + attributes: + label: Environment URL(s) + description: Affected URL(s) + + - type: textarea + id: expected-behaviour + attributes: + label: Expected and actual behavior + description: Verbose description + + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce the behavior + description: Verbose description + + - type: textarea + id: files + attributes: + label: Attached files + description: Screenshots, screencasts, dolibarr.log, debugging informations diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 32e2deff2c1..00000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: Feature request -about: Suggest a new idea for this project -title: '' -labels: Feature request -assignees: '' - ---- - -# Instructions -*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.* -*Please:* -- *replace the bracket enclosed texts with meaningful information* -- *remove any unused sub-section* - - -# Feature Request -[*Short description*] - -## Use case -[*Verbose description*] - -## Suggested implementation -[*Verbose description*] - -## Suggested steps -[*List of tasks to achieve goal*] diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000000..885f3472d18 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,35 @@ +name: Feature request +description: Suggest a new idea for this project +labels: ["Feature request"] + +body: + - type: markdown + attributes: + value: | + This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report. + + - type: textarea + id: feature-request + attributes: + label: Feature Request + description: Short description + validations: + required: true + + - type: textarea + id: use-case + attributes: + label: Use case + description: Verbose description + + - type: textarea + id: suggested-implementation + attributes: + label: Suggested implementation + description: Verbose description + + - type: textarea + id: suggested-steps + attributes: + label: Suggested steps + description: List of tasks to achieve goal diff --git a/.travis.yml b/.travis.yml index ddeefaab256..5d7eb7a1678 100644 --- a/.travis.yml +++ b/.travis.yml @@ -414,6 +414,9 @@ script: php upgrade.php 14.0.0 15.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade14001500.log php upgrade2.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-2.log php step5.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-3.log + php upgrade.php 15.0.0 16.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade15001600.log + php upgrade2.php 15.0.0 16.0.0 > $TRAVIS_BUILD_DIR/upgrade15001600-2.log + php step5.php 15.0.0 16.0.0 > $TRAVIS_BUILD_DIR/upgrade15001600-3.log ls -alrt $TRAVIS_BUILD_DIR/ - | diff --git a/SECURITY.md b/SECURITY.md index 4e7e5fa933a..cadd4a23791 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -67,7 +67,7 @@ Scope is the web application (back office) and the APIs. * Remote code execution (RCE) * Local files access and manipulation (LFI, RFI, XXE, SSRF, XSPA) * Code injections (HTML, JS, SQL, PHP, ...) -* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose or into module "Web site" when permission to edit website content is allowed). +* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose) and except into module "Web site" when permission to edit website content is allowed (injecting any data in this case is allowed too). * Cross-Site Requests Forgery (CSRF) with real security impact (when using GET URLs, CSRF are qualified only for creating, updating or deleting data from pages restricted to admin users) * Open redirect * Broken authentication & session management diff --git a/build/pad/README b/build/pad/README index 3cbc171686c..241d27d01c2 100644 --- a/build/pad/README +++ b/build/pad/README @@ -1,6 +1,7 @@ README (English) ################################################## Building PAD files +http://pad.asp-software.org/padgen.php ################################################## This directory contains files and docs used to build diff --git a/build/perl/virtualmin/dolibarr.pl b/build/perl/virtualmin/dolibarr.pl index 8b6a9888db0..b5bacf59356 100644 --- a/build/perl/virtualmin/dolibarr.pl +++ b/build/perl/virtualmin/dolibarr.pl @@ -30,7 +30,7 @@ return "Regis Houssin"; # script_dolibarr_versions() sub script_dolibarr_versions { -return ( "12.0.3", "11.0.5", "10.0.7", "9.0.4", "8.0.6", "7.0.5" ); +return ( "14.0.5", "13.0.5", "12.0.5", "11.0.5", "10.0.7", "9.0.4", "8.0.6", "7.0.5" ); } sub script_dolibarr_release @@ -400,6 +400,8 @@ sub script_dolibarr_check_latest { local ($ver) = @_; local @vers = &osdn_package_versions("dolibarr", + $ver >= 14.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" : + $ver >= 13.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" : $ver >= 12.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" : $ver >= 11.0 ? "dolibarr\\-(11\\.0\\.[0-9\\.]+)\\.tgz" : $ver >= 10.0 ? "dolibarr\\-(10\\.0\\.[0-9\\.]+)\\.tgz" : diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index d4a9b725524..204988c5442 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -111,6 +111,10 @@ with // DOL CHANGE If we keep this, the image is not visible on pages after the first one. //var_dump($file.' '.(!@TCPDF_STATIC::file_exists($file))); //return false; + $tfile = str_replace(' ', '%20', $file); + if (@TCPDF_STATIC::file_exists($tfile)) { + $file = $tfile; + } } * Replace in tcpdf.php diff --git a/dev/examples/code/README b/dev/examples/code/README index b7c31558de5..bf3dd3f4969 100644 --- a/dev/examples/code/README +++ b/dev/examples/code/README @@ -5,4 +5,4 @@ This directory contains samples of code to use Dolibarr business classes to buil external interfaces that need to read/update data from/into Dolibarr. You can also have a look at the Dolibarr doxygen doc that describes all files and classes: -http://www.dolibarr.org/html_doxygen/index.html +https://doxygen.dolibarr.org/ diff --git a/dev/examples/zapier/package.json b/dev/examples/zapier/package.json index a9d519dec69..8852928771f 100644 --- a/dev/examples/zapier/package.json +++ b/dev/examples/zapier/package.json @@ -15,7 +15,7 @@ "npm": ">=5.6.0" }, "dependencies": { - "zapier-platform-core": "11.0.1" + "zapier-platform-core": "11.3.1" }, "devDependencies": { "mocha": "^5.2.0", diff --git a/dev/setup/apache/virtualhost b/dev/setup/apache/virtualhost index c3a2dff3e43..8c7682fe3d9 100644 --- a/dev/setup/apache/virtualhost +++ b/dev/setup/apache/virtualhost @@ -1,62 +1,93 @@ -#php_admin_value sendmail_path "/usr/sbin/sendmail -t -i" -#php_admin_value mail.force_extra_parameters "-f postmaster@mydomain.com" -php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f postmaster@mydomain.com" -php_admin_value open_basedir /tmp/:/home/../htdocs + #php_admin_value sendmail_path "/usr/sbin/sendmail -t -i" + #php_admin_value mail.force_extra_parameters "-f postmaster@mydomain.com" + php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f postmaster@mydomain.com" + php_admin_value open_basedir /tmp/:/home/.../htdocs:/home/.../dolibarr_documents: + + ServerName myvirtualalias + ServerAlias myvirtualalias + + UseCanonicalName On + + KeepAlive On + KeepAliveTimeout 5 + MaxKeepAliveRequests 20 + + AddDefaultCharset UTF-8 + + DocumentRoot "/home/.../htdocs" + + + AllowOverride None + Options -Indexes -MultiViews +FollowSymLinks -ExecCGI + Require all granted -ServerName myvirtualalias -ServerAlias myvirtualalias + # To restrict access by a HTTP basic auth + #AuthType Basic + #AuthName "Authenticate to backoffice" + #AuthUserFile /etc/apache2/.htpasswd + #require valid-user + + + # Leaving /public and /api, /dav, .well_known but also wrappers for document and viewimage accessible to everyone + + AuthType None + Require all granted + Satisfy any + + + AuthType None + Require all granted + Satisfy any + + + AuthType None + Require all granted + Satisfy any + + + AuthType None + Require all granted + Satisfy any + + + AuthType None + Require all granted + Satisfy any + -UseCanonicalName On - -AddDefaultCharset UTF-8 - -DocumentRoot "/home/.../htdocs" - - - AllowOverride None - Options -Indexes -MultiViews +FollowSymLinks -ExecCGI - Require all granted - - - - Deny from all - RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml - AddType application/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml - - - -ErrorLog /var/log/apache2/myvirtualalias_error_log -TransferLog /var/log/apache2/myvirtualalias_access_log - -# Compress returned resources of type php pages, text file export, css and javascript -AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript - -AddType text/javascript .jgz -AddEncoding gzip .jgz -ExpiresActive On -ExpiresByType image/x-icon A2592000 -ExpiresByType image/gif A2592000 -ExpiresByType image/png A2592000 -ExpiresByType image/jpeg A2592000 -ExpiresByType text/css A2592000 -ExpiresByType text/javascript A2592000 -ExpiresByType application/x-javascript A2592000 -ExpiresByType application/javascript A2592000 - -SSLEngine On - -# A self-signed (snakeoil) certificate can be created by installing -# the ssl-cert package. See -# /usr/share/doc/apache2.2-common/README.Debian.gz for more info. -# If both key and certificate are stored in the same file, only the -# SSLCertificateFile directive is needed. -SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem -SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem -SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com/chain.pem - -#RewriteEngine on -#RewriteCond %{SERVER_PORT} ^80$ -#RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R] + + ErrorLog /var/log/apache2/myvirtualalias_error_log + TransferLog /var/log/apache2/myvirtualalias_access_log + + # Compress returned resources of type php pages, text file export, css and javascript + AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript + + AddType text/javascript .jgz + AddEncoding gzip .jgz + ExpiresActive On + ExpiresByType image/x-icon A2592000 + ExpiresByType image/gif A2592000 + ExpiresByType image/png A2592000 + ExpiresByType image/jpeg A2592000 + ExpiresByType text/css A2592000 + ExpiresByType text/javascript A2592000 + ExpiresByType application/x-javascript A2592000 + ExpiresByType application/javascript A2592000 + + SSLEngine On + + # A self-signed (snakeoil) certificate can be created by installing + # the ssl-cert package. See + # /usr/share/doc/apache2.2-common/README.Debian.gz for more info. + # If both key and certificate are stored in the same file, only the + # SSLCertificateFile directive is needed. + SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem + SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem + SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com/chain.pem + + #RewriteEngine on + #RewriteCond %{SERVER_PORT} ^80$ + #RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R] diff --git a/htdocs/accountancy/admin/accountmodel.php b/htdocs/accountancy/admin/accountmodel.php index 29c2b7d5510..fd0ff2e72da 100644 --- a/htdocs/accountancy/admin/accountmodel.php +++ b/htdocs/accountancy/admin/accountmodel.php @@ -185,11 +185,6 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $ok = 0; setEventMessages($langs->transnoentities('ErrorCodeCantContainZero'), null, 'errors'); } - /*if (!is_numeric($_POST['code'])) // disabled, code may not be in numeric base - { - $ok = 0; - $msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'
'; - }*/ } if (GETPOSTISSET("country") && (GETPOST("country") == '0') && ($id != 2)) { $ok = 0; @@ -228,17 +223,17 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $i = 0; foreach ($listfieldinsert as $f => $value) { if ($value == 'price' || preg_match('/^amount/i', $value) || $value == 'taux') { - $_POST[$listfieldvalue[$i]] = price2num($_POST[$listfieldvalue[$i]], 'MU'); + $_POST[$listfieldvalue[$i]] = price2num(GETPOST($listfieldvalue[$i]), 'MU'); } elseif ($value == 'entity') { $_POST[$listfieldvalue[$i]] = $conf->entity; } if ($i) { $sql .= ","; } - if ($_POST[$listfieldvalue[$i]] == '') { + if (GETPOST($listfieldvalue[$i]) == '') { $sql .= "null"; } else { - $sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'"; + $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'"; } $i++; } @@ -276,7 +271,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $i = 0; foreach ($listfieldmodify as $field) { if ($field == 'price' || preg_match('/^amount/i', $field) || $field == 'taux') { - $_POST[$listfieldvalue[$i]] = price2num($_POST[$listfieldvalue[$i]], 'MU'); + $_POST[$listfieldvalue[$i]] = price2num(GETPOST($listfieldvalue[$i]), 'MU'); } elseif ($field == 'entity') { $_POST[$listfieldvalue[$i]] = $conf->entity; } @@ -284,10 +279,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $sql .= ","; } $sql .= $field."="; - if ($_POST[$listfieldvalue[$i]] == '') { + if (GETPOST($listfieldvalue[$i]) == '') { $sql .= "null"; } else { - $sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'"; + $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'"; } $i++; } diff --git a/htdocs/accountancy/admin/categories_list.php b/htdocs/accountancy/admin/categories_list.php index bb629577ab6..c0439445261 100644 --- a/htdocs/accountancy/admin/categories_list.php +++ b/htdocs/accountancy/admin/categories_list.php @@ -148,10 +148,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { if ($value == 'formula' && !GETPOST('formula')) { continue; } - if ($value == 'range_account' && empty($_POST['range_account'])) { + if ($value == 'range_account' && !GETPOST('range_account')) { continue; } - if (($value == 'country' || $value == 'country_id') && (!empty($_POST['country_id']))) { + if (($value == 'country' || $value == 'country_id') && GETPOST('country_id')) { continue; } if (!GETPOSTISSET($value) || GETPOST($value) == '') { @@ -195,17 +195,6 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { setEventMessages($langs->transnoentities('ErrorFieldMustBeANumeric', $langs->transnoentities("Position")), null, 'errors'); } - // Clean some parameters - if ($_POST["accountancy_code"] <= 0) { - $_POST["accountancy_code"] = ''; // If empty, we force to null - } - if ($_POST["accountancy_code_sell"] <= 0) { - $_POST["accountancy_code_sell"] = ''; // If empty, we force to null - } - if ($_POST["accountancy_code_buy"] <= 0) { - $_POST["accountancy_code_buy"] = ''; // If empty, we force to null - } - // Si verif ok et action add, on ajoute la ligne if ($ok && GETPOST('actionadd', 'alpha')) { if ($tabrowid[$id]) { @@ -243,7 +232,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { if ($i) { $sql .= ","; } - if ($_POST[$listfieldvalue[$i]] == '' && !$listfieldvalue[$i] == 'formula') { + if (GETPOST($listfieldvalue[$i]) == '' && !$listfieldvalue[$i] == 'formula') { $sql .= "null"; // For vat, we want/accept code = '' } else { $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'"; @@ -283,8 +272,8 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } $i = 0; foreach ($listfieldmodify as $field) { - if ($field == 'fk_country' && $_POST['country'] > 0) { - $_POST[$listfieldvalue[$i]] = $_POST['country']; + if ($field == 'fk_country' && GETPOST('country') > 0) { + $_POST[$listfieldvalue[$i]] = GETPOST('country'); } elseif ($field == 'entity') { $_POST[$listfieldvalue[$i]] = $conf->entity; } @@ -292,10 +281,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $sql .= ","; } $sql .= $field."="; - if ($_POST[$listfieldvalue[$i]] == '' && !$listfieldvalue[$i] == 'range_account') { + if (GETPOST($listfieldvalue[$i]) == '' && !$listfieldvalue[$i] == 'range_account') { $sql .= "null"; // For range_account, we want/accept code = '' } else { - $sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'"; + $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'"; } $i++; } diff --git a/htdocs/accountancy/bookkeeping/balance.php b/htdocs/accountancy/bookkeeping/balance.php index 0b67327b11c..3c2e8763fe1 100644 --- a/htdocs/accountancy/bookkeeping/balance.php +++ b/htdocs/accountancy/bookkeeping/balance.php @@ -237,7 +237,7 @@ if ($action != 'export_csv') { print ''; $parameters = array(); - $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + $reshook = $hookmanager->executeHooks('addMoreActionsButtonsList', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $button = 'global->ACCOUNTING_EXPORT_FORMAT.')" />'; diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 8a66acee0d9..5b645796a32 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -663,7 +663,7 @@ if ($action == 'create') { // Also, it is not possible to use a value that is not in the list. // Also, the label is not automatically filled when a value is selected. if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { - print $formaccounting->select_auxaccount((GETPOSTISSET("subledger_account") ? GETPOST("subledger_account", "alpha") : $line->subledger_account), 'subledger_account', 1); + print $formaccounting->select_auxaccount((GETPOSTISSET("subledger_account") ? GETPOST("subledger_account", "alpha") : $line->subledger_account), 'subledger_account', 1, 'maxwidth250', '', 'subledger_label'); } else { print 'subledger_account).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccount")).'">'; } @@ -746,7 +746,7 @@ if ($action == 'create') { // Also, it is not possible to use a value that is not in the list. // Also, the label is not automatically filled when a value is selected. if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { - print $formaccounting->select_auxaccount('', 'subledger_account', 1); + print $formaccounting->select_auxaccount('', 'subledger_account', 1, 'maxwidth250', '', 'subledger_label'); } else { print ''; } diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index b67b134e3e1..67f521806cb 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -769,7 +769,7 @@ if (count($filter)) { } $parameters = array(); -$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('addMoreActionsButtonsList', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { // Button re-export if (!empty($conf->global->ACCOUNTING_REEXPORT)) { diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index d73f4228f97..837a372a32d 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -473,7 +473,7 @@ print ''; print ''; $parameters = array(); -$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('addMoreActionsButtonsList', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param); $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); diff --git a/htdocs/accountancy/bookkeeping/listbysubaccount.php b/htdocs/accountancy/bookkeeping/listbysubaccount.php index e529126d8ce..c6fb95d5ab7 100644 --- a/htdocs/accountancy/bookkeeping/listbysubaccount.php +++ b/htdocs/accountancy/bookkeeping/listbysubaccount.php @@ -473,7 +473,7 @@ print ''; print ''; $parameters = array(); -$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('addMoreActionsButtonsList', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param); $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly')); diff --git a/htdocs/accountancy/class/accountingaccount.class.php b/htdocs/accountancy/class/accountingaccount.class.php index a4dcac8c1ad..ac943180b58 100644 --- a/htdocs/accountancy/class/accountingaccount.class.php +++ b/htdocs/accountancy/class/accountingaccount.class.php @@ -476,7 +476,7 @@ class AccountingAccount extends CommonObject */ public function getNomUrl($withpicto = 0, $withlabel = 0, $nourl = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1, $withcompletelabel = 0, $option = '') { - global $langs, $conf; + global $langs, $conf, $hookmanager; require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; if (!empty($conf->dol_no_mouse_hover)) { @@ -561,6 +561,15 @@ class AccountingAccount extends CommonObject if ($withpicto != 2) { $result .= $linkstart . $label_link . $linkend; } + global $action; + $hookmanager->initHooks(array($this->element . 'dao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } diff --git a/htdocs/accountancy/class/accountingjournal.class.php b/htdocs/accountancy/class/accountingjournal.class.php index 376178b45ba..d805838566f 100644 --- a/htdocs/accountancy/class/accountingjournal.class.php +++ b/htdocs/accountancy/class/accountingjournal.class.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017-2022 OpenDSI * * 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 @@ -81,6 +81,24 @@ class AccountingJournal extends CommonObject */ public $lines; + /** + * @var array Accounting account cached + */ + static public $accounting_account_cached = array(); + + /** + * @var array Nature mapping + */ + static public $nature_maps = array( + 1 => 'variousoperations', + 2 => 'sells', + 3 => 'purchases', + 4 => 'bank', + 5 => 'expensereports', + 8 => 'inventories', + 9 => 'hasnew', + ); + /** * Constructor * @@ -221,7 +239,7 @@ class AccountingJournal extends CommonObject */ public function getNomUrl($withpicto = 0, $withlabel = 0, $nourl = 0, $moretitle = '', $notooltip = 0) { - global $langs, $conf, $user; + global $langs, $conf, $user, $hookmanager; if (!empty($conf->dol_no_mouse_hover)) { $notooltip = 1; // Force disable tooltips @@ -276,6 +294,15 @@ class AccountingJournal extends CommonObject } $result .= $linkend; + global $action; + $hookmanager->initHooks(array('accountingjournaldao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } @@ -336,4 +363,680 @@ class AccountingJournal extends CommonObject } } } + + + /** + * Get journal data + * + * @param User $user User who get infos + * @param string $type Type data returned ('view', 'bookkeeping', 'csv') + * @param int $date_start Filter 'start date' + * @param int $date_end Filter 'end date' + * @param string $in_bookkeeping Filter 'in bookkeeping' ('already', 'notyet') + * @return array|int <0 if KO, >0 if OK + */ + public function getData(User $user, $type = 'view', $date_start = null, $date_end = null, $in_bookkeeping = 'notyet') + { + global $hookmanager; + + // Clean parameters + if (empty($type)) $type = 'view'; + if (empty($in_bookkeeping)) $in_bookkeeping = 'notyet'; + + // Hook + if (!is_object($hookmanager)) { + include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $data = array(); + + $hookmanager->initHooks(array('accountingjournaldao')); + $parameters = array('data' => &$data, 'user' => $user, 'type' => $type, 'date_start' => $date_start, 'date_end' => $date_end, 'in_bookkeeping' => $in_bookkeeping); + $reshook = $hookmanager->executeHooks('getData', $parameters, $this); // Note that $action and $object may have been + if ($reshook < 0) { + $this->error = $hookmanager->error; + $this->errors = $hookmanager->errors; + return -1; + } elseif (empty($reshook)) { + switch ($this->nature) { + case 1: // Various Journal + $data = $this->getAssetData($user, $type, $date_start, $date_end, $in_bookkeeping); + break; + // case 2: // Sells Journal + // case 3: // Purchases Journal + // case 4: // Bank Journal + // case 5: // Expense reports Journal + // case 8: // Inventory Journal + // case 9: // hasnew Journal + } + } + + return $data; + } + + /** + * Get asset data for various journal + * + * @param User $user User who get infos + * @param string $type Type data returned ('view', 'bookkeeping', 'csv') + * @param int $date_start Filter 'start date' + * @param int $date_end Filter 'end date' + * @param string $in_bookkeeping Filter 'in bookkeeping' ('already', 'notyet') + * @return array|int <0 if KO, >0 if OK + */ + public function getAssetData(User $user, $type = 'view', $date_start = null, $date_end = null, $in_bookkeeping = 'notyet') + { + global $conf, $langs; + + if (empty($conf->asset->enabled)) { + return array(); + } + + require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; + require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php'; + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php'; + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php'; + + $langs->loadLangs(array("assets")); + + // Clean parameters + if (empty($type)) $type = 'view'; + if (empty($in_bookkeeping)) $in_bookkeeping = 'notyet'; + + $sql = ""; + if ($in_bookkeeping == 'already' || $in_bookkeeping == 'notyet') { + $sql .= "WITH in_accounting_bookkeeping(fk_docdet) AS ("; + $sql .= " SELECT DISTINCT fk_docdet"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping"; + $sql .= " WHERE doc_type = 'asset'"; + $sql .= ")"; + } + $sql .= "SELECT ad.fk_asset AS rowid, a.ref AS asset_ref, a.label AS asset_label, a.acquisition_value_ht AS asset_acquisition_value_ht"; + $sql .= ", a.disposal_date AS asset_disposal_date, a.disposal_amount_ht AS asset_disposal_amount_ht, a.disposal_subject_to_vat AS asset_disposal_subject_to_vat"; + $sql .= ", ad.rowid AS depreciation_id, ad.depreciation_mode, ad.ref AS depreciation_ref, ad.depreciation_date, ad.depreciation_ht, ad.accountancy_code_debit, ad.accountancy_code_credit"; + $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation as ad"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "asset as a ON a.rowid = ad.fk_asset"; + if ($in_bookkeeping == 'already' || $in_bookkeeping == 'notyet') { + $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid"; + } + $sql .= " WHERE a.entity IN (" . getEntity('asset', 0) . ')'; // We don't share object for accountancy, we use source object sharing + $sql .= " AND ad.ref != ''"; // not reversal lines + if ($date_start && $date_end) { + $sql .= " AND ad.depreciation_date >= '" . $this->db->idate($date_start) . "' AND ad.depreciation_date <= '" . $this->db->idate($date_end) . "'"; + } + // Define begin binding date + if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND ad.depreciation_date >= '" . $this->db->idate($conf->global->ACCOUNTING_DATE_START_BINDING) . "'"; + } + // Already in bookkeeping or not + if ($in_bookkeeping == 'already' || $in_bookkeeping == 'notyet') { + $sql .= " AND iab.fk_docdet IS" . ($in_bookkeeping == 'already' ? " NOT" : "") . " NULL"; + } + $sql .= " ORDER BY ad.depreciation_date"; + + dol_syslog(__METHOD__, LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $this->db->lasterror(); + return -1; + } + + $pre_data = array( + 'elements' => array(), + ); + while ($obj = $this->db->fetch_object($resql)) { + if (!isset($pre_data['elements'][$obj->rowid])) { + $pre_data['elements'][$obj->rowid] = array( + 'ref' => $obj->asset_ref, + 'label' => $obj->asset_label, + 'acquisition_value_ht' => $obj->asset_acquisition_value_ht, + 'depreciation' => array(), + ); + + // Disposal infos + if (isset($obj->asset_disposal_date)) { + $pre_data['elements'][$obj->rowid]['disposal'] = array( + 'date' => $this->db->jdate($obj->asset_disposal_date), + 'amount' => $obj->asset_disposal_amount_ht, + 'subject_to_vat' => !empty($obj->asset_disposal_subject_to_vat), + ); + } + } + + $compta_debit = empty($obj->accountancy_code_debit) ? 'NotDefined' : $obj->accountancy_code_debit; + $compta_credit = empty($obj->accountancy_code_credit) ? 'NotDefined' : $obj->accountancy_code_credit; + + $pre_data['elements'][$obj->rowid]['depreciation'][$obj->depreciation_id] = array( + 'date' => $this->db->jdate($obj->depreciation_date), + 'ref' => $obj->depreciation_ref, + 'lines' => array( + $compta_debit => -$obj->depreciation_ht, + $compta_credit => $obj->depreciation_ht, + ), + ); + } + + $disposal_ref = $langs->transnoentitiesnoconv('AssetDisposal'); + $journal = $this->code; + $journal_label = $this->label; + $journal_label_formatted = $langs->transnoentities($journal_label); + $now = dol_now(); + + $element_static = new Asset($this->db); + + $journal_data = array(); + foreach ($pre_data['elements'] as $pre_data_id => $pre_data_info) { + $element_static->id = $pre_data_id; + $element_static->ref = (string) $pre_data_info["ref"]; + $element_static->label = (string) $pre_data_info["label"]; + $element_static->acquisition_value_ht = $pre_data_info["acquisition_value_ht"]; + $element_link = $element_static->getNomUrl(1, 'with_label'); + + $element_name_formatted_0 = dol_trunc($element_static->label, 16); + $element_name_formatted_1 = utf8_decode(dol_trunc($element_static->label, 32)); + $element_name_formatted_2 = utf8_decode(dol_trunc($element_static->label, 16)); + $label_operation = $element_static->getNomUrl(0, 'label', 16); + + $element = array( + 'ref' => dol_trunc($element_static->ref, 16, 'right', 'UTF-8', 1), + 'error' => $pre_data_info['error'], + 'blocks' => array(), + ); + + // Depreciation lines + //-------------------- + foreach ($pre_data_info['depreciation'] as $depreciation_id => $line) { + $depreciation_ref = $line["ref"]; + $depreciation_date = $line["date"]; + $depreciation_date_formatted = dol_print_date($depreciation_date, 'day'); + + // lines + $blocks = array(); + foreach ($line['lines'] as $account => $mt) { + $account_infos = $this->getAccountingAccountInfos($account); + + if ($type == 'view') { + $account_to_show = length_accounta($account); + if (($account_to_show == "") || $account_to_show == 'NotDefined') { + $account_to_show = '' . $langs->trans("AssetInAccountNotDefined") . ''; + } + + $blocks[] = array( + 'date' => $depreciation_date_formatted, + 'piece' => $element_link, + 'account_accounting' => $account_to_show, + 'subledger_account' => '', + 'label_operation' => $label_operation . ' - ' . $depreciation_ref, + 'debit' => $mt < 0 ? price(-$mt) : '', + 'credit' => $mt >= 0 ? price($mt) : '', + ); + } elseif ($type == 'bookkeeping') { + if ($account_infos['found']) { + $blocks[] = array( + 'doc_date' => $depreciation_date, + 'date_lim_reglement' => '', + 'doc_ref' => $element_static->ref, + 'date_creation' => $now, + 'doc_type' => 'asset', + 'fk_doc' => $element_static->id, + 'fk_docdet' => $depreciation_id, // Useless, can be several lines that are source of this record to add + 'thirdparty_code' => '', + 'subledger_account' => '', + 'subledger_label' => '', + 'numero_compte' => $account, + 'label_compte' => $account_infos['label'], + 'label_operation' => $element_name_formatted_0 . ' - ' . $depreciation_ref, + 'montant' => $mt, + 'sens' => $mt < 0 ? 'D' : 'C', + 'debit' => $mt < 0 ? -$mt : 0, + 'credit' => $mt >= 0 ? $mt : 0, + 'code_journal' => $journal, + 'journal_label' => $journal_label_formatted, + 'piece_num' => '', + 'import_key' => '', + 'fk_user_author' => $user->id, + 'entity' => $conf->entity, + ); + } + } else { // $type == 'csv' + $blocks[] = array( + $depreciation_date, // Date + $element_static->ref, // Piece + $account_infos['code_formatted_1'], // AccountAccounting + $element_name_formatted_0 . ' - ' . $depreciation_ref, // LabelOperation + $mt < 0 ? price(-$mt) : '', // Debit + $mt >= 0 ? price($mt) : '', // Credit + ); + } + } + $element['blocks'][] = $blocks; + } + + // Disposal line + //-------------------- + if (!empty($pre_data_info['disposal'])) { + $disposal_date = $pre_data_info['disposal']['date']; + + if ((!($date_start && $date_end) || ($date_start <= $disposal_date && $disposal_date <= $date_end)) && + (empty($conf->global->ACCOUNTING_DATE_START_BINDING) || $conf->global->ACCOUNTING_DATE_START_BINDING <= $disposal_date) + ) { + $disposal_amount = $pre_data_info['disposal']['amount']; + $disposal_subject_to_vat = $pre_data_info['disposal']['subject_to_vat']; + $disposal_date_formatted = dol_print_date($disposal_date, 'day'); + $disposal_vat = $conf->global->ASSET_DISPOSAL_VAT > 0 ? $conf->global->ASSET_DISPOSAL_VAT : 20; + + // Get accountancy codes + //--------------------------- + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php'; + $accountancy_codes = new AssetAccountancyCodes($this->db); + $result = $accountancy_codes->fetchAccountancyCodes($element_static->id); + if ($result < 0) { + $element['error'] = $accountancy_codes->errorsToString(); + } else { + // Get last depreciation cumulative amount + $element_static->fetchDepreciationLines(); + foreach ($element_static->depreciation_lines as $mode_key => $depreciation_lines) { + $accountancy_codes_list = $accountancy_codes->accountancy_codes[$mode_key]; + + if (!isset($accountancy_codes_list['value_asset_sold'])) { + continue; + } + + $accountancy_code_value_asset_sold = empty($accountancy_codes_list['value_asset_sold']) ? 'NotDefined' : $accountancy_codes_list['value_asset_sold']; + $accountancy_code_depreciation_asset = empty($accountancy_codes_list['depreciation_asset']) ? 'NotDefined' : $accountancy_codes_list['depreciation_asset']; + $accountancy_code_asset = empty($accountancy_codes_list['asset']) ? 'NotDefined' : $accountancy_codes_list['asset']; + $accountancy_code_receivable_on_assignment = empty($accountancy_codes_list['receivable_on_assignment']) ? 'NotDefined' : $accountancy_codes_list['receivable_on_assignment']; + $accountancy_code_vat_collected = empty($accountancy_codes_list['vat_collected']) ? 'NotDefined' : $accountancy_codes_list['vat_collected']; + $accountancy_code_proceeds_from_sales = empty($accountancy_codes_list['proceeds_from_sales']) ? 'NotDefined' : $accountancy_codes_list['proceeds_from_sales']; + + $last_cumulative_amount_ht = 0; + $depreciated_ids = array_keys($pre_data_info['depreciation']); + foreach ($depreciation_lines as $line) { + $last_cumulative_amount_ht = $line['cumulative_depreciation_ht']; + if (!in_array($line['id'], $depreciated_ids) && empty($line['bookkeeping']) && !empty($line['ref'])) { + break; + } + } + + $lines = array(); + $lines[0][$accountancy_code_value_asset_sold] = -($element_static->acquisition_value_ht - $last_cumulative_amount_ht); + $lines[0][$accountancy_code_depreciation_asset] = -$last_cumulative_amount_ht; + $lines[0][$accountancy_code_asset] = $element_static->acquisition_value_ht; + + $disposal_amount_vat = $disposal_subject_to_vat ? (double) price2num($disposal_amount * $disposal_vat / 100, 'MT') : 0; + $lines[1][$accountancy_code_receivable_on_assignment] = -($disposal_amount + $disposal_amount_vat); + if ($disposal_subject_to_vat) $lines[1][$accountancy_code_vat_collected] = $disposal_amount_vat; + $lines[1][$accountancy_code_proceeds_from_sales] = $disposal_amount; + + foreach ($lines as $lines_block) { + $blocks = array(); + foreach ($lines_block as $account => $mt) { + $account_infos = $this->getAccountingAccountInfos($account); + + if ($type == 'view') { + $account_to_show = length_accounta($account); + if (($account_to_show == "") || $account_to_show == 'NotDefined') { + $account_to_show = '' . $langs->trans("AssetInAccountNotDefined") . ''; + } + + $blocks[] = array( + 'date' => $disposal_date_formatted, + 'piece' => $element_link, + 'account_accounting' => $account_to_show, + 'subledger_account' => '', + 'label_operation' => $label_operation . ' - ' . $disposal_ref, + 'debit' => $mt < 0 ? price(-$mt) : '', + 'credit' => $mt >= 0 ? price($mt) : '', + ); + } elseif ($type == 'bookkeeping') { + if ($account_infos['found']) { + $blocks[] = array( + 'doc_date' => $disposal_date, + 'date_lim_reglement' => '', + 'doc_ref' => $element_static->ref, + 'date_creation' => $now, + 'doc_type' => 'asset', + 'fk_doc' => $element_static->id, + 'fk_docdet' => 0, // Useless, can be several lines that are source of this record to add + 'thirdparty_code' => '', + 'subledger_account' => '', + 'subledger_label' => '', + 'numero_compte' => $account, + 'label_compte' => $account_infos['label'], + 'label_operation' => $element_name_formatted_0 . ' - ' . $disposal_ref, + 'montant' => $mt, + 'sens' => $mt < 0 ? 'D' : 'C', + 'debit' => $mt < 0 ? -$mt : 0, + 'credit' => $mt >= 0 ? $mt : 0, + 'code_journal' => $journal, + 'journal_label' => $journal_label_formatted, + 'piece_num' => '', + 'import_key' => '', + 'fk_user_author' => $user->id, + 'entity' => $conf->entity, + ); + } + } else { // $type == 'csv' + $blocks[] = array( + $disposal_date, // Date + $element_static->ref, // Piece + $account_infos['code_formatted_1'], // AccountAccounting + $element_name_formatted_0 . ' - ' . $disposal_ref, // LabelOperation + $mt < 0 ? price(-$mt) : '', // Debit + $mt >= 0 ? price($mt) : '', // Credit + ); + } + } + $element['blocks'][] = $blocks; + } + } + } + } + } + + $journal_data[$pre_data_id] = $element; + } + unset($pre_data); + + return $journal_data; + } + + /** + * Write bookkeeping + * + * @param User $user User who write in the bookkeeping + * @param array $journal_data Journal data to write in the bookkeeping + * $journal_data = array( + * id_element => array( + * 'ref' => 'ref', + * 'error' => '', + * 'blocks' => array( + * pos_block => array( + * num_line => array( + * 'doc_date' => '', + * 'date_lim_reglement' => '', + * 'doc_ref' => '', + * 'date_creation' => '', + * 'doc_type' => '', + * 'fk_doc' => '', + * 'fk_docdet' => '', + * 'thirdparty_code' => '', + * 'subledger_account' => '', + * 'subledger_label' => '', + * 'numero_compte' => '', + * 'label_compte' => '', + * 'label_operation' => '', + * 'montant' => '', + * 'sens' => '', + * 'debit' => '', + * 'credit' => '', + * 'code_journal' => '', + * 'journal_label' => '', + * 'piece_num' => '', + * 'import_key' => '', + * 'fk_user_author' => '', + * 'entity' => '', + * ), + * ), + * ), + * ), + * ); + * @param int $max_nb_errors Nb error authorized before stop the process + * @return int <0 if KO, >0 if OK + */ + public function writeIntoBookkeeping(User $user, &$journal_data = array(), $max_nb_errors = 10) + { + global $conf, $langs, $hookmanager; + require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeeping.class.php'; + + // Hook + if (!is_object($hookmanager)) { + include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $error = 0; + + $hookmanager->initHooks(array('accountingjournaldao')); + $parameters = array('journal_data' => &$journal_data); + $reshook = $hookmanager->executeHooks('writeBookkeeping', $parameters, $this); // Note that $action and $object may have been + if ($reshook < 0) { + $this->error = $hookmanager->error; + $this->errors = $hookmanager->errors; + return -1; + } elseif (empty($reshook)) { + // Clean parameters + $journal_data = is_array($journal_data) ? $journal_data : array(); + + foreach ($journal_data as $element_id => $element) { + $error_for_line = 0; + $total_credit = 0; + $total_debit = 0; + + $this->db->begin(); + + if ($element['error'] == 'somelinesarenotbound') { + $error++; + $error_for_line++; + $this->errors[] = $langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $element['ref']); + } + + if (!$error_for_line) { + foreach ($element['blocks'] as $lines) { + foreach ($lines as $line) { + $bookkeeping = new BookKeeping($this->db); + $bookkeeping->doc_date = $line['doc_date']; + $bookkeeping->date_lim_reglement = $line['date_lim_reglement']; + $bookkeeping->doc_ref = $line['doc_ref']; + $bookkeeping->date_creation = $line['date_creation']; // not used + $bookkeeping->doc_type = $line['doc_type']; + $bookkeeping->fk_doc = $line['fk_doc']; + $bookkeeping->fk_docdet = $line['fk_docdet']; + $bookkeeping->thirdparty_code = $line['thirdparty_code']; + $bookkeeping->subledger_account = $line['subledger_account']; + $bookkeeping->subledger_label = $line['subledger_label']; + $bookkeeping->numero_compte = $line['numero_compte']; + $bookkeeping->label_compte = $line['label_compte']; + $bookkeeping->label_operation = $line['label_operation']; + $bookkeeping->montant = $line['montant']; + $bookkeeping->sens = $line['sens']; + $bookkeeping->debit = $line['debit']; + $bookkeeping->credit = $line['credit']; + $bookkeeping->code_journal = $line['code_journal']; + $bookkeeping->journal_label = $line['journal_label']; + $bookkeeping->piece_num = $line['piece_num']; + $bookkeeping->import_key = $line['import_key']; + $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; + + $total_debit += $bookkeeping->debit; + $total_credit += $bookkeeping->credit; + + $result = $bookkeeping->create($user); + if ($result < 0) { + if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists + $error++; + $error_for_line++; + $journal_data[$element_id]['error'] = 'alreadyjournalized'; + } else { + $error++; + $error_for_line++; + $journal_data[$element_id]['error'] = 'other'; + $this->errors[] = $bookkeeping->errorsToString(); + } + } + // + // if (!$error_for_line && !empty($conf->asset->enabled) && $this->nature == 1 && $bookkeeping->fk_doc > 0) { + // // Set last cumulative depreciation + // require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php'; + // $asset = new Asset($this->db); + // $result = $asset->setLastCumulativeDepreciation($bookkeeping->fk_doc); + // if ($result < 0) { + // $error++; + // $error_for_line++; + // $journal_data[$element_id]['error'] = 'other'; + // $this->errors[] = $asset->errorsToString(); + // } + // } + } + + if ($error_for_line) { + break; + } + } + } + + // Protection against a bug on lines before + if (!$error_for_line && (price2num($total_debit, 'MT') != price2num($total_credit, 'MT'))) { + $error++; + $error_for_line++; + $journal_data[$element_id]['error'] = 'amountsnotbalanced'; + $this->errors[] = 'Try to insert a non balanced transaction in book for ' . $element['blocks'] . '. Canceled. Surely a bug.'; + } + + if (!$error_for_line) { + $this->db->commit(); + } else { + $this->db->rollback(); + + if ($error >= $max_nb_errors) { + $this->errors[] = $langs->trans("ErrorTooManyErrorsProcessStopped"); + break; // Break in the foreach + } + } + } + } + + return $error ? -$error : 1; + } + + /** + * Export journal CSV + * ISO and not UTF8 ! + * + * @param array $journal_data Journal data to write in the bookkeeping + * $journal_data = array( + * id_element => array( + * 'continue' => false, + * 'blocks' => array( + * pos_block => array( + * num_line => array( + * data to write in the CSV line + * ), + * ), + * ), + * ), + * ); + * @param int $search_date_end Search date end + * @param string $sep CSV separator + * @return int|string <0 if KO, >0 if OK + */ + public function exportCsv(&$journal_data = array(), $search_date_end = 0, $sep = '') + { + global $conf, $langs, $hookmanager; + + if (empty($sep)) $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV; + $out = ''; + + // Hook + if (!is_object($hookmanager)) { + include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $hookmanager->initHooks(array('accountingjournaldao')); + $parameters = array('journal_data' => &$journal_data, 'search_date_end' => &$search_date_end, 'sep' => &$sep, 'out' => &$out); + $reshook = $hookmanager->executeHooks('exportCsv', $parameters, $this); // Note that $action and $object may have been + if ($reshook < 0) { + $this->error = $hookmanager->error; + $this->errors = $hookmanager->errors; + return -1; + } elseif (empty($reshook)) { + // Clean parameters + $journal_data = is_array($journal_data) ? $journal_data : array(); + + // CSV header line + $header = array(); + if ($this->nature == 4) { + $header = array( + $langs->transnoentitiesnoconv("BankId"), + $langs->transnoentitiesnoconv("Date"), + $langs->transnoentitiesnoconv("PaymentMode"), + $langs->transnoentitiesnoconv("AccountAccounting"), + $langs->transnoentitiesnoconv("LedgerAccount"), + $langs->transnoentitiesnoconv("SubledgerAccount"), + $langs->transnoentitiesnoconv("Label"), + $langs->transnoentitiesnoconv("Debit"), + $langs->transnoentitiesnoconv("Credit"), + $langs->transnoentitiesnoconv("Journal"), + $langs->transnoentitiesnoconv("Note"), + ); + } elseif ($this->nature == 5) { + $header = array( + $langs->transnoentitiesnoconv("Date"), + $langs->transnoentitiesnoconv("Piece"), + $langs->transnoentitiesnoconv("AccountAccounting"), + $langs->transnoentitiesnoconv("LabelOperation"), + $langs->transnoentitiesnoconv("Debit"), + $langs->transnoentitiesnoconv("Credit"), + ); + } elseif ($this->nature == 1) { + $header = array( + $langs->transnoentitiesnoconv("Date"), + $langs->transnoentitiesnoconv("Piece"), + $langs->transnoentitiesnoconv("AccountAccounting"), + $langs->transnoentitiesnoconv("LabelOperation"), + $langs->transnoentitiesnoconv("Debit"), + $langs->transnoentitiesnoconv("Credit"), + ); + } + + if (!empty($header)) $out .= '"' . implode('"' . $sep . '"', $header) . '"' . "\n"; + foreach ($journal_data as $element_id => $element) { + foreach ($element['blocks'] as $lines) { + foreach ($lines as $line) { + $out .= '"' . implode('"' . $sep . '"', $line) . '"' . "\n"; + } + } + } + } + + return $out; + } + + /** + * Get accounting account infos + * + * @param string $account Accounting account number + * @return array Accounting account infos + */ + public function getAccountingAccountInfos($account) + { + if (!isset(self::$accounting_account_cached[$account])) { + require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; + require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php'; + $accountingaccount = new AccountingAccount($this->db); + $result = $accountingaccount->fetch(null, $account, true); + if ($result > 0) { + self::$accounting_account_cached[$account] = array( + 'found' => true, + 'label' => $accountingaccount->label, + 'code_formatted_1' => length_accounta(html_entity_decode($account)), + 'label_formatted_1' => utf8_decode(dol_trunc($accountingaccount->label, 32)), + 'label_formatted_2' => dol_trunc($accountingaccount->label, 32), + ); + } else { + self::$accounting_account_cached[$account] = array( + 'found' => false, + 'label' => '', + 'code_formatted_1' => length_accounta(html_entity_decode($account)), + 'label_formatted_1' => '', + 'label_formatted_2' => '', + ); + } + } + + return self::$accounting_account_cached[$account]; + } } diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 507292d777a..a83a311010d 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -460,7 +460,7 @@ class BookKeeping extends CommonObject { global $db, $conf, $langs; global $dolibarr_main_authentication, $dolibarr_main_demo; - global $menumanager; + global $menumanager, $hookmanager; if (!empty($conf->dol_no_mouse_hover)) { $notooltip = 1; // Force disable tooltips @@ -512,6 +512,15 @@ class BookKeeping extends CommonObject $result .= $linkend; //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + global $action; + $hookmanager->initHooks(array($this->element . 'dao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } diff --git a/htdocs/accountancy/expensereport/lines.php b/htdocs/accountancy/expensereport/lines.php index fb3bf1a6e04..ff7b9295693 100644 --- a/htdocs/accountancy/expensereport/lines.php +++ b/htdocs/accountancy/expensereport/lines.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2017 Alexandre Spangaro + * Copyright (C) 2013-2022 Alexandre Spangaro * Copyright (C) 2014-2015 Ari Elbaz (elarifr) * Copyright (C) 2013-2016 Florian Henry * Copyright (C) 2014 Juanjo Menent @@ -26,8 +26,8 @@ */ require '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; @@ -49,9 +49,14 @@ $search_desc = GETPOST('search_desc', 'alpha'); $search_amount = GETPOST('search_amount', 'alpha'); $search_account = GETPOST('search_account', 'alpha'); $search_vat = GETPOST('search_vat', 'alpha'); -$search_day = GETPOST("search_day", "int"); -$search_month = GETPOST("search_month", "int"); -$search_year = GETPOST("search_year", "int"); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); @@ -61,9 +66,9 @@ $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("pa if (empty($page) || $page < 0) { $page = 0; } +$offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; -$offset = $limit * $page; if (!$sortfield) { $sortfield = "erd.date, erd.rowid"; } @@ -101,9 +106,14 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_amount = ''; $search_account = ''; $search_vat = ''; - $search_day = ''; - $search_month = ''; - $search_year = ''; + $search_date_startday = ''; + $search_date_startmonth = ''; + $search_date_startyear = ''; + $search_date_endday = ''; + $search_date_endmonth = ''; + $search_date_endyear = ''; + $search_date_start = ''; + $search_date_end = ''; } if (is_array($changeaccount) && count($changeaccount) > 0 && $user->rights->accounting->bind->write) { @@ -204,7 +214,12 @@ if (strlen(trim($search_account))) { if (strlen(trim($search_vat))) { $sql .= natural_search("erd.tva_tx", price2num($search_vat), 1); } -$sql .= dolSqlDateFilter('erd.date', $search_day, $search_month, $search_year); +if ($search_date_start) { + $sql .= " AND erd.date >= '".$db->idate($search_date_start)."'"; +} +if ($search_date_end) { + $sql .= " AND erd.date <= '".$db->idate($search_date_end)."'"; +} $sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy $sql .= $db->order($sortfield, $sortorder); @@ -222,9 +237,8 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { $sql .= $db->plimit($limit + 1, $offset); -dol_syslog('accountancy/expensereport/lines.php::list'); +dol_syslog("accountancy/expensereport/lines.php", LOG_DEBUG); $result = $db->query($sql); - if ($result) { $num_lines = $db->num_rows($result); $i = 0; @@ -254,14 +268,23 @@ if ($result) { if ($search_vat) { $param .= "&search_vat=".urlencode($search_vat); } - if ($search_day) { - $param .= '&search_day='.urlencode($search_day); + if ($search_date_startday) { + $param .= '&search_date_startday='.urlencode($search_date_startday); } - if ($search_month) { - $param .= '&search_month='.urlencode($search_month); + if ($search_date_startmonth) { + $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); } - if ($search_year) { - $param .= '&search_year='.urlencode($search_year); + if ($search_date_startyear) { + $param .= '&search_date_startyear='.urlencode($search_date_startyear); + } + if ($search_date_endday) { + $param .= '&search_date_endday='.urlencode($search_date_endday); + } + if ($search_date_endmonth) { + $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); + } + if ($search_date_endyear) { + $param .= '&search_date_endyear='.urlencode($search_date_endyear); } print '
'."\n"; @@ -276,12 +299,11 @@ if ($result) { print ''; print_barre_liste($langs->trans("ExpenseReportLinesDone"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num_lines, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit); - print ''.$langs->trans("DescVentilDoneExpenseReport").'
'; - print '
'.$langs->trans("ChangeAccount").'
'; + print '
'.$langs->trans("ChangeAccount").' '; print $formaccounting->select_account($account_parent, 'account_parent', 2, array(), 0, 0, 'maxwidth300 maxwidthonsmartphone valignmiddle'); - print '
'; + print '
'; $moreforfilter = ''; @@ -296,11 +318,12 @@ if ($result) { print ''; } print ''; - if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) { - print ''; - } - print ''; - $formother->select_year($search_year, 'search_year', 1, 20, 5); + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; print ''; print ''; print ''; @@ -394,12 +417,11 @@ if ($result) { print ''.vatrate($objp->tva_tx.($objp->vat_src_code ? ' ('.$objp->vat_src_code.')' : '')).''; // Accounting account affected - print ''; + print ''; print $accountingaccountstatic->getNomUrl(0, 1, 1, '', 1); print ' '; print img_edit(); print ''; - print ''; print ""; diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 863001c3bc0..d95f4ff67b9 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2017 Alexandre Spangaro + * Copyright (C) 2013-2022 Alexandre Spangaro * Copyright (C) 2014-2015 Ari Elbaz (elarifr) * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2014 Juanjo Menent s @@ -30,9 +30,9 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; // Load translation files required by the page @@ -59,9 +59,14 @@ $search_desc = GETPOST('search_desc', 'alpha'); $search_amount = GETPOST('search_amount', 'alpha'); $search_account = GETPOST('search_account', 'alpha'); $search_vat = GETPOST('search_vat', 'alpha'); -$search_day = GETPOST("search_day", "int"); -$search_month = GETPOST("search_month", "int"); -$search_year = GETPOST("search_year", "int"); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); @@ -83,6 +88,9 @@ if (!$sortorder) { } } +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('accountancyexpensereportlist')); + $formaccounting = new FormAccounting($db); $accounting = new AccountingAccount($db); @@ -101,7 +109,7 @@ if (empty($user->rights->accounting->mouvements->lire)) { /* - * Action + * Actions */ if (GETPOST('cancel', 'alpha')) { @@ -111,30 +119,47 @@ if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massa $massaction = ''; } -// Purge search criteria -if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers - $search_login = ''; - $search_expensereport = ''; - $search_label = ''; - $search_desc = ''; - $search_amount = ''; - $search_account = ''; - $search_vat = ''; - $search_day = ''; - $search_month = ''; - $search_year = ''; +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers + $search_login = ''; + $search_expensereport = ''; + $search_label = ''; + $search_desc = ''; + $search_amount = ''; + $search_account = ''; + $search_vat = ''; + $search_date_startday = ''; + $search_date_startmonth = ''; + $search_date_startyear = ''; + $search_date_endday = ''; + $search_date_endmonth = ''; + $search_date_endyear = ''; + $search_date_start = ''; + $search_date_end = ''; + $search_country = ''; + $search_tvaintra = ''; + } + + // Mass actions + $objectclass = 'ExpenseReport'; + $objectlabel = 'ExpenseReport'; + $permissiontoread = $user->rights->expensereport->read; + $permissiontodelete = $user->rights->expensereport->delete; + $uploaddir = $conf->expensereport->dir_output; + include DOL_DOCUMENT_ROOT . '/core/actions_massactions.inc.php'; } -// Mass actions -$objectclass = 'ExpenseReport'; -$objectlabel = 'ExpenseReport'; -$permissiontoread = $user->rights->expensereport->read; -$permissiontodelete = $user->rights->expensereport->delete; -$uploaddir = $conf->expensereport->dir_output; -include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; if ($massaction == 'ventil' && $user->rights->accounting->bind->write) { $msg = ''; + //print '
' . $langs->trans("Processing") . '...
'; if (!empty($mesCasesCochees)) { $msg = '
'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'
'; @@ -159,7 +184,7 @@ if ($massaction == 'ventil' && $user->rights->accounting->bind->write) { $accountventilated = new AccountingAccount($db); $accountventilated->fetch($monCompte, '', 1); - dol_syslog('accountancy/expensereport/list.php', LOG_DEBUG); + dol_syslog('accountancy/expensereport/list.php:: sql='.$sql, LOG_DEBUG); if ($db->query($sql)) { $msg .= '
'.$langs->trans("LineOfExpenseReport").' '.$monId.' - '.$langs->trans("VentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'
'; $ok++; @@ -201,6 +226,9 @@ $sql .= " erd.rowid, erd.fk_c_type_fees, erd.comments, erd.total_ht as price, er $sql .= " f.id as type_fees_id, f.code as type_fees_code, f.label as type_fees_label, f.accountancy_code as code_buy,"; $sql .= " u.rowid as userid, u.login, u.lastname, u.firstname, u.email, u.gender, u.employee, u.photo, u.statut,"; $sql .= " aa.rowid as aarowid"; +$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."expensereport as er"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."expensereport_det as erd ON er.rowid = erd.fk_expensereport"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_type_fees as f ON f.id = erd.fk_c_type_fees"; @@ -233,9 +261,19 @@ if (strlen(trim($search_account))) { if (strlen(trim($search_vat))) { $sql .= natural_search("erd.tva_tx", $search_vat, 1); } -$sql .= dolSqlDateFilter('erd.date', $search_day, $search_month, $search_year); +if ($search_date_start) { + $sql .= " AND erd.date >= '".$db->idate($search_date_start)."'"; +} +if ($search_date_end) { + $sql .= " AND erd.date <= '".$db->idate($search_date_end)."'"; +} $sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + $sql .= $db->order($sortfield, $sortorder); // Count total nb of records @@ -251,7 +289,13 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { $sql .= $db->plimit($limit + 1, $offset); -dol_syslog('accountancy/expensereport/list.php'); +dol_syslog("accountancy/expensereport/list.php", LOG_DEBUG); +// MAX_JOIN_SIZE can be very low (ex: 300000) on some limited configurations (ex: https://www.online.net/fr/hosting/online-perso) +// This big SELECT command may exceed the MAX_JOIN_SIZE limit => Therefore we use SQL_BIG_SELECTS=1 to disable the MAX_JOIN_SIZE security +if ($db->type == 'mysqli') { + $db->query("SET SQL_BIG_SELECTS=1"); +} + $result = $db->query($sql); if ($result) { $num_lines = $db->num_rows($result); @@ -272,14 +316,23 @@ if ($result) { if ($search_lineid) { $param .= '&search_lineid='.urlencode($search_lineid); } - if ($search_day) { - $param .= '&search_day='.urlencode($search_day); + if ($search_date_startday) { + $param .= '&search_date_startday='.urlencode($search_date_startday); } - if ($search_month) { - $param .= '&search_month='.urlencode($search_month); + if ($search_date_startmonth) { + $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); } - if ($search_year) { - $param .= '&search_year='.urlencode($search_year); + if ($search_date_startyear) { + $param .= '&search_date_startyear='.urlencode($search_date_startyear); + } + if ($search_date_endday) { + $param .= '&search_date_endday='.urlencode($search_date_endday); + } + if ($search_date_endmonth) { + $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); + } + if ($search_date_endyear) { + $param .= '&search_date_endyear='.urlencode($search_date_endyear); } if ($search_expensereport) { $param .= '&search_expensereport='.urlencode($search_expensereport); @@ -302,7 +355,6 @@ if ($result) { ); $massactionbutton = $form->selectMassAction('ventil', $arrayofmassactions, 1); - print ''."\n"; print ''; if ($optioncss != '') { @@ -335,20 +387,21 @@ if ($result) { if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) { print ''; } - print ''; - if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) { - print ''; - } - print ''; - $formother->select_year($search_year, 'search_year', 1, 20, 5); + print ''; + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; print ''; print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; print ''; - print ''; + print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; print ''; @@ -468,6 +521,9 @@ if ($result) { } else { print $db->error(); } +if ($db->type == 'mysqli') { + $db->query("SET SQL_BIG_SELECTS=0"); // Enable MAX_JOIN_SIZE limitation +} // Add code to auto check the box when we select an account print ''; + +$object_label = $langs->trans("ObjectsRef"); +if ($object->nature == 2 || $object->nature == 3) $object_label = $langs->trans("InvoiceRef"); +if ($object->nature == 5) $object_label = $langs->trans("ExpenseReportRef"); + +/* + * Show result array + */ +print '
'; + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +if ($object->nature == 4) print ''; // bank +print ''; +print ''; +print "\n"; + +foreach ($journal_data as $element_id => $element) { + foreach ($element['blocks'] as $lines) { + foreach ($lines as $line) { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if ($object->nature == 4) print ''; + print ''; + print ''; + print ''; + } + } +} + +print '
' . $langs->trans("Date") . '' . $langs->trans("Piece") . ' (' . $object_label . ')' . $langs->trans("AccountAccounting") . '' . $langs->trans("SubledgerAccount") . '' . $langs->trans("LabelOperation") . '' . $langs->trans("PaymentMode") . '' . $langs->trans("Debit") . '' . $langs->trans("Credit") . '
' . $line['date'] . '' . $line['piece'] . '' . $line['account_accounting'] . '' . $line['subledger_account'] . '' . $line['label_operation'] . '' . $line['payment_mode'] . '' . $line['debit'] . '' . $line['credit'] . '
'; +print '
'; + +llxFooter(); + +$db->close(); diff --git a/htdocs/adherents/agenda.php b/htdocs/adherents/agenda.php index cb942ba3176..9132dae5802 100644 --- a/htdocs/adherents/agenda.php +++ b/htdocs/adherents/agenda.php @@ -65,6 +65,9 @@ if (GETPOST('actioncode', 'array')) { } $search_agenda_label = GETPOST('search_agenda_label'); +// Get object canvas (By default, this is not defined, so standard usage of dolibarr) +$objcanvas = null; + // Security check $result = restrictedArea($user, 'adherent', $id); diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index a2e3779d52b..caf2bbe61d6 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -55,6 +55,7 @@ $id = GETPOST('id') ?GETPOST('id', 'int') : $rowid; $typeid = GETPOST('typeid', 'int'); $userid = GETPOST('userid', 'int'); $socid = GETPOST('socid', 'int'); +$ref = GETPOST('ref', 'alpha'); if (!empty($conf->mailmanspip->enabled)) { include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php'; diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 6a2c69e32fe..60311518ef8 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -7,7 +7,7 @@ * Copyright (C) 2009-2017 Regis Houssin * Copyright (C) 2014-2018 Alexandre Spangaro * Copyright (C) 2015 Marcos García - * Copyright (C) 2015-2020 Frédéric France + * Copyright (C) 2015-2022 Frédéric France * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Juanjo Menent * Copyright (C) 2018-2019 Thibault FOUCART @@ -2163,7 +2163,7 @@ class Adherent extends CommonObject */ public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0) { - global $conf, $langs; + global $conf, $langs, $hookmanager; if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) { $withpictoimg = 0; @@ -2281,7 +2281,15 @@ class Adherent extends CommonObject $result .= ''; } } - + global $action; + $hookmanager->initHooks(array($this->element . 'dao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index e26db90c4ff..5f578869e6e 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -40,6 +40,8 @@ require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; $langs->loadLangs(array("companies", "bills", "members", "users", "mails", 'other')); +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') + $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $id = GETPOST('rowid', 'int') ?GETPOST('rowid', 'int') : GETPOST('id', 'int'); @@ -1163,9 +1165,13 @@ if ($rowid > 0) { print dol_get_fiche_end(); print '
'; - print ''; - print '     '; - print ''; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); + if (empty($reshook)) { + print ''; + print '     '; + print ''; + } print '
'; print ''; diff --git a/htdocs/adherents/subscription/card.php b/htdocs/adherents/subscription/card.php index 5967d670856..a18259fefe4 100644 --- a/htdocs/adherents/subscription/card.php +++ b/htdocs/adherents/subscription/card.php @@ -93,8 +93,8 @@ if ($user->rights->adherent->cotisation->creer && $action == 'update' && !$cance if ($accountline->rappro) { $errmsg = $langs->trans("SubscriptionLinkedToConciliatedTransaction"); } else { - $accountline->datev = dol_mktime($_POST['datesubhour'], $_POST['datesubmin'], 0, $_POST['datesubmonth'], $_POST['datesubday'], $_POST['datesubyear']); - $accountline->dateo = dol_mktime($_POST['datesubhour'], $_POST['datesubmin'], 0, $_POST['datesubmonth'], $_POST['datesubday'], $_POST['datesubyear']); + $accountline->datev = dol_mktime(GETPOST('datesubhour', 'int'), GETPOST('datesubmin', 'int'), 0, GETPOST('datesubmonth', 'int'), GETPOST('datesubday', 'int'), GETPOST('datesubyear', 'int')); + $accountline->dateo = dol_mktime(GETPOST('datesubhour', 'int'), GETPOST('datesubmin', 'int'), 0, GETPOST('datesubmonth', 'int'), GETPOST('datesubday', 'int'), GETPOST('datesubyear', 'int')); $accountline->amount = $amount; $result = $accountline->update($user); if ($result < 0) { @@ -105,12 +105,12 @@ if ($user->rights->adherent->cotisation->creer && $action == 'update' && !$cance if (!$errmsg) { // Modify values - $object->dateh = dol_mktime($_POST['datesubhour'], $_POST['datesubmin'], 0, $_POST['datesubmonth'], $_POST['datesubday'], $_POST['datesubyear']); - $object->datef = dol_mktime($_POST['datesubendhour'], $_POST['datesubendmin'], 0, $_POST['datesubendmonth'], $_POST['datesubendday'], $_POST['datesubendyear']); + $object->dateh = dol_mktime(GETPOST('datesubhour', 'int'), GETPOST('datesubmin', 'int'), 0, GETPOST('datesubmonth', 'int'), GETPOST('datesubday', 'int'), GETPOST('datesubyear', 'int')); + $object->datef = dol_mktime(GETPOST('datesubendhour', 'int'), GETPOST('datesubendmin', 'int'), 0, GETPOST('datesubendmonth', 'int'), GETPOST('datesubendday', 'int'), GETPOST('datesubendyear', 'int')); $object->fk_type = $typeid; $object->note = $note; + $object->note_private = $note; $object->amount = $amount; - //print 'datef='.$object->datef.' '.$_POST['datesubendday']; $result = $object->update($user); if ($result >= 0 && !count($object->errors)) { diff --git a/htdocs/admin/agenda.php b/htdocs/admin/agenda.php index 730983ad090..af09d32bc73 100644 --- a/htdocs/admin/agenda.php +++ b/htdocs/admin/agenda.php @@ -88,7 +88,6 @@ if ($action == "save" && empty($cancel)) { foreach ($triggers as $trigger) { $keyparam = 'MAIN_AGENDA_ACTIONAUTO_'.$trigger['code']; - //print "param=".$param." - ".$_POST[$param]; if ($search_event === '' || preg_match('/'.preg_quote($search_event, '/').'/i', $keyparam)) { $res = dolibarr_set_const($db, $keyparam, (GETPOST($keyparam, 'alpha') ?GETPOST($keyparam, 'alpha') : ''), 'chaine', 0, '', $conf->entity); if (!($res > 0)) { @@ -192,6 +191,7 @@ if (!empty($triggers)) { } if ($search_event === '' || preg_match('/'.preg_quote($search_event, '/').'/i', $trigger['code'])) { + print ''; print ''; print ''.$trigger['code'].''; print ''.$trigger['label'].''; diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php index 8e50380e2ae..1014d40de50 100644 --- a/htdocs/admin/agenda_other.php +++ b/htdocs/admin/agenda_other.php @@ -41,6 +41,8 @@ $langs->loadLangs(array('admin', 'other', 'agenda', 'users')); $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $param = GETPOST('param', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); diff --git a/htdocs/admin/agenda_reminder.php b/htdocs/admin/agenda_reminder.php index 1d8cd8f723c..79aa081ddef 100644 --- a/htdocs/admin/agenda_reminder.php +++ b/htdocs/admin/agenda_reminder.php @@ -36,6 +36,8 @@ $langs->loadLangs(array("admin", "other", "agenda")); $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $param = GETPOST('param', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); $scandir = GETPOST('scandir', 'alpha'); diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php index 2fbfed35536..ee0fcd5d130 100644 --- a/htdocs/admin/barcode.php +++ b/htdocs/admin/barcode.php @@ -36,6 +36,7 @@ if (!$user->admin) { } $action = GETPOST('action', 'aZ09'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php /* diff --git a/htdocs/admin/bom.php b/htdocs/admin/bom.php index a36c3698306..e3adb206d7e 100644 --- a/htdocs/admin/bom.php +++ b/htdocs/admin/bom.php @@ -36,6 +36,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'bom'; diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index 24a45bb413a..5c8eb88126c 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -46,6 +46,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'order'; diff --git a/htdocs/admin/contract.php b/htdocs/admin/contract.php index 1c6a0ec0458..0c8aba5ae2d 100644 --- a/htdocs/admin/contract.php +++ b/htdocs/admin/contract.php @@ -37,6 +37,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'contract'; diff --git a/htdocs/admin/delivery.php b/htdocs/admin/delivery.php index 8e60b02a5bf..6f0f4c1b415 100644 --- a/htdocs/admin/delivery.php +++ b/htdocs/admin/delivery.php @@ -43,6 +43,8 @@ if (!$user->admin) { $action = GETPOST('action', 'alpha'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'delivery'; diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 5245e60ad67..437d58aeac9 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -3,7 +3,7 @@ * Copyright (C) 2004-2018 Laurent Destailleur * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2005-2017 Regis Houssin - * Copyright (C) 2010-2016 Juanjo Menent + * Copyright (C) 2010-2022 Juanjo Menent * Copyright (C) 2011-2021 Philippe Grand * Copyright (C) 2011 Remy Younes * Copyright (C) 2012-2015 Marcos García @@ -12,7 +12,7 @@ * Copyright (C) 2015 Ferran Marcet * Copyright (C) 2016 Raphaël Doursenaud * Copyright (C) 2019-2020 Frédéric France - * Copyright (C) 2020 Open-Dsi + * Copyright (C) 2020-2022 Open-Dsi * * 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 @@ -100,7 +100,7 @@ $hookmanager->initHooks(array('admin')); // Put here declaration of dictionaries properties // Sort order to show dictionary (0 is space). All other dictionaries (added by modules) will be at end of this. -$taborder = array(9, 15, 30, 0, 4, 3, 2, 0, 1, 8, 19, 16, 39, 27, 40, 38, 0, 5, 11, 0, 6, 24, 0, 29, 0, 33, 34, 32, 28, 17, 35, 36, 0, 10, 23, 12, 13, 7, 0, 14, 0, 22, 20, 18, 21, 41, 0, 37, 42, 0, 43, 0, 25, 0); +$taborder = array(9, 15, 30, 0, 4, 3, 2, 0, 1, 8, 19, 16, 39, 27, 40, 38, 0, 5, 11, 0, 6, 24, 0, 29, 0, 33, 34, 32, 28, 17, 35, 36, 0, 10, 23, 12, 13, 7, 0, 14, 0, 22, 20, 18, 21, 41, 0, 37, 42, 0, 43, 0, 25, 0, 44, 0); // Name of SQL tables of dictionaries $tabname = array(); @@ -147,6 +147,7 @@ $tabname[40] = MAIN_DB_PREFIX."c_stcommcontact"; $tabname[41] = MAIN_DB_PREFIX."c_transport_mode"; $tabname[42] = MAIN_DB_PREFIX."c_product_nature"; $tabname[43] = MAIN_DB_PREFIX."c_productbatch_qcstatus"; +$tabname[44] = MAIN_DB_PREFIX."c_asset_disposal_type"; // Dictionary labels $tablib = array(); @@ -193,6 +194,7 @@ $tablib[40] = "DictionaryProspectContactStatus"; $tablib[41] = "DictionaryTransportMode"; $tablib[42] = "DictionaryProductNature"; $tablib[43] = "DictionaryBatchStatus"; +$tablib[44] = "DictionaryAssetDisposalType"; // Requests to extract data $tabsql = array(); @@ -223,7 +225,7 @@ $tabsql[24] = "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFI $tabsql[25] = "SELECT rowid as rowid, code, label, active, module FROM ".MAIN_DB_PREFIX."c_type_container as t WHERE t.entity = ".getEntity($tabname[25]); //$tabsql[26]= "SELECT rowid as rowid, code, label, short_label, active FROM ".MAIN_DB_PREFIX."c_units"; $tabsql[27] = "SELECT id as rowid, code, libelle, picto, active FROM ".MAIN_DB_PREFIX."c_stcomm"; -$tabsql[28] = "SELECT h.rowid as rowid, h.code, h.label, h.affect, h.delay, h.newbymonth, h.fk_country as country_id, c.code as country_code, c.label as country, h.active FROM ".MAIN_DB_PREFIX."c_holiday_types as h LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON h.fk_country=c.rowid"; +$tabsql[28] = "SELECT h.rowid as rowid, h.code, h.label, h.affect, h.delay, h.newbymonth, h.fk_country as country_id, c.code as country_code, c.label as country, h.block_if_negative, h.active FROM ".MAIN_DB_PREFIX."c_holiday_types as h LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON h.fk_country=c.rowid"; $tabsql[29] = "SELECT rowid as rowid, code, label, percent, position, active FROM ".MAIN_DB_PREFIX."c_lead_status"; $tabsql[30] = "SELECT rowid, code, name, paper_size, orientation, metric, leftmargin, topmargin, nx, ny, spacex, spacey, width, height, font_size, custom_x, custom_y, active FROM ".MAIN_DB_PREFIX."c_format_cards"; //$tabsql[31]= "SELECT s.rowid as rowid, pcg_version, s.label, s.active FROM ".MAIN_DB_PREFIX."accounting_system as s"; @@ -239,6 +241,7 @@ $tabsql[40] = "SELECT id as rowid, code, libelle, picto, active FROM ".MAIN $tabsql[41] = "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_transport_mode"; $tabsql[42] = "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_product_nature"; $tabsql[43] = "SELECT rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_productbatch_qcstatus"; +$tabsql[44] = "SELECT rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_asset_disposal_type"; // Criteria to sort dictionaries $tabsqlsort = array(); @@ -285,6 +288,7 @@ $tabsqlsort[40] = "code ASC"; $tabsqlsort[41] = "code ASC"; $tabsqlsort[42] = "code ASC"; $tabsqlsort[43] = "code ASC"; +$tabsqlsort[44] = "code ASC"; // Field names in select result for dictionary display $tabfield = array(); @@ -315,7 +319,7 @@ $tabfield[24] = "code,label"; $tabfield[25] = "code,label"; //$tabfield[26]= "code,label,short_label"; $tabfield[27] = "code,libelle,picto"; -$tabfield[28] = "code,label,affect,delay,newbymonth,country_id,country"; +$tabfield[28] = "code,label,affect,delay,newbymonth,country_id,country,block_if_negative"; $tabfield[29] = "code,label,percent,position"; $tabfield[30] = "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y"; //$tabfield[31]= "pcg_version,label"; @@ -331,6 +335,7 @@ $tabfield[40] = "code,libelle,picto"; $tabfield[41] = "code,label"; $tabfield[42] = "code,label"; $tabfield[43] = "code,label"; +$tabfield[44] = "code,label"; // Edit field names for editing a record $tabfieldvalue = array(); @@ -361,7 +366,7 @@ $tabfieldvalue[24] = "code,label"; $tabfieldvalue[25] = "code,label"; //$tabfieldvalue[26]= "code,label,short_label"; $tabfieldvalue[27] = "code,libelle,picto"; -$tabfieldvalue[28] = "code,label,affect,delay,newbymonth,country"; +$tabfieldvalue[28] = "code,label,affect,delay,newbymonth,country,block_if_negative"; $tabfieldvalue[29] = "code,label,percent,position"; $tabfieldvalue[30] = "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y"; //$tabfieldvalue[31]= "pcg_version,label"; @@ -377,6 +382,7 @@ $tabfieldvalue[40] = "code,libelle,picto"; $tabfieldvalue[41] = "code,label"; $tabfieldvalue[42] = "code,label"; $tabfieldvalue[43] = "code,label"; +$tabfieldvalue[44] = "code,label"; // Field names in the table for inserting a record $tabfieldinsert = array(); @@ -407,7 +413,7 @@ $tabfieldinsert[24] = "code,label"; $tabfieldinsert[25] = "code,label"; //$tabfieldinsert[26]= "code,label,short_label"; $tabfieldinsert[27] = "code,libelle,picto"; -$tabfieldinsert[28] = "code,label,affect,delay,newbymonth,fk_country"; +$tabfieldinsert[28] = "code,label,affect,delay,newbymonth,fk_country,block_if_negative"; $tabfieldinsert[29] = "code,label,percent,position"; $tabfieldinsert[30] = "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y"; //$tabfieldinsert[31]= "pcg_version,label"; @@ -424,6 +430,7 @@ $tabfieldinsert[40] = "code,libelle,picto"; $tabfieldinsert[41] = "code,label"; $tabfieldinsert[42] = "code,label"; $tabfieldinsert[43] = "code,label"; +$tabfieldinsert[44] = "code,label"; // Rowid name of field depending if field is autoincrement on or off.. // Use "" if id field is "rowid" and has autoincrement on @@ -472,6 +479,7 @@ $tabrowid[40] = "id"; $tabrowid[41] = ""; $tabrowid[42] = "rowid"; $tabrowid[43] = "rowid"; +$tabrowid[44] = "rowid"; // Condition to show dictionary in setup page $tabcond = array(); @@ -518,6 +526,7 @@ $tabcond[40] = (!empty($conf->societe->enabled) && !empty($conf->global->THIRDPA $tabcond[41] = !empty($conf->intracommreport->enabled); $tabcond[42] = !empty($conf->product->enabled); $tabcond[43] = !empty($conf->product->enabled) && !empty($conf->productbatch->enabled) && $conf->global->MAIN_FEATURES_LEVEL >= 2; +$tabcond[44] = !empty($conf->asset->enabled); // List of help for fields $tabhelp = array(); @@ -564,6 +573,7 @@ $tabhelp[40] = array('code'=>$langs->trans("EnterAnyCode"), 'picto'=>$langs->tra $tabhelp[41] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[42] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[43] = array('code'=>$langs->trans("EnterAnyCode")); +$tabhelp[44] = array('code'=>$langs->trans("EnterAnyCode")); // Table to store complete informations (will replace all other table). Key is table name. $tabcomplete = array( @@ -609,6 +619,7 @@ $tabcomplete = array( 'c_stcommcontact'=>array('picto'=>'company'), 'c_product_nature'=>array('picto'=>'product'), 'c_productbatch_qcstatus'=>array('picto'=>'lot'), + 'c_asset_disposal_type'=>array('picto'=>'asset'), ); @@ -706,19 +717,19 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { continue; // For some pages, country is not mandatory } // Discard check of mandatory fiedls for other fields - if ($value == 'localtax1' && empty($_POST['localtax1_type'])) { + if ($value == 'localtax1' && !GETPOST('localtax1_type')) { continue; } - if ($value == 'localtax2' && empty($_POST['localtax2_type'])) { + if ($value == 'localtax2' && !GETPOST('localtax2_type')) { continue; } - if ($value == 'color' && empty($_POST['color'])) { + if ($value == 'color' && !GETPOST('color')) { continue; } - if ($value == 'formula' && empty($_POST['formula'])) { + if ($value == 'formula' && !GETPOST('formula')) { continue; } - if ($value == 'dayrule' && empty($_POST['dayrule'])) { + if ($value == 'dayrule' && !GETPOST('dayrule')) { continue; } if ($value == 'sortorder') { @@ -794,11 +805,6 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { $ok = 0; setEventMessages($langs->transnoentities('ErrorCodeCantContainZero'), null, 'errors'); } - /*if (!is_numeric($_POST['code'])) // disabled, code may not be in numeric base - { - $ok = 0; - $msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'
'; - }*/ } if (GETPOSTISSET("country") && (GETPOST("country") == '0') && ($id != 2)) { if (in_array($tablib[$id], array('DictionaryCompanyType', 'DictionaryHolidayTypes'))) { // Field country is no mandatory for such dictionaries @@ -830,7 +836,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { $_POST["accountancy_code_buy"] = ''; // If empty, we force to null } if ($id == 10 && GETPOSTISSET("code")) { // Spaces are not allowed into code for tax dictionary - $_POST["code"] = preg_replace('/[^a-zA-Z0-9\-\+]/', '', $_POST["code"]); + $_POST["code"] = preg_replace('/[^a-zA-Z0-9\-\+]/', '', GETPOST("code")); } // If check ok and action add, add the line @@ -883,7 +889,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { if ($keycode == 'sortorder') { // For column name 'sortorder', we use the field name 'position' $sql .= (int) GETPOST('position', 'int'); - } elseif ($_POST[$keycode] == '' && !($keycode == 'code' && $id == 10)) { + } elseif (GETPOST($keycode) == '' && !($keycode == 'code' && $id == 10)) { $sql .= "null"; // For vat, we want/accept code = '' } elseif ($keycode == 'content') { $sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'"; @@ -952,7 +958,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { $sql .= $field."="; if ($listfieldvalue[$i] == 'sortorder') { // For column name 'sortorder', we use the field name 'position' $sql .= (int) GETPOST('position', 'int'); - } elseif ($_POST[$keycode] == '' && !($keycode == 'code' && $id == 10)) { + } elseif (GETPOST($keycode) == '' && !($keycode == 'code' && $id == 10)) { $sql .= "null"; // For vat, we want/accept code = '' } elseif ($keycode == 'content') { $sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'"; @@ -1418,6 +1424,9 @@ if ($id) { if ($value == 'public' && $tablib[$id] == 'TicketDictCategory') { $valuetoshow = $langs->trans('TicketGroupIsPublic'); $class = 'center'; } + if ($value == 'block_if_negative') { + $valuetoshow = $langs->trans('BlockHolidayIfNegative'); + } if ($id == 2) { // Special case for state page if ($value == 'region_id') { @@ -1764,6 +1773,9 @@ if ($id) { if ($value == 'public' && $tablib[$id] == 'TicketDictCategory') { $valuetoshow = $langs->trans('TicketGroupIsPublic'); $cssprefix = 'center '; } + if ($value == 'block_if_negative') { + $valuetoshow = $langs->trans('BlockHolidayIfNegative'); + } if ($value == 'region_id' || $value == 'country_id') { $showfield = 0; @@ -1981,8 +1993,9 @@ if ($id) { } } } elseif ($value == 'fk_c_exp_tax_cat') { - $valuetoshow = getDictionaryValue(MAIN_DB_PREFIX.'c_exp_tax_cat', 'label', $valuetoshow); - $valuetoshow = $langs->trans($valuetoshow); + $tmpid = $valuetoshow; + $valuetoshow = getDictionaryValue(MAIN_DB_PREFIX.'c_exp_tax_cat', 'label', $tmpid); + $valuetoshow = $langs->trans($valuetoshow ? $valuetoshow : $tmpid); } elseif ($tabname[$id] == MAIN_DB_PREFIX.'c_exp_tax_cat') { $valuetoshow = $langs->trans($valuetoshow); } elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_units') { @@ -1997,6 +2010,8 @@ if ($id) { } elseif ($fieldlist[$field] == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_productbatch_qcstatus') { $langs->load("productbatch"); $valuetoshow = $langs->trans($obj->{$value}); + } elseif ($value == 'block_if_negative') { + $valuetoshow = yn($obj->{$value}); } $class .= ($class ? ' ' : '').'tddict'; if ($value == 'note' && $id == 10) { @@ -2379,6 +2394,10 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') print ''; print $form->selectExpenseRanges($obj->fk_range); print ''; + } elseif ($value == 'block_if_negative') { + print ''; + print $form->selectyesno("block_if_negative", (!empty($obj->{$value}) ? $obj->{$value}:''), 1); + print ''; } else { $fieldValue = isset($obj->{$value}) ? $obj->{$value}: ''; @@ -2408,6 +2427,31 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') $fieldValue = '0'; } } + + // Labels Length + $maxlength = ''; + if (in_array($fieldlist[$field], array('libelle', 'label'))) { + switch ($tabname) { + case MAIN_DB_PREFIX . 'c_accounting_category': + case MAIN_DB_PREFIX . 'c_ecotaxe': + case MAIN_DB_PREFIX . 'c_email_senderprofile': + case MAIN_DB_PREFIX . 'c_forme_juridique': + case MAIN_DB_PREFIX . 'c_holiday_types': + case MAIN_DB_PREFIX . 'c_payment_term': + case MAIN_DB_PREFIX . 'c_transport_mode': + $maxlength = ' maxlength="255"'; + break; + case MAIN_DB_PREFIX . 'c_email_templates': + $maxlength = ' maxlength="180"'; + break; + case MAIN_DB_PREFIX . 'c_socialnetworks': + $maxlength = ' maxlength="150"'; + break; + default: + $maxlength = ' maxlength="128"'; + } + } + print ''; $transfound = 0; $transkey = ''; @@ -2426,7 +2470,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') } } if (!$transfound) { - print ''; + print ''; } else { print ''; } diff --git a/htdocs/admin/eventorganization.php b/htdocs/admin/eventorganization.php index 8edc61bf255..904d10bff67 100644 --- a/htdocs/admin/eventorganization.php +++ b/htdocs/admin/eventorganization.php @@ -41,6 +41,8 @@ $backtopage = GETPOST('backtopage', 'alpha'); $value = GETPOST('value', 'alpha'); $label = GETPOST('label', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $scandir = GETPOST('scan_dir', 'alpha'); $type = 'myobject'; diff --git a/htdocs/admin/expedition.php b/htdocs/admin/expedition.php index 2d4736cc49d..12e0d0a6d01 100644 --- a/htdocs/admin/expedition.php +++ b/htdocs/admin/expedition.php @@ -43,6 +43,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'shipping'; diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php index 5b73d995b5c..fc63940f0b8 100644 --- a/htdocs/admin/expensereport.php +++ b/htdocs/admin/expensereport.php @@ -43,6 +43,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'expensereport'; diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php index ae269492ddf..9eec54b03a7 100644 --- a/htdocs/admin/facture.php +++ b/htdocs/admin/facture.php @@ -42,6 +42,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'invoice'; diff --git a/htdocs/admin/facture_situation.php b/htdocs/admin/facture_situation.php index 91134671692..609a6605d1a 100644 --- a/htdocs/admin/facture_situation.php +++ b/htdocs/admin/facture_situation.php @@ -28,24 +28,93 @@ */ require '../main.inc.php'; + +// Libraries require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php'; // Load translation files required by the page $langs->loadLangs(array('admin', 'errors', 'other', 'bills')); +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('situationinvoicesetup', 'globalsetup')); + +// Access control if (!$user->admin) { accessforbidden(); } $action = GETPOST('action', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + $value = GETPOST('value', 'alpha'); $label = GETPOST('label', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $scandir = GETPOST('scan_dir', 'alpha'); $type = 'invoice'; +$form = new Form($db); +$formSetup = new FormSetup($db); + + +// Setup conf MYMODULE_MYPARAM4 : exemple of quick define write style +$formSetup->newItem('INVOICE_USE_SITUATION') + ->setAsYesNo() + ->nameText = $langs->trans('UseSituationInvoices'); + +$item = $formSetup->newItem('INVOICE_USE_SITUATION_CREDIT_NOTE') + ->setAsYesNo() + ->nameText = $langs->trans('UseSituationInvoicesCreditNote'); + +//$item = $formSetup->newItem('INVOICE_USE_RETAINED_WARRANTY') +// ->setAsYesNo() +// ->nameText = $langs->trans('Retainedwarranty'); + + +$item = $formSetup->newItem('INVOICE_USE_RETAINED_WARRANTY'); +$item->nameText = $langs->trans('AllowedInvoiceForRetainedWarranty'); + +$arrayAvailableType = array( + Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation"), + Facture::TYPE_STANDARD.'+'.Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation").' + '.$langs->trans("InvoiceStandard"), +); + +if ($action == 'edit') { + $item->fieldInputOverride = $form->selectarray('INVOICE_USE_RETAINED_WARRANTY', $arrayAvailableType, $conf->global->INVOICE_USE_RETAINED_WARRANTY, 1); +} else { + $item->fieldOutputOverride= isset($arrayAvailableType[$conf->global->INVOICE_USE_RETAINED_WARRANTY])?$arrayAvailableType[$conf->global->INVOICE_USE_RETAINED_WARRANTY]:''; +} + +//$item = $formSetup->newItem('INVOICE_RETAINED_WARRANTY_LIMITED_TO_SITUATION')->setAsYesNo(); +//$item->nameText = $langs->trans('RetainedwarrantyOnlyForSituation'); + +$formSetup->newItem('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION') + ->setAsYesNo() + ->nameText = $langs->trans('RetainedwarrantyOnlyForSituationFinal'); + + +$item = $formSetup->newItem('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_PERCENT'); +$item->nameText = $langs->trans('RetainedwarrantyDefaultPercent'); +$item->fieldAttr = array( + 'type' => 'number', + 'step' => '0.01', + 'min' => 0, + 'max' => 100 +); + + +// Conditions paiements +$item = $formSetup->newItem('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID'); +$item->nameText = $langs->trans('PaymentConditionsShortRetainedWarranty'); +$form->load_cache_conditions_paiements(); +if (!empty($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID) && isset($form->cache_conditions_paiements[$conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID]['label'])) { + $item->fieldOutputOverride = $form->cache_conditions_paiements[$conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID]['label']; +} +$item->fieldInputOverride = $form->getSelectConditionsPaiements($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID, 'INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID', -1, 1); + /* * Actions @@ -67,7 +136,6 @@ llxHeader( 'EN:Invoice_Configuration|FR:Configuration_module_facture|ES:ConfiguracionFactura' ); -$form = new Form($db); $linkback = ''.$langs->trans("BackToModuleList").''; @@ -84,170 +152,25 @@ print ''.$langs->trans("InvoiceFirstSituationDesc"). * Numbering module */ -print '
'; -print ''; +if ($action == 'edit') { + print $formSetup->generateOutput(true); +} else { + print $formSetup->generateOutput(); +} +if (count($formSetup->items) > 0) { + if ($action != 'edit') { + print '
'; + print ''.$langs->trans("Modify").''; + print '
'; + } +} else { + print '
'.$langs->trans("NothingToSetup"); +} -print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table -print ''; - -print ''; -print ''; -print ''; -print ''; -print "\n"; - -_printOnOff('INVOICE_USE_SITUATION', $langs->trans('UseSituationInvoices')); -_printOnOff('INVOICE_USE_SITUATION_CREDIT_NOTE', $langs->trans('UseSituationInvoicesCreditNote')); -//_printOnOff('INVOICE_USE_RETAINED_WARRANTY', $langs->trans('Retainedwarranty')); - -$confkey = 'INVOICE_USE_RETAINED_WARRANTY'; - -$arrayAvailableType = array( - Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation"), - Facture::TYPE_STANDARD.'+'.Facture::TYPE_SITUATION => $langs->trans("InvoiceSituation").' + '.$langs->trans("InvoiceStandard"), -); -$selected = $conf->global->$confkey; -$curentInput = (empty($inputCount) ? 1 : ($inputCount + 1)); -$formSelectInvoiceType = $form->selectarray('value'.$curentInput, $arrayAvailableType, $selected, 1); -_printInputFormPart($confkey, $langs->trans('AllowedInvoiceForRetainedWarranty'), '', array(), $formSelectInvoiceType); - -//_printOnOff('INVOICE_RETAINED_WARRANTY_LIMITED_TO_SITUATION', $langs->trans('RetainedwarrantyOnlyForSituation')); -_printOnOff('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION', $langs->trans('RetainedwarrantyOnlyForSituationFinal')); - -$metas = array( - 'type' => 'number', - 'step' => '0.01', - 'min' => 0, - 'max' => 100 -); -_printInputFormPart('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_PERCENT', $langs->trans('RetainedwarrantyDefaultPercent'), '', $metas); - -// Conditions paiements -$inputCount = empty($inputCount) ? 1 : ($inputCount + 1); -print ''; -print ''; -print ''; -print ''; - - -print '
'.$langs->trans("Parameter").''.$langs->trans("Value").' 
'.$langs->trans('PaymentConditionsShortRetainedWarranty').' '; -print ''; -$form->select_conditions_paiements($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID, 'value'.$inputCount, -1, 1); -print '
'; -print '
'; - -print '
'; - -_updateBtn(); - -print '
'; print dol_get_fiche_end(); // End of page llxFooter(); $db->close(); - -/** - * Print an update button - * - * @return void - */ -function _updateBtn() -{ - global $langs; - print '
'; - print ''; - print '
'; -} - -/** - * Print a On/Off button - * - * @param string $confkey the conf key - * @param bool $title Title of conf - * @param string $desc Description - * - * @return void - */ -function _printOnOff($confkey, $title = false, $desc = '') -{ - global $langs; - - print ''; - print ''.($title ? $title : $langs->trans($confkey)); - if (!empty($desc)) { - print '
'.$langs->trans($desc).''; - } - print ''; - print ' '; - print ''; - print ajax_constantonoff($confkey); - print ''; -} - - -/** - * Print a form part - * - * @param string $confkey the conf key - * @param bool $title Title of conf - * @param string $desc Description of - * @param array $metas html meta - * @param string $type type of input textarea or input - * @param bool $help help description - * - * @return void - */ -function _printInputFormPart($confkey, $title = false, $desc = '', $metas = array(), $type = 'input', $help = false) -{ - global $langs, $conf, $db, $inputCount; - - $inputCount = empty($inputCount) ? 1 : ($inputCount + 1); - $form = new Form($db); - - $defaultMetas = array( - 'name' => 'value'.$inputCount - ); - - if ($type != 'textarea') { - $defaultMetas['type'] = 'text'; - $defaultMetas['value'] = $conf->global->{$confkey}; - } - - - $metas = array_merge($defaultMetas, $metas); - $metascompil = ''; - foreach ($metas as $key => $values) { - $metascompil .= ' '.$key.'="'.$values.'" '; - } - - print ''; - print ''; - - if (!empty($help)) { - print $form->textwithtooltip(($title ? $title : $langs->trans($confkey)), $langs->trans($help), 2, 1, img_help(1, '')); - } else { - print $title ? $title : $langs->trans($confkey); - } - - if (!empty($desc)) { - print '
'.$langs->trans($desc).''; - } - - print ''; - print ' '; - print ''; - print ''; - print ''; - if ($type == 'textarea') { - print ''; - } elseif ($type == 'input') { - print ''; - } else { - // custom - print $type; - } - print ''; -} diff --git a/htdocs/admin/fichinter.php b/htdocs/admin/fichinter.php index 4369bb9a2a7..c95f354a189 100644 --- a/htdocs/admin/fichinter.php +++ b/htdocs/admin/fichinter.php @@ -43,6 +43,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'ficheinter'; diff --git a/htdocs/admin/holiday.php b/htdocs/admin/holiday.php index bfd7e22c461..c1755b17edf 100644 --- a/htdocs/admin/holiday.php +++ b/htdocs/admin/holiday.php @@ -39,6 +39,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'contract'; diff --git a/htdocs/admin/hrm.php b/htdocs/admin/hrm.php index 1ad84ce19ac..aea86069f4d 100644 --- a/htdocs/admin/hrm.php +++ b/htdocs/admin/hrm.php @@ -50,6 +50,8 @@ $backtopage = GETPOST('backtopage', 'alpha'); $value = GETPOST('value', 'alpha'); $label = GETPOST('label', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $scandir = GETPOST('scan_dir', 'alpha'); $type = 'myobject'; diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php index 697f8fa2130..2c997d746d9 100644 --- a/htdocs/admin/ihm.php +++ b/htdocs/admin/ihm.php @@ -5,6 +5,7 @@ * Copyright (C) 2016 Juanjo Menent * Copyright (C) 2018 Ferran Marcet * Copyright (C) 2021 Alexandre Spangaro + * Copyright (C) 2021 Anthony Berton * * 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 @@ -199,6 +200,20 @@ if ($action == 'update') { } else { dolibarr_set_const($db, "THEME_ELDY_USE_CHECKED", $val, 'chaine', 0, '', $conf->entity); } + + $val=(implode(',', (colorStringToArray(GETPOST('THEME_ELDY_BTNACTION'), array())))); + if ($val == '') { + dolibarr_del_const($db, 'THEME_ELDY_BTNACTION', $conf->entity); + } else { + dolibarr_set_const($db, 'THEME_ELDY_BTNACTION', $val, 'chaine', 0, '', $conf->entity); + } + + $val=(implode(',', (colorStringToArray(GETPOST('THEME_ELDY_TEXTBTNACTION'), array())))); + if ($val == '') { + dolibarr_del_const($db, 'THEME_ELDY_TEXTBTNACTION', $conf->entity); + } else { + dolibarr_set_const($db, 'THEME_ELDY_TEXTBTNACTION', $val, 'chaine', 0, '', $conf->entity); + } } if ($mode == 'dashboard') { @@ -265,6 +280,10 @@ if ($action == 'update') { $_SESSION["mainmenu"] = ""; // The menu manager may have changed + if (GETPOST('dol_resetcache')) { + dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", ((int) $conf->global->MAIN_IHM_PARAMS_REV) + 1, 'chaine', 0, '', $conf->entity); + } + header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup".'&mode='.$mode.(GETPOSTISSET('page_y') ? '&page_y='.GETPOST('page_y', 'int') : '')); exit; } @@ -294,6 +313,7 @@ print ''; print ''; print ''; print ''; +print ''; $head = ihm_prepare_head(); @@ -634,6 +654,7 @@ if ($mode == 'login') { print '
'; print ''; +print ''; print '
'; print ''; diff --git a/htdocs/admin/import.php b/htdocs/admin/import.php index cd9d7b44074..37168baa3d4 100644 --- a/htdocs/admin/import.php +++ b/htdocs/admin/import.php @@ -41,6 +41,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + /* * Actions diff --git a/htdocs/admin/knowledgemanagement.php b/htdocs/admin/knowledgemanagement.php index 8d93c16741a..c2440bbb885 100644 --- a/htdocs/admin/knowledgemanagement.php +++ b/htdocs/admin/knowledgemanagement.php @@ -37,8 +37,9 @@ $langs->loadLangs(array("admin", "knowledgemanagement")); // Parameters $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); - $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'knowledgemanagement'; diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 41a436b70a8..fc8e24b9322 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -903,8 +903,8 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; $formmail = new FormMail($db); $formmail->trackid = (($action == 'testhtml') ? "testhtml" : "test"); - $formmail->fromname = (GETPOSTISSET('fromname') ? $_POST['fromname'] : $conf->global->MAIN_MAIL_EMAIL_FROM); - $formmail->frommail = (GETPOSTISSET('frommail') ? $_POST['frommail'] : $conf->global->MAIN_MAIL_EMAIL_FROM); + $formmail->fromname = (GETPOSTISSET('fromname') ? GETPOST('fromname') : $conf->global->MAIN_MAIL_EMAIL_FROM); + $formmail->frommail = (GETPOSTISSET('frommail') ? GETPOST('frommail') : $conf->global->MAIN_MAIL_EMAIL_FROM); $formmail->fromid = $user->id; $formmail->fromalsorobot = 1; $formmail->fromtype = (GETPOSTISSET('fromtype') ?GETPOST('fromtype', 'aZ09') : (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) ? $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE : 'user')); @@ -912,9 +912,9 @@ if ($action == 'edit') { $formmail->withsubstit = 1; $formmail->withfrom = 1; $formmail->witherrorsto = 1; - $formmail->withto = (!empty($_POST['sendto']) ? GETPOST('sendto', 'restricthtml') : ($user->email ? $user->email : 1)); - $formmail->withtocc = (!empty($_POST['sendtocc']) ? GETPOST('sendtocc', 'restricthtml') : 1); // ! empty to keep field if empty - $formmail->withtoccc = (!empty($_POST['sendtoccc']) ? GETPOST('sendtoccc', 'restricthtml') : 1); // ! empty to keep field if empty + $formmail->withto = (GETPOSTISSET('sendto') ? GETPOST('sendto', 'restricthtml') : ($user->email ? $user->email : 1)); + $formmail->withtocc = (GETPOSTISSET('sendtocc') ? GETPOST('sendtocc', 'restricthtml') : 1); // ! empty to keep field if empty + $formmail->withtoccc = (GETPOSTISSET('sendtoccc') ? GETPOST('sendtoccc', 'restricthtml') : 1); // ! empty to keep field if empty $formmail->withtopic = (GETPOSTISSET('subject') ? GETPOST('subject') : $langs->trans("Test")); $formmail->withtopicreadonly = 0; $formmail->withfile = 2; diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index fb3a1ccf702..476f15459cb 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -308,7 +308,7 @@ if (empty($reshook)) { // Rename some POST variables into a generic name if (GETPOST('actionmodify', 'alpha') && $value == 'topic') { - $_POST['topic'] = $_POST['topic-'.$rowid]; + $_POST['topic'] = GETPOST('topic-'.$rowid); } if ((!GETPOSTISSET($value) || GETPOST($value) == '' || GETPOST($value) == '-1') && $value != 'lang' && $value != 'fk_user' && $value != 'position') { diff --git a/htdocs/admin/mails_ticket.php b/htdocs/admin/mails_ticket.php index 79c549c0609..481fcad212c 100644 --- a/htdocs/admin/mails_ticket.php +++ b/htdocs/admin/mails_ticket.php @@ -537,16 +537,16 @@ if ($action == 'edit') { // Cree l'objet formulaire mail include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; $formmail = new FormMail($db); - $formmail->fromname = (GETPOSTISSET('fromname') ? $_POST['fromname'] : $conf->global->MAIN_MAIL_EMAIL_FROM); - $formmail->frommail = (GETPOSTISSET('frommail') ? $_POST['frommail'] : $conf->global->MAIN_MAIL_EMAIL_FROM); + $formmail->fromname = (GETPOSTISSET('fromname') ? GETPOST('fromname') : $conf->global->MAIN_MAIL_EMAIL_FROM); + $formmail->frommail = (GETPOSTISSET('frommail') ? GETPOST('frommail') : $conf->global->MAIN_MAIL_EMAIL_FROM); $formmail->trackid = (($action == 'testhtml') ? "testhtml" : "test"); $formmail->withfromreadonly = 0; $formmail->withsubstit = 0; $formmail->withfrom = 1; $formmail->witherrorsto = 1; - $formmail->withto = (!empty($_POST['sendto']) ? GETPOST('sendto', 'restricthtml') : ($user->email ? $user->email : 1)); - $formmail->withtocc = (!empty($_POST['sendtocc']) ? GETPOST('sendtocc', 'restricthtml') : 1); // ! empty to keep field if empty - $formmail->withtoccc = (!empty($_POST['sendtoccc']) ? GETPOST('sendtoccc', 'restricthtml') : 1); // ! empty to keep field if empty + $formmail->withto = (GETPOSTISSET('sendto') ? GETPOST('sendto', 'restricthtml') : ($user->email ? $user->email : 1)); + $formmail->withtocc = (GETPOSTISSET('sendtocc') ? GETPOST('sendtocc', 'restricthtml') : 1); + $formmail->withtoccc = (GETPOSTISSET('sendtoccc') ? GETPOST('sendtoccc', 'restricthtml') : 1); $formmail->withtopic = (GETPOSTISSET('subject') ? GETPOST('subject') : $langs->trans("Test")); $formmail->withtopicreadonly = 0; $formmail->withfile = 2; diff --git a/htdocs/admin/menus/edit.php b/htdocs/admin/menus/edit.php index 02c46d8ca35..b3c3e5066c2 100644 --- a/htdocs/admin/menus/edit.php +++ b/htdocs/admin/menus/edit.php @@ -152,32 +152,32 @@ if ($action == 'add') { $langs->load("errors"); $error = 0; - if (!$error && !$_POST['menu_handler']) { + if (!$error && !GETPOST('menu_handler')) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("MenuHandler")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['type']) { + if (!$error && !GETPOST('type')) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['url']) { + if (!$error && !GETPOST('url')) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("URL")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['titre']) { + if (!$error && !GETPOST('titre')) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Title")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && $_POST['menuId'] && $_POST['type'] == 'top') { + if (!$error && GETPOST('menuId') && GETPOST('type') == 'top') { setEventMessages($langs->trans("ErrorTopMenuMustHaveAParentWithId0"), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['menuId'] && $_POST['type'] == 'left') { + if (!$error && !GETPOST('menuId') && GETPOST('type') == 'left') { setEventMessages($langs->trans("ErrorLeftMenuMustHaveAParentId"), null, 'errors'); $action = 'create'; $error++; diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 29d2335a0f9..4ad384233d8 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -48,7 +48,6 @@ if (empty($mode)) { $mode = 'common'; } $action = GETPOST('action', 'aZ09'); -//var_dump($_POST);exit; $value = GETPOST('value', 'alpha'); $page_y = GETPOST('page_y', 'int'); $search_keyword = GETPOST('search_keyword', 'alpha'); diff --git a/htdocs/admin/mrp.php b/htdocs/admin/mrp.php index 54efdc4df19..fac6a3f3d41 100644 --- a/htdocs/admin/mrp.php +++ b/htdocs/admin/mrp.php @@ -37,6 +37,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'mrp'; diff --git a/htdocs/admin/oauth.php b/htdocs/admin/oauth.php index 9bf5be2c294..a0d82d1d6bd 100644 --- a/htdocs/admin/oauth.php +++ b/htdocs/admin/oauth.php @@ -27,6 +27,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; +// $supportedoauth2array is defined into oauth.lib.php // Define $urlwithroot $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); @@ -96,10 +97,12 @@ print ''; $i = 0; -// $list is defined into oauth.lib.php +// $list is defined into oauth.lib.php to the list of supporter OAuth providers. foreach ($list as $key) { $supported = 0; - if (in_array($key[0], array_keys($supportedoauth2array))) { + $keyforsupportedoauth2array = $key[0]; + + if (in_array($keyforsupportedoauth2array, array_keys($supportedoauth2array))) { $supported = 1; } if (!$supported) { @@ -110,20 +113,23 @@ foreach ($list as $key) { print ''; // Api Name - $label = $langs->trans($key[0]); - print ''; + $label = $langs->trans($keyforsupportedoauth2array); print ''; + print ''; print ''; if ($supported) { - $redirect_uri = $urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$key[0]].'_oauthcallback.php'; + $redirect_uri = $urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$keyforsupportedoauth2array]['callbackfile'].'_oauthcallback.php'; print ''; print ''; - print ''; } else { print ''; diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php index 8697b400a2b..73a9139f856 100644 --- a/htdocs/admin/oauthlogintokens.php +++ b/htdocs/admin/oauthlogintokens.php @@ -25,17 +25,13 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // This define $list +require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // This define $list and $supportedoauth2array require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; use OAuth\Common\Storage\DoliStorage; // Load translation files required by the page $langs->loadLangs(array('admin', 'printing', 'oauth')); -if (!$user->admin) { - accessforbidden(); -} - $action = GETPOST('action', 'aZ09'); $mode = GETPOST('mode', 'alpha'); $value = GETPOST('value', 'alpha'); @@ -50,6 +46,10 @@ if (!$mode) { $mode = 'setup'; } +if (!$user->admin) { + accessforbidden(); +} + /* * Action @@ -122,7 +122,7 @@ $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domai $form = new Form($db); -llxHeader('', $langs->trans("PrintingSetup")); +llxHeader('', $langs->trans("TokenManager")); $linkback = ''.$langs->trans("BackToModuleList").''; print load_fiche_titre($langs->trans('ConfigOAuth'), $linkback, 'title_setup'); @@ -140,7 +140,9 @@ if ($mode == 'setup' && $user->admin) { foreach ($list as $key) { $supported = 0; - if (in_array($key[0], array_keys($supportedoauth2array))) { + $keyforsupportedoauth2array = $key[0]; + + if (in_array($keyforsupportedoauth2array, array_keys($supportedoauth2array))) { $supported = 1; } if (!$supported) { @@ -148,34 +150,44 @@ if ($mode == 'setup' && $user->admin) { } - $OAUTH_SERVICENAME = 'Unknown'; - if ($key[0] == 'OAUTH_GITHUB_NAME') { - $OAUTH_SERVICENAME = 'GitHub'; + $OAUTH_SERVICENAME = empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name']; + + // Define $shortscope, $urltorenew, $urltodelete, $urltocheckperms + // TODO Use array $supportedoauth2array + if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') { // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). // We pass this param list in to 'state' because we need it before and after the redirect. $shortscope = 'user,public_repo'; $urltorenew = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltocheckperms = 'https://github.com/settings/applications/'; - } elseif ($key[0] == 'OAUTH_GOOGLE_NAME') { - $OAUTH_SERVICENAME = 'Google'; + } elseif ($keyforsupportedoauth2array == 'OAUTH_GOOGLE_NAME') { // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). - // We pass this param list in to 'state' because we need it before and after the redirect. - $shortscope = 'userinfo_email,userinfo_profile,cloud_print'; - if (!empty($conf->global->OAUTH_GSUITE)) { + // List of scopes for Google are here: https://developers.google.com/identity/protocols/oauth2/scopes + // We pass this key list into the param 'state' because we need it before and after the redirect. + $shortscope = 'userinfo_email,userinfo_profile'; + $shortscope .= ',openid,email,profile'; // For openid connect + if (!empty($conf->printing->enabled)) { + $shortscope .= ',cloud_print'; + } + if (!empty($conf->global->OAUTH_GOOGLE_GSUITE)) { $shortscope .= ',admin_directory_user'; } - //$scope.=',gmail_full'; - $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + if (!empty($conf->global->OAUTH_GOOGLE_GMAIL)) { + $shortscope.=',gmail_full'; + } + + $oauthstateanticsrf = bin2hex(random_bytes(128/8)); + $_SESSION['oauthstateanticsrf'] = $shortscope.'-'.$oauthstateanticsrf; + + $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'-'.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltocheckperms = 'https://security.google.com/settings/security/permissions'; - } elseif ($key[0] == 'OAUTH_STRIPE_TEST_NAME') { - $OAUTH_SERVICENAME = 'StripeTest'; + } elseif ($keyforsupportedoauth2array == 'OAUTH_STRIPE_TEST_NAME') { $urltorenew = $urlwithroot.'/core/modules/oauth/stripetest_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = ''; $urltocheckperms = ''; - } elseif ($key[0] == 'OAUTH_STRIPE_LIVE_NAME') { - $OAUTH_SERVICENAME = 'StripeLive'; + } elseif ($keyforsupportedoauth2array == 'OAUTH_STRIPE_LIVE_NAME') { $urltorenew = $urlwithroot.'/core/modules/oauth/stripelive_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = ''; $urltocheckperms = ''; @@ -230,11 +242,14 @@ if ($mode == 'setup' && $user->admin) { print ''; print ''; - print '
'; + print '
'; print '
'.$label.''; - if (!empty($key[3])) { - print $langs->trans($key[3]); + print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); + print $label; + print ''; + if (!empty($supportedoauth2array[$keyforsupportedoauth2array]['urlforapp'])) { + print $langs->trans($supportedoauth2array[$keyforsupportedoauth2array]['urlforapp']); } print '
'.$langs->trans("UseTheFollowingUrlAsRedirectURI").''; + print ''; print '
'."\n"; print ''; - print ''; + print ''; print ''; print ''; print "\n"; @@ -244,7 +259,7 @@ if ($mode == 'setup' && $user->admin) { //var_dump($key); print $langs->trans("OAuthIDSecret").''; print ''; print ''; @@ -259,7 +274,7 @@ if ($mode == 'setup' && $user->admin) { if (is_object($tokenobj)) { print $langs->trans("HasAccessToken"); } else { - print $langs->trans("NoAccessToken"); + print ''.$langs->trans("NoAccessToken").''; } print ''; print ''; +print '"; +print ''; +print ''; +print ''; + +print ''; +print '"; +print ''; +print ''; +print ''; + +print ''; + +print '
'.$langs->trans($key[0]).''; + print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); + print $langs->trans($keyforsupportedoauth2array); + print '
'; - print $langs->trans("SeePreviousTab"); + print ''.$langs->trans("SeePreviousTab").''; print ''; print ''; @@ -346,7 +361,7 @@ if ($mode == 'setup' && $user->admin) { if ($mode == 'test' && $user->admin) { print $langs->trans('PrintTestDesc'.$driver)."

\n"; - print '
'; + print '
'; print ''; if (!empty($driver)) { require_once DOL_DOCUMENT_ROOT.'/core/modules/printing/'.$driver.'.modules.php'; diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index 33f8f5b87f2..fd8377b0a27 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -96,9 +96,9 @@ if ($action == 'update') { dolibarr_set_const($db, "MAIN_PDF_NO_RECIPENT_FRAME", GETPOST("MAIN_PDF_NO_RECIPENT_FRAME"), 'chaine', 0, '', $conf->entity); } - if (GETPOSTISSET('MAIN_PDF_HIDE_SENDER_NAME')) { + /*if (GETPOSTISSET('MAIN_PDF_HIDE_SENDER_NAME')) { dolibarr_set_const($db, "MAIN_PDF_HIDE_SENDER_NAME", GETPOST("MAIN_PDF_HIDE_SENDER_NAME"), 'chaine', 0, '', $conf->entity); - } + }*/ if (GETPOSTISSET('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT')) { dolibarr_set_const($db, "MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT", GETPOST("MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT"), 'chaine', 0, '', $conf->entity); @@ -307,6 +307,18 @@ print '
'; print '
'; print ''; +// Show sender name + +/* Set option as hidden because no need of this for 99.99% of users. +print ''; +*/ + // Hide VAT Intra on address print ''; - //Invert sender and recipient print ''; -print ''; - -print ''; - // Desc print ''; +// Swicth in Bold + +print ''; + +// Swicth in Bold + +print ''; + // SHOW_SUBPRODUCT_REF_IN_PDF - Option to show the detail of product ref for kits. print ''; print ''; print "\n"; +// Auto mark ticket read when created from backoffice +print ''; +print ''; +print ''; +print ''; + // Auto assign ticket at user who created it -print ''; +print ''; +print ''; print ''; print ''; -print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'.$langs->trans("MAIN_PDF_HIDE_SENDER_NAME").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_PDF_HIDE_SENDER_NAME'); +} else { + print $form->selectyesno('MAIN_PDF_HIDE_SENDER_NAME', (!empty($conf->global->MAIN_PDF_HIDE_SENDER_NAME)) ? $conf->global->MAIN_PDF_HIDE_SENDER_NAME : 0, 1); +} +print '
'.$langs->trans("ShowVATIntaInAddress").''; @@ -358,16 +370,6 @@ if ($conf->use_javascript_ajax) { print $form->selectarray("MAIN_PDF_NO_RECIPENT_FRAME", $arrval, $conf->global->MAIN_PDF_NO_RECIPENT_FRAME); } -// Show sender name - -print '
'.$langs->trans("MAIN_PDF_HIDE_SENDER_NAME").''; -if ($conf->use_javascript_ajax) { - print ajax_constantonoff('MAIN_PDF_HIDE_SENDER_NAME'); -} else { - print $form->selectyesno('MAIN_PDF_HIDE_SENDER_NAME', (!empty($conf->global->MAIN_PDF_HIDE_SENDER_NAME)) ? $conf->global->MAIN_PDF_HIDE_SENDER_NAME : 0, 1); -} -print '
'.$langs->trans("SwapSenderAndRecipientOnPDF").''; @@ -506,22 +508,6 @@ if ($conf->use_javascript_ajax) { } print '
'.$langs->trans("BoldLabelOnPDF").''; -if ($conf->use_javascript_ajax) { - print ajax_constantonoff('PDF_BOLD_PRODUCT_LABEL'); -} else { - print $form->selectyesno('PDF_BOLD_PRODUCT_LABEL', (!empty($conf->global->PDF_BOLD_PRODUCT_LABEL)) ? $conf->global->PDF_BOLD_PRODUCT_LABEL : 0, 1); -} -print '
'.$langs->trans("BoldRefAndPeriodOnPDF").''; -if ($conf->use_javascript_ajax) { - print ajax_constantonoff('PDF_BOLD_PRODUCT_REF_AND_PERIOD'); -} else { - print $form->selectyesno('PDF_BOLD_PRODUCT_REF_AND_PERIOD', (!empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) ? $conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD : 0, 1); -} -print '
'.$langs->trans("HideDescOnPDF").''; @@ -542,6 +528,26 @@ if ($conf->use_javascript_ajax) { } print '
'.$langs->trans("BoldLabelOnPDF").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('PDF_BOLD_PRODUCT_LABEL'); +} else { + print $form->selectyesno('PDF_BOLD_PRODUCT_LABEL', (!empty($conf->global->PDF_BOLD_PRODUCT_LABEL)) ? $conf->global->PDF_BOLD_PRODUCT_LABEL : 0, 1); +} +print '
'.$langs->trans("BoldRefAndPeriodOnPDF").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('PDF_BOLD_PRODUCT_REF_AND_PERIOD'); +} else { + print $form->selectyesno('PDF_BOLD_PRODUCT_REF_AND_PERIOD', (!empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) ? $conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD : 0, 1); +} +print '
'.$langs->trans("SHOW_SUBPRODUCT_REF_IN_PDF", $langs->transnoentitiesnoconv("AssociatedProductsAbility"), $langs->transnoentitiesnoconv("Products")).''; diff --git a/htdocs/admin/propal.php b/htdocs/admin/propal.php index 22ce045a7ab..6384c561967 100644 --- a/htdocs/admin/propal.php +++ b/htdocs/admin/propal.php @@ -43,6 +43,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'propal'; diff --git a/htdocs/admin/reception_setup.php b/htdocs/admin/reception_setup.php index 218cc1ef853..26300ece329 100644 --- a/htdocs/admin/reception_setup.php +++ b/htdocs/admin/reception_setup.php @@ -36,6 +36,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'reception'; diff --git a/htdocs/admin/sms.php b/htdocs/admin/sms.php index 05abf8c3995..19a94d05dd8 100644 --- a/htdocs/admin/sms.php +++ b/htdocs/admin/sms.php @@ -62,7 +62,7 @@ if ($action == 'update' && !$cancel) { // Send sms -if ($action == 'send' && !$_POST['cancel']) { +if ($action == 'send' && !$cancel) { $error = 0; $smsfrom = ''; diff --git a/htdocs/admin/supplier_order.php b/htdocs/admin/supplier_order.php index 808528cdc0a..0da79845d14 100644 --- a/htdocs/admin/supplier_order.php +++ b/htdocs/admin/supplier_order.php @@ -43,6 +43,8 @@ if (!$user->admin) { $type = GETPOST('type', 'alpha'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $action = GETPOST('action', 'aZ09'); $scandir = GETPOST('scan_dir', 'alpha'); diff --git a/htdocs/admin/supplier_payment.php b/htdocs/admin/supplier_payment.php index b31e4c9a433..a41f9fdf80c 100644 --- a/htdocs/admin/supplier_payment.php +++ b/htdocs/admin/supplier_payment.php @@ -37,6 +37,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scandir', 'alpha'); $type = 'supplier_payment'; diff --git a/htdocs/admin/supplier_proposal.php b/htdocs/admin/supplier_proposal.php index 6e3f190aeb6..9bd684afb22 100644 --- a/htdocs/admin/supplier_proposal.php +++ b/htdocs/admin/supplier_proposal.php @@ -38,6 +38,8 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scan_dir', 'alpha'); $type = 'supplier_proposal'; diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php index 9321fa11c12..c48acebe140 100644 --- a/htdocs/admin/system/security.php +++ b/htdocs/admin/system/security.php @@ -99,6 +99,7 @@ if (!ini_get('session.cookie_samesite') || ini_get('session.cookie_samesite') == } print "
\n"; print "PHP open_basedir = ".(ini_get('open_basedir') ? ini_get('open_basedir') : yn(0).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("ARestrictedPath").', '.$langs->transnoentitiesnoconv("Example").': '.$_SERVER["DOCUMENT_ROOT"].','.DOL_DATA_ROOT).')')."
\n"; +print "PHP short_open_tag = ".((empty(ini_get('short_open_tag')) || ini_get('short_open_tag') == 'Off') ? yn(0) : img_warning().' '.yn(0)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).')'."
\n"; print "PHP allow_url_fopen = ".(ini_get('allow_url_fopen') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning').' '.ini_get('allow_url_fopen') : yn(0)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).")
\n"; print "PHP allow_url_include = ".(ini_get('allow_url_include') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning').' '.ini_get('allow_url_include') : yn(0)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).")
\n"; //print "PHP safe_mode = ".(ini_get('safe_mode') ? ini_get('safe_mode') : yn(0)).'   '.$langs->trans("Deprecated")." (removed in PHP 5.4)
\n"; diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index 03fd647dd29..c36f6ae1d1b 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -38,6 +38,8 @@ if (!$user->admin) { // Parameters $value = GETPOST('value', 'alpha'); $action = GETPOST('action', 'aZ09'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $label = GETPOST('label', 'alpha'); $scandir = GETPOST('scandir', 'alpha'); $type = 'ticket'; @@ -141,6 +143,20 @@ if ($action == 'updateMask') { } } +if ($action == 'setvarworkflow') { + $param_auto_read = GETPOST('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'alpha'); + $res = dolibarr_set_const($db, 'TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', $param_auto_read, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + $param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha'); + $res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } +} + if ($action == 'setvarother') { $param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha'); $res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity); @@ -176,8 +192,14 @@ if ($action == 'setvarother') { $error++; } - $param_auto_assign = GETPOST('TICKET_AUTO_ASSIGN_USER_CREATE', 'alpha'); - $res = dolibarr_set_const($db, 'TICKET_AUTO_ASSIGN_USER_CREATE', $param_auto_assign, 'chaine', 0, '', $conf->entity); + $param_delay_first_response = GETPOST('delay_first_response', 'int'); + $res = dolibarr_set_const($db, 'TICKET_DELAY_BEFORE_FIRST_RESPONSE', $param_delay_first_response, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + $param_delay_between_responses = GETPOST('delay_between_responses', 'int'); + $res = dolibarr_set_const($db, 'TICKET_DELAY_SINCE_LAST_RESPONSE', $param_delay_between_responses, 'chaine', 0, '', $conf->entity); if (!($res > 0)) { $error++; } @@ -465,7 +487,7 @@ print '
'; if (!$conf->use_javascript_ajax) { print '
'; print ''; - print ''; + print ''; } print load_fiche_titre($langs->trans("Other"), '', ''); @@ -477,8 +499,24 @@ print '
'.$langs->trans("TicketsAutoReadTicket").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND'); +} else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND", $arrval, $conf->global->TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND); +} +print ''; +print $form->textwithpicto('', $langs->trans("TicketsAutoReadTicketHelp"), 1, 'help'); +print '
'.$langs->trans("TicketsAutoAssignTicket").'
'.$langs->trans("TicketsAutoAssignTicket").''; if ($conf->use_javascript_ajax) { print ajax_constantonoff('TICKET_AUTO_ASSIGN_USER_CREATE'); @@ -492,12 +530,41 @@ print $form->textwithpicto('', $langs->trans("TicketsAutoAssignTicketHelp"), 1, print '

'; - if (!$conf->use_javascript_ajax) { print ''; } +// Define wanted maximum time elapsed before answers to tickets +print '
'; +print ''; + +print '
'.$langs->trans("TicketsDelayBeforeFirstAnswer")." + + + '; +print $form->textwithpicto('', $langs->trans("TicketsDelayBeforeFirstAnswerHelp"), 1, 'help'); +print '
'.$langs->trans("TicketsDelayBetweenAnswers")." + + + '; +print $form->textwithpicto('', $langs->trans("TicketsDelayBetweenAnswersHelp"), 1, 'help'); +print '

'; + + // Admin var of module print load_fiche_titre($langs->trans("Notification"), '', ''); diff --git a/htdocs/admin/user.php b/htdocs/admin/user.php index 85ab0f0e9a8..53de8fe2502 100644 --- a/htdocs/admin/user.php +++ b/htdocs/admin/user.php @@ -43,9 +43,11 @@ $extrafields = new ExtraFields($db); $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php $value = GETPOST('value', 'alpha'); $label = GETPOST('label', 'alpha'); + $scandir = GETPOST('scandir', 'alpha'); $type = 'user'; diff --git a/htdocs/admin/usergroup.php b/htdocs/admin/usergroup.php index 3319ab994a6..709b60068f7 100644 --- a/htdocs/admin/usergroup.php +++ b/htdocs/admin/usergroup.php @@ -42,6 +42,8 @@ $extrafields = new ExtraFields($db); $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + $type = 'group'; /* diff --git a/htdocs/admin/website.php b/htdocs/admin/website.php index d1a24ff072c..b5098bfd3ce 100644 --- a/htdocs/admin/website.php +++ b/htdocs/admin/website.php @@ -198,15 +198,15 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $_POST[$listfieldvalue[$i]] = $conf->entity; } if ($value == 'ref') { - $_POST[$listfieldvalue[$i]] = strtolower($_POST[$listfieldvalue[$i]]); + $_POST[$listfieldvalue[$i]] = strtolower(GETPOST($listfieldvalue[$i])); } if ($i) { $sql .= ","; } - if ($_POST[$listfieldvalue[$i]] == '') { + if (GETPOST($listfieldvalue[$i]) == '') { $sql .= "null"; } else { - $sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'"; + $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'"; } $i++; } @@ -259,7 +259,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { if ($_POST[$listfieldvalue[$i]] == '') { $sql .= "null"; } else { - $sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'"; + $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'"; } $i++; } diff --git a/htdocs/admin/workstation.php b/htdocs/admin/workstation.php index e89cbb2fd41..58118827ed4 100644 --- a/htdocs/admin/workstation.php +++ b/htdocs/admin/workstation.php @@ -36,6 +36,7 @@ $langs->loadLangs(array("admin", "workstation")); // Parameters $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php $value = GETPOST('value', 'alpha'); diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index 2a6b5f33a27..fa21c37649f 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -173,6 +173,7 @@ class DolibarrApi unset($object->stats_mrptoproduce); unset($object->element); + unset($object->element_for_permission); unset($object->fk_element); unset($object->table_element); unset($object->table_element_line); diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index 2ab8c7837ac..9c7cc01630d 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -209,7 +209,7 @@ class Setup extends DolibarrApi if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } @@ -239,7 +239,6 @@ class Setup extends DolibarrApi return $list; } - /** * Get the list of states/provinces. * @@ -252,27 +251,34 @@ class Setup extends DolibarrApi * @param string $sortorder Sort order * @param int $limit Number of items per page * @param int $page Page number (starting from zero) - * @param string $filter To filter the countries by name + * @param int $country To filter on country + * @param string $filter To filter the states by name * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" - * @return array List of countries + * @return array List of states * * @url GET dictionary/states * * @throws RestException */ - public function getListOfStates($sortfield = "code_departement", $sortorder = 'ASC', $limit = 100, $page = 0, $filter = '', $sqlfilters = '') + public function getListOfStates($sortfield = "code_departement", $sortorder = 'ASC', $limit = 100, $page = 0, $country = 0, $filter = '', $sqlfilters = '') { $list = array(); // Note: The filter is not applied in the SQL request because it must // be applied to the translated names, not to the names in database. - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."c_departements as t"; + $sql = "SELECT t.rowid FROM ".MAIN_DB_PREFIX."c_departements as t"; + if ($country) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_regions as d ON t.fk_region = d.code_region"; + } $sql .= " WHERE 1 = 1"; + if ($country) { + $sql .= " AND d.fk_pays = ".((int) $country); + } // Add sql filters if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -373,7 +379,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -665,7 +671,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -729,7 +735,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -797,7 +803,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -860,7 +866,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -933,7 +939,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1004,7 +1010,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1078,7 +1084,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1143,9 +1149,9 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(400, 'error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } @@ -1202,9 +1208,9 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(400, 'error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } @@ -1261,7 +1267,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1301,7 +1307,7 @@ class Setup extends DolibarrApi * @param string $sortorder Sort order * @param int $limit Number of items per page * @param int $page Page number (starting from zero) - * @param string $country To filter on country + * @param int $country To filter on country * @param int $active Lega form is active or not {@min 0} {@max 1} * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" * @return array List of legal form @@ -1310,7 +1316,7 @@ class Setup extends DolibarrApi * * @throws RestException */ - public function getListOfLegalForm($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $country = '', $active = 1, $sqlfilters = '') + public function getListOfLegalForm($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $country = 0, $active = 1, $sqlfilters = '') { $list = array(); @@ -1318,13 +1324,13 @@ class Setup extends DolibarrApi $sql .= " FROM ".MAIN_DB_PREFIX."c_forme_juridique as t"; $sql .= " WHERE t.active = ".((int) $active); if ($country) { - $sql .= " AND t.fk_pays = '".$this->db->escape($country)."'"; + $sql .= " AND t.fk_pays = ".((int) $country); } // Add sql filters if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1383,7 +1389,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1449,7 +1455,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1508,7 +1514,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1567,7 +1573,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; @@ -1628,7 +1634,7 @@ class Setup extends DolibarrApi if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { - throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; diff --git a/htdocs/asset/accountancy_codes.php b/htdocs/asset/accountancy_codes.php new file mode 100644 index 00000000000..431b4ba7c68 --- /dev/null +++ b/htdocs/asset/accountancy_codes.php @@ -0,0 +1,189 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/accountancy_code.php + * \ingroup asset + * \brief Card with accountancy code on Asset + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new Asset($db); +$assetaccountancycodes = new AssetAccountancyCodes($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output . '/temp/massgeneration/' . $user->id; +$hookmanager->initHooks(array('assetaccountancycodes', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity] . "/" . $object->id; +} + +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); + +$result = $assetaccountancycodes->fetchAccountancyCodes($object->id); +if ($result < 0) { + setEventMessages($assetaccountancycodes->error, $assetaccountancycodes->errors, 'errors'); +} + + +/* + * Actions + */ + +$reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { + $backurlforlist = DOL_URL_ROOT.'/asset/list.php'; + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = DOL_URL_ROOT.'/asset/accountancy_codes.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__'); + } + } + } + + if ($cancel) { + /*var_dump($cancel);var_dump($backtopage);var_dump($backtopageforcancel);exit;*/ + if (!empty($backtopageforcancel)) { + header("Location: ".$backtopageforcancel); + exit; + } elseif (!empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + $action = ''; + } + + if ($action == "update") { + $assetaccountancycodes->setAccountancyCodesFromPost(); + + $result = $assetaccountancycodes->updateAccountancyCodes($user, $object->id); + if ($result < 0) { + setEventMessages($assetaccountancycodes->error, $assetaccountancycodes->errors, 'errors'); + $action = 'edit'; + } else { + setEventMessage($langs->trans('RecordSaved')); + header("Location: " . $_SERVER["PHP_SELF"] . '?id=' . $object->id); + exit; + } + } +} + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +llxHeader('', $langs->trans('Asset'), $help_url); + +if ($id > 0 || !empty($ref)) { + $head = assetPrepareHead($object); + print dol_get_fiche_head($head, 'accountancy_codes', $langs->trans("Asset"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
'; + $morehtmlref .= '
'; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + print '
'; + + if ($action == 'edit') { + print '
'; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(array(), ''); + + include DOL_DOCUMENT_ROOT . '/asset/tpl/accountancy_codes_edit.tpl.php'; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel(); + + print '
'; + } else { + include DOL_DOCUMENT_ROOT . '/asset/tpl/accountancy_codes_view.tpl.php'; + } + + print dol_get_fiche_end(); + + if ($action != 'edit') { + print '
' . "\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + + if (empty($reshook)) { + if ($object->status == $object::STATUS_DRAFT/* && !empty($object->enabled_modes)*/) { + print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoadd); + } + } + print '
' . "\n"; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/admin/assets_type_extrafields.php b/htdocs/asset/admin/asset_extrafields.php similarity index 56% rename from htdocs/asset/admin/assets_type_extrafields.php rename to htdocs/asset/admin/asset_extrafields.php index 165361f7f57..a84d3bc2016 100644 --- a/htdocs/asset/admin/assets_type_extrafields.php +++ b/htdocs/asset/admin/asset_extrafields.php @@ -1,5 +1,11 @@ +/* Copyright (C) 2001-2002 Rodolphe Quiedeville + * Copyright (C) 2003 Jean-Louis Bergamo + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2012 Regis Houssin + * Copyright (C) 2014 Florian Henry + * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2018 Alexandre Spangaro * * 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 @@ -13,20 +19,20 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * or see https://www.gnu.org/ */ /** - * \file htdocs/asset/admin/assets_type_extrafields.php - * \ingroup asset - * \brief Page to setup extra fields type of assets + * \file htdocs/asset/admin/asset_extrafields.php + * \ingroup asset + * \brief Page to setup extra fields of asset */ + require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/asset.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; // Load translation files required by the page -$langs->loadLangs(array('assets', 'admin')); +$langs->loadLangs(array("assets", "admin", "companies")); $extrafields = new ExtraFields($db); $form = new Form($db); @@ -40,7 +46,7 @@ foreach ($tmptype2label as $key => $val) { $action = GETPOST('action', 'aZ09'); $attrname = GETPOST('attrname', 'alpha'); -$elementtype = 'adherent_type'; //Must be the $table_element of the class that manage extrafield +$elementtype = 'asset'; //Must be the $table_element of the class that manage extrafield if (!$user->admin) { accessforbidden(); @@ -59,38 +65,47 @@ require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; * View */ -$textobject = $langs->transnoentitiesnoconv("AssetsTypes"); +$help_url = ''; +$page_name = "AssetSetup"; +$textobject = $langs->transnoentitiesnoconv("Assets"); -llxHeader('', $langs->trans("AssetsSetup")); - -$linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("AssetsSetup"), $linkback, 'title_setup'); +llxHeader('', $langs->trans("AssetSetup"), $help_url); -$head = asset_admin_prepare_head(); +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); -print dol_get_fiche_head($head, 'attributes_type', $langs->trans("Assets"), -1, 'generic'); + +$head = assetAdminPrepareHead(); + +print dol_get_fiche_head($head, 'asset_extrafields', $langs->trans($page_name), -1, 'asset'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; print dol_get_fiche_end(); + // Buttons if ($action != 'create' && $action != 'edit') { print '"; } -// Creation of an optional field + +/* + * Creation of an optional field + */ if ($action == 'create') { - print "
"; + print '
'; print load_fiche_titre($langs->trans('NewAttribute')); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; } -// Edition of an optional field +/* + * Edition of an optional field + */ if ($action == 'edit' && !empty($attrname)) { print "
"; print load_fiche_titre($langs->trans("FieldEdition", $attrname)); diff --git a/htdocs/asset/admin/assets_extrafields.php b/htdocs/asset/admin/assetmodel_extrafields.php similarity index 54% rename from htdocs/asset/admin/assets_extrafields.php rename to htdocs/asset/admin/assetmodel_extrafields.php index 9a68f99fe06..387c43df635 100644 --- a/htdocs/asset/admin/assets_extrafields.php +++ b/htdocs/asset/admin/assetmodel_extrafields.php @@ -1,6 +1,11 @@ - * Copyright (C) 2018 Alexandre Spangaro +/* Copyright (C) 2001-2002 Rodolphe Quiedeville + * Copyright (C) 2003 Jean-Louis Bergamo + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2012 Regis Houssin + * Copyright (C) 2014 Florian Henry + * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2018 Alexandre Spangaro * * 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 @@ -17,9 +22,9 @@ */ /** - * \file htdocs/asset/admin/assets_extrafields.php + * \file htdocs/asset/admin/assetmodel_extrafields.php * \ingroup asset - * \brief Page to setup extra fields of assets + * \brief Page to setup extra fields of asset model */ require '../../main.inc.php'; @@ -41,7 +46,7 @@ foreach ($tmptype2label as $key => $val) { $action = GETPOST('action', 'aZ09'); $attrname = GETPOST('attrname', 'alpha'); -$elementtype = 'don'; //Must be the $table_element of the class that manage extrafield +$elementtype = 'asset_model'; //Must be the $table_element of the class that manage extrafield if (!$user->admin) { accessforbidden(); @@ -60,17 +65,20 @@ require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; * View */ -$textobject = $langs->transnoentitiesnoconv("Assets"); +$help_url = ''; +$page_name = "AssetSetup"; +$textobject = $langs->transnoentitiesnoconv("AssetModels"); -llxHeader('', $langs->trans("AssetsSetup")); - -$linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("AssetsSetup"), $linkback, 'title_setup'); +llxHeader('', $langs->trans("AssetSetup"), $help_url); -$head = asset_admin_prepare_head(); +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); -print dol_get_fiche_head($head, 'attributes', $langs->trans("Assets"), -1, 'generic'); + +$head = assetAdminPrepareHead(); + +print dol_get_fiche_head($head, 'assetmodel_extrafields', $langs->trans($page_name), -1, 'asset'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; @@ -80,29 +88,24 @@ print dol_get_fiche_end(); // Buttons if ($action != 'create' && $action != 'edit') { print '"; } -/* ************************************************************************** */ -/* */ -/* Create optional field */ -/* */ -/* ************************************************************************** */ - +/* + * Creation of an optional field + */ if ($action == 'create') { - print "
"; + print '
'; print load_fiche_titre($langs->trans('NewAttribute')); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; } -/* ************************************************************************** */ -/* */ -/* Edit optional field */ -/* */ -/* ************************************************************************** */ +/* + * Edition of an optional field + */ if ($action == 'edit' && !empty($attrname)) { print "
"; print load_fiche_titre($langs->trans("FieldEdition", $attrname)); diff --git a/htdocs/asset/admin/setup.php b/htdocs/asset/admin/setup.php index a90c2b479c4..afa4777de3d 100644 --- a/htdocs/asset/admin/setup.php +++ b/htdocs/asset/admin/setup.php @@ -18,8 +18,8 @@ /** * \file htdocs/asset/admin/setup.php - * \ingroup assets - * \brief Assets setup page. + * \ingroup asset + * \brief Asset setup page. */ require '../../main.inc.php'; @@ -40,30 +40,421 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); -$arrayofparameters = array('FIXEDASSETS_MYPARAM1'=>array('css'=>'minwidth200'), 'FIXEDASSETS_MYPARAM2'=>array('css'=>'minwidth500')); +$value = GETPOST('value', 'alpha'); +$label = GETPOST('label', 'alpha'); +$scandir = GETPOST('scan_dir', 'alpha'); +$type = 'asset'; + +$arrayofparameters = array( + 'ASSET_ACCOUNTANCY_CATEGORY'=>array('type'=>'accountancy_category', 'enabled'=>1), + 'ASSET_DEPRECIATION_DURATION_PER_YEAR'=>array('type'=>'string', 'css'=>'minwidth200', 'enabled'=>1), + //'ASSET_MYPARAM2'=>array('type'=>'textarea','enabled'=>1), + //'ASSET_MYPARAM3'=>array('type'=>'category:'.Categorie::TYPE_CUSTOMER, 'enabled'=>1), + //'ASSET_MYPARAM4'=>array('type'=>'emailtemplate:thirdparty', 'enabled'=>1), + //'ASSET_MYPARAM5'=>array('type'=>'yesno', 'enabled'=>1), + //'ASSET_MYPARAM5'=>array('type'=>'thirdparty_type', 'enabled'=>1), + //'ASSET_MYPARAM6'=>array('type'=>'securekey', 'enabled'=>1), + //'ASSET_MYPARAM7'=>array('type'=>'product', 'enabled'=>1), +); + +$error = 0; +$setupnotempty = 0; + +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); /* * Actions */ -include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; +if ((float) DOL_VERSION >= 6) { + include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; +} + +if ($action == 'updateMask') { + $maskconstorder = GETPOST('maskconstorder', 'alpha'); + $maskorder = GETPOST('maskorder', 'alpha'); + + if ($maskconstorder) { + $res = dolibarr_set_const($db, $maskconstorder, $maskorder, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + } + + if (!$error) { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} elseif ($action == 'specimen') { + $modele = GETPOST('module', 'alpha'); + $tmpobjectkey = GETPOST('object'); + + $tmpobject = new $tmpobjectkey($db); + $tmpobject->initAsSpecimen(); + + // Search template files + $file = ''; $classname = ''; $filefound = 0; + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) { + $file = dol_buildpath($reldir."core/modules/asset/doc/pdf_".$modele."_".strtolower($tmpobjectkey).".modules.php", 0); + if (file_exists($file)) { + $filefound = 1; + $classname = "pdf_".$modele; + break; + } + } + + if ($filefound) { + require_once $file; + + $module = new $classname($db); + + if ($module->write_file($tmpobject, $langs) > 0) { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=".strtolower($tmpobjectkey)."&file=SPECIMEN.pdf"); + return; + } else { + setEventMessages($module->error, null, 'errors'); + dol_syslog($module->error, LOG_ERR); + } + } else { + setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors'); + dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR); + } +} elseif ($action == 'setmod') { + // TODO Check if numbering module chosen can be activated by calling method canBeActivated + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'ASSET_'.strtoupper($tmpobjectkey)."_ADDON"; + dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity); + } +} elseif ($action == 'set') { + // Activate a model + $ret = addDocumentModel($value, $type, $label, $scandir); +} elseif ($action == 'del') { + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'ASSET_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if ($conf->global->$constforval == "$value") { + dolibarr_del_const($db, $constforval, $conf->entity); + } + } + } +} elseif ($action == 'setdoc') { + // Set or unset default model + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'ASSET_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if (dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity)) { + // The constant that was read before the new set + // We therefore requires a variable to have a coherent view + $conf->global->$constforval = $value; + } + + // We disable/enable the document template (into llx_document_model table) + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $ret = addDocumentModel($value, $type, $label, $scandir); + } + } +} elseif ($action == 'unsetdoc') { + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'ASSET_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + dolibarr_del_const($db, $constforval, $conf->entity); + } +} + /* * View */ -llxHeader('', $langs->trans("AssetsSetup")); +$form = new Form($db); -$linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("AssetsSetup"), $linkback, 'title_setup'); +$help_url = ''; +$page_name = "AssetSetup"; + +llxHeader('', $langs->trans($page_name), $help_url); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); + +// Configuration header +$head = assetAdminPrepareHead(); +print dol_get_fiche_head($head, 'settings', $langs->trans($page_name), -1, "asset"); + +// Setup page goes here +echo ''.$langs->trans("AssetSetupPage").''; -$head = asset_admin_prepare_head(); +$moduledir = 'asset'; +$myTmpObjects = array(); +$myTmpObjects['Asset'] = array('includerefgeneration'=>1, 'includedocgeneration'=>0); -print dol_get_fiche_head($head, 'settings', $langs->trans("Assets"), -1, 'generic'); +foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'MyObject') { + continue; + } + if ($myTmpObjectArray['includerefgeneration']) { + /* + * Orders Numbering model + */ + $setupnotempty++; + + print load_fiche_titre($langs->trans("NumberingModules", $myTmpObjectKey), '', ''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''."\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/".$moduledir); + + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + if (strpos($file, 'mod_'.strtolower($myTmpObjectKey).'_') === 0 && substr($file, dol_strlen($file) - 3, 3) == 'php') { + $file = substr($file, 0, dol_strlen($file) - 4); + + require_once $dir.'/'.$file.'.php'; + + $module = new $file($db); + + // Show modules according to features level + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) { + continue; + } + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) { + continue; + } + + if ($module->isEnabled()) { + dol_include_once('/'.$moduledir.'/class/'.strtolower($myTmpObjectKey).'.class.php'); + + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $mytmpinstance = new $myTmpObjectKey($db); + $mytmpinstance->initAsSpecimen(); + + // Info + $htmltooltip = ''; + $htmltooltip .= ''.$langs->trans("Version").': '.$module->getVersion().'
'; + + $nextval = $module->getNextValue($mytmpinstance); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= ''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') { + $nextval = $langs->trans($nextval); + } + $htmltooltip .= $nextval.'
'; + } else { + $htmltooltip .= $langs->trans($module->error).'
'; + } + } + + print ''; + + print "\n"; + } + } + } + closedir($handle); + } + } + } + print "
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'.$module->name."\n"; + print $module->info(); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') { + print $langs->trans($tmp); + } else { + print $tmp; + } + print '
'; + $constforvar = 'ASSET_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $file) { + print img_picto($langs->trans("Activated"), 'switch_on'); + } else { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print '

\n"; + } + + if ($myTmpObjectArray['includedocgeneration']) { + /* + * Document templates generators + */ + $setupnotempty++; + $type = strtolower($myTmpObjectKey); + + print load_fiche_titre($langs->trans("DocumentModules", $myTmpObjectKey), '', ''); + + // Load array def with activated templates + $def = array(); + $sql = "SELECT nom"; + $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; + $sql .= " WHERE type = '".$db->escape($type)."'"; + $sql .= " AND entity = ".$conf->entity; + $resql = $db->query($sql); + if ($resql) { + $i = 0; + $num_rows = $db->num_rows($resql); + while ($i < $num_rows) { + $array = $db->fetch_array($resql); + array_push($def, $array[0]); + $i++; + } + } else { + dol_print_error($db); + } + + print "\n"; + print "\n"; + print ''; + print ''; + print '\n"; + print '\n"; + print ''; + print ''; + print "\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) { + foreach (array('', '/doc') as $valdir) { + $realpath = $reldir."core/modules/".$moduledir.$valdir; + $dir = dol_buildpath($realpath); + + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + $filelist[] = $file; + } + closedir($handle); + arsort($filelist); + + foreach ($filelist as $file) { + if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) { + if (file_exists($dir.'/'.$file)) { + $name = substr($file, 4, dol_strlen($file) - 16); + $classname = substr($file, 0, dol_strlen($file) - 12); + + require_once $dir.'/'.$file; + $module = new $classname($db); + + $modulequalified = 1; + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) { + $modulequalified = 0; + } + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) { + $modulequalified = 0; + } + + if ($modulequalified) { + print ''; + + // Active + if (in_array($name, $def)) { + print ''; + } else { + print '"; + } + + // Default + print ''; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip .= '
'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown")); + if ($module->type == 'pdf') { + $htmltooltip .= '
'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + } + $htmltooltip .= '
'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file; + + $htmltooltip .= '

'.$langs->trans("FeaturesSupported").':'; + $htmltooltip .= '
'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1); + $htmltooltip .= '
'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1); + + print ''; + + // Preview + print ''; + + print "\n"; + } + } + } + } + } + } + } + } + + print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
'; + print (empty($module->name) ? $name : $module->name); + print "\n"; + if (method_exists($module, 'info')) { + print $module->info($langs); + } else { + print $module->description; + } + print ''."\n"; + print ''; + print img_picto($langs->trans("Enabled"), 'switch_on'); + print ''; + print ''."\n"; + print 'scandir).'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print "'; + $constforvar = 'ASSET_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $name) { + //print img_picto($langs->trans("Default"), 'on'); + // Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset + print 'scandir).'&label='.urlencode($module->name).'&type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').''; + } else { + print 'scandir).'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print ''; + if ($module->type == 'pdf') { + print ''.img_object($langs->trans("Preview"), 'pdf').''; + } else { + print img_object($langs->trans("PreviewNotAvailable"), 'generic'); + } + print '
'; + } +} if ($action == 'edit') { print '
'; @@ -73,37 +464,221 @@ if ($action == 'edit') { print ''; print ''; - foreach ($arrayofparameters as $key => $val) { - print ''; - } + foreach ($arrayofparameters as $constname => $val) { + if ($val['enabled']==1) { + $setupnotempty++; + print ''; + } + } print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; - print $form->textwithpicto($langs->trans($key), $langs->trans($key.'Tooltip')); - print '
'; + $tooltiphelp = (($langs->trans($constname . 'Tooltip') != $constname . 'Tooltip') ? $langs->trans($constname . 'Tooltip') : ''); + print ''.$form->textwithpicto($langs->trans($constname), $tooltiphelp, 1, 'info', '', 0, 3, 'tootips'.$constname).''; + print ''; + if ($val['type'] == 'textarea') { + print '\n"; + } elseif ($val['type']== 'html') { + require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; + $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); + $doleditor->Create(); + } elseif ($val['type'] == 'yesno') { + print $form->selectyesno($constname, $conf->global->{$constname}, 1); + } elseif (preg_match('/emailtemplate:/', $val['type'])) { + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + + $tmp = explode(':', $val['type']); + $nboftemplates = $formmail->fetchAllEMailTemplate($tmp[1], $user, null, 1); // We set lang=null to get in priority record with no lang + //$arraydefaultmessage = $formmail->getEMailTemplate($db, $tmp[1], $user, null, 0, 1, ''); + $arrayofmessagename = array(); + if (is_array($formmail->lines_model)) { + foreach ($formmail->lines_model as $modelmail) { + //var_dump($modelmail); + $moreonlabel = ''; + if (!empty($arrayofmessagename[$modelmail->label])) { + $moreonlabel = ' (' . $langs->trans("SeveralLangugeVariatFound") . ')'; + } + // The 'label' is the key that is unique if we exclude the language + $arrayofmessagename[$modelmail->id] = $langs->trans(preg_replace('/\(|\)/', '', $modelmail->label)) . $moreonlabel; + } + } + print $form->selectarray($constname, $arrayofmessagename, $conf->global->{$constname}, 'None', 0, 0, '', 0, 0, 0, '', '', 1); + } elseif (preg_match('/category:/', $val['type'])) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; + $formother = new FormOther($db); + + $tmp = explode(':', $val['type']); + print img_picto('', 'category', 'class="pictofixedwidth"'); + print $formother->select_categories($tmp[1], $conf->global->{$constname}, $constname, 0, $langs->trans('CustomersProspectsCategoriesShort')); + } elseif (preg_match('/thirdparty_type/', $val['type'])) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + $formcompany = new FormCompany($db); + print $formcompany->selectProspectCustomerType($conf->global->{$constname}, $constname); + } elseif ($val['type'] == 'securekey') { + print ''; + if (!empty($conf->use_javascript_ajax)) { + print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token'.$constname.'" class="linkobject"'); + } + if (!empty($conf->use_javascript_ajax)) { + print "\n".''; + } + } elseif ($val['type'] == 'product') { + if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + $form->select_produits($selected, $constname, '', 0); + } + } elseif ($val['type'] == 'accountancy_code') { + $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + if (!empty($conf->accounting->enabled)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php'; + $formaccounting = new FormAccounting($db); + print $formaccounting->select_account($selected, $constname, 1, null, 1, 1, 'minwidth150 maxwidth300', 1); + } else { + print ''; + } + } elseif ($val['type'] == 'accountancy_category') { + $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + if (!empty($conf->accounting->enabled)) { + print ''; + // autosuggest from existing account types if found + print ''; + require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountancysystem.class.php'; + $accountsystem = new AccountancySystem($db); + $accountsystem->fetch($conf->global->CHARTOFACCOUNTS); + $sql = 'SELECT DISTINCT pcg_type FROM ' . MAIN_DB_PREFIX . 'accounting_account'; + $sql .= " WHERE fk_pcg_version = '" . $db->escape($accountsystem->ref) . "'"; + $sql .= ' AND entity in ('.getEntity('accounting_account', 0).')'; // Always limit to current entity. No sharing in accountancy. + $sql .= ' LIMIT 50000'; // just as a sanity check + $resql = $db->query($sql); + if ($resql) { + while ($obj = $db->fetch_object($resql)) { + print ''; + } else { + print ''; + } + } else { + print ''; + } + print '
'; - print $form->buttonsSaveCancel("Save", ''); + print '
'; + print ''; + print '
'; print '
'; print '
'; } else { - print ''; - print ''; + if (!empty($arrayofparameters)) { + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + print ''; - foreach ($arrayofparameters as $key => $val) { - print ''; + foreach ($arrayofparameters as $constname => $val) { + if ($val['enabled']==1) { + $setupnotempty++; + print ''; + } + } + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; - print $form->textwithpicto($langs->trans($key), $langs->trans($key.'Tooltip')); - print ''.$conf->global->$key.'
'; + $tooltiphelp = (($langs->trans($constname . 'Tooltip') != $constname . 'Tooltip') ? $langs->trans($constname . 'Tooltip') : ''); + print $form->textwithpicto($langs->trans($constname), $tooltiphelp); + print ''; + + if ($val['type'] == 'textarea') { + print dol_nl2br($conf->global->{$constname}); + } elseif ($val['type']== 'html') { + print $conf->global->{$constname}; + } elseif ($val['type'] == 'yesno') { + print ajax_constantonoff($constname); + } elseif (preg_match('/emailtemplate:/', $val['type'])) { + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + + $tmp = explode(':', $val['type']); + + $template = $formmail->getEMailTemplate($db, $tmp[1], $user, $langs, $conf->global->{$constname}); + if ($template<0) { + setEventMessages(null, $formmail->errors, 'errors'); + } + print $langs->trans($template->label); + } elseif (preg_match('/category:/', $val['type'])) { + $c = new Categorie($db); + $result = $c->fetch($conf->global->{$constname}); + if ($result < 0) { + setEventMessages(null, $c->errors, 'errors'); + } elseif ($result > 0 ) { + $ways = $c->print_all_ways(' >> ', 'none', 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formated text + $toprint = array(); + foreach ($ways as $way) { + $toprint[] = '
  • color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '
  • '; + } + print '
      ' . implode(' ', $toprint) . '
    '; + } + } elseif (preg_match('/thirdparty_type/', $val['type'])) { + if ($conf->global->{$constname}==2) { + print $langs->trans("Prospect"); + } elseif ($conf->global->{$constname}==3) { + print $langs->trans("ProspectCustomer"); + } elseif ($conf->global->{$constname}==1) { + print $langs->trans("Customer"); + } elseif ($conf->global->{$constname}==0) { + print $langs->trans("NorProspectNorCustomer"); + } + } elseif ($val['type'] == 'product') { + $product = new Product($db); + $resprod = $product->fetch($conf->global->{$constname}); + if ($resprod > 0) { + print $product->ref; + } elseif ($resprod < 0) { + setEventMessages(null, $object->errors, "errors"); + } + } elseif ($val['type'] == 'accountancy_code') { + if (!empty($conf->accounting->enabled)) { + require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php'; + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('', $conf->global->{$constname}, 1); + + print $accountingaccount->getNomUrl(0, 1, 1, '', 1); + } else { + print $conf->global->{$constname}; + } + } else { + print $conf->global->{$constname}; + } + print '
    '; + + print '
    '; + print ''.$langs->trans("Modify").''; + print '
    '; + } else { + print '
    '.$langs->trans("NothingToSetup"); } - - print ''; - - print '
    '; - print ''.$langs->trans("Modify").''; - print '
    '; } +if (empty($setupnotempty)) { + print '
    '.$langs->trans("NothingToSetup"); +} + +// Page end print dol_get_fiche_end(); -// End of page llxFooter(); $db->close(); diff --git a/htdocs/asset/agenda.php b/htdocs/asset/agenda.php new file mode 100644 index 00000000000..49a0c215701 --- /dev/null +++ b/htdocs/asset/agenda.php @@ -0,0 +1,215 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 . + */ + +/** + * \file htdocs/asset/agenda.php + * \ingroup asset + * \brief Tab of events on Asset + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/asset/class/asset.class.php'; +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode', 'array')) { + $actioncode = GETPOST('actioncode', 'array', 3); + if (!count($actioncode)) { + $actioncode = '0'; + } +} else { + $actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : (empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label = GETPOST('search_agenda_label'); + +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST("sortfield", 'alpha'); +$sortorder = GETPOST("sortorder", 'alpha'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { + $page = 0; +} // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortfield) { + $sortfield = 'a.datep,a.id'; +} +if (!$sortorder) { + $sortorder = 'DESC,DESC'; +} + +// Initialize technical objects +$object = new Asset($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('assetagenda', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity]."/".$object->id; +} + +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array('id'=>$id); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Cancel + if (GETPOST('cancel', 'alpha') && !empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $actioncode = ''; + $search_agenda_label = ''; + } +} + + + +/* + * View + */ + +$form = new Form($db); + +if ($object->id > 0) { + $title = $langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = 'EN:Module_Agenda_En'; + llxHeader('', $title, $help_url); + + if (!empty($conf->notification->enabled)) { + $langs->load("mails"); + } + $head = assetPrepareHead($object); + + + print dol_get_fiche_head($head, 'agenda', $langs->trans("Asset"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + + $object->info($object->id); + dol_print_object_info($object, 1); + + print '
    '; + + print dol_get_fiche_end(); + + + // Actions buttons + + $objthirdparty = $object; + $objcon = new stdClass(); + + $out = '&origin=' . urlencode($object->element . '@' . $object->module) . '&originid=' . urlencode($object->id); + $urlbacktopage = $_SERVER['PHP_SELF'] . '?id=' . $object->id; + $out .= '&backtopage=' . urlencode($urlbacktopage); + $permok = $user->rights->agenda->myactions->create; + if ((!empty($objthirdparty->id) || !empty($objcon->id)) && $permok) { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
    '; + + if (!empty($conf->agenda->enabled)) { + if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) { + print '' . $langs->trans("AddAction") . ''; + } else { + print '' . $langs->trans("AddAction") . ''; + } + } + + print '
    '; + + if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { + $param = '&id=' . $object->id . '&socid=' . $socid; + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage=' . urlencode($contextpage); + } + if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit=' . urlencode($limit); + } + + + print load_fiche_titre($langs->trans("ActionsOnAsset"), '', ''); + + // List of all actions + $filters = array(); + $filters['search_agenda_label'] = $search_agenda_label; + + // TODO Replace this with same code than into list.php + show_actions_done($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module); + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/card.php b/htdocs/asset/card.php index 35c0ffcff88..c516866b7d0 100644 --- a/htdocs/asset/card.php +++ b/htdocs/asset/card.php @@ -1,6 +1,6 @@ - * Copyright (C) 2018 Alexandre Spangaro +/* Copyright (C) 2017 Laurent Destailleur + * Copyright (C) 2018 Alexandre Spangaro * * 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 @@ -29,7 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; // Load translation files required by the page -$langs->loadLangs(array("asset")); +$langs->loadLangs(array("assets", "other")); // Get parameters $id = GETPOST('id', 'int'); @@ -68,12 +68,6 @@ if (empty($action) && empty($id) && empty($ref)) { // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. -// Security check -if (!empty($user->socid)) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'asset', $id); - $permissiontoread = $user->rights->asset->read; $permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php $permissiontodelete = $user->rights->asset->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); @@ -81,7 +75,13 @@ $permissionnote = $user->rights->asset->write; // Used by the include of actions $permissiondellink = $user->rights->asset->write; // Used by the include of actions_dellink.inc.php $upload_dir = $conf->asset->multidir_output[isset($object->entity) ? $object->entity : 1]; -$error = 0; +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +if ($user->socid > 0) $socid = $user->socid; +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); /* @@ -95,6 +95,8 @@ if ($reshook < 0) { } if (empty($reshook)) { + $error = 0; + $backurlforlist = DOL_URL_ROOT.'/asset/list.php'; if (empty($backtopage) || ($cancel && empty($id))) { @@ -107,6 +109,27 @@ if (empty($reshook)) { } } + $object->oldcopy = dol_clone($object); + $triggermodname = 'ASSET_MODIFY'; // Name of trigger action code to execute when we modify record + + // Action dispose object + if ($action == 'confirm_disposal' && $confirm == 'yes' && $permissiontoadd) { + $object->disposal_date = dol_mktime(12, 0, 0, GETPOST('disposal_datemonth', 'int'), GETPOST('disposal_dateday', 'int'), GETPOST('disposal_dateyear', 'int')); // for date without hour, we use gmt + $object->disposal_amount_ht = GETPOST('disposal_amount', 'int'); + $object->fk_disposal_type = GETPOST('fk_disposal_type', 'int'); + $disposal_invoice_id = GETPOST('disposal_invoice_id', 'int'); + $object->disposal_depreciated = ((GETPOST('disposal_depreciated') == '1' || GETPOST('disposal_depreciated') == 'on') ? 1 : 0); + $object->disposal_subject_to_vat = ((GETPOST('disposal_subject_to_vat') == '1' || GETPOST('disposal_subject_to_vat') == 'on') ? 1 : 0); + + $result = $object->dispose($user, $disposal_invoice_id); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } + $action = ''; + } elseif ($action == "add") { + $object->supplier_invoice_id = GETPOST('supplier_invoice_id', 'int'); + } + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; @@ -122,13 +145,6 @@ if (empty($reshook)) { // Action to build doc include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; - if ($action == 'set_thirdparty' && $permissiontoadd) { - $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, 'MYOBJECT_MODIFY'); - } - if ($action == 'classin' && $permissiontoadd) { - $object->setProject(GETPOST('projectid', 'int')); - } - // Actions to send emails $triggersendname = 'ASSET_SENTBYMAIL'; $autocopy = 'MAIN_MAIL_AUTOCOPY_ASSET_TO'; @@ -136,6 +152,7 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; } + /* * View * @@ -150,7 +167,7 @@ llxHeader('', $title, $help_url); // Part to create if ($action == 'create') { - print load_fiche_titre($langs->trans("NewAsset"), '', $object->picto); + print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Asset")), '', 'object_'.$object->picto); print '
    '; print ''; @@ -161,9 +178,16 @@ if ($action == 'create') { if ($backtopageforcancel) { print ''; } + if (GETPOSTISSET('supplier_invoice_id')) { + $object->fields['supplier_invoice_id'] = array('type' => 'integer:FactureFournisseur:fourn/class/fournisseur.facture.class.php:1:entity IN (__SHARED_ENTITIES__)', 'label' => 'SupplierInvoice', 'enabled' => '1', 'noteditable' => '1', 'position' => 280, 'notnull' => 0, 'visible' => 1, 'index' => 1, 'validate' => '1',); + print ''; + } print dol_get_fiche_head(array(), ''); + // Set some default values + //if (! GETPOSTISSET('fieldname')) $_POST['fieldname'] = 'myvalue'; + print ''."\n"; // Common attributes @@ -185,12 +209,11 @@ if ($action == 'create') { // Part to edit record if (($id || $ref) && $action == 'edit') { - print load_fiche_titre($langs->trans("Assets")); + print load_fiche_titre($langs->trans("Asset"), '', 'object_'.$object->picto); print ''; print ''; print ''; - print ''; print ''; if ($backtopage) { print ''; @@ -222,18 +245,60 @@ if (($id || $ref) && $action == 'edit') { if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { $res = $object->fetch_optionals(); - $head = asset_prepare_head($object); + $head = assetPrepareHead($object); print dol_get_fiche_head($head, 'card', $langs->trans("Asset"), -1, $object->picto); $formconfirm = ''; // Confirmation to delete if ($action == 'delete') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteAssets'), $langs->trans('ConfirmDeleteAsset'), 'confirm_delete', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteAsset'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); + } elseif ($action == 'disposal') { + // Disposal + $langs->load('bills'); + + $disposal_date = dol_mktime(12, 0, 0, GETPOST('disposal_datemonth', 'int'), GETPOST('disposal_dateday', 'int'), GETPOST('disposal_dateyear', 'int')); // for date without hour, we use gmt + $disposal_amount = GETPOST('disposal_amount', 'int'); + $fk_disposal_type = GETPOST('fk_disposal_type', 'int'); + $disposal_invoice_id = GETPOST('disposal_invoice_id', 'int'); + $disposal_depreciated = GETPOSTISSET('disposal_depreciated') ? GETPOST('disposal_depreciated') : 1; + $disposal_depreciated = !empty($disposal_depreciated) ? 1 : 0; + $disposal_subject_to_vat = GETPOSTISSET('disposal_subject_to_vat') ? GETPOST('disposal_subject_to_vat') : 1; + $disposal_subject_to_vat = !empty($disposal_subject_to_vat) ? 1 : 0; + + $object->fields['fk_disposal_type']['visible'] = 1; + $disposal_type_form = $object->showInputField(null, 'fk_disposal_type', $fk_disposal_type, '', '', '', 0); + $object->fields['fk_disposal_type']['visible'] = -2; + + $object->fields['disposal_invoice_id'] = array('type' => 'integer:Facture:compta/facture/class/facture.class.php::entity IN (__SHARED_ENTITIES__)', 'enabled' => '1', 'notnull' => 1, 'visible' => 1, 'index' => 1, 'validate' => '1',); + $disposal_invoice_form = $object->showInputField(null, 'disposal_invoice_id', $disposal_invoice_id, '', '', '', 0); + unset($object->fields['disposal_invoice_id']); + + // Create an array for form + $formquestion = array( + array('type' => 'date', 'name' => 'disposal_date', 'tdclass' => 'fieldrequired', 'label' => $langs->trans("AssetDisposalDate"), 'value' => $disposal_date), + array('type' => 'text', 'name' => 'disposal_amount', 'tdclass' => 'fieldrequired', 'label' => $langs->trans("AssetDisposalAmount"), 'value' => $disposal_amount), + array('type' => 'other', 'name' => 'fk_disposal_type', 'tdclass' => 'fieldrequired', 'label' => $langs->trans("AssetDisposalType"), 'value' => $disposal_type_form), + array('type' => 'other', 'name' => 'disposal_invoice_id', 'label' => $langs->trans("InvoiceCustomer"), 'value' => $disposal_invoice_form), + array('type' => 'checkbox', 'name' => 'disposal_depreciated', 'label' => $langs->trans("AssetDisposalDepreciated"), 'value' => $disposal_depreciated), + array('type' => 'checkbox', 'name' => 'disposal_subject_to_vat', 'label' => $langs->trans("AssetDisposalSubjectToVat"), 'value' => $disposal_subject_to_vat), + ); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('AssetDisposal'), $langs->trans('AssetConfirmDisposalAsk', $object->ref . ' - ' . $object->label), 'confirm_disposal', $formquestion, 'yes', 1); + } elseif ($action == 'reopen') { + // Re-open + // Create an array for form + $formquestion = array(); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ReOpen'), $langs->trans('AssetConfirmReOpenAsk', $object->ref), 'confirm_reopen', $formquestion, 'yes', 1); } + // Clone confirmation + /* elseif ($action == 'clone') { + // Create an array for form + $formquestion = array(); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + }*/ // Call Hook formConfirm - $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $parameters = array('formConfirm' => $formconfirm); $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $formconfirm .= $hookmanager->resPrint; @@ -250,24 +315,19 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $linkback = ''.$langs->trans("BackToList").''; $morehtmlref = '
    '; - /* - // Ref bis - $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->asset->creer, 'string', '', 0, 1); - $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->asset->creer, 'string', '', null, null, '', 1); - // Thirdparty - $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); - */ $morehtmlref .= '
    '; + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + print '
    '; print '
    '; print '
    '; - print '
    '."\n"; + print '
    '."\n"; // Common attributes - //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just after this field + $keyforbreak='date_acquisition'; // We change column just before this field //unset($object->fields['fk_project']); // Hide field already shown in banner //unset($object->fields['fk_soc']); // Hide field already shown in banner include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; @@ -277,69 +337,100 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
    '; print ''; + print ''; print '
    '; print dol_get_fiche_end(); - - /* - * Buttons - */ - if ($user->socid == 0) { - print '
    '; - + // Buttons for actions + if ($action != 'presend' && $action != 'editline') { + print '
    ' . "\n"; $parameters = array(); $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } if (empty($reshook)) { - if ($user->rights->asset->write) { - print ''.$langs->trans("Modify").''."\n"; - } else { - print ''.$langs->trans('Modify').''."\n"; + // Send + if (empty($user->socid)) { + print dolGetButtonAction($langs->trans('SendMail'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=presend&mode=init&token=' . newToken() . '#formmailbeforetitle'); } - if ($user->rights->asset->delete) { - print ''.$langs->trans('Delete').''."\n"; - } else { - print ''.$langs->trans('Delete').''."\n"; + if ($object->status == $object::STATUS_DRAFT) { + print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoadd); } + + // Clone + //print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=clone&token=' . newToken(), '', false && $permissiontoadd); + + if ($object->status == $object::STATUS_DRAFT) { + print dolGetButtonAction($langs->trans('AssetDisposal'), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=disposal&token=' . newToken(), '', $permissiontoadd); + } else { + print dolGetButtonAction($langs->trans('ReOpen'), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=reopen&token=' . newToken(), '', $permissiontoadd); + } + + // Delete (need delete permission, or if draft, just need create/modify permission) + print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=delete&token=' . newToken(), '', $permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)); } - print "
    "; + print '
    ' . "\n"; + } + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; } if ($action != 'presend') { print '
    '; print ''; // ancre - // Documents - $filename = dol_sanitizeFileName($object->ref); - $filedir = $conf->contrat->dir_output."/".dol_sanitizeFileName($object->ref); - $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; - $genallowed = $user->rights->asset->read; // If you can read, you can build the PDF to read content - $delallowed = $user->rights->asset->write; // If you can create/edit, you can remove a file on card + $includedocgeneration = 0; - print $formfile->showdocuments('asset', $filename, $filedir, $urlsource, 0, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang); + // Documents + if ($includedocgeneration) { + $objref = dol_sanitizeFileName($object->ref); + $relativepath = $objref.'/'.$objref.'.pdf'; + $filedir = $conf->asset->dir_output.'/'.$objref; + $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; + $genallowed = $user->rights->asset->read; // If you can read, you can build the PDF to read content + $delallowed = $user->rights->asset->write; // If you can create/edit, you can remove a file on card + print $formfile->showdocuments('asset:Asset', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); + } // Show links to link elements $linktoelem = $form->showLinkToObjectBlock($object, null, array('asset')); $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + print '
    '; $MAXEVENT = 10; - $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-list-alt imgforviewmode', DOL_URL_ROOT.'/asset/info.php?id='.$object->id); + $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-list-alt imgforviewmode', DOL_URL_ROOT.'/asset/agenda.php?id='.$object->id); // List of actions on element include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; $formactions = new FormActions($db); - $somethingshown = $formactions->showactions($object, $object->element, $socid, 1, '', $MAXEVENT, '', $morehtmlright); + $somethingshown = $formactions->showactions($object, $object->element, 0, 1, '', $MAXEVENT, '', $morehtmlright); print '
    '; } -} + //Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + // Presend form + $modelmail = 'asset'; + $defaulttopic = 'InformationMessage'; + $diroutput = $conf->asset->dir_output; + $trackid = 'asset'.$object->id; + + include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; +} // End of page llxFooter(); diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php index e5ec21bfa6d..19c15839231 100644 --- a/htdocs/asset/class/asset.class.php +++ b/htdocs/asset/class/asset.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2018 Alexandre Spangaro +/* Copyright (C) 2017 Laurent Destailleur + * Copyright (C) 2018 Alexandre Spangaro * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ /** * \file asset/class/asset.class.php * \ingroup asset - * \brief This file is a CRUD class file for asset (Create/Read/Update/Delete) + * \brief This file is a CRUD class file for Asset (Create/Read/Update/Delete) */ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; @@ -30,22 +30,28 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; class Asset extends CommonObject { /** - * @var string ID to identify managed object + * @var string ID of module. + */ + public $module = 'asset'; + + /** + * @var string ID to identify managed object. */ public $element = 'asset'; /** - * @var string Name of table without prefix where object is stored + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. */ public $table_element = 'asset'; /** - * @var int Does module support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table */ - public $ismultientitymanaged = 0; + public $ismultientitymanaged = 1; /** - * @var int Does asset support extrafields ? 0=No, 1=Yes + * @var int Does object support extrafields ? 0=No, 1=Yes */ public $isextrafieldmanaged = 1; @@ -54,111 +60,124 @@ class Asset extends CommonObject */ public $picto = 'asset'; - - const STATUS_DRAFT = 0; - const STATUS_VALIDATED = 1; - const STATUS_CANCELED = 9; - + const STATUS_DRAFT = 0; // In progress + const STATUS_DISPOSED = 9; // Disposed /** - * 'type' if the field format. + * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" * 'label' the translation key. - * 'enabled' is a condition when the field must be managed. - * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only. Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. * 'index' if we want an index in database. * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). - * 'position' is the sort order of field. * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. - * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). - * 'help' is a string visible as a tooltip on field + * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' + * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. * 'comment' is not used. You can store here any text of your choice. It is not used by application. - * 'default' is a default value for creation (can still be replaced by the global setup of default values) - * 'showoncombobox' if field must be shown into the label of combobox + * 'validate' is 1 if need to validate with $this->validateField() + * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. */ /** * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. */ - public $fields = array( - 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>-1, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id",), - 'ref' => array('type'=>'varchar(10)', 'label'=>'Ref', 'visible'=>1, 'enabled'=>1, 'position'=>10, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'showoncombobox'=>1), - 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), - 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1), - 'fk_asset_type' => array('type'=>'integer:AssetType:asset/class/asset_type.class.php', 'label'=>'AssetsType', 'visible'=>1, 'enabled'=>1, 'position'=>35, 'notnull'=>1, 'index'=>1, 'searchall'=>1), - 'amount_ht' => array('type'=>'double(24,8)', 'label'=>'AmountHTShort', 'visible'=>1, 'enabled'=>1, 'position'=>40, 'notnull'=>-1, 'isameasure'=>'1', 'help'=>"Help text",), - 'amount_vat' => array('type'=>'double(24,8)', 'label'=>'AmountVAT', 'visible'=>1, 'enabled'=>1, 'position'=>41, 'notnull'=>-1, 'isameasure'=>'1', 'help'=>"Help text",), - 'description' => array('type'=>'text', 'label'=>'Description', 'visible'=>-1, 'enabled'=>1, 'position'=>90, 'notnull'=>-1,), - 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'visible'=>-1, 'enabled'=>1, 'position'=>91, 'notnull'=>-1,), - 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'visible'=>-1, 'enabled'=>1, 'position'=>92, 'notnull'=>-1,), - 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>-2, 'enabled'=>1, 'position'=>500, 'notnull'=>1,), - 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'visible'=>-2, 'enabled'=>1, 'position'=>501, 'notnull'=>1,), - 'fk_user_creat' => array('type'=>'integer', 'label'=>'UserAuthor', 'visible'=>-2, 'enabled'=>1, 'position'=>510, 'notnull'=>1,), - 'fk_user_modif' => array('type'=>'integer', 'label'=>'UserModif', 'visible'=>-2, 'enabled'=>1, 'position'=>511, 'notnull'=>-1,), - 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'visible'=>-2, 'enabled'=>1, 'position'=>1000, 'notnull'=>-1,), - 'status' => array('type'=>'integer', 'label'=>'Status', 'visible'=>1, 'enabled'=>1, 'position'=>1000, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Active', '9'=>'Cancel')), + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>1, 'noteditable'=>'0', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'validate'=>'1', 'comment'=>"Reference of object"), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'cssview'=>'wordbreak', 'showoncombobox'=>'2', 'validate'=>'1',), + 'fk_asset_model' => array('type'=>'integer:AssetModel:asset/class/assetmodel.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'AssetModel', 'enabled'=>'1', 'position'=>40, 'notnull'=>0, 'visible'=>1, 'index'=>1, 'validate'=>'1',), + 'qty' => array('type'=>'real', 'label'=>'Qty', 'enabled'=>'1', 'position'=>50, 'notnull'=>1, 'visible'=>0, 'default'=>'1', 'isameasure'=>'1', 'css'=>'maxwidth75imp', 'validate'=>'1',), + 'acquisition_type' => array('type'=>'smallint', 'label'=>'AssetAcquisitionType', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'arrayofkeyval'=>array('0'=>'AssetAcquisitionTypeNew', '1'=>'AssetAcquisitionTypeOccasion'), 'validate'=>'1',), + 'asset_type' => array('type'=>'smallint', 'label'=>'AssetType', 'enabled'=>'1', 'position'=>70, 'notnull'=>1, 'visible'=>1, 'arrayofkeyval'=>array('0'=>'AssetTypeIntangible', '1'=>'AssetTypeTangible', '2'=>'AssetTypeInProgress', '3'=>'AssetTypeFinancial'), 'validate'=>'1',), + 'not_depreciated' => array('type'=>'boolean', 'label'=>'AssetNotDepreciated', 'enabled'=>'1', 'position'=>80, 'notnull'=>0, 'default'=>'0', 'visible'=>1, 'validate'=>'1',), + 'date_acquisition' => array('type'=>'date', 'label'=>'AssetDateAcquisition', 'enabled'=>'1', 'position'=>90, 'notnull'=>1, 'visible'=>1,), + 'date_start' => array('type'=>'date', 'label'=>'AssetDateStart', 'enabled'=>'1', 'position'=>100, 'notnull'=>0, 'visible'=>-1,), + 'acquisition_value_ht' => array('type'=>'price', 'label'=>'AssetAcquisitionValueHT', 'enabled'=>'1', 'position'=>110, 'notnull'=>1, 'visible'=>1, 'isameasure'=>'1', 'validate'=>'1',), + 'recovered_vat' => array('type'=>'price', 'label'=>'AssetRecoveredVAT', 'enabled'=>'1', 'position'=>120, 'notnull'=>0, 'visible'=>1, 'isameasure'=>'1', 'validate'=>'1',), + 'reversal_date' => array('type'=>'date', 'label'=>'AssetReversalDate', 'enabled'=>'1', 'position'=>130, 'notnull'=>0, 'visible'=>1,), + 'reversal_amount_ht' => array('type'=>'price', 'label'=>'AssetReversalAmountHT', 'enabled'=>'1', 'position'=>140, 'notnull'=>0, 'visible'=>1, 'isameasure'=>'1', 'validate'=>'1',), + 'disposal_date' => array('type'=>'date', 'label'=>'AssetDisposalDate', 'enabled'=>'1', 'position'=>200, 'notnull'=>0, 'visible'=>-2,), + 'disposal_amount_ht' => array('type'=>'price', 'label'=>'AssetDisposalAmount', 'enabled'=>'1', 'position'=>210, 'notnull'=>0, 'visible'=>-2, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1',), + 'fk_disposal_type' => array('type'=>'sellist:c_asset_disposal_type:label:rowid::active=1', 'label'=>'AssetDisposalType', 'enabled'=>'1', 'position'=>220, 'notnull'=>0, 'visible'=>-2, 'index'=>1, 'validate'=>'1',), + 'disposal_depreciated' => array('type'=>'boolean', 'label'=>'AssetDisposalDepreciated', 'enabled'=>'1', 'position'=>230, 'notnull'=>0, 'default'=>'0', 'visible'=>-2, 'validate'=>'1',), + 'disposal_subject_to_vat' => array('type'=>'boolean', 'label'=>'AssetDisposalSubjectToVat', 'enabled'=>'1', 'position'=>240, 'notnull'=>0, 'default'=>'0', 'visible'=>-2, 'validate'=>'1',), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>300, 'notnull'=>0, 'visible'=>0, 'validate'=>'1',), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>301, 'notnull'=>0, 'visible'=>0, 'validate'=>'1',), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'last_main_doc' => array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>'1', 'position'=>600, 'notnull'=>0, 'visible'=>0,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), + 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'default'=>'0', 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '9'=>'Canceled'), 'validate'=>'1',), ); - - /** - * @var int ID - */ public $rowid; - - /** - * @var string Ref - */ public $ref; - - /** - * @var int Entity - */ - public $entity; - - /** - * @var string Asset label - */ public $label; - - public $amount; - - /** - * @var int Thirdparty ID - */ - public $fk_soc; - - /** - * @var string description - */ - public $description; - - /** - * @var integer|string date_creation - */ + public $fk_asset_model; + public $reversal_amount_ht; + public $acquisition_value_ht; + public $recovered_vat; + public $reversal_date; + public $date_acquisition; + public $date_start; + public $qty; + public $acquisition_type; + public $asset_type; + public $not_depreciated; + public $disposal_date; + public $disposal_amount_ht; + public $fk_disposal_type; + public $disposal_depreciated; + public $disposal_subject_to_vat; + public $note_public; + public $note_private; public $date_creation; - - public $tms; - - /** - * @var int ID - */ public $fk_user_creat; - - /** - * @var int ID - */ public $fk_user_modif; - - /** - * @var string import key - */ + public $last_main_doc; public $import_key; - - /** - * @var int Status - */ + public $model_pdf; public $status; + // /** + // * @var string Field with ID of parent key if this object has a parent + // */ + // public $fk_element = 'fk_asset'; + // /** + // * @var array List of child tables. To test if we can delete object. + // */ + // protected $childtables = array(); + // /** + // * @var array List of child tables. To know object to delete on cascade. + // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + // */ + // protected $childtablesoncascade = array('asset_assetdet'); + + /** + * @var AssetDepreciationOptions Used for computed fields of depreciation options class. + */ + public $asset_depreciation_options; + /** + * @var array List of depreciation lines for each mode (sort by depreciation date). + */ + public $depreciation_lines = array(); /** * Constructor @@ -167,16 +186,34 @@ class Asset extends CommonObject */ public function __construct(DoliDB $db) { - global $conf; + global $conf, $langs; $this->db = $db; - if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) { + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) { $this->fields['rowid']['visible'] = 0; } - if (empty($conf->multicompany->enabled)) { + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) { $this->fields['entity']['enabled'] = 0; } + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } } /** @@ -188,11 +225,27 @@ class Asset extends CommonObject */ public function create(User $user, $notrigger = false) { - return $this->createCommon($user, $notrigger); + if (!isset($this->date_start) || $this->date_start === "") $this->date_start = $this->date_acquisition; + + $this->db->begin(); + + $result = $result_create = $this->createCommon($user, $notrigger); + if ($result > 0 && $this->fk_asset_model > 0) $result = $this->setDataFromAssetModel($user, $notrigger); + if ($result > 0) { + if ($this->supplier_invoice_id > 0) $this->add_object_linked('invoice_supplier', $this->supplier_invoice_id); + } + + if ($result < 0) { + $this->db->rollback(); + } else { + $this->db->commit(); + } + + return $result > 0 ? $result_create : $result; } /** - * Clone and object into another one + * Clone an object into another one * * @param User $user User that creates * @param int $fromid Id of object to clone @@ -200,45 +253,95 @@ class Asset extends CommonObject */ public function createFromClone(User $user, $fromid) { - global $hookmanager, $langs; + global $langs, $extrafields; $error = 0; dol_syslog(__METHOD__, LOG_DEBUG); - $object = new self($this->db); - - $this->db->begin(); - - // Load source object - $object->fetchCommon($fromid); - // Reset some properties - unset($object->id); - unset($object->fk_user_creat); - unset($object->import_key); - - // Clear fields - $object->ref = "copy_of_".$object->ref; - $object->title = $langs->trans("CopyOf")." ".$object->title; - - // Create clone - $object->context['createfromclone'] = 'createfromclone'; - $result = $object->createCommon($user); - if ($result < 0) { - $error++; - $this->error = $object->error; - $this->errors = $object->errors; - } - - unset($object->context['createfromclone']); - - // End - if (!$error) { - $this->db->commit(); - return $object; - } else { - $this->db->rollback(); - return -1; - } + // $object = new self($this->db); + // + // $this->db->begin(); + // + // // Load source object + // $result = $object->fetchCommon($fromid); + // if ($result > 0 && !empty($object->table_element_line)) { + // $object->fetchLines(); + // } + // + // // get lines so they will be clone + // //foreach($this->lines as $line) + // // $line->fetch_optionals(); + // + // // Reset some properties + // unset($object->id); + // unset($object->fk_user_creat); + // unset($object->import_key); + // + // // Clear fields + // if (property_exists($object, 'ref')) { + // $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; + // } + // if (property_exists($object, 'label')) { + // $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + // } + // if (property_exists($object, 'status')) { + // $object->status = self::STATUS_DRAFT; + // } + // if (property_exists($object, 'date_creation')) { + // $object->date_creation = dol_now(); + // } + // if (property_exists($object, 'date_modification')) { + // $object->date_modification = null; + // } + // // ... + // // Clear extrafields that are unique + // if (is_array($object->array_options) && count($object->array_options) > 0) { + // $extrafields->fetch_name_optionals_label($this->table_element); + // foreach ($object->array_options as $key => $option) { + // $shortkey = preg_replace('/options_/', '', $key); + // if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) { + // //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + // unset($object->array_options[$key]); + // } + // } + // } + // + // // Create clone + // $object->context['createfromclone'] = 'createfromclone'; + // $result = $object->createCommon($user); + // if ($result < 0) { + // $error++; + // $this->error = $object->error; + // $this->errors = $object->errors; + // } + // + // if (!$error) { + // // copy internal contacts + // if ($this->copy_linked_contact($object, 'internal') < 0) { + // $error++; + // } + // } + // + // if (!$error) { + // // copy external contacts if same company + // if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) { + // if ($this->copy_linked_contact($object, 'external') < 0) { + // $error++; + // } + // } + // } + // + // unset($object->context['createfromclone']); + // + // // End + // if (!$error) { + // $this->db->commit(); + // return $object; + // } else { + // $this->db->rollback(); + // return -1; + // } + return -1; } /** @@ -251,7 +354,21 @@ class Asset extends CommonObject public function fetch($id, $ref = null) { $result = $this->fetchCommon($id, $ref); - //if ($result > 0 && ! empty($this->table_element_line)) $this->fetchLines(); + if ($result > 0) { + if (!empty($this->table_element_line)) $this->fetchLines(); + + $res = $this->hasDepreciationLinesInBookkeeping(); + if ($res < 0) { + return -1; + } elseif ($res > 0) { + $this->fields['date_acquisition']['noteditable'] = '1'; + $this->fields['date_start']['noteditable'] = '1'; + $this->fields['acquisition_value_ht']['noteditable'] = '1'; + $this->fields['recovered_vat']['noteditable'] = '1'; + $this->fields['reversal_date']['noteditable'] = '1'; + $this->fields['reversal_amount_ht']['noteditable'] = '1'; + } + } return $result; } @@ -260,14 +377,93 @@ class Asset extends CommonObject * * @return int <0 if KO, 0 if not found, >0 if OK */ - /*public function fetchLines() + public function fetchLines() { - $this->lines=array(); + $this->lines = array(); - // Load lines with object AssetsLine + return 1; + } - return count($this->lines)?1:0; - }*/ + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = "SELECT "; + $sql .= $this->getFieldList('t'); + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + } else { + $sql .= " WHERE 1 = 1"; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; + } else { + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } /** * Update object into database @@ -278,7 +474,32 @@ class Asset extends CommonObject */ public function update(User $user, $notrigger = false) { - return $this->updateCommon($user, $notrigger); + if (!isset($this->date_start) || $this->date_start === "") $this->date_start = $this->date_acquisition; + + $this->db->begin(); + + $result = $this->updateCommon($user, $notrigger); + if ($result > 0 && $this->fk_asset_model > 0 && $this->fk_asset_model != $this->oldcopy->fk_asset_model) { + $result = $this->setDataFromAssetModel($user, $notrigger); + } + if ($result > 0 && ( + $this->date_start != $this->oldcopy->date_start || + $this->acquisition_value_ht != $this->oldcopy->acquisition_value_ht || + $this->reversal_date != $this->oldcopy->reversal_date || + $this->reversal_amount_ht != $this->oldcopy->reversal_amount_ht || + ($this->fk_asset_model > 0 && $this->fk_asset_model != $this->oldcopy->fk_asset_model) + ) + ) { + $result = $this->calculationDepreciation(); + } + + if ($result < 0) { + $this->db->rollback(); + } else { + $this->db->commit(); + } + + return $result; } /** @@ -291,21 +512,760 @@ class Asset extends CommonObject public function delete(User $user, $notrigger = false) { return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Set asset model + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function setDataFromAssetModel(User $user, $notrigger = false) + { + global $langs; + $langs->load('assets'); + + // Clean parameters + $this->id = $this->id > 0 ? $this->id : 0; + $this->fk_asset_model = $this->fk_asset_model > 0 ? $this->fk_asset_model : 0; + + // Check parameters + $error = 0; + if (empty($this->id)) { + $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')'); + $error++; + } + if (empty($this->fk_asset_model)) { + $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("AssetModel") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')'); + $error++; + } + if ($error) { + return -1; + } + + $this->db->begin(); + + // Get depreciation options + //--------------------------- + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php'; + $options_model = new AssetDepreciationOptions($this->db); + $result = $options_model->fetchDeprecationOptions(0, $this->fk_asset_model); + if ($result < 0) { + $this->error = $options_model->error; + $this->errors = $options_model->errors; + $error++; + } elseif ($result > 0) { + $options = new AssetDepreciationOptions($this->db); + $result = $options->fetchDeprecationOptions($this->id); + if ($result < 0) { + $this->error = $options->error; + $this->errors = $options->errors; + $error++; + } + + if (!$error) { + foreach ($options_model->deprecation_options as $mode_key => $fields) { + foreach ($fields as $field_key => $value) { + $options->deprecation_options[$mode_key][$field_key] = $value; + } + } + + $result = $options->updateDeprecationOptions($user, $this->id, 0, $notrigger); + if ($result < 0) { + $this->error = $options->error; + $this->errors = $options->errors; + $error++; + } + } + } + + // Get accountancy codes + //--------------------------- + if (!$error) { + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php'; + $accountancy_codes_model = new AssetAccountancyCodes($this->db); + $result = $accountancy_codes_model->fetchAccountancyCodes(0, $this->fk_asset_model); + if ($result < 0) { + $this->error = $accountancy_codes_model->error; + $this->errors = $accountancy_codes_model->errors; + $error++; + } elseif ($result > 0) { + $accountancy_codes = new AssetAccountancyCodes($this->db); + $result = $accountancy_codes->fetchAccountancyCodes($this->id); + if ($result < 0) { + $this->error = $accountancy_codes->error; + $this->errors = $accountancy_codes->errors; + $error++; + } + + if (!$error) { + foreach ($accountancy_codes_model->accountancy_codes as $mode_key => $fields) { + foreach ($fields as $field_key => $value) { + $accountancy_codes->accountancy_codes[$mode_key][$field_key] = $value; + } + } + + $result = $accountancy_codes->updateAccountancyCodes($user, $this->id, 0, $notrigger); + if ($result < 0) { + $this->error = $accountancy_codes->error; + $this->errors = $accountancy_codes->errors; + $error++; + } + } + } + } + + if ($error) { + $this->db->rollback(); + return -1; + } else { + $this->db->commit(); + return 1; + } + } + + /** + * Fetch depreciation lines for each mode in $this->depreciation_lines (sort by depreciation date) + * + * @return int <0 if KO, Id of created object if OK + */ + public function fetchDepreciationLines() + { + global $langs; + $langs->load('assets'); + $this->depreciation_lines = array(); + + // Clean parameters + $this->id = $this->id > 0 ? $this->id : 0; + + // Check parameters + $error = 0; + if (empty($this->id)) { + $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')'); + $error++; + } + if ($error) { + return -1; + } + + $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS ("; + $sql .= " SELECT DISTINCT fk_docdet"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping"; + $sql .= " WHERE doc_type = 'asset'"; + $sql .= ")"; + $sql .= "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht"; + $sql .= ", " . $this->db->ifsql('iab.fk_docdet IS NOT NULL', 1, 0) . " AS bookkeeping"; + $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad"; + $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid"; + $sql .= " WHERE ad.fk_asset = " . (int) $this->id; + $sql .= " ORDER BY ad.depreciation_date ASC"; + + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorFetchDepreciationLines') . ': ' . $this->db->lasterror(); + return -1; + } + + while ($obj = $this->db->fetch_object($resql)) { + if (!isset($this->depreciation_lines[$obj->depreciation_mode])) $this->depreciation_lines[$obj->depreciation_mode] = array(); + $this->depreciation_lines[$obj->depreciation_mode][] = array( + 'id' => $obj->rowid, + 'ref' => $obj->ref, + 'depreciation_date' => $this->db->jdate($obj->depreciation_date), + 'depreciation_ht' => $obj->depreciation_ht, + 'cumulative_depreciation_ht' => $obj->cumulative_depreciation_ht, + 'bookkeeping' => $obj->bookkeeping, + ); + } + + return 1; + } + + /** + * If has depreciation lines in bookkeeping + * + * @return int <0 if KO, 0 if NO, 1 if Yes + */ + public function hasDepreciationLinesInBookkeeping() + { + global $langs; + $langs->load('assets'); + + // Clean parameters + $this->id = $this->id > 0 ? $this->id : 0; + + // Check parameters + $error = 0; + if (empty($this->id)) { + $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')'); + $error++; + } + if ($error) { + return -1; + } + + $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS ("; + $sql .= " SELECT DISTINCT fk_docdet"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping"; + $sql .= " WHERE doc_type = 'asset'"; + $sql .= ")"; + $sql .= "SELECT COUNT(*) AS has_bookkeeping"; + $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad"; + $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid"; + $sql .= " WHERE ad.fk_asset = " . (int) $this->id; + $sql .= " AND iab.fk_docdet IS NOT NULL"; + + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorFetchDepreciationLines') . ': ' . $this->db->lasterror(); + return -1; + } + + if ($obj = $this->db->fetch_object($resql)) { + return $obj->has_bookkeeping > 0 ? 1 : 0; + } + + return 0; + } + + /** + * Add depreciation line for a mode + * + * @param string $mode Depreciation mode (economic, accelerated_depreciation, ...) + * @param string $ref Ref line + * @param int $depreciation_date Depreciation date + * @param double $depreciation_ht Depreciation amount HT + * @param double $cumulative_depreciation_ht Depreciation cumulative amount HT + * @param string $accountancy_code_debit Accountancy code Debit + * @param string $accountancy_code_credit Accountancy code Credit + * @return int <0 if KO, Id of created line if OK + */ + public function addDepreciationLine($mode, $ref, $depreciation_date, $depreciation_ht, $cumulative_depreciation_ht, $accountancy_code_debit, $accountancy_code_credit) + { + global $langs; + $langs->load('assets'); + + // Clean parameters + $this->id = $this->id > 0 ? $this->id : 0; + $mode = strtolower(trim($mode)); + $ref = trim($ref); + $accountancy_code_debit = trim($accountancy_code_debit); + $accountancy_code_credit = trim($accountancy_code_credit); + + // Check parameters + $error = 0; + if (empty($this->id)) { + $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')'); + $error++; + } + if ($error) { + return -1; + } + + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "asset_depreciation(fk_asset, depreciation_mode, ref, depreciation_date, depreciation_ht, cumulative_depreciation_ht, accountancy_code_debit, accountancy_code_credit)"; + $sql .= " VALUES ( "; + $sql .= " " . (int) $this->id; + $sql .= ", '" . $this->db->escape($mode) . "'"; + $sql .= ", '" . $this->db->escape($ref) . "'"; + $sql .= ", '" . $this->db->idate($depreciation_date) . "'"; + $sql .= ", " . (double) $depreciation_ht; + $sql .= ", " . (double) $cumulative_depreciation_ht; + $sql .= ", '" . $this->db->escape($accountancy_code_debit) . "'"; + $sql .= ", '" . $this->db->escape($accountancy_code_credit) . "'"; + $sql .= ")"; + + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorAddDepreciationLine') . ': ' . $this->db->lasterror(); + return -1; + } + + return 1; + } + + /** + * Calculation depreciation lines (reversal and future) for each mode + * + * @return int <0 if KO, Id of created object if OK + */ + public function calculationDepreciation() + { + global $conf, $langs; + $langs->load('assets'); + + // Clean parameters + $this->id = $this->id > 0 ? $this->id : 0; + + // Check parameters + $error = 0; + if (empty($this->id)) { + $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')'); + $error++; + } + if ($error) { + return -1; + } + + // Get depreciation options + //--------------------------- + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php'; + $options = new AssetDepreciationOptions($this->db); + $result = $options->fetchDeprecationOptions($this->id); + if ($result < 0) { + $this->error = $options->error; + $this->errors = $options->errors; + return -1; + } + + // Get accountancy codes + //--------------------------- + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php'; + $accountancy_codes = new AssetAccountancyCodes($this->db); + $result = $accountancy_codes->fetchAccountancyCodes($this->id); + if ($result < 0) { + $this->error = $accountancy_codes->error; + $this->errors = $accountancy_codes->errors; + return -1; + } + + $this->db->begin(); + + // Delete old lines + $modes = array(); + foreach ($options->deprecation_options as $mode_key => $fields) { + $modes[$mode_key] = $this->db->escape($mode_key); + } + $sql = "DELETE FROM " . MAIN_DB_PREFIX . "asset_depreciation"; + $sql .= " WHERE fk_asset = " . (int) $this->id; + $sql .= " AND depreciation_mode NOT IN ('" . $this->db->sanitize(implode("', '", $modes)) . "')"; + + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorClearDepreciationLines') . ': ' . $this->db->lasterror(); + $error++; + } + + if (!$error) { + // Get fiscal period + require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; + require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; + $dates = getDefaultDatesForTransfer(); + $init_fiscal_period_start = $dates['date_start']; + $init_fiscal_period_end = $dates['date_end']; + if (empty($init_fiscal_period_start) || empty($init_fiscal_period_end)) { + $pastmonthyear = $dates['pastmonthyear']; + $pastmonth = $dates['pastmonth']; + $init_fiscal_period_start = dol_get_first_day($pastmonthyear, $pastmonth, false); + $init_fiscal_period_end = dol_get_last_day($pastmonthyear, $pastmonth, false); + } + + foreach ($options->deprecation_options as $mode_key => $fields) { + // Get last depreciation lines save in bookkeeping + //----------------------------------------------------- + $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS ("; + $sql .= " SELECT fk_docdet"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping"; + $sql .= " WHERE doc_type = 'asset'"; + $sql .= ")"; + $sql .= "SELECT ad.depreciation_date, ad.cumulative_depreciation_ht"; + $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad"; + $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid"; + $sql .= " WHERE ad.fk_asset = " . (int) $this->id; + $sql .= " AND ad.depreciation_mode = '" . $this->db->escape($mode_key) . "'"; + $sql .= " AND iab.fk_docdet IS NOT NULL"; + $sql .= " ORDER BY ad.depreciation_date DESC"; + $sql .= " LIMIT 1"; + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorFetchMaxDepreciationDateForMode', $mode_key) . ': ' . $this->db->lasterror(); + $error++; + break; + } + $last_depreciation_date = ''; + $last_cumulative_depreciation_ht = $this->reversal_amount_ht; + if ($obj = $this->db->fetch_object($resql)) { + $last_depreciation_date = $this->db->jdate($obj->depreciation_date); + $last_cumulative_depreciation_ht = $obj->cumulative_depreciation_ht; + } + + // Set last cumulative depreciation + $sql = "UPDATE " . MAIN_DB_PREFIX . $options->deprecation_options_fields[$mode_key]['table']; + $sql .= " SET total_amount_last_depreciation_ht = " . (empty($last_cumulative_depreciation_ht) ? 0 : $last_cumulative_depreciation_ht); + $sql .= " WHERE fk_asset = " . (int) $this->id; + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorSetLastCumulativeDepreciation') . ': ' . $this->db->lasterror(); + $error++; + break; + } + + // Delete old lines + $sql = "DELETE " . MAIN_DB_PREFIX . "asset_depreciation FROM " . MAIN_DB_PREFIX . "asset_depreciation"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab ON ab.doc_type = 'asset' AND ab.fk_docdet = " . MAIN_DB_PREFIX . "asset_depreciation.rowid"; + $sql .= " WHERE " . MAIN_DB_PREFIX . "asset_depreciation.fk_asset = " . (int) $this->id; + $sql .= " AND " . MAIN_DB_PREFIX . "asset_depreciation.depreciation_mode = '" . $this->db->escape($mode_key) . "'"; + $sql .= " AND ab.fk_docdet IS NULL"; + if ($last_depreciation_date !== "") $sql .= " AND " . MAIN_DB_PREFIX . "asset_depreciation.ref != ''"; + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorClearDepreciationLines') . ': ' . $this->db->lasterror(); + $error++; + break; + } + + // Get depreciation period + $depreciation_date_start = $this->date_start > $this->date_acquisition ? $this->date_start : $this->date_acquisition; + $depreciation_date_end = dol_time_plus_duree($depreciation_date_start, $fields['duration'], $fields['duration_type'] == 1 ? 'm' : ($fields['duration_type'] == 2 ? 'd' : 'y')); + $depreciation_amount = $fields['amount_base_depreciation_ht']; + if ($fields['duration_type'] == 2) { // Daily + $fiscal_period_start = $depreciation_date_start; + $fiscal_period_end = $depreciation_date_start; + } elseif ($fields['duration_type'] == 1) { // Monthly + $date_temp = dol_getdate($depreciation_date_start); + $fiscal_period_start = dol_get_first_day($date_temp['year'], $date_temp['mon'], false); + $fiscal_period_end = dol_get_last_day($date_temp['year'], $date_temp['mon'], false); + } else { // Annually + $fiscal_period_start = $init_fiscal_period_start; + $fiscal_period_end = $init_fiscal_period_end; + } + $cumulative_depreciation_ht = $last_cumulative_depreciation_ht; + $depreciation_period_amount = $depreciation_amount - $this->reversal_amount_ht; + $start_date = $depreciation_date_start; + $disposal_date = isset($this->disposal_date) && $this->disposal_date !== "" ? $this->disposal_date : ""; + $finish_date = $disposal_date !== "" ? $disposal_date : $depreciation_date_end; + $accountancy_code_depreciation_debit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_debit']; + $accountancy_code_depreciation_debit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_debit_key]; + $accountancy_code_depreciation_credit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_credit']; + $accountancy_code_credit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_credit_key]; + + // Reversal depreciation line + //----------------------------------------------------- + if ($last_depreciation_date === "" && ($depreciation_date_start < $fiscal_period_start || is_numeric($this->reversal_date))) { + if (is_numeric($this->reversal_date)) { + if ($this->reversal_date < $fiscal_period_start) { + $this->errors[] = $langs->trans('AssetErrorReversalDateNotGreaterThanCurrentBeginFiscalDateForMode', $mode_key); + $error++; + break; + } + + if (empty($this->reversal_amount_ht)) { + $this->errors[] = $langs->trans('AssetErrorReversalAmountNotProvidedForMode', $mode_key); + $error++; + break; + } + + $start_date = $this->reversal_date; + $result = $this->addDepreciationLine($mode_key, '', $start_date, $this->reversal_amount_ht, $this->reversal_amount_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit); + if ($result < 0) { + $error++; + break; + } + } else { + $this->errors[] = $langs->trans('AssetErrorReversalDateNotProvidedForMode', $mode_key); + $error++; + break; + } + } + + // futures depreciation lines + //----------------------------------------------------- + $nb_days_in_year = !empty($conf->global->ASSET_DEPRECIATION_DURATION_PER_YEAR) ? $conf->global->ASSET_DEPRECIATION_DURATION_PER_YEAR : 365; + $nb_days_in_month = !empty($conf->global->ASSET_DEPRECIATION_DURATION_PER_MONTH) ? $conf->global->ASSET_DEPRECIATION_DURATION_PER_MONTH : 30; + $period_amount = (double) price2num($depreciation_period_amount / $fields['duration'], 'MT'); + $first_period_found = false; + $first_period_date = isset($begin_period) && $begin_period > $fiscal_period_start ? $begin_period : $fiscal_period_start; + + $ref_date_format = "%Y" . ($fields['duration_type'] == 1 || $fields['duration_type'] == 2 ? '-%m' : '') . ($fields['duration_type'] == 2 ? '-%d' : ''); + + // Loop security + $idx_loop = 0; + $max_loop = $fields['duration'] + 2; + do { + // Loop security + $idx_loop++; + if ($idx_loop > $max_loop) break; + + if ($last_depreciation_date < $fiscal_period_end && ($first_period_date <= $start_date || $first_period_found)) { + // Disposal not depreciated + if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end && empty($this->disposal_depreciated)) { + break; + } + + $first_period_found = true; + + $period_begin = dol_print_date($fiscal_period_start, $ref_date_format); + $period_end = dol_print_date($fiscal_period_end, $ref_date_format); + $ref = $period_begin . ($period_begin != $period_end ? ' - ' . $period_end : ''); + if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end) { + $ref .= ' - ' . $langs->transnoentitiesnoconv('AssetDisposal'); + } + + $begin_date = $fiscal_period_start < $start_date && $start_date <= $fiscal_period_end ? $start_date : $fiscal_period_start; + $end_date = $fiscal_period_start < $finish_date && $finish_date <= $fiscal_period_end ? $finish_date : $fiscal_period_end; + if ($fields['duration_type'] == 2) { // Daily + $depreciation_ht = $period_amount; + } elseif ($fields['duration_type'] == 1) { // Monthly + $nb_days = min($nb_days_in_month, num_between_day($begin_date, $end_date, 1)); + if ($nb_days >= 28) { + $date_temp = dol_getdate($begin_date); + if ($date_temp['mon'] == 2) { + $nb_days = 30; + } + } + $depreciation_ht = (double) price2num($period_amount * $nb_days / $nb_days_in_month, 'MT'); + } else { // Annually + $nb_days = min($nb_days_in_year, num_between_day($begin_date, $end_date, 1)); + $depreciation_ht = (double) price2num($period_amount * $nb_days / $nb_days_in_year, 'MT'); + } + + if ($fiscal_period_start <= $depreciation_date_end && $depreciation_date_end <= $fiscal_period_end) { // last period + $depreciation_ht = (double) price2num($depreciation_amount - $cumulative_depreciation_ht, 'MT'); + $cumulative_depreciation_ht = $depreciation_amount; + } else { + $cumulative_depreciation_ht += $depreciation_ht; + } + + $result = $this->addDepreciationLine($mode_key, $ref, $fiscal_period_end, $depreciation_ht, $cumulative_depreciation_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit); + if ($result < 0) { + $error++; + break; + } + } + + // Next fiscal period (+1 day/month/year) + $fiscal_period_start = dol_time_plus_duree($fiscal_period_end, 1, 'd'); + if ($fields['duration_type'] == 2) { // Daily + $fiscal_period_end = $fiscal_period_start; + } elseif ($fields['duration_type'] == 1) { // Monthly + $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'm'), -1, 'd'); + } else { // Annually + $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'y'), -1, 'd'); + } + $last_period_date = $disposal_date !== "" && $disposal_date < $depreciation_date_end ? $disposal_date : $depreciation_date_end; + } while ($fiscal_period_start < $last_period_date); + + if ($error) { + break; + } + } + } + + if ($error) { + $this->db->rollback(); + return -1; + } else { + $this->db->commit(); + return 1; + } + } + + /** + * Set last cumulative depreciation for each mode + * + * @param int $asset_depreciation_id Asset depreciation line ID + * @return int <0 if KO, >0 if OK + */ + public function setLastCumulativeDepreciation($asset_depreciation_id) + { + global $langs; + $langs->load('assets'); + + // Clean parameters + $asset_depreciation_id = $asset_depreciation_id > 0 ? $asset_depreciation_id : 0; + + // Check parameters + $error = 0; + if (empty($asset_depreciation_id)) { + $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("AssetDepreciation") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')'); + $error++; + } + if ($error) { + return -1; + } + + $this->db->begin(); + + require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php'; + $options = new AssetDepreciationOptions($this->db); + + // Get last depreciation lines save in bookkeeping + //----------------------------------------------------- + $sql = "SELECT fk_asset, depreciation_mode, cumulative_depreciation_ht"; + $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation"; + $sql .= " WHERE rowid = " . (int) $asset_depreciation_id; + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorFetchCumulativeDepreciation') . ': ' . $this->db->lasterror(); + $error++; + } else { + if ($obj = $this->db->fetch_object($resql)) { + $mode_key = $obj->depreciation_mode; + if (!empty($options->deprecation_options_fields[$mode_key])) { + $sql = "UPDATE " . MAIN_DB_PREFIX . $options->deprecation_options_fields[$mode_key]['table']; + $sql .= " SET total_amount_last_depreciation_ht = " . $obj->cumulative_depreciation_ht; + $sql .= " WHERE fk_asset = " . (int) $obj->fk_asset; + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorSetLastCumulativeDepreciation') . ': ' . $this->db->lasterror(); + $error++; + } + } + } + } + + if ($error) { + $this->db->rollback(); + return -1; + } else { + $this->db->commit(); + return 1; + } + } + + /** + * Set dispose status + * + * @param User $user Object user that dispose + * @param int $disposal_invoice_id Disposal invoice ID + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function dispose($user, $disposal_invoice_id, $notrigger = 0) + { + global $conf, $langs; + + // Protection + if ($this->status != self::STATUS_DRAFT || $this->status == self::STATUS_DISPOSED) { + return 0; + } + + $this->db->begin(); + + $required_fields = array('disposal_date', 'disposal_date', 'fk_disposal_type'); + foreach ($required_fields as $field) { + $this->fields[$field]['notnull'] = 1; + } + $result = $this->update($user, 1); + foreach ($required_fields as $field) { + $this->fields[$field]['notnull'] = 0; + } + if ($result > 0) { + if ($disposal_invoice_id > 0) $this->add_object_linked('facture', $disposal_invoice_id); + $result = $this->setStatusCommon($user, self::STATUS_DISPOSED, $notrigger, 'ASSET_DISPOSED'); + } + if ($result > 0) $result = $this->calculationDepreciation(); + + if ($result < 0) { + $this->db->rollback(); + } else { + $this->db->commit(); + } + + // Define output language + if ($result > 0 && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { + if (method_exists($this, 'generateDocument')) { + global $hidedetails, $hidedesc, $hideref; + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); + } + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + $newlang = $this->thirdparty->default_lang; + } + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model = $this->model_pdf; + $ret = $this->fetch($this->id); // Reload to get new records + + $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + + return $result; + } + + /** + * Set back to validated status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function reopen($user, $notrigger = 0) + { + global $conf, $langs; + + // Protection + if ($this->status != self::STATUS_DISPOSED || $this->status == self::STATUS_DRAFT) { + return 0; + } + + + $this->db->begin(); + + $this->disposal_date = null; + $this->disposal_amount_ht = null; + $this->fk_disposal_type = null; + $this->disposal_depreciated = null; + $this->disposal_subject_to_vat = null; + $result = $this->update($user, 1); + if ($result > 0) { + $this->deleteObjectLinked(null, 'facture'); + $result = $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'ASSET_REOPEN'); + } + if ($result > 0) $result = $this->calculationDepreciation(); + + if ($result < 0) { + $this->db->rollback(); + } else { + $this->db->commit(); + } + + // Define output language + if ($result > 0 && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { + if (method_exists($this, 'generateDocument')) { + global $hidedetails, $hidedesc, $hideref; + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); + } + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + $newlang = $this->thirdparty->default_lang; + } + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model = $this->model_pdf; + $ret = $this->fetch($this->id); // Reload to get new records + + $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + + return $result; } /** * Return a link to the object card (with optionaly the picto) * - * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) - * @param string $option On what the link point to ('nolink', ...) - * @param int $notooltip 1=Disable tooltip - * @param string $morecss Add more css on link - * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking - * @return string String with URL + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $maxlen Max length of name + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) { - global $db, $conf, $langs; + global $db, $conf, $langs, $hookmanager; global $dolibarr_main_authentication, $dolibarr_main_demo; global $menumanager; @@ -338,7 +1298,7 @@ class Asset extends CommonObject $linkclose = ''; if (empty($notooltip)) { if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { - $label = $langs->trans("ShowAssets"); + $label = $langs->trans("ShowAsset"); $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; } $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; @@ -347,28 +1307,87 @@ class Asset extends CommonObject $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); } - $linkstart = ''; - $linkend = ''; + if ($option == 'nolink') { + $linkend = ''; + } else { + $linkend = ''; + } $result .= $linkstart; - if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
    No photo
    '; + } else { + $result .= '
    No photo
    '; + } + + $result .= ''; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } } + if ($withpicto != 2) { - $result .= $this->ref; + $name = $this->ref; + if ($option == 'label') $name = $this->label; + elseif ($option == 'with_label') $name .= ' - ' . $this->label; + $result .= dol_escape_htmltag($maxlen ? dol_trunc($name, $maxlen) : $name); } + $result .= $linkend; //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + global $action; + $hookmanager->initHooks(array($this->element . 'dao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } /** - * Retourne le libelle du status d'un user (actif, inactif) + * Return the label of the status * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto - * @return string Label of status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLabelStatus($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status */ public function getLibStatut($mode = 0) { @@ -379,43 +1398,43 @@ class Asset extends CommonObject /** * Return the status * - * @param int $status Id status - * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto - * @return string Label of status + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status */ - public static function LibStatut($status, $mode = 0) + public function LibStatut($status, $mode = 0) { // phpcs:enable - global $langs; - - $langs->load("contracts"); - $labelStatus = array(); - $labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Disabled'); - $labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); - $labelStatusShort = array(); - $labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Disabled'); - $labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); - - $statusType = 'status0'; - if ($status == self::STATUS_VALIDATED) { - $statusType = 'status4'; + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { + global $langs; + //$langs->load("asset@asset"); + $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInProgress'); + $this->labelStatus[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed'); + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInProgress'); + $this->labelStatusShort[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed'); } - return dolGetStatus($labelStatus[$status], $labelStatusShort[$status], '', $statusType, $mode); + $statusType = 'status4'; + if ($status == self::STATUS_DISPOSED) { + $statusType = 'status6'; + } + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); } /** - * Load info into asset object + * Load the info information in the object * - * @param int $id Id of order + * @param int $id Id of object * @return void */ public function info($id) { - $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; - $sql .= ' fk_user_creat, fk_user_modif'; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - $sql .= ' WHERE t.rowid = '.((int) $id); + $sql = "SELECT rowid, date_creation as datec, tms as datem,"; + $sql .= " fk_user_creat, fk_user_modif"; + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + $sql .= " WHERE t.rowid = ".((int) $id); + $result = $this->db->query($sql); if ($result) { if ($this->db->num_rows($result)) { @@ -458,25 +1477,116 @@ class Asset extends CommonObject */ public function initAsSpecimen() { + // Set here init that are not commonf fields + // $this->property1 = ... + // $this->property2 = ... + $this->initAsSpecimenCommon(); } + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + return $this->lines; + } /** - * Action executed by scheduler - * CAN BE A CRON TASK + * Returns the reference to the following non used object depending on the active numbering module. * - * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + * @return string Object free reference */ - public function doScheduledJob() + public function getNextNumRef() { - global $conf, $langs; + global $langs, $conf; + $langs->load("asset@asset"); - $this->output = ''; - $this->error = ''; + if (empty($conf->global->ASSET_ASSET_ADDON)) { + $conf->global->ASSET_ASSET_ADDON = 'mod_asset_standard'; + } - dol_syslog(__METHOD__, LOG_DEBUG); + if (!empty($conf->global->ASSET_ASSET_ADDON)) { + $mybool = false; - return 0; + $file = $conf->global->ASSET_ASSET_ADDON.".php"; + $classname = $conf->global->ASSET_ASSET_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/asset/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + // public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + // { + // global $conf, $langs; + // + // $result = 0; + // $includedocgeneration = 1; + // + // $langs->load("asset@asset"); + // + // if (!dol_strlen($modele)) { + // $modele = 'standard_asset'; + // + // if (!empty($this->model_pdf)) { + // $modele = $this->model_pdf; + // } elseif (!empty($conf->global->ASSET_ADDON_PDF)) { + // $modele = $conf->global->ASSET_ADDON_PDF; + // } + // } + // + // $modelpath = "core/modules/asset/doc/"; + // + // if ($includedocgeneration && !empty($modele)) { + // $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + // } + // + // return $result; + // } } diff --git a/htdocs/asset/class/asset_type.class.php b/htdocs/asset/class/asset_type.class.php deleted file mode 100644 index be8643e3f20..00000000000 --- a/htdocs/asset/class/asset_type.class.php +++ /dev/null @@ -1,445 +0,0 @@ - - * - * 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 . - */ - -/** - * \file htdocs/asset/class/asset_type.class.php - * \ingroup asset - * \brief File of class to manage asset types - */ - -require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; - - -/** - * Class to manage asset type - */ -class AssetType extends CommonObject -{ - /** - * @var string Name of table without prefix where object is stored - */ - public $table_element = 'asset_type'; - - /** - * @var string ID to identify managed object - */ - public $element = 'asset_type'; - - /** - * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png - */ - public $picto = 'asset'; - - /** - * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe - * @var int - */ - public $ismultientitymanaged = 1; - - /** - * @var string Asset type label - */ - public $label; - - /** @var string Accountancy code asset */ - public $accountancy_code_asset; - - /** @var string Accountancy code depreciation asset */ - public $accountancy_code_depreciation_asset; - - /** @var string Accountancy code depreciation expense */ - public $accountancy_code_depreciation_expense; - - /** @var string Public note */ - public $note; - - /** @var array Array of asset */ - public $asset = array(); - - public $fields = array( - 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10), - 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>15, 'index'=>1), - 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>20), - 'label' =>array('type'=>'varchar(50)', 'label'=>'Label', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>25, 'showoncombobox'=>1), - 'accountancy_code_asset' =>array('type'=>'varchar(32)', 'label'=>'Accountancy code asset', 'enabled'=>1, 'visible'=>-1, 'position'=>30), - 'accountancy_code_depreciation_asset' =>array('type'=>'varchar(32)', 'label'=>'Accountancy code depreciation asset', 'enabled'=>1, 'visible'=>-1, 'position'=>35), - 'accountancy_code_depreciation_expense' =>array('type'=>'varchar(32)', 'label'=>'Accountancy code depreciation expense', 'enabled'=>1, 'visible'=>-1, 'position'=>40), - 'note' =>array('type'=>'mediumtext', 'label'=>'Note', 'enabled'=>1, 'visible'=>-1, 'position'=>45), - ); - - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct($db) - { - $this->db = $db; - } - - - /** - * Fonction qui permet de creer le type d'immobilisation - * - * @param User $user User making creation - * @param int $notrigger 1=do not execute triggers, 0 otherwise - * @return int >0 if OK, < 0 if KO - */ - public function create($user, $notrigger = 0) - { - global $conf; - - $error = 0; - - $this->label = trim($this->label); - $this->accountancy_code_asset = trim($this->accountancy_code_asset); - $this->accountancy_code_depreciation_asset = trim($this->accountancy_code_depreciation_asset); - $this->accountancy_code_depreciation_expense = trim($this->accountancy_code_depreciation_expense); - - $this->db->begin(); - - $sql = "INSERT INTO ".MAIN_DB_PREFIX."asset_type ("; - $sql .= "label"; - $sql .= ", accountancy_code_asset"; - $sql .= ", accountancy_code_depreciation_asset"; - $sql .= ", accountancy_code_depreciation_expense"; - $sql .= ", note"; - $sql .= ", entity"; - $sql .= ") VALUES ("; - $sql .= "'".$this->db->escape($this->label)."'"; - $sql .= ", '".$this->db->escape($this->accountancy_code_asset)."'"; - $sql .= ", '".$this->db->escape($this->accountancy_code_depreciation_asset)."'"; - $sql .= ", '".$this->db->escape($this->accountancy_code_depreciation_expense)."'"; - $sql .= ", '".$this->db->escape($this->note)."'"; - $sql .= ", ".((int) $conf->entity); - $sql .= ")"; - - dol_syslog("Asset_type::create", LOG_DEBUG); - $result = $this->db->query($sql); - if ($result) { - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."asset_type"); - - $result = $this->update($user, 1); - if ($result < 0) { - $this->db->rollback(); - return -3; - } - - if (!$notrigger) { - // Call trigger - $result = $this->call_trigger('ASSET_TYPE_CREATE', $user); - if ($result < 0) { - $error++; - } - // End call triggers - } - - if (!$error) { - $this->db->commit(); - return $this->id; - } else { - dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR); - $this->db->rollback(); - return -2; - } - } else { - $this->error = $this->db->lasterror(); - $this->db->rollback(); - return -1; - } - } - - /** - * Met a jour en base donnees du type - * - * @param User $user Object user making change - * @param int $notrigger 1=do not execute triggers, 0 otherwise - * @return int >0 if OK, < 0 if KO - */ - public function update($user, $notrigger = 0) - { - global $conf, $hookmanager; - - $error = 0; - - $this->label = trim($this->label); - - $this->db->begin(); - - $sql = "UPDATE ".MAIN_DB_PREFIX."asset_type "; - $sql .= "SET "; - $sql .= "label = '".$this->db->escape($this->label)."',"; - $sql .= "accountancy_code_asset = '".$this->db->escape($this->accountancy_code_asset)."',"; - $sql .= "accountancy_code_depreciation_asset = '".$this->db->escape($this->accountancy_code_depreciation_asset)."',"; - $sql .= "accountancy_code_depreciation_expense = '".$this->db->escape($this->accountancy_code_depreciation_expense)."',"; - $sql .= "note = '".$this->db->escape($this->note)."'"; - $sql .= " WHERE rowid = ".((int) $this->id); - - $result = $this->db->query($sql); - if ($result) { - $action = 'update'; - - // Actions on extra fields - if (!$error) { - $result = $this->insertExtraFields(); - if ($result < 0) { - $error++; - } - } - - if (!$error && !$notrigger) { - // Call trigger - $result = $this->call_trigger('ASSET_TYPE_MODIFY', $user); - if ($result < 0) { - $error++; - } - // End call triggers - } - - if (!$error) { - $this->db->commit(); - return 1; - } else { - $this->db->rollback(); - dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR); - return -$error; - } - } else { - $this->error = $this->db->lasterror(); - $this->db->rollback(); - return -1; - } - } - - /** - * Fonction qui permet de supprimer le status de l'adherent - * - * @return int >0 if OK, 0 if not found, < 0 if KO - */ - public function delete() - { - global $user; - - $error = 0; - - $sql = "DELETE FROM ".MAIN_DB_PREFIX."asset_type"; - $sql .= " WHERE rowid = ".((int) $this->id); - - $resql = $this->db->query($sql); - if ($resql) { - // Call trigger - $result = $this->call_trigger('ASSET_TYPE_DELETE', $user); - if ($result < 0) { - $error++; $this->db->rollback(); return -2; - } - // End call triggers - - $this->db->commit(); - return 1; - } else { - $this->db->rollback(); - $this->error = $this->db->lasterror(); - return -1; - } - } - - /** - * Fonction qui permet de recuperer le status de l'immobilisation - * - * @param int $rowid Id of member type to load - * @return int <0 if KO, >0 if OK - */ - public function fetch($rowid) - { - $sql = "SELECT d.rowid, d.label as label, d.accountancy_code_asset, d.accountancy_code_depreciation_asset, d.accountancy_code_depreciation_expense, d.note"; - $sql .= " FROM ".MAIN_DB_PREFIX."asset_type as d"; - $sql .= " WHERE d.rowid = ".(int) $rowid; - - dol_syslog("Asset_type::fetch", LOG_DEBUG); - - $resql = $this->db->query($sql); - if ($resql) { - if ($this->db->num_rows($resql)) { - $obj = $this->db->fetch_object($resql); - - $this->id = $obj->rowid; - $this->ref = $obj->rowid; - $this->label = $obj->label; - $this->accountancy_code_asset = $obj->accountancy_code_asset; - $this->accountancy_code_depreciation_asset = $obj->accountancy_code_depreciation_asset; - $this->accountancy_code_depreciation_expense = $obj->accountancy_code_depreciation_expense; - $this->note = $obj->note; - } - - return 1; - } else { - $this->error = $this->db->lasterror(); - return -1; - } - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Return list of asset's type - * - * @return array List of types of members - */ - public function liste_array() - { - // phpcs:enable - global $conf, $langs; - - $assettypes = array(); - - $sql = "SELECT rowid, label as label"; - $sql .= " FROM ".MAIN_DB_PREFIX."asset_type"; - $sql .= " WHERE entity IN (".getEntity('asset_type').")"; - - $resql = $this->db->query($sql); - if ($resql) { - $nump = $this->db->num_rows($resql); - - if ($nump) { - $i = 0; - while ($i < $nump) { - $obj = $this->db->fetch_object($resql); - - $assettypes[$obj->rowid] = $langs->trans($obj->label); - $i++; - } - } - } else { - print $this->db->error(); - } - return $assettypes; - } - - /** - * Return array of Asset objects for asset type this->id (or all if this->id not defined) - * - * @param string $excludefilter Filter string to exclude. This parameter must not be provided by input of users - * @param int $mode 0=Return array of asset instance - * 1=Return array of asset instance without extra data - * 2=Return array of asset id only - * @return mixed Array of asset or -1 on error - */ - public function listAssetForAssetType($excludefilter = '', $mode = 0) - { - global $conf, $user; - - $ret = array(); - - $sql = "SELECT a.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."asset as a"; - $sql .= " WHERE a.entity IN (".getEntity('asset').")"; - $sql .= " AND a.fk_asset_type = ".((int) $this->id); - if (!empty($excludefilter)) { - $sql .= ' AND ('.$excludefilter.')'; - } - - dol_syslog(get_class($this)."::listAssetsForGroup", LOG_DEBUG); - $resql = $this->db->query($sql); - if ($resql) { - while ($obj = $this->db->fetch_object($resql)) { - if (!array_key_exists($obj->rowid, $ret)) { - if ($mode < 2) { - $assetstatic = new Asset($this->db); - $assetstatic->fetch($obj->rowid); - $ret[$obj->rowid] = $assetstatic; - } else { - $ret[$obj->rowid] = $obj->rowid; - } - } - } - - $this->db->free($resql); - - $this->asset = $ret; - - return $ret; - } else { - $this->error = $this->db->lasterror(); - return -1; - } - } - - /** - * Return clicable name (with picto eventually) - * - * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto - * @param int $maxlen length max label - * @param int $notooltip 1=Disable tooltip - * @return string String with URL - */ - public function getNomUrl($withpicto = 0, $maxlen = 0, $notooltip = 0) - { - global $langs; - - $result = ''; - $label = $langs->trans("ShowTypeCard", $this->label); - - $linkstart = ''; - $linkend = ''; - - $result .= $linkstart; - if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); - } - if ($withpicto != 2) { - $result .= ($maxlen ?dol_trunc($this->label, $maxlen) : $this->label); - } - $result .= $linkend; - - return $result; - } - - /** - * Initialise an instance with random values. - * Used to build previews or test instances. - * id must be 0 if object instance is a specimen. - * - * @return void - */ - public function initAsSpecimen() - { - global $conf, $user, $langs; - - // Initialize parameters - $this->id = 0; - $this->ref = 'ATSPEC'; - $this->specimen = 1; - - $this->label = 'ASSET TYPE SPECIMEN'; - $this->note = 'This is a note'; - - // Assets of this asset type is just me - $this->asset = array( - $user->id => $user - ); - } - - /** - * getLibStatut - * - * @return string Return status of a type of asset - */ - public function getLibStatut() - { - return ''; - } -} diff --git a/htdocs/asset/class/assetaccountancycodes.class.php b/htdocs/asset/class/assetaccountancycodes.class.php new file mode 100644 index 00000000000..720dd1e745d --- /dev/null +++ b/htdocs/asset/class/assetaccountancycodes.class.php @@ -0,0 +1,279 @@ + + * + * 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 . + */ + +/** + * \file asset/class/assetaccountancycodes.class.php + * \ingroup asset + * \brief This file is a class file for AssetAccountancyCodes + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; + +/** + * Class for AssetAccountancyCodes + */ +class AssetAccountancyCodes extends CommonObject +{ + /** + * @var array Array with all accountancy codes info by mode. + * Note : 'economic' mode is mandatory and is the primary accountancy codes + * 'depreciation_asset' and 'depreciation_expense' is mandatory and is used for write depreciation in bookkeeping + */ + public $accountancy_codes_fields = array( + 'economic' => array( + 'label' => 'AssetAccountancyCodeDepreciationEconomic', + 'table' => 'asset_accountancy_codes_economic', + 'depreciation_debit' => 'depreciation_asset', + 'depreciation_credit' => 'depreciation_expense', + 'fields' => array( + 'asset' => array('label' => 'AssetAccountancyCodeAsset'), + 'depreciation_asset' => array('label' => 'AssetAccountancyCodeDepreciationAsset'), + 'depreciation_expense' => array('label' => 'AssetAccountancyCodeDepreciationExpense'), + 'value_asset_sold' => array('label' => 'AssetAccountancyCodeValueAssetSold'), + 'receivable_on_assignment' => array('label' => 'AssetAccountancyCodeReceivableOnAssignment'), + 'proceeds_from_sales' => array('label' => 'AssetAccountancyCodeProceedsFromSales'), + 'vat_collected' => array('label' => 'AssetAccountancyCodeVatCollected'), + 'vat_deductible' => array('label' => 'AssetAccountancyCodeVatDeductible'), + ), + ), + 'accelerated_depreciation' => array( + 'label' => 'AssetAccountancyCodeDepreciationAcceleratedDepreciation', + 'table' => 'asset_accountancy_codes_fiscal', + 'depreciation_debit' => 'accelerated_depreciation', + 'depreciation_credit' => 'endowment_accelerated_depreciation', + 'fields' => array( + 'accelerated_depreciation' => array('label' => 'AssetAccountancyCodeAcceleratedDepreciation'), + 'endowment_accelerated_depreciation' => array('label' => 'AssetAccountancyCodeEndowmentAcceleratedDepreciation'), + 'provision_accelerated_depreciation' => array('label' => 'AssetAccountancyCodeProvisionAcceleratedDepreciation'), + ), + ), + ); + + /** + * @var array Array with all accountancy codes by mode. + */ + public $accountancy_codes = array(); + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } + + /** + * Fill accountancy_codes property of object (using for data sent by forms) + * + * @return array Array of values + */ + public function setAccountancyCodesFromPost() + { + $this->accountancy_codes = array(); + foreach ($this->accountancy_codes_fields as $mode_key => $mode_info) { + $this->accountancy_codes[$mode_key] = array(); + foreach ($mode_info['fields'] as $field_key => $field_info) { + $accountancy_code = GETPOST($mode_key . '_' . $field_key, 'aZ09'); + if (empty($accountancy_code) || $accountancy_code == '-1') $accountancy_code = ''; + $this->accountancy_codes[$mode_key][$field_key] = $accountancy_code; + } + } + } + + /** + * Load accountancy codes of a asset or a asset model + * + * @param int $asset_id Asset ID to set + * @param int $asset_model_id Asset model ID to set + * @return int <0 if KO, >0 if OK + */ + public function fetchAccountancyCodes($asset_id = 0, $asset_model_id = 0) + { + global $langs, $hookmanager; + dol_syslog(__METHOD__ . " asset_id=$asset_id, asset_model_id=$asset_model_id"); + + $error = 0; + $this->errors = array(); + $this->accountancy_codes = array(); + + // Clean parameters + $asset_id = $asset_id > 0 ? $asset_id : 0; + $asset_model_id = $asset_model_id > 0 ? $asset_model_id : 0; + + if (!is_object($hookmanager)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $hookmanager->initHooks(array('assetaccountancycodesdao')); + $parameters = array('asset_id' => $asset_id, 'asset_model_id' => $asset_model_id); + $reshook = $hookmanager->executeHooks('fetchAccountancyCodes', $parameters, $this); // Note that $action and $object may have been modified by some hooks + if (!empty($reshook)) { + return $reshook; + } + + // Check parameters + if (empty($asset_id) && empty($asset_model_id)) { + $this->errors[] = $langs->trans('AssetErrorAssetOrAssetModelIDNotProvide'); + $error++; + } + if ($error) { + dol_syslog(__METHOD__ . " Error check parameters: " . $this->errorsToString(), LOG_ERR); + return -1; + } + + $accountancy_codes = array(); + foreach ($this->accountancy_codes_fields as $mode_key => $mode_info) { + $sql = "SELECT " . implode(',', array_keys($mode_info['fields'])); + $sql .= " FROM " . MAIN_DB_PREFIX . $mode_info['table']; + $sql .= " WHERE " . ($asset_id > 0 ? " fk_asset = " . (int) $asset_id : " fk_asset_model = " . (int) $asset_model_id); + + $resql = $this->db->query($sql); + if ($resql) { + if ($obj = $this->db->fetch_object($resql)) { + $accountancy_codes[$mode_key] = array(); + foreach ($mode_info['fields'] as $field_key => $field_info) { + $accountancy_codes[$mode_key][$field_key] = $obj->$field_key; + } + } + } else { + $this->errors[] = $langs->trans('AssetErrorFetchAccountancyCodesForMode', $mode_key) . ': ' . $this->db->lasterror(); + $error++; + } + } + + if ($error) { + dol_syslog(__METHOD__ . " Error fetch accountancy codes: " . $this->errorsToString(), LOG_ERR); + return -1; + } else { + $this->accountancy_codes = $accountancy_codes; + return 1; + } + } + + /** + * Update accountancy codes of a asset or a asset model + * + * @param User $user User making update + * @param int $asset_id Asset ID to set + * @param int $asset_model_id Asset model ID to set + * @param int $notrigger 1=disable trigger UPDATE (when called by create) + * @return int <0 if KO, >0 if OK + */ + public function updateAccountancyCodes($user, $asset_id = 0, $asset_model_id = 0, $notrigger = 0) + { + global $langs, $hookmanager; + dol_syslog(__METHOD__ . " user_id={$user->id}, asset_id=$asset_id, asset_model_id=$asset_model_id, notrigger=$notrigger"); + + $error = 0; + $this->errors = array(); + + // Clean parameters + $asset_id = $asset_id > 0 ? $asset_id : 0; + $asset_model_id = $asset_model_id > 0 ? $asset_model_id : 0; + + if (!is_object($hookmanager)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $hookmanager->initHooks(array('assetaccountancycodesdao')); + $parameters = array('user' => $user, 'asset_id' => $asset_id, 'asset_model_id' => $asset_model_id); + $reshook = $hookmanager->executeHooks('updateAccountancyCodes', $parameters, $this); // Note that $action and $object may have been modified by some hooks + if (!empty($reshook)) { + return $reshook; + } + + // Check parameters + if (empty($asset_id) && empty($asset_model_id)) { + $this->errors[] = $langs->trans('AssetErrorAssetOrAssetModelIDNotProvide'); + $error++; + } + if ($error) { + dol_syslog(__METHOD__ . " Error check parameters: " . $this->errorsToString(), LOG_ERR); + return -1; + } + + $this->db->begin(); + $now = dol_now(); + + foreach ($this->accountancy_codes_fields as $mode_key => $mode_info) { + // Delete old accountancy codes + $sql = "DELETE FROM " . MAIN_DB_PREFIX . $mode_info['table']; + $sql .= " WHERE " . ($asset_id > 0 ? " fk_asset = " . (int) $asset_id : " fk_asset_model = " . (int) $asset_model_id); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorDeleteAccountancyCodesForMode', $mode_key) . ': ' . $this->db->lasterror(); + $error++; + } + + if (!$error && !empty($this->accountancy_codes[$mode_key])) { + // Insert accountancy codes + $sql = "INSERT INTO " . MAIN_DB_PREFIX . $mode_info['table'] . "("; + $sql .= $asset_id > 0 ? "fk_asset," : "fk_asset_model,"; + $sql .= implode(',', array_keys($mode_info['fields'])); + $sql .= ", tms, fk_user_modif"; + $sql .= ") VALUES("; + $sql .= $asset_id > 0 ? $asset_id : $asset_model_id; + foreach ($mode_info['fields'] as $field_key => $field_info) { + $sql .= ', ' . (empty($this->accountancy_codes[$mode_key][$field_key]) ? 'NULL' : "'" . $this->db->escape($this->accountancy_codes[$mode_key][$field_key]) . "'"); + } + $sql .= ", '" . $this->db->idate($now) . "'"; + $sql .= ", " . $user->id; + $sql .= ")"; + + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorInsertAccountancyCodesForMode', $mode_key) . ': ' . $this->db->lasterror(); + $error++; + } + } + } + + if (!$error && $asset_id > 0) { + // Calculation of depreciation lines (reversal and future) + require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php'; + $asset = new Asset($this->db); + $result = $asset->fetch($asset_id); + if ($result > 0) $result = $asset->calculationDepreciation(); + if ($result < 0) { + $this->errors[] = $langs->trans('AssetErrorCalculationDepreciationLines'); + $this->errors[] = $asset->errorsToString(); + $error++; + } + } + + if (!$error && !$notrigger) { + // Call trigger + $result = $this->call_trigger('ASSET_ACCOUNTANCY_CODES_MODIFY', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } +} diff --git a/htdocs/asset/class/assetdepreciationoptions.class.php b/htdocs/asset/class/assetdepreciationoptions.class.php new file mode 100644 index 00000000000..ce2ddd73c08 --- /dev/null +++ b/htdocs/asset/class/assetdepreciationoptions.class.php @@ -0,0 +1,546 @@ + + * + * 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 . + */ + +/** + * \file asset/class/assetdepreciationoptions.class.php + * \ingroup asset + * \brief This file is a class file for AssetDepreciationOptions + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; + +/** + * Class for AssetDepreciationOptions + */ +class AssetDepreciationOptions extends CommonObject +{ + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = ''; + + /** + * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' + * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'validate' is 1 if need to validate with $this->validateField() + * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) + * 'enabled_field' if the mode block or a field is enabled if another field equal a value (="mode_key:field_key:value") + * 'only_on_asset' is 1 if only a field on a asset + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields = array(); + + /** + * @var array Array with all deprecation options info by mode. + * Note : economic mode is mandatory and is the primary options + */ + public $deprecation_options_fields = array( + 'economic' => array( + 'label' => 'AssetDepreciationOptionEconomic', + 'table' => 'asset_depreciation_options_economic', + 'fields' => array( + 'depreciation_type' => array('type'=>'smallint', 'label'=>'AssetDepreciationOptionDepreciationType', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'arrayofkeyval'=>array('0'=>'AssetDepreciationOptionDepreciationTypeLinear', '1'=>'AssetDepreciationOptionDepreciationTypeDegressive', '2'=>'AssetDepreciationOptionDepreciationTypeExceptional'), 'validate'=>'1',), + 'degressive_coefficient' => array('type'=>'double(24,8)', 'label'=>'AssetDepreciationOptionDegressiveRate', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1','enabled_field' => 'economic:depreciation_type:1'), + 'duration' => array('type'=>'integer', 'label'=>'AssetDepreciationOptionDuration', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1',), + 'duration_type' => array('type'=>'smallint', 'label'=>'AssetDepreciationOptionDurationType', 'enabled'=>'1', 'position'=>40, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'arrayofkeyval'=>array('0'=>'AssetDepreciationOptionDurationTypeAnnual', '1'=>'AssetDepreciationOptionDurationTypeMonthly'/*, '2'=>'AssetDepreciationOptionDurationTypeDaily'*/), 'validate'=>'1',), + 'rate' => array('type'=>'double(24,8)', 'label'=>'AssetDepreciationOptionRate', 'enabled'=>'1', 'position'=>50, 'visible'=>3, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1', 'computed' => '$object->asset_depreciation_options->getRate("economic")',), + 'accelerated_depreciation_option' => array('type'=>'boolean', 'label'=>'AssetDepreciationOptionAcceleratedDepreciation', 'enabled'=>'1', 'position'=>60, 'column_break' => true, 'notnull'=>0, 'default'=>'0', 'visible'=>1, 'validate'=>'1',), + 'amount_base_depreciation_ht' => array('type'=>'price', 'label'=>'AssetDepreciationOptionAmountBaseDepreciationHT', 'enabled'=>'isset($object)&&get_class($object)=="Asset"', 'only_on_asset'=>1, 'position'=>90, 'notnull'=>0, 'required'=>1, 'visible'=>1, 'default'=>'$object->reversal_amount_ht > 0 ? $object->reversal_amount_ht : $object->acquisition_value_ht', 'isameasure'=>'1', 'validate'=>'1',), + 'amount_base_deductible_ht' => array('type'=>'price', 'label'=>'AssetDepreciationOptionAmountBaseDeductibleHT', 'enabled'=>'isset($object)&&get_class($object)=="Asset"', 'only_on_asset'=>1, 'position'=>100, 'notnull'=>0, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1',), + 'total_amount_last_depreciation_ht' => array('type'=>'price', 'label'=>'AssetDepreciationOptionTotalAmountLastDepreciationHT', 'enabled'=>'isset($object)&&get_class($object)=="Asset"', 'only_on_asset'=>1, 'position'=>110, 'noteditable'=> 1, 'notnull'=>0, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1',), + ), + ), + 'accelerated_depreciation' => array( + 'label' => 'AssetDepreciationOptionAcceleratedDepreciation', + 'table' => 'asset_depreciation_options_fiscal', + 'enabled_field' => 'economic:accelerated_depreciation_option:1', + 'fields' => array( + 'depreciation_type' => array('type'=>'smallint', 'label'=>'AssetDepreciationOptionDepreciationType', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'arrayofkeyval'=>array('0'=>'AssetDepreciationOptionDepreciationTypeLinear', '1'=>'AssetDepreciationOptionDepreciationTypeDegressive', '2'=>'AssetDepreciationOptionDepreciationTypeExceptional'), 'validate'=>'1',), + 'degressive_coefficient' => array('type'=>'double(24,8)', 'label'=>'AssetDepreciationOptionDegressiveRate', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1','enabled_field' => 'accelerated_depreciation:depreciation_type:1'), + 'duration' => array('type'=>'integer', 'label'=>'AssetDepreciationOptionDuration', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1',), + 'duration_type' => array('type'=>'smallint', 'label'=>'AssetDepreciationOptionDurationType', 'enabled'=>'1', 'position'=>40, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'arrayofkeyval'=>array('0'=>'AssetDepreciationOptionDurationTypeAnnual', '1'=>'AssetDepreciationOptionDurationTypeMonthly'/*, '2'=>'AssetDepreciationOptionDurationTypeDaily'*/), 'validate'=>'1',), + 'rate' => array('type'=>'double(24,8)', 'label'=>'AssetDepreciationOptionRate', 'enabled'=>'1', 'position'=>50, 'visible'=>3, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1', 'computed' => '$object->asset_depreciation_options->getRate("accelerated_depreciation")',), + 'amount_base_depreciation_ht' => array('type'=>'price', 'label'=>'AssetDepreciationOptionAmountBaseDepreciationHT', 'enabled'=>'isset($object)&&get_class($object)=="Asset"', 'only_on_asset'=>1, 'position'=>80, 'column_break' => true, 'notnull'=>0, 'required'=>1, 'visible'=>1, 'default'=>'$object->reversal_amount_ht > 0 ? $object->reversal_amount_ht : $object->acquisition_value_ht', 'isameasure'=>'1', 'validate'=>'1',), + 'amount_base_deductible_ht' => array('type'=>'price', 'label'=>'AssetDepreciationOptionAmountBaseDeductibleHT', 'enabled'=>'isset($object)&&get_class($object)=="Asset"', 'only_on_asset'=>1, 'position'=>90, 'notnull'=>0, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1',), + 'total_amount_last_depreciation_ht' => array('type'=>'price', 'label'=>'AssetDepreciationOptionTotalAmountLastDepreciationHT', 'enabled'=>'isset($object)&&get_class($object)=="Asset"', 'only_on_asset'=>1, 'position'=>100, 'noteditable'=> 1, 'notnull'=>0, 'visible'=>1, 'default'=>'0', 'isameasure'=>'1', 'validate'=>'1',), + ), + ), + ); + public $fk_asset; + public $fk_asset_model; + public $tms; + public $fk_user_modif; + + /** + * @var array Array with all deprecation options by mode. + */ + public $deprecation_options = array(); + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $langs; + $this->db = $db; + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->deprecation_options_fields as $mode_key => $mode_info) { + if (!empty($mode_info['fields']) && is_array($mode_info['fields'])) { + foreach ($mode_info['fields'] as $field_key => $field_info) { + if (!empty($field_info['arrayofkeyval']) && is_array($field_info['arrayofkeyval'])) { + foreach ($field_info['arrayofkeyval'] as $key => $val) { + $this->deprecation_options_fields[$mode_key]['fields'][$field_key]['arrayofkeyval'][$key] = $langs->trans($val); + } + } + } + } + } + } + } + + /** + * Set object infos for a mode + * + * @param string $mode Depreciation mode (economic, accelerated_depreciation, ...) + * @param int $class_type Type (0:asset, 1:asset model) + * @param bool $all_field Get all fields + * @return int <0 if KO, >0 if OK + */ + public function setInfosForMode($mode, $class_type = 0, $all_field = false) + { + // Clean parameters + $mode = strtolower(trim($mode)); + + if (!empty($this->deprecation_options_fields[$mode])) { + $this->table_element = $this->deprecation_options_fields[$mode]['table']; + $this->fields = $this->deprecation_options_fields[$mode]['fields']; + foreach ($this->fields as $field_key => $field_info) { + if ((!empty($field_info['computed']) && !$all_field) || (!empty($field_info['only_on_asset']) && !empty($class_type))) { + unset($this->fields[$field_key]); + continue; + } + + // Unset required option (notnull) if field disabled + if (!empty($mode_info['enabled_field'])) { + $info = explode(':', $mode_info['enabled_field']); + if ($this->deprecation_options[$info[0]][$info[1]] != $info[2] && isset($this->fields[$field_key]['notnull'])) { + unset($this->fields[$field_key]['notnull']); + } + } + // Set value of the field in the object (for createCommon and setDeprecationOptionsFromPost functions) + $this->{$field_key} = $this->deprecation_options[$mode][$field_key]; + } + + $this->fields['rowid'] = array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"); + if (empty($class_type)) { + $this->fields['fk_asset'] = array('type' => 'integer:Asset:asset/class/asset.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label' => 'Asset', 'enabled' => '1', 'position' => 0, 'notnull' => 0, 'visible' => 0, 'index' => 1, 'validate' => '1',); + } else { + $this->fields['fk_asset_model'] = array('type' => 'integer:AssetModel:asset/class/assetmodel.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label' => 'AssetModel', 'enabled' => '1', 'position' => 0, 'notnull' => 0, 'visible' => 0, 'index' => 1, 'validate' => '1',); + } + $this->fields['tms'] = array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => '1', 'position' => 501, 'notnull' => 0, 'visible' => 0,); + $this->fields['fk_user_modif'] = array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => '1', 'position' => 511, 'notnull' => -1, 'visible' => 0,); + } + + return 1; + } + + /** + * Fill deprecation_options property of object (using for data sent by forms) + * + * @param int $class_type Type (0:asset, 1:asset model) + * @return int <0 if KO, >0 if OK + */ + public function setDeprecationOptionsFromPost($class_type = 0) + { + global $conf, $langs; + + $error = 0; + + $deprecation_options = array(); + foreach ($this->deprecation_options_fields as $mode_key => $mode_info) { + $this->setInfosForMode($mode_key, $class_type); + + foreach ($mode_info['fields'] as $field_key => $field_info) { + if (!empty($field_info['computed'])) { + continue; + } + + $html_name = $mode_key . '_' . $field_key; + if ($field_info['type'] == 'duration') { + if (GETPOST($html_name . 'hour') == '' && GETPOST($html_name . 'min') == '') { + continue; // The field was not submited to be saved + } + } else { + if (!GETPOSTISSET($html_name)) { + continue; // The field was not submited to be saved + } + } + // Ignore special fields + if (in_array($field_key, array('rowid', 'entity', 'import_key'))) { + continue; + } + if (in_array($field_key, array('date_creation', 'tms', 'fk_user_creat', 'fk_user_modif'))) { + if (!in_array(abs($field_info['visible']), array(1, 3))) { + continue; // Only 1 and 3 that are case to create + } + } + + // Set value to insert + if (in_array($field_info['type'], array('text', 'html'))) { + $value = GETPOST($html_name, 'restricthtml'); + } elseif ($field_info['type'] == 'date') { + $value = dol_mktime(12, 0, 0, GETPOST($html_name . 'month', 'int'), GETPOST($html_name . 'day', 'int'), GETPOST($html_name . 'year', 'int')); // for date without hour, we use gmt + } elseif ($field_info['type'] == 'datetime') { + $value = dol_mktime(GETPOST($html_name . 'hour', 'int'), GETPOST($html_name . 'min', 'int'), GETPOST($html_name . 'sec', 'int'), GETPOST($html_name . 'month', 'int'), GETPOST($html_name . 'day', 'int'), GETPOST($html_name . 'year', 'int'), 'tzuserrel'); + } elseif ($field_info['type'] == 'duration') { + $value = 60 * 60 * GETPOST($html_name . 'hour', 'int') + 60 * GETPOST($html_name . 'min', 'int'); + } elseif (preg_match('/^(integer|price|real|double)/', $field_info['type'])) { + $value = price2num(GETPOST($html_name, 'alphanohtml')); // To fix decimal separator according to lang setup + } elseif ($field_info['type'] == 'boolean') { + $value = ((GETPOST($html_name) == '1' || GETPOST($html_name) == 'on') ? 1 : 0); + } elseif ($field_info['type'] == 'reference') { + // todo to check + $tmparraykey = array(); //array_keys($object->param_list); + $value = $tmparraykey[GETPOST($html_name)] . ',' . GETPOST($html_name . '2'); + } else { + if ($field_key == 'lang') { + $value = GETPOST($html_name, 'aZ09') ? GETPOST($html_name, 'aZ09') : ""; + } else { + $value = GETPOST($html_name, 'alphanohtml'); + } + } + if (preg_match('/^integer:/i', $field_info['type']) && $value == '-1') { + $value = ''; // This is an implicit foreign key field + } + if (!empty($field_info['foreignkey']) && $value == '-1') { + $value = ''; // This is an explicit foreign key field + } + + //var_dump($field_key.' '.$value.' '.$field_info['type']); + $field_value = $value; + if ($field_info['notnull'] > 0 && $field_value == '' && !is_null($field_info['default']) && $field_info['default'] == '(PROV)') { + $field_value = '(PROV)'; + } elseif ((!empty($field_info['required']) || $field_info['notnull'] > 0) && $field_value == '' && !empty($field_info['default'])) { + $field_value = dol_eval($field_info['default'], 1); + } + if ($field_info['notnull'] > 0 && $field_value == '' && is_null($field_info['default'])) { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv($field_info['label'])), null, 'errors'); + } + $deprecation_options[$mode_key][$field_key] = $field_value; + + // Validation of fields values + if ($conf->global->MAIN_FEATURE_LEVEL >= 2 || !empty($conf->global->MAIN_ACTIVATE_VALIDATION_RESULT)) { + if (!$error && !empty($field_info['validate']) && is_callable(array($this, 'validateField'))) { + if (!$this->validateField($mode_info['fields'], $field_key, $value)) { + $error++; + } + } + } + } + } + // Unset not enabled modes + foreach ($this->deprecation_options_fields as $mode_key => $mode_info) { + if (!empty($mode_info['enabled_field'])) { + $info = explode(':', $mode_info['enabled_field']); + if ($deprecation_options[$info[0]][$info[1]] != $info[2]) { + unset($deprecation_options[$info[0]][$info[1]]); + } + } + } + $this->deprecation_options = $deprecation_options; + + if ($error) { + return -1; + } else { + return 1; + } + } + + /** + * Load deprecation options of a asset or a asset model + * + * @param int $asset_id Asset ID to set + * @param int $asset_model_id Asset model ID to set + * @return int <0 if KO, >0 if OK + */ + public function fetchDeprecationOptions($asset_id = 0, $asset_model_id = 0) + { + global $langs, $hookmanager; + dol_syslog(__METHOD__ . " asset_id=$asset_id, asset_model_id=$asset_model_id"); + + $error = 0; + $this->errors = array(); + $this->deprecation_options = array(); + + // Clean parameters + $asset_id = $asset_id > 0 ? $asset_id : 0; + $asset_model_id = $asset_model_id > 0 ? $asset_model_id : 0; + + if (!is_object($hookmanager)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $hookmanager->initHooks(array('assetdepreciationoptionsdao')); + $parameters = array('asset_id' => $asset_id, 'asset_model_id' => $asset_model_id); + $reshook = $hookmanager->executeHooks('fetchDepreciationOptions', $parameters, $this); // Note that $action and $object may have been modified by some hooks + if (!empty($reshook)) { + return $reshook; + } + + // Check parameters + if (empty($asset_id) && empty($asset_model_id)) { + $this->errors[] = $langs->trans('AssetErrorAssetOrAssetModelIDNotProvide'); + $error++; + } + if ($error) { + dol_syslog(__METHOD__ . " Error check parameters: " . $this->errorsToString(), LOG_ERR); + return -1; + } + + $class_type = $asset_id > 0 ? 0 : 1; + $deprecation_options = array(); + foreach ($this->deprecation_options_fields as $mode_key => $mode_info) { + $this->setInfosForMode($mode_key, $class_type); + + $result = $this->fetchCommon(0, '', " AND " . ($asset_id > 0 ? " fk_asset = " . (int) $asset_id : " fk_asset_model = " . (int) $asset_model_id)); + if ($result < 0) { + $this->errors = array_merge(array($langs->trans('AssetErrorFetchDepreciationOptionsForMode', $mode_key) . ':'), $this->errors); + $error++; + } elseif ($result > 0) { + foreach ($this->fields as $field_key => $field_info) { + if (in_array($field_key, array('rowid', 'fk_asset', 'fk_asset_model', 'tms', 'fk_user_modif'))) continue; + $deprecation_options[$mode_key][$field_key] = $this->{$field_key}; + } + } + } + // Unset not enabled modes + foreach ($this->deprecation_options_fields as $mode_key => $mode_info) { + if (!empty($mode_info['enabled_field'])) { + $info = explode(':', $mode_info['enabled_field']); + if ($deprecation_options[$info[0]][$info[1]] != $info[2]) { + unset($deprecation_options[$info[0]][$info[1]]); + } + } + } + + if ($error) { + dol_syslog(__METHOD__ . " Error fetch accountancy codes: " . $this->errorsToString(), LOG_ERR); + return -1; + } else { + $this->deprecation_options = $deprecation_options; + return 1; + } + } + + /** + * get general depreciation info for a mode (used in depreciation card) + * + * @param string $mode Depreciation mode (economic, accelerated_depreciation, ...) + * @return array|int <0 if KO otherwise array with general depreciation info + */ + public function getGeneralDepreciationInfoForMode($mode) + { + global $hookmanager; + dol_syslog(__METHOD__ . " mode=$mode"); + + $this->errors = array(); + + // Clean parameters + $mode = strtolower(trim($mode)); + + if (!is_object($hookmanager)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $hookmanager->initHooks(array('assetdepreciationoptionsdao')); + $parameters = array('mode' => $mode); + $reshook = $hookmanager->executeHooks('getGeneralDepreciationInfoForMode', $parameters, $this); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) { + return $reshook; + } elseif ($reshook > 0) { + return $hookmanager->resArray; + } + + $duration_type_list = $this->deprecation_options_fields[$mode]['fields']['duration_type']['arrayofkeyval']; + + return array( + 'base_depreciation_ht' => $this->deprecation_options[$mode]['amount_base_depreciation_ht'], + 'duration' => $this->deprecation_options[$mode]['duration'], + 'duration_type' => $duration_type_list[$this->deprecation_options[$mode]['duration_type']], + 'rate' => $this->getRate($mode), + ); + } + + /** + * Update deprecation options of a asset or a asset model + * + * @param User $user User making update + * @param int $asset_id Asset ID to set + * @param int $asset_model_id Asset model ID to set + * @param int $notrigger 1=disable trigger UPDATE (when called by create) + * @return int <0 if KO, >0 if OK + */ + public function updateDeprecationOptions($user, $asset_id = 0, $asset_model_id = 0, $notrigger = 0) + { + global $langs, $hookmanager; + dol_syslog(__METHOD__ . " user_id={$user->id}, asset_id=$asset_id, asset_model_id=$asset_model_id, notrigger=$notrigger"); + + $error = 0; + $this->errors = array(); + + // Clean parameters + $asset_id = $asset_id > 0 ? $asset_id : 0; + $asset_model_id = $asset_model_id > 0 ? $asset_model_id : 0; + + if (!is_object($hookmanager)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $hookmanager->initHooks(array('assetdepreciationoptionsdao')); + $parameters = array('user' => $user, 'asset_id' => $asset_id, 'asset_model_id' => $asset_model_id); + $reshook = $hookmanager->executeHooks('updateDepreciationOptions', $parameters, $this); // Note that $action and $object may have been modified by some hooks + if (!empty($reshook)) { + return $reshook; + } + + // Check parameters + if (empty($asset_id) && empty($asset_model_id)) { + $this->errors[] = $langs->trans('AssetErrorAssetOrAssetModelIDNotProvide'); + $error++; + } + if ($error) { + dol_syslog(__METHOD__ . " Error check parameters: " . $this->errorsToString(), LOG_ERR); + return -1; + } + + $this->db->begin(); + + if ($asset_id > 0) { + $this->fk_asset = $asset_id; + $class_type = 0; + } else { + $this->fk_asset_model = $asset_model_id; + $class_type = 1; + } + $this->tms = dol_now(); + $this->fk_user_modif = $user->id; + + foreach ($this->deprecation_options_fields as $mode_key => $mode_info) { + // Delete old accountancy codes + $sql = "DELETE FROM " . MAIN_DB_PREFIX . $mode_info['table']; + $sql .= " WHERE " . ($asset_id > 0 ? " fk_asset = " . (int) $asset_id : " fk_asset_model = " . (int) $asset_model_id); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $langs->trans('AssetErrorDeleteDepreciationOptionsForMode', $mode_key) . ': ' . $this->db->lasterror(); + $error++; + } + + if (!$error && !empty($this->deprecation_options[$mode_key])) { + if (!empty($mode_info['enabled_field'])) { + $info = explode(':', $mode_info['enabled_field']); + if ($this->deprecation_options[$info[0]][$info[1]] != $info[2]) { + continue; + } + } + + $this->setInfosForMode($mode_key, $class_type); + + $result = $this->createCommon($user, 1); + if ($result < 0) { + $this->errors = array_merge(array($langs->trans('AssetErrorInsertDepreciationOptionsForMode', $mode_key) . ':'), $this->errors); + $error++; + } + } + } + + if (!$error && $this->fk_asset > 0) { + // Calculation of depreciation lines (reversal and future) + require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php'; + $asset = new Asset($this->db); + $result = $asset->fetch($this->fk_asset); + if ($result > 0) $result = $asset->calculationDepreciation(); + if ($result < 0) { + $this->errors[] = $langs->trans('AssetErrorCalculationDepreciationLines'); + $this->errors[] = $asset->errorsToString(); + $error++; + } + } + + if (!$error && !$notrigger) { + // Call trigger + $result = $this->call_trigger('ASSET_DEPRECIATION_OPTIONS_MODIFY', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + + if ($error) { + $this->db->rollback(); + return -1; + } else { + $this->db->commit(); + return 1; + } + } + + /** + * Get rate + * + * @param string $mode Depreciation mode (economic, accelerated_depreciation, ...) + * @return string Rate of the provided mode option + */ + public function getRate($mode) + { + $duration = $this->deprecation_options[$mode]["duration"] > 0 ? $this->deprecation_options[$mode]["duration"] : 0; + $duration_type = $this->deprecation_options[$mode]["duration_type"] > 0 ? $this->deprecation_options[$mode]["duration_type"] : 0; + + return price(price2num($duration > 0 ? (100 * ($duration_type == 1 ? 12 : 1) / $duration) : 0, 2)); + } +} diff --git a/htdocs/asset/class/assetmodel.class.php b/htdocs/asset/class/assetmodel.class.php new file mode 100644 index 00000000000..eae7b5d0fde --- /dev/null +++ b/htdocs/asset/class/assetmodel.class.php @@ -0,0 +1,822 @@ + + * Copyright (C) 2021 Open-Dsi + * + * 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 . + */ + +/** + * \file class/assetmodel.class.php + * \ingroup asset + * \brief This file is a CRUD class file for AssetModel (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for AssetModel + */ +class AssetModel extends CommonObject +{ + /** + * @var string ID of module. + */ + public $module = 'asset'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'assetmodel'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'asset_model'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 1; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 1; + + /** + * @var string String with name of icon for assetmodel. Must be the part after the 'object_' into object_assetmodel.png + */ + public $picto = 'asset'; + + + const STATUS_DRAFT = 0; + const STATUS_VALIDATED = 1; + const STATUS_CANCELED = 9; + + + /** + * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' + * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'validate' is 1 if need to validate with $this->validateField() + * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'validate'=>'1'), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'cssview'=>'wordbreak', 'showoncombobox'=>'2', 'validate'=>'1',), + 'asset_type' => array('type'=>'smallint', 'label'=>'AssetType', 'enabled'=>'1', 'position'=>40, 'notnull'=>1, 'visible'=>1, 'arrayofkeyval'=>array('0'=>'AssetTypeIntangible', '1'=>'AssetTypeTangible', '2'=>'AssetTypeInProgress', '3'=>'AssetTypeFinancial'), 'validate'=>'1',), + 'fk_pays' =>array('type'=>'integer:Ccountry:core/class/ccountry.class.php', 'label'=>'Country', 'enabled'=>1, 'visible'=>1, 'position'=>50), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>300, 'notnull'=>0, 'visible'=>0, 'validate'=>'1',), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>301, 'notnull'=>0, 'visible'=>0, 'validate'=>'1',), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'default'=>'0', 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Enabled', '9'=>'Disabled'), 'validate'=>'1',), + ); + public $rowid; + public $ref; + public $label; + public $asset_type; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $last_main_doc; + public $import_key; + public $model_pdf; + public $status; + + // /** + // * @var string Field with ID of parent key if this object has a parent + // */ + // public $fk_element = 'fk_assetmodel'; + // /** + // * @var array List of child tables. To test if we can delete object. + // */ + // protected $childtables = array(); + // /** + // * @var array List of child tables. To know object to delete on cascade. + // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + // */ + // protected $childtablesoncascade = array('asset_assetmodeldet'); + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) { + $this->fields['rowid']['visible'] = 0; + } + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) { + $this->fields['entity']['enabled'] = 0; + } + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + $resultcreate = $this->createCommon($user, $notrigger); + + return $resultcreate; + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetchCommon($fromid); + if ($result > 0 && !empty($object->table_element_line)) { + $object->fetchLines(); + } + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + // Clear fields + if (property_exists($object, 'ref')) { + $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; + } + if (property_exists($object, 'label')) { + $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + } + if (property_exists($object, 'status')) { + $object->status = self::STATUS_DRAFT; + } + if (property_exists($object, 'date_creation')) { + $object->date_creation = dol_now(); + } + if (property_exists($object, 'date_modification')) { + $object->date_modification = null; + } + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach ($object->array_options as $key => $option) { + $shortkey = preg_replace('/options_/', '', $key); + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->createCommon($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (!$error) { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) { + $error++; + } + } + + if (!$error) { + // copy external contacts if same company + if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) { + if ($this->copy_linked_contact($object, 'external') < 0) { + $error++; + } + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && !empty($this->table_element_line)) { + $this->fetchLines(); + } + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines = array(); + + return 1; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = "SELECT "; + $sql .= $this->getFieldList('t'); + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + } else { + $sql .= " WHERE 1 = 1"; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; + } else { + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int <=0 if OK, 0=Nothing done, >0 if KO + */ + public function validate($user, $notrigger = 0) + { + global $conf, $langs; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) { + dol_syslog(get_class($this) . "::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + $now = dol_now(); + + $this->db->begin(); + + // Validate + $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " SET status = " . self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) { + $sql .= ", date_validation = '" . $this->db->idate($now) . "'"; + } + if (!empty($this->fields['fk_user_valid'])) { + $sql .= ", fk_user_valid = " . ((int) $user->id); + } + $sql .= " WHERE rowid = " . ((int) $this->id); + + dol_syslog(get_class($this) . "::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) { + // Call trigger + $result = $this->call_trigger('ASSETMODEL_VALIDATE', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + + // Set new ref and current status + if (!$error) { + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDraft($user, $notrigger = 0) + { + // Protection + if ($this->status <= self::STATUS_DRAFT) { + return 0; + } + + return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'ASSETMODEL_UNVALIDATE'); + } + + /** + * Set cancel status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function cancel($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_VALIDATED) { + return 0; + } + + return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'ASSETMODEL_CANCEL'); + } + + /** + * Set back to validated status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function reopen($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_CANCELED) { + return 0; + } + + return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'ASSETMODEL_REOPEN'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (!empty($conf->dol_no_mouse_hover)) { + $notooltip = 1; // Force disable tooltips + } + + $result = ''; + + $label = img_picto('', $this->picto).' '.$langs->trans("AssetModel").''; + if (isset($this->status)) { + $label .= ' '.$this->getLibStatut(5); + } + $label .= '
    '; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + + $url = dol_buildpath('/asset/model/card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) { + $add_save_lastsearch_values = 1; + } + if ($add_save_lastsearch_values) { + $url .= '&save_lastsearch_values=1'; + } + } + + $linkclose = ''; + if (empty($notooltip)) { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { + $label = $langs->trans("ShowAssetModel"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else { + $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + } + + if ($option == 'nolink') { + $linkstart = ''; + if ($option == 'nolink') { + $linkend = ''; + } else { + $linkend = ''; + } + + $result .= $linkstart; + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
    No photo
    '; + } else { + $result .= '
    No photo
    '; + } + + $result .= ''; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } + } + + if ($withpicto != 2) { + $result .= $this->ref; + } + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('assetmodeldao')); + $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } + + return $result; + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLabelStatus($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut($status, $mode = 0) + { + // phpcs:enable + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { + global $langs; + //$langs->load("asset@asset"); + $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); + $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); + $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); + } + + $statusType = 'status'.$status; + //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; + if ($status == self::STATUS_CANCELED) { + $statusType = 'status6'; + } + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = "SELECT rowid, date_creation as datec, tms as datem,"; + $sql .= " fk_user_creat, fk_user_modif"; + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + $sql .= " WHERE t.rowid = ".((int) $id); + + $result = $this->db->query($sql); + if ($result) { + if ($this->db->num_rows($result)) { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if ($obj->fk_user_author) { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_valid) { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if ($obj->fk_user_cloture) { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + // Set here init that are not commonf fields + // $this->property1 = ... + // $this->property2 = ... + + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + return $this->lines; + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * Use public function doScheduledJob($param1, $param2, ...) to get parameters + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error = ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} diff --git a/htdocs/asset/depreciation.php b/htdocs/asset/depreciation.php new file mode 100644 index 00000000000..8f3547d81fb --- /dev/null +++ b/htdocs/asset/depreciation.php @@ -0,0 +1,199 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/depreciation.php + * \ingroup asset + * \brief Card with depreciation on Asset + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new Asset($db); +$assetdepreciationoptions = new AssetDepreciationOptions($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('assetdepreciation', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity] . "/" . $object->id; +} + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!empty($object->not_depreciated)) accessforbidden(); + +$object->asset_depreciation_options = &$assetdepreciationoptions; +$result = $assetdepreciationoptions->fetchDeprecationOptions($object->id); +if ($result < 0) { + setEventMessages($assetdepreciationoptions->error, $assetdepreciationoptions->errors, 'errors'); +} +$result = $object->fetchDepreciationLines(); +if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); +} + + +/* + * Actions + */ + +$reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { +} + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +llxHeader('', $langs->trans('Asset'), $help_url); + +if ($id > 0 || !empty($ref)) { + $head = assetPrepareHead($object); + print dol_get_fiche_head($head, 'depreciation', $langs->trans("Asset"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + print '
    '; + + print dol_get_fiche_end(); + + $parameters = array(); + $reshook = $hookmanager->executeHooks('listAssetDeprecation', $parameters, $object, $action); + print $hookmanager->resPrint; + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } elseif (empty($reshook)) { + $bookkeeping_icon = ''; + $future_icon = ''; + $now = dol_now(); + + foreach ($assetdepreciationoptions->deprecation_options_fields as $mode_key => $fields) { + $lines = $object->depreciation_lines[$mode_key]; + if (!empty($lines)) { + $mode_info = $assetdepreciationoptions->deprecation_options_fields[$mode_key]; + $depreciation_info = $assetdepreciationoptions->getGeneralDepreciationInfoForMode($mode_key); + + print load_fiche_titre($langs->trans($mode_info['label']), '', ''); + + // Depreciation general info + //--------------------------------- + print '
    '; + print '
    '; + print '
    '; + print '' . "\n"; + print ''; + print ''; + print '
    ' . $langs->trans('AssetBaseDepreciationHT') . '' . price($depreciation_info['base_depreciation_ht']) . '
    ' . $langs->trans('AssetDepreciationBeginDate') . '' . dol_print_date($object->date_start > $object->date_acquisition ? $object->date_start : $object->date_acquisition, 'day') . '
    '; + + // We close div and reopen for second column + print '
    '; + print '
    '; + + print '
    '; + print ''; + print ''; + print ''; + print '
    ' . $langs->trans('AssetDepreciationDuration') . '' . $depreciation_info['duration'] . ' ( ' . $depreciation_info['duration_type'] . ' )
    ' . $langs->trans('AssetDepreciationRate') . '' . $depreciation_info['rate'] . '
    '; + print '
    '; + print '
    '; + print '
    '; + + // Depreciation lines + //--------------------------------- + print '
    '; + print '
    '; + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + if (empty($lines)) { + print ''; + } else { + foreach ($lines as $line) { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + } + } + + print '
    ' . $langs->trans("Ref") . '' . $langs->trans("AssetDepreciationDate") . '' . $langs->trans("AssetDepreciationHT") . '' . $langs->trans("AssetCumulativeDepreciationHT") . '' . $langs->trans("AssetResidualHT") . '
    ' . $langs->trans("None") . '
    ' . ($line['bookkeeping'] ? $bookkeeping_icon : ($line['depreciation_date'] > $now ? $future_icon : '')) . '' . (empty($line['ref']) ? $langs->trans('AssetDepreciationReversal') : $line['ref']) . '' . dol_print_date($line['depreciation_date'], 'day') . ''; + print price($line['depreciation_ht']); + print ''; + print price($line['cumulative_depreciation_ht']); + print ''; + print price(price2num($depreciation_info['base_depreciation_ht'] - $line['cumulative_depreciation_ht'], 'MT')); + print '
    '; + print '
    '; + } + } + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/depreciation_options.php b/htdocs/asset/depreciation_options.php new file mode 100644 index 00000000000..ba5719705dc --- /dev/null +++ b/htdocs/asset/depreciation_options.php @@ -0,0 +1,190 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/depreciation_options.php + * \ingroup asset + * \brief Card with depreciation options on Asset + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new Asset($db); +$assetdepreciationoptions = new AssetDepreciationOptions($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('assetdepreciationoptions', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity] . "/" . $object->id; +} + +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!empty($object->not_depreciated)) accessforbidden(); + +$object->asset_depreciation_options = &$assetdepreciationoptions; +$result = $assetdepreciationoptions->fetchDeprecationOptions($object->id); +if ($result < 0) { + setEventMessages($assetdepreciationoptions->error, $assetdepreciationoptions->errors, 'errors'); +} + + +/* + * Actions + */ + +$reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { + $backurlforlist = DOL_URL_ROOT.'/asset/list.php'; + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = DOL_URL_ROOT.'/asset/depreciation_options.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__'); + } + } + } + + if ($cancel) { + /*var_dump($cancel);var_dump($backtopage);var_dump($backtopageforcancel);exit;*/ + if (!empty($backtopageforcancel)) { + header("Location: ".$backtopageforcancel); + exit; + } elseif (!empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + $action = ''; + } + + if ($action == "update") { + $result = $assetdepreciationoptions->setDeprecationOptionsFromPost(); + if ($result > 0) $result = $assetdepreciationoptions->updateDeprecationOptions($user, $object->id); + if ($result < 0) { + setEventMessages($assetdepreciationoptions->error, $assetdepreciationoptions->errors, 'errors'); + $action = 'edit'; + } else { + setEventMessage($langs->trans('RecordSaved')); + header("Location: " . $_SERVER["PHP_SELF"] . '?id=' . $object->id); + exit; + } + } +} + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +llxHeader('', $langs->trans('Asset'), $help_url); + +if ($id > 0 || !empty($ref)) { + $head = assetPrepareHead($object); + print dol_get_fiche_head($head, 'depreciation_options', $langs->trans("Asset"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + print '
    '; + + if ($action == 'edit') { + print ''; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(array(), ''); + + include DOL_DOCUMENT_ROOT . '/asset/tpl/depreciation_options_edit.tpl.php'; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel(); + + print ''; + } else { + include DOL_DOCUMENT_ROOT . '/asset/tpl/depreciation_options_view.tpl.php'; + } + + print dol_get_fiche_end(); + + if ($action != 'edit') { + print '
    ' . "\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + + if (empty($reshook)) { + if ($object->status == $object::STATUS_DRAFT/* && !empty($object->enabled_modes)*/) { + print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoadd); + } + } + print '
    ' . "\n"; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/disposal.php b/htdocs/asset/disposal.php new file mode 100644 index 00000000000..7fddb92b05f --- /dev/null +++ b/htdocs/asset/disposal.php @@ -0,0 +1,120 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/disposal.php + * \ingroup asset + * \brief Card with disposal info on Asset + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/asset/class/asset.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new Asset($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('assetdisposal', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity]."/".$object->id; +} + +$permissionnote = $user->rights->asset->write; // Used by the include of actions_setnotes.inc.php +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!isset($object->disposal_date) || $object->disposal_date === "") accessforbidden(); + + +/* + * Actions + */ + +$reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { +} + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +llxHeader('', $langs->trans('Asset'), $help_url); + +if ($id > 0 || !empty($ref)) { + $object->fetch_thirdparty(); + + $head = assetPrepareHead($object); + + print dol_get_fiche_head($head, 'disposal', $langs->trans("Asset"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + print ''."\n"; + + // Common attributes + $show_fields = array('disposal_date', 'disposal_amount_ht', 'fk_disposal_type', 'disposal_depreciated', 'disposal_subject_to_vat'); + foreach ($object->fields as $field_key => $field_info) { + $object->fields[$field_key]['visible'] = in_array($field_key, $show_fields) ? 1 : 0; + } + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + + print '
    '; + print '
    '; + + print dol_get_fiche_end(); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/document.php b/htdocs/asset/document.php index 9d46e9ae0b6..96b222b26c1 100644 --- a/htdocs/asset/document.php +++ b/htdocs/asset/document.php @@ -31,19 +31,18 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; // Load translation files required by the page -$langs->loadLangs(array('assets', 'companies', 'other')); +$langs->loadLangs(array('assets', 'companies', 'other', 'mails')); -$id = (GETPOST('id', 'int') ?GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility -$ref = GETPOST('ref', 'alpha'); -$socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST('sortfield', 'aZ09comma'); -$sortorder = GETPOST('sortorder', 'aZ09comma'); +$sortfield = GETPOST("sortfield", 'alpha'); +$sortorder = GETPOST("sortorder", 'alpha'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; @@ -58,18 +57,28 @@ if (!$sortfield) { $sortfield = "name"; } +// Initialize technical objects $object = new Asset($db); -if ($object->fetch($id)) { - $upload_dir = $conf->asset->dir_output."/".dol_sanitizeFileName($object->ref); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('assetdocument', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity ? $object->entity : $conf->entity]."/".get_exdir(0, 0, 0, 1, $object); } -$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php +$permissiontoadd = $user->rights->asset->asset->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result=restrictedArea($user, 'asset', $id, ''); +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); /* @@ -83,60 +92,67 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; * View */ -$title = $langs->trans('Assets')." - ".$langs->trans('Documents'); - -$help_url = ''; - -llxHeader('', $title, $help_url); - $form = new Form($db); +$title = $langs->trans("Asset").' - '.$langs->trans("Files"); +$help_url = ''; +llxHeader('', $title, $help_url); + +if ($object->id) { + /* + * Show tabs + */ + $head = assetPrepareHead($object); + + print dol_get_fiche_head($head, 'document', $langs->trans("Asset"), -1, $object->picto); -if ($id > 0 || !empty($ref)) { - if ($object->fetch($id, $ref) > 0) { - $upload_dir = $conf->asset->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref); - - $head = asset_prepare_head($object); - print dol_get_fiche_head($head, 'documents', $langs->trans('Asset'), -1, 'accounting'); - - // Build file list - $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ?SORT_DESC:SORT_ASC), 1); - $totalsize = 0; - foreach ($filearray as $key => $file) { - $totalsize += $file['size']; - } - - // Asset content - - $linkback = ''.$langs->trans("BackToList").''; - - $morehtmlref = ''; - dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, '', 0); - - print '
    '; - print '
    '; - - print ''; - - print ''; - print ''; - print "
    '.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
    '.$langs->trans("TotalSizeOfAttachedFiles").''.dol_print_size($totalsize, 1, 1).'
    \n"; - - print "
    \n"; - - print dol_get_fiche_end(); - - $modulepart = 'asset'; - $permissiontoadd = $user->rights->asset->write; - $permtoedit = $user->rights->asset->write; - $param = '&id='.$object->id; - include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; - } else { - dol_print_error($db); + // Build file list + $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ? SORT_DESC : SORT_ASC), 1); + $totalsize = 0; + foreach ($filearray as $key => $file) { + $totalsize += $file['size']; } + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + + print '
    '; + print ''; + + // Number of files + print ''; + + // Total size + print ''; + + print '
    ' . $langs->trans("NbOfAttachedFiles") . '' . count($filearray) . '
    ' . $langs->trans("TotalSizeOfAttachedFiles") . '' . $totalsize . ' ' . $langs->trans("bytes") . '
    '; + + print '
    '; + + print dol_get_fiche_end(); + + $modulepart = 'asset'; + $permissiontoadd = $user->rights->asset->write; + // $permissiontoadd = 1; + $permtoedit = $user->rights->asset->write; + // $permtoedit = 1; + $param = '&id=' . $object->id; + + //$relativepathwithnofile='asset/' . dol_sanitizeFileName($object->id).'/'; + $relativepathwithnofile = dol_sanitizeFileName($object->ref) . '/'; + + include DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_post_headers.tpl.php'; } else { - print $langs->trans("ErrorUnknown"); + accessforbidden('', 0, 1); } // End of page diff --git a/htdocs/asset/info.php b/htdocs/asset/info.php deleted file mode 100644 index 7a8f4c20ce2..00000000000 --- a/htdocs/asset/info.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * 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 . - */ - -/** - * \file htdocs/asset/info.php - * \ingroup asset - * \brief Page to show an asset information - */ - -require '../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/asset.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/asset/class/asset.class.php'; - -// Load translation files required by the page -$langs->loadLangs(array("asset")); - -$id = GETPOSTINT('id'); -$ref = GETPOST('ref', 'alpha'); -$action = GETPOST('action', 'aZ09'); - -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'asset', $id); - -$object = new Asset($db); -$object->fetch($id); - - -/* - * Actions - */ - -// None - - -/* - * View - */ - -$form = new Form($db); - -$title = $langs->trans('Asset')." - ".$langs->trans('Info'); - -$help_url = ""; - -llxHeader('', $title, $help_url); - -$object->info($id); - -$head = asset_prepare_head($object); - -print dol_get_fiche_head($head, 'info', $langs->trans("Asset"), -1, 'generic'); - -$linkback = ''.$langs->trans("BackToList").''; - -$morehtmlref = '
    '; -$morehtmlref .= '
    '; - -dol_banner_tab($object, 'rowid', $linkback, 1, 'rowid', 'ref', $morehtmlref); - -print '
    '; -print '
    '; - -print '
    '; - -print '
    '; -dol_print_object_info($object); -print '
    '; - -print '
    '; - -print dol_get_fiche_end(); - -// End of page -llxFooter(); -$db->close(); diff --git a/htdocs/asset/list.php b/htdocs/asset/list.php index 1abdabd333e..c475e22fc83 100644 --- a/htdocs/asset/list.php +++ b/htdocs/asset/list.php @@ -31,26 +31,26 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/asset/class/asset.class.php'; // Load translation files required by the page -$langs->loadLangs(array("assets")); +$langs->loadLangs(array("assets", "other")); -$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... -$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) -$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? -$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation -$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button -$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list -$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'assetlist'; // To manage different context of search -$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page -$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') +$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'assetlist'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') $id = GETPOST('id', 'int'); // Load variable for pagination -$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action $offset = $limit * $page; @@ -71,33 +71,24 @@ $search_array_options = $extrafields->getOptionalsFromPost($object->table_elemen // Default sort order (if not yet defined by previous GETPOST) if (!$sortfield) { + reset($object->fields); // Reset is required to avoid key() to return null. $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition. } if (!$sortorder) { $sortorder = "ASC"; } -// Security check -$socid = 0; -if ($user->socid) { - $socid = $user->socid; -} -if ($user->socid > 0) { - // Protection if external user - //$socid = $user->socid; - accessforbidden(); -} -// Security check -$result = restrictedArea($user, 'asset', $id); - - // Initialize array of search criterias -$search_all = GETPOST("search_all", 'alpha'); +$search_all = GETPOST('search_all', 'alphanohtml'); $search = array(); foreach ($object->fields as $key => $val) { if (GETPOST('search_'.$key, 'alpha') !== '') { $search[$key] = GETPOST('search_'.$key, 'alpha'); } + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int')); + $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int')); + } } // List of fields to search into when doing a "search in all" @@ -108,27 +99,24 @@ foreach ($object->fields as $key => $val) { } } -// Definition of fields for list +// Definition of array of fields for columns $arrayfields = array(); foreach ($object->fields as $key => $val) { // If $val['visible']==0, then we never show the field if (!empty($val['visible'])) { - $arrayfields['t.'.$key] = array('label'=>$val['label'], 'checked'=>(($val['visible'] < 0) ? 0 : 1), 'enabled'=>($val['enabled'] && ($val['visible'] != 3)), 'position'=>$val['position']); + $visible = (int) dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'], + 'help'=> isset($val['help']) ? $val['help'] : '' + ); } } // Extra fields -if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) { - foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { - if (!empty($extrafields->attributes[$object->table_element]['list'][$key])) { - $arrayfields["ef.".$key] = array( - 'label'=>$extrafields->attributes[$object->table_element]['label'][$key], - 'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1), - 'position'=>$extrafields->attributes[$object->table_element]['pos'][$key], - 'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key]) - ); - } - } -} +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; + $object->fields = dol_sort_array($object->fields, 'position'); $arrayfields = dol_sort_array($arrayfields, 'position'); @@ -136,13 +124,28 @@ $permissiontoread = $user->rights->asset->read; $permissiontoadd = $user->rights->asset->write; $permissiontodelete = $user->rights->asset->delete; +// Security check +if (empty($conf->asset->enabled)) { + accessforbidden('Module not enabled'); +} + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$socid = 0; if ($user->socid > 0) $socid = $user->socid; +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + /* * Actions */ if (GETPOST('cancel', 'alpha')) { - $action = 'list'; $massaction = ''; + $action = 'list'; + $massaction = ''; } if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; @@ -162,8 +165,12 @@ if (empty($reshook)) { if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers foreach ($object->fields as $key => $val) { $search[$key] = ''; + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = ''; + $search[$key.'_dtend'] = ''; + } } - $toselect = ''; + $toselect = array(); $search_array_options = array(); } if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') @@ -188,21 +195,20 @@ $form = new Form($db); $now = dol_now(); -//$help_url="EN:Module_Asset|FR:Module_Asset_FR|ES:MĂłdulo_Asset"; $help_url = ''; $title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("Assets")); +$morejs = array(); +$morecss = array(); // Build and execute select // -------------------------------------------------------------------- $sql = 'SELECT '; -foreach ($object->fields as $key => $val) { - $sql .= "t.".$key.", "; -} +$sql .= $object->getFieldList('t'); // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { - $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key." as options_".$key.', ' : ''); + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : ''); } } // Add fields from hooks @@ -211,27 +217,45 @@ $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $obje $sql .= preg_replace('/^,/', '', $hookmanager->resPrint); $sql = preg_replace('/,\s*$/', '', $sql); $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; -if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { +if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; } +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; if ($object->ismultientitymanaged == 1) { $sql .= " WHERE t.entity IN (".getEntity($object->element).")"; } else { $sql .= " WHERE 1 = 1"; } foreach ($search as $key => $val) { - if ($key == 'status' && $search[$key] == -1) { - continue; - } - $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); - if (strpos($object->fields[$key]['type'], 'integer:') === 0) { - if ($search[$key] == '-1') { - $search[$key] = ''; + if (array_key_exists($key, $object->fields)) { + if ($key == 'status' && $search[$key] == -1) { + continue; + } + $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); + if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) { + if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) { + $search[$key] = ''; + } + $mode_search = 2; + } + if ($search[$key] != '') { + $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); + } + } else { + if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { + $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key); + if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) { + if (preg_match('/_dtstart$/', $key)) { + $sql .= " AND t.".$columnName." >= '".$db->idate($search[$key])."'"; + } + if (preg_match('/_dtend$/', $key)) { + $sql .= " AND t." . $columnName . " <= '" . $db->idate($search[$key]) . "'"; + } + } } - $mode_search = 2; - } - if ($search[$key] != '') { - $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); } } if ($search_all) { @@ -246,51 +270,69 @@ $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $objec $sql .= $hookmanager->resPrint; /* If a group by is required -$sql.= " GROUP BY " -foreach($object->fields as $key => $val) -{ +$sql .= " GROUP BY "; +foreach($object->fields as $key => $val) { $sql .= "t.".$key.", "; } // Add fields from extrafields -if (! empty($extrafields->attributes[$object->table_element]['label'])) { - foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); + } } // Add where from hooks -$parameters=array(); -$reshook=$hookmanager->executeHooks('printFieldListGroupBy',$parameters); // Note that $action and $object may have been modified by hook -$sql.=$hookmanager->resPrint; -$sql=preg_replace('/,\s*$/','', $sql); +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +$sql = preg_replace('/,\s*$/', '', $sql); */ -$sql .= $db->order($sortfield, $sortorder); +// Add HAVING from hooks +/* +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= !empty($hookmanager->resPrint) ? (" HAVING 1=1 " . $hookmanager->resPrint) : ""; +*/ // Count total nb of records $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + /* This old and fast method to get and count full list returns all record so use a high amount of memory. $resql = $db->query($sql); $nbtotalofrecords = $db->num_rows($resql); + */ + /* The slow method does not consume memory on mysql (not tested on pgsql) */ + /*$resql = $db->query($sql, 0, 'auto', 1); + while ($db->fetch_object($resql)) { + $nbtotalofrecords++; + }*/ + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^SELECT[a-z0-9\._\s\(\),]+FROM/i', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); + $resql = $db->query($sqlforcount); + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 $page = 0; $offset = 0; } + $db->free($resql); } -// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. -if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) { - $num = $nbtotalofrecords; -} else { - if ($limit) { - $sql .= $db->plimit($limit + 1, $offset); - } - $resql = $db->query($sql); - if (!$resql) { - dol_print_error($db); - exit; - } - - $num = $db->num_rows($resql); +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); } +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + + // Direct jump if only one record found if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) { $obj = $db->fetch_object($resql); @@ -303,7 +345,7 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $ // Output page // -------------------------------------------------------------------- -llxHeader('', $title, $help_url); +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); $arrayofselected = is_array($toselect) ? $toselect : array(); @@ -317,9 +359,11 @@ if ($limit > 0 && $limit != $conf->liste_limit) { foreach ($search as $key => $val) { if (is_array($search[$key]) && count($search[$key])) { foreach ($search[$key] as $skey) { - $param .= '&search_'.$key.'[]='.urlencode($skey); + if ($skey != '') { + $param .= '&search_'.$key.'[]='.urlencode($skey); + } } - } else { + } elseif ($search[$key] != '') { $param .= '&search_'.$key.'='.urlencode($search[$key]); } } @@ -328,11 +372,17 @@ if ($optioncss != '') { } // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; // List of mass actions available $arrayofmassactions = array( - //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), + //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"), + //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), + //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), ); if ($permissiontodelete) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); @@ -351,24 +401,25 @@ print ''; print ''; print ''; +print ''; print ''; -$newcardbutton = dolGetButtonTitle($langs->trans('NewAsset'), '', 'fa fa-plus-circle', dol_buildpath('/asset/card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd); +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/asset/card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd); -print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); // Add code for pre mass action (confirmation or email presend form) -$topicmail = "SendAssetsRef"; +$topicmail = "SendAssetRef"; $modelmail = "asset"; $objecttmp = new Asset($db); $trackid = 'asset'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; -if ($sall) { +if ($search_all) { foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); } - print '
    '.$langs->trans("FilterOnInto", $sall).join(', ', $fieldstosearchall).'
    '; + print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '; } $moreforfilter = ''; @@ -395,31 +446,42 @@ $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfi $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); print '
    '; // You can use div-table-responsive-no-min if you dont need reserved height for your table -print ''."\n"; +print '
    '."\n"; // Fields title search // -------------------------------------------------------------------- print ''; foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['css']) ? '' : $val['css']); + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if ($key == 'status') { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } if (!empty($arrayfields['t.'.$key]['checked'])) { print ''; } @@ -443,14 +505,14 @@ print ''."\n"; // -------------------------------------------------------------------- print ''; foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['css']) ? '' : $val['css']); + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if ($key == 'status') { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } if (!empty($arrayfields['t.'.$key]['checked'])) { @@ -464,13 +526,13 @@ $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$ $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch ')."\n"; +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; print ''."\n"; // Detect if we need a fetch on each output line $needToFetchEachLine = 0; -if (is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { +if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) { if (preg_match('/\$object/', $val)) { $needToFetchEachLine++; // There is at least one compute field that use $object @@ -483,6 +545,7 @@ if (is_array($extrafields->attributes[$object->table_element]['computed']) && co // -------------------------------------------------------------------- $i = 0; $totalarray = array(); +$totalarray['nbfield'] = 0; while ($i < ($limit ? min($num, $limit) : $num)) { $obj = $db->fetch_object($resql); if (empty($obj)) { @@ -495,7 +558,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Show here line of result print ''; foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['css']) ? '' : $val['css']); + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif ($key == 'status') { @@ -508,14 +571,17 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; } - if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'status') { + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; if (!empty($arrayfields['t.'.$key]['checked'])) { print ''; if ($key == 'status') { print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); } else { print $object->showOutputField($val, $key, $object->$key, ''); } @@ -545,7 +611,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { print $hookmanager->resPrint; // Action column print ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo "\n"; +} +if (count($linkedObjectBlock) > 1) { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo "\n"; +} + +echo "\n"; diff --git a/htdocs/asset/type.php b/htdocs/asset/type.php deleted file mode 100644 index cd802c1c4fd..00000000000 --- a/htdocs/asset/type.php +++ /dev/null @@ -1,608 +0,0 @@ - - * - * 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 . - */ - -/** - * \file htdocs/asset/type.php - * \ingroup asset - * \brief Asset's type setup - */ - -require '../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/asset.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/asset/class/asset.class.php'; -require_once DOL_DOCUMENT_ROOT.'/asset/class/asset_type.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; -if (!empty($conf->accounting->enabled)) { - require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; -} -if (!empty($conf->accounting->enabled)) { - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; -} -if (!empty($conf->accounting->enabled)) { - require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php'; -} - -// Load translation files required by the page -$langs->load("assets"); - -$rowid = GETPOST('rowid', 'int'); -$action = GETPOST('action', 'aZ09'); -$cancel = GETPOST('cancel', 'alpha'); -$backtopage = GETPOST('backtopage', 'alpha'); - -$type = GETPOST('type', 'alpha'); - -$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST('sortfield', 'aZ09comma'); -$sortorder = GETPOST('sortorder', 'aZ09comma'); -$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -if (empty($page) || $page == -1) { - $page = 0; -} // If $page is not defined, or '' or -1 -$offset = $limit * $page; -$pageprev = $page - 1; -$pagenext = $page + 1; -if (!$sortorder) { - $sortorder = "DESC"; -} -if (!$sortfield) { - $sortfield = "a.label"; -} - -$label = GETPOST("label", "alpha"); -$accountancy_code_asset = GETPOST('accountancy_code_asset', 'string'); -$accountancy_code_depreciation_asset = GETPOST('accountancy_code_depreciation_asset', 'string'); -$accountancy_code_depreciation_expense = GETPOST('accountancy_code_depreciation_expense', 'string'); -$comment = GETPOST('comment', 'string'); - -// Security check -$result = restrictedArea($user, 'asset', $rowid, 'asset_type'); - -$object = new AssetType($db); - -$extrafields = new ExtraFields($db); - -// fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label($object->table_element); - -if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers - $type = ""; - $sall = ""; -} - - -// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context -$hookmanager->initHooks(array('assettypecard', 'globalcard')); - -$permissiontoadd = $user->rights->asset->setup_advance; - - -/* - * Actions - */ - -if ($cancel) { - $action = ''; - - if (!empty($backtopage)) { - header("Location: ".$backtopage); - exit; - } -} - -if ($action == 'add' && $user->rights->asset->write) { - $object->label = trim($label); - $object->accountancy_code_asset = trim($accountancy_code_asset); - $object->accountancy_code_depreciation_asset = trim($accountancy_code_depreciation_asset); - $object->accountancy_code_depreciation_expense = trim($accountancy_code_depreciation_expense); - $object->note = trim($comment); - - // Fill array 'array_options' with data from add form - $ret = $extrafields->setOptionalsFromPost(null, $object); - if ($ret < 0) { - $error++; - } - - if (empty($object->label)) { - $error++; - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); - } else { - $sql = "SELECT label FROM ".MAIN_DB_PREFIX."asset_type WHERE label='".$db->escape($object->label)."'"; - $result = $db->query($sql); - if ($result) { - $num = $db->num_rows($result); - } - if ($num) { - $error++; - $langs->load("errors"); - setEventMessages($langs->trans("ErrorLabelAlreadyExists", $login), null, 'errors'); - } - } - - if (!$error) { - $id = $object->create($user); - if ($id > 0) { - header("Location: ".$_SERVER["PHP_SELF"]); - exit; - } else { - setEventMessages($object->error, $object->errors, 'errors'); - $action = 'create'; - } - } else { - $action = 'create'; - } -} - -if ($action == 'update' && $user->rights->asset->write) { - $object->fetch($rowid); - - $object->oldcopy = clone $object; - - $object->label = trim($label); - $object->accountancy_code_asset = trim($accountancy_code_asset); - $object->accountancy_code_depreciation_asset = trim($accountancy_code_depreciation_asset); - $object->accountancy_code_depreciation_expense = trim($accountancy_code_depreciation_expense); - $object->note = trim($comment); - - // Fill array 'array_options' with data from add form - $ret = $extrafields->setOptionalsFromPost(null, $object, '@GETPOSTISSET'); - if ($ret < 0) { - $error++; - } - - $ret = $object->update($user); - - if ($ret >= 0 && !count($object->errors)) { - setEventMessages($langs->trans("AssetTypeModified"), null, 'mesgs'); - } else { - setEventMessages($object->error, $object->errors, 'errors'); - } - - header("Location: ".$_SERVER["PHP_SELF"]."?rowid=".$object->id); - exit; -} - -if ($action == 'confirm_delete' && $user->rights->asset->write) { - $object->fetch($rowid); - $res = $object->delete(); - - if ($res > 0) { - setEventMessages($langs->trans("AssetsTypeDeleted"), null, 'mesgs'); - header("Location: ".$_SERVER["PHP_SELF"]); - exit; - } else { - setEventMessages($langs->trans("AssetsTypeCanNotBeDeleted"), null, 'errors'); - $action = ''; - } -} - - -/* - * View - */ - -$form = new Form($db); - -$help_url = ''; - -llxHeader('', $langs->trans("AssetsTypeSetup"), $help_url); - - -// List of asset type -if (!$rowid && $action != 'create' && $action != 'edit') { - //print dol_get_fiche_head(''); - - $sql = "SELECT d.rowid, d.label as label, d.accountancy_code_asset, d.accountancy_code_depreciation_asset, d.accountancy_code_depreciation_expense, d.note"; - $sql .= " FROM ".MAIN_DB_PREFIX."asset_type as d"; - $sql .= " WHERE d.entity IN (".getEntity('asset_type').")"; - - $result = $db->query($sql); - if ($result) { - $num = $db->num_rows($result); - $nbtotalofrecords = $num; - - $i = 0; - - $param = ''; - - print '
    '; - if ($optioncss != '') { - print ''; - } - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - - $newcardbutton = dolGetButtonTitle($langs->trans('NewAssetType'), '', 'fa fa-plus-circle', dol_buildpath('/asset/type.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd); - - print_barre_liste($langs->trans("AssetsTypes"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, $object->picto, 0, $newcardbutton, '', $limit); - - $moreforfilter = ''; - - print '
    '; - print '
    '; if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { - print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); - } elseif (strpos($val['type'], 'integer:') === 0) { - print $object->showInputField($val, $key, $search[$key], '', '', 'search_', 'maxwidth150', 1); - } elseif (!preg_match('/^(date|timestamp)/', $val['type'])) { - print ''; + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { + print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1); + } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + print '
    '; + print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
    '; + print '
    '; + print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
    '; + } elseif ($key == 'lang') { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); + print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2); + } else { + print ''; } print '
    '; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined $selected = 0; if (in_array($object->id, $arrayofselected)) { $selected = 1; @@ -605,7 +671,7 @@ if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $n $genallowed = $permissiontoread; $delallowed = $permissiontoadd; - print $formfile->showdocuments('massfilesarea_asset', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, ''); + print $formfile->showdocuments('massfilesarea_asset', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); } // End of page diff --git a/htdocs/asset/model/accountancy_codes.php b/htdocs/asset/model/accountancy_codes.php new file mode 100644 index 00000000000..fd5999b20b0 --- /dev/null +++ b/htdocs/asset/model/accountancy_codes.php @@ -0,0 +1,191 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/model/accountancy_code.php + * \ingroup asset + * \brief Card with accountancy code on Asset Model + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetmodel.class.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new AssetModel($db); +$assetaccountancycodes = new AssetAccountancyCodes($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output . '/temp/massgeneration/' . $user->id; +$hookmanager->initHooks(array('assetmodelaccountancycodes', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity] . "/" . $object->id; +} + +$permissiontoread = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->read) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->read))); +$permissiontoadd = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->write) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->write))); // Used by the include of actions_addupdatedelete.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, 'asset', $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + +$result = $assetaccountancycodes->fetchAccountancyCodes(0, $object->id); +if ($result < 0) { + setEventMessages($assetaccountancycodes->error, $assetaccountancycodes->errors, 'errors'); +} + + +/* + * Actions + */ + +$reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { + $backurlforlist = DOL_URL_ROOT.'/asset/list.php'; + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = DOL_URL_ROOT.'/asset/model/accountancy_codes.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__'); + } + } + } + + if ($cancel) { + /*var_dump($cancel);var_dump($backtopage);var_dump($backtopageforcancel);exit;*/ + if (!empty($backtopageforcancel)) { + header("Location: ".$backtopageforcancel); + exit; + } elseif (!empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + $action = ''; + } + + if ($action == "update") { + $assetaccountancycodes->setAccountancyCodesFromPost(); + + $result = $assetaccountancycodes->updateAccountancyCodes($user, 0, $object->id); + if ($result < 0) { + setEventMessages($assetaccountancycodes->error, $assetaccountancycodes->errors, 'errors'); + $action = 'edit'; + } else { + setEventMessage($langs->trans('RecordSaved')); + header("Location: " . $_SERVER["PHP_SELF"] . '?id=' . $object->id); + exit; + } + } +} + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +llxHeader('', $langs->trans('AssetModel'), $help_url); + +if ($id > 0 || !empty($ref)) { + $head = assetModelPrepareHead($object); + print dol_get_fiche_head($head, 'accountancy_codes', $langs->trans("AssetModel"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + print '
    '; + + if ($action == 'edit') { + print '
    '; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(array(), ''); + + include DOL_DOCUMENT_ROOT . '/asset/tpl/accountancy_codes_edit.tpl.php'; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel(); + + print '
    '; + } else { + include DOL_DOCUMENT_ROOT . '/asset/tpl/accountancy_codes_view.tpl.php'; + } + + print dol_get_fiche_end(); + + if ($action != 'edit') { + print '
    ' . "\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + + if (empty($reshook)) { + if ($object->status == $object::STATUS_DRAFT/* && !empty($object->enabled_modes)*/) { + print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoadd); + } + } + print '
    ' . "\n"; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/model/agenda.php b/htdocs/asset/model/agenda.php new file mode 100644 index 00000000000..cd0365a1418 --- /dev/null +++ b/htdocs/asset/model/agenda.php @@ -0,0 +1,217 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 . + */ + +/** + * \file htdocs/asset/model/agenda.php + * \ingroup asset + * \brief Tab of events on Asset Model + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetmodel.class.php'; +require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode', 'array')) { + $actioncode = GETPOST('actioncode', 'array', 3); + if (!count($actioncode)) { + $actioncode = '0'; + } +} else { + $actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : (empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label = GETPOST('search_agenda_label'); + +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST("sortfield", 'alpha'); +$sortorder = GETPOST("sortorder", 'alpha'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { + $page = 0; +} // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortfield) { + $sortfield = 'a.datep,a.id'; +} +if (!$sortorder) { + $sortorder = 'DESC,DESC'; +} + +// Initialize technical objects +$object = new AssetModel($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output . '/temp/massgeneration/' . $user->id; +$hookmanager->initHooks(array('assetmodelagenda', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity] . "/model/" . $object->id; +} + +$permissiontoread = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->read) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->read))); +$permissiontoadd = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->write) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->write))); // Used by the include of actions_addupdatedelete.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +if ($user->socid > 0) $socid = $user->socid; +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, 'asset', $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array('id' => $id); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Cancel + if (GETPOST('cancel', 'alpha') && !empty($backtopage)) { + header("Location: " . $backtopage); + exit; + } + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $actioncode = ''; + $search_agenda_label = ''; + } +} + + +/* + * View + */ + +$form = new Form($db); + +if ($object->id > 0) { + $title = $langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = 'EN:Module_Agenda_En'; + llxHeader('', $title, $help_url); + + if (!empty($conf->notification->enabled)) { + $langs->load("mails"); + } + $head = assetModelPrepareHead($object); + + + print dol_get_fiche_head($head, 'agenda', $langs->trans("AssetModel"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + + $object->info($object->id); + dol_print_object_info($object, 1); + + print '
    '; + + print dol_get_fiche_end(); + + + // Actions buttons + + $objthirdparty = $object; + $objcon = new stdClass(); + + $out = '&origin=' . urlencode($object->element . '@' . $object->module) . '&originid=' . urlencode($object->id); + $urlbacktopage = $_SERVER['PHP_SELF'] . '?id=' . $object->id; + $out .= '&backtopage=' . urlencode($urlbacktopage); + $permok = $user->rights->agenda->myactions->create; + if ((!empty($objthirdparty->id) || !empty($objcon->id)) && $permok) { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
    '; + + // if (!empty($conf->agenda->enabled)) { + // if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) { + // print '' . $langs->trans("AddAction") . ''; + // } else { + // print '' . $langs->trans("AddAction") . ''; + // } + // } + + print '
    '; + + // if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { + // $param = '&id=' . $object->id . '&socid=' . $socid; + // if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + // $param .= '&contextpage=' . urlencode($contextpage); + // } + // if ($limit > 0 && $limit != $conf->liste_limit) { + // $param .= '&limit=' . urlencode($limit); + // } + // + // + // print load_fiche_titre($langs->trans("ActionsOnAssetModel"), '', ''); + // + // // List of all actions + // $filters = array(); + // $filters['search_agenda_label'] = $search_agenda_label; + // + // // TODO Replace this with same code than into list.php + // show_actions_done($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module); + // } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/model/card.php b/htdocs/asset/model/card.php new file mode 100644 index 00000000000..3e0858da55e --- /dev/null +++ b/htdocs/asset/model/card.php @@ -0,0 +1,330 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/model/card.php + * \ingroup asset + * \brief Page to create/edit/view asset Model + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetmodel.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'assetmodelcard'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); + +// Initialize technical objects +$object = new AssetModel($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output . '/temp/massgeneration/' . $user->id; +$hookmanager->initHooks(array('assetmodelcard', 'globalcard')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Initialize array of search criterias +$search_all = GETPOST("search_all", 'alpha'); +$search = array(); +foreach ($object->fields as $key => $val) { + if (GETPOST('search_' . $key, 'alpha')) { + $search[$key] = GETPOST('search_' . $key, 'alpha'); + } +} + +if (empty($action) && empty($id) && empty($ref)) { + $action = 'view'; +} + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once. + +$permissiontoread = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->read) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->read))); +$permissiontoadd = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->write) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->write))); // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->delete) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->delete))) || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); +$permissionnote = $permissiontoadd; // Used by the include of actions_setnotes.inc.php +$permissiondellink = $permissiontoadd; // Used by the include of actions_dellink.inc.php +$upload_dir = $conf->asset->multidir_output[isset($object->entity) ? $object->entity : 1]; + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +if ($user->socid > 0) $socid = $user->socid; +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, 'asset', $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + $error = 0; + + $backurlforlist = DOL_URL_ROOT . '/asset/model/list.php'; + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = DOL_URL_ROOT . '/asset/model/card.php?id=' . ((!empty($id) && $id > 0) ? $id : '__ID__'); + } + } + } + + $triggermodname = 'ASSETMODEL_MODIFY'; // Name of trigger action code to execute when we modify record + + if (($action == 'edit' && !($permissiontoadd && $object->status == $object::STATUS_DRAFT)) || + ($action == 'confirm_setdraft' && !($permissiontoadd && $object->status != $object::STATUS_DRAFT)) || + ($action == 'confirm_validate' && !($permissiontoadd && $object->status != $object::STATUS_VALIDATED)) || + ($action == 'confirm_close' && !($permissiontoadd && $object->status != $object::STATUS_CANCELED)) + ) { + $action = ""; + } + + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen + include DOL_DOCUMENT_ROOT . '/core/actions_addupdatedelete.inc.php'; +} + + +/* + * View + * + * Put here all code to build page + */ + +$form = new Form($db); +$formfile = new FormFile($db); + +$title = $langs->trans("AssetModel") . ' - ' . $langs->trans("Card"); +$help_url = ''; +llxHeader('', $title, $help_url); + +// Part to create +if ($action == 'create') { + print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("AssetModel")), '', 'object_' . $object->picto); + + print '
    '; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(array(), ''); + + // Set some default values + //if (! GETPOSTISSET('fieldname')) $_POST['fieldname'] = 'myvalue'; + + print '' . "\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_add.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_add.tpl.php'; + + print '
    ' . "\n"; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel("Create"); + + print '
    '; + + //dol_set_focus('input[name="ref"]'); +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') { + print load_fiche_titre($langs->trans("AssetModel"), '', 'object_' . $object->picto); + + print '
    '; + print ''; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(); + + print '' . "\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_edit.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_edit.tpl.php'; + + print '
    '; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel(); + + print '
    '; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { + $res = $object->fetch_optionals(); + + $head = assetModelPrepareHead($object); + print dol_get_fiche_head($head, 'card', $langs->trans("AssetModel"), -1, $object->picto); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteAssetModel'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); + } elseif ($action == 'clone') { + // Clone confirmation + // Create an array for form + $formquestion = array(); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + } + + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $formconfirm .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $formconfirm = $hookmanager->resPrint; + } + + // Print form confirm + print $formconfirm; + + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + print '
    '; + print '' . "\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php'; + + // Other attributes. Fields from hook formObjectOptions and Extrafields. + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; + + print '
    '; + print '
    '; + print '
    '; + + print '
    '; + + print dol_get_fiche_end(); + + + // Buttons for actions + if ($action != 'editline') { + print '
    ' . "\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + + if (empty($reshook)) { + if ($object->status == $object::STATUS_DRAFT) { + print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoadd); + } + + // Back to draft + if ($object->status != $object::STATUS_DRAFT) { + print dolGetButtonAction($langs->trans('SetToDraft'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=confirm_setdraft&confirm=yes&token=' . newToken(), '', $permissiontoadd); + } + + if ($object->status != $object::STATUS_VALIDATED) { + print dolGetButtonAction($langs->trans('Enable'), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=confirm_validate&confirm=yes&token=' . newToken(), '', $permissiontoadd); + } + + if ($object->status != $object::STATUS_CANCELED) { + print dolGetButtonAction($langs->trans('Disable'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=confirm_close&confirm=yes&token='.newToken(), '', $permissiontoadd); + } + + // Clone + print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&socid=' . $object->socid . '&action=clone&token=' . newToken(), '', $permissiontoadd); + + // Delete (need delete permission, or if draft, just need create/modify permission) + print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=delete&token=' . newToken(), '', $permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)); + } + print '
    ' . "\n"; + } + + print '
    '; + print ''; // ancre + + print '
    '; + + // $MAXEVENT = 10; + // + // $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-list-alt imgforviewmode', DOL_URL_ROOT . '/asset/model/agenda.php?id=' . $object->id); + // + // // List of actions on element + // include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + // $formactions = new FormActions($db); + // $somethingshown = $formactions->showactions($object, $object->element.'@'.$object->module, 0, 1, '', $MAXEVENT, '', $morehtmlright); + + print '
    '; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/model/depreciation_options.php b/htdocs/asset/model/depreciation_options.php new file mode 100644 index 00000000000..f5bc751663b --- /dev/null +++ b/htdocs/asset/model/depreciation_options.php @@ -0,0 +1,191 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/model/depreciation_options.php + * \ingroup asset + * \brief Card with depreciation options on Asset Model + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetmodel.class.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new AssetModel($db); +$assetdepreciationoptions = new AssetDepreciationOptions($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output . '/temp/massgeneration/' . $user->id; +$hookmanager->initHooks(array('assetmodeldeprectationoptions', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity] . "/" . $object->id; +} + +$permissiontoread = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->read) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->read))); +$permissiontoadd = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->write) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->write))); // Used by the include of actions_addupdatedelete.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, 'asset', $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + +$object->asset_depreciation_options = &$assetdepreciationoptions; +$result = $assetdepreciationoptions->fetchDeprecationOptions(0, $object->id); +if ($result < 0) { + setEventMessages($assetdepreciationoptions->error, $assetdepreciationoptions->errors, 'errors'); +} + + +/* + * Actions + */ + +$reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { + $backurlforlist = DOL_URL_ROOT.'/asset/list.php'; + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = DOL_URL_ROOT.'/asset/model/depreciation_options.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__'); + } + } + } + + if ($cancel) { + /*var_dump($cancel);var_dump($backtopage);var_dump($backtopageforcancel);exit;*/ + if (!empty($backtopageforcancel)) { + header("Location: ".$backtopageforcancel); + exit; + } elseif (!empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + $action = ''; + } + + if ($action == "update") { + $result = $assetdepreciationoptions->setDeprecationOptionsFromPost(1); + if ($result > 0) $result = $assetdepreciationoptions->updateDeprecationOptions($user, 0, $object->id); + if ($result < 0) { + setEventMessages($assetdepreciationoptions->error, $assetdepreciationoptions->errors, 'errors'); + $action = 'edit'; + } else { + setEventMessage($langs->trans('RecordSaved')); + header("Location: " . $_SERVER["PHP_SELF"] . '?id=' . $object->id); + exit; + } + } +} + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +llxHeader('', $langs->trans('AssetModel'), $help_url); + +if ($id > 0 || !empty($ref)) { + $head = assetModelPrepareHead($object); + print dol_get_fiche_head($head, 'depreciation_options', $langs->trans("AssetModel"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + print '
    '; + print '
    '; + + if ($action == 'edit') { + print '
    '; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(array(), ''); + + include DOL_DOCUMENT_ROOT . '/asset/tpl/depreciation_options_edit.tpl.php'; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel(); + + print '
    '; + } else { + include DOL_DOCUMENT_ROOT . '/asset/tpl/depreciation_options_view.tpl.php'; + } + + print dol_get_fiche_end(); + + if ($action != 'edit') { + print '
    ' . "\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + + if (empty($reshook)) { + if ($object->status == $object::STATUS_DRAFT/* && !empty($object->enabled_modes)*/) { + print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoadd); + } + } + print '
    ' . "\n"; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/model/list.php b/htdocs/asset/model/list.php new file mode 100644 index 00000000000..a6423bb3a73 --- /dev/null +++ b/htdocs/asset/model/list.php @@ -0,0 +1,681 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/model/list.php + * \ingroup asset + * \brief List page for asset model + */ + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/asset/class/assetmodel.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "other")); + +$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'assetmodellist'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') + +$id = GETPOST('id', 'int'); + +// Load variable for pagination +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { + $page = 0; +} // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +// Initialize technical objects +$object = new AssetModel($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('assetmodellist')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); +//$extrafields->fetch_name_optionals_label($object->table_element_line); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Default sort order (if not yet defined by previous GETPOST) +if (!$sortfield) { + reset($object->fields); // Reset is required to avoid key() to return null. + $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition. +} +if (!$sortorder) { + $sortorder = "ASC"; +} + +// Initialize array of search criterias +$search_all = GETPOST('search_all', 'alphanohtml'); +$search = array(); +foreach ($object->fields as $key => $val) { + if ($key == 'fk_pays' && !GETPOSTISSET('search_'.$key)) { + $search[$key] = $mysoc->country_id; + } elseif (GETPOST('search_'.$key, 'alpha') !== '') { + $search[$key] = GETPOST('search_'.$key, 'alpha'); + } + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int')); + $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int')); + } +} + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array(); +foreach ($object->fields as $key => $val) { + if (!empty($val['searchall'])) { + $fieldstosearchall['t.'.$key] = $val['label']; + } +} + +// Definition of array of fields for columns +$arrayfields = array(); +foreach ($object->fields as $key => $val) { + // If $val['visible']==0, then we never show the field + if (!empty($val['visible'])) { + $visible = (int) dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'], + 'help'=> isset($val['help']) ? $val['help'] : '' + ); + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; + +$object->fields = dol_sort_array($object->fields, 'position'); +$arrayfields = dol_sort_array($arrayfields, 'position'); + +$permissiontoread = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->read) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->read))); +$permissiontoadd = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->write) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->write))); +$permissiontodelete = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->delete) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->delete))); + +// Security check +if (empty($conf->asset->enabled)) { + accessforbidden('Module not enabled'); +} + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$socid = 0; if ($user->socid > 0) $socid = $user->socid; +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, 'asset', $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + + +/* + * Actions + */ + +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; + $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { + $massaction = ''; +} + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + foreach ($object->fields as $key => $val) { + $search[$key] = ''; + if ($key == 'fk_pays') $search[$key] = $mysoc->country_id; + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = ''; + $search[$key.'_dtend'] = ''; + } + } + $toselect = array(); + $search_array_options = array(); + } + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') + || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) { + $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass = 'AssetModel'; + $objectlabel = 'AssetModel'; + $uploaddir = $conf->asset->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + + +/* + * View + */ + +$form = new Form($db); + +$now = dol_now(); + +$help_url = ''; +$title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("AssetModels")); +$morejs = array(); +$morecss = array(); + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +$sql .= $object->getFieldList('t'); +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : ''); + } +} +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= preg_replace('/^,/', '', $hookmanager->resPrint); +$sql = preg_replace('/,\s*$/', '', $sql); +$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; +if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; +} +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +if ($object->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($object->element).")"; +} else { + $sql .= " WHERE 1 = 1"; +} +foreach ($search as $key => $val) { + if (array_key_exists($key, $object->fields)) { + if ($key == 'status' && $search[$key] == -1) { + continue; + } + $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); + if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) { + if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) { + $search[$key] = ''; + } + $mode_search = 2; + } + if ($search[$key] != '') { + $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); + } + } else { + if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { + $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key); + if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) { + if (preg_match('/_dtstart$/', $key)) { + $sql .= " AND t.".$columnName." >= '".$db->idate($search[$key])."'"; + } + if (preg_match('/_dtend$/', $key)) { + $sql .= " AND t." . $columnName . " <= '" . $db->idate($search[$key]) . "'"; + } + } + } + } +} +if ($search_all) { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +} +//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); +// Add where from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +/* If a group by is required +$sql .= " GROUP BY "; +foreach($object->fields as $key => $val) { + $sql .= "t.".$key.", "; +} +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); + } +} +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +$sql = preg_replace('/,\s*$/', '', $sql); +*/ + +// Add HAVING from hooks +/* +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= !empty($hookmanager->resPrint) ? (" HAVING 1=1 " . $hookmanager->resPrint) : ""; +*/ + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + /* This old and fast method to get and count full list returns all record so use a high amount of memory. + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); + */ + /* The slow method does not consume memory on mysql (not tested on pgsql) */ + /*$resql = $db->query($sql, 0, 'auto', 1); + while ($db->fetch_object($resql)) { + $nbtotalofrecords++; + }*/ + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^SELECT[a-z0-9\._\s\(\),]+FROM/i', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); + $resql = $db->query($sqlforcount); + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + $page = 0; + $offset = 0; + } + $db->free($resql); +} + +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} + +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + + +// Direct jump if only one record found +if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) { + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".DOL_URL_ROOT.'/asset/model/card.php?id='.$id); + exit; +} + + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$param = ''; +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); +} +if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); +} +foreach ($search as $key => $val) { + if (is_array($search[$key]) && count($search[$key])) { + foreach ($search[$key] as $skey) { + if ($skey != '') { + $param .= '&search_'.$key.'[]='.urlencode($skey); + } + } + } elseif ($search[$key] != '') { + $param .= '&search_'.$key.'='.urlencode($search[$key]); + } +} +if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); +} +// Add $param from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; + +// List of mass actions available +$arrayofmassactions = array( + //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"), + //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), + //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), + //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), +); +if ($permissiontodelete) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { + $arrayofmassactions = array(); +} +$massactionbutton = $form->selectMassAction('', $arrayofmassactions); + +print '
    '."\n"; +if ($optioncss != '') { + print ''; +} +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/asset/model/card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); + +// Add code for pre mass action (confirmation or email presend form) +$topicmail = "SendAssetModelRef"; +$modelmail = "assetmodel"; +$objecttmp = new AssetModel($db); +$trackid = 'assetmodel'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +if ($search_all) { + foreach ($fieldstosearchall as $key => $val) { + $fieldstosearchall[$key] = $langs->trans($val); + } + print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '; +} + +$moreforfilter = ''; +/*$moreforfilter.='
    '; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
    ';*/ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; +} else { + $moreforfilter = $hookmanager->resPrint; +} + +if (!empty($moreforfilter)) { + print '
    '; + print $moreforfilter; + print '
    '; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
    '; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters = array('arrayfields'=>$arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print ''; +print ''."\n"; + + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + if (!empty($arrayfields['t.'.$key]['checked'])) { + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine = 0; +if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { + foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) { + if (preg_match('/\$object/', $val)) { + $needToFetchEachLine++; // There is at least one compute field that use $object + } + } +} + + +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$totalarray = array(); +$totalarray['nbfield'] = 0; +while ($i < ($limit ? min($num, $limit) : $num)) { + $obj = $db->fetch_object($resql); + if (empty($obj)) { + break; // Should not happen + } + + // Store properties in $object + $object->setVarsFromFetchObj($obj); + + // Show here line of result + print ''; + foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } + + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + if ($key == 'status') { + print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); + } else { + print $object->showOutputField($val, $key, $object->$key, ''); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val']['t.'.$key])) { + $totalarray['val']['t.'.$key] = 0; + } + $totalarray['val']['t.'.$key] += $object->$key; + } + } + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Action column + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + + print ''."\n"; + + $i++; +} + +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} + + +$db->free($resql); + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
    '; + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { + print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1); + } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + print '
    '; + print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
    '; + print '
    '; + print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
    '; + } elseif ($key == 'lang') { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); + print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2); + } else { + print ''; + } + print '
    '; +$searchpicto = $form->showFilterButtons(); +print $searchpicto; +print '
    '; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
    '.$langs->trans("NoRecordFound").'
    '."\n"; +print '
    '."\n"; + +print '
    '."\n"; + +if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) { + $hidegeneratedfilelistifempty = 1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) { + $hidegeneratedfilelistifempty = 0; + } + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource .= str_replace('&', '&', $param); + + $filedir = $diroutputmassaction; + $genallowed = $permissiontoread; + $delallowed = $permissiontoadd; + + print $formfile->showdocuments('massfilesarea_asset', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/model/note.php b/htdocs/asset/model/note.php new file mode 100644 index 00000000000..4af8407976f --- /dev/null +++ b/htdocs/asset/model/note.php @@ -0,0 +1,120 @@ + + * Copyright (C) 2018 Alexandre Spangaro + * + * 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 . + */ + +/** + * \file htdocs/asset/model/note.php + * \ingroup asset + * \brief Card with notes on Asset Model + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/asset.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/asset/class/assetmodel.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("assets", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new AssetModel($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->asset->dir_output . '/temp/massgeneration/' . $user->id; +$hookmanager->initHooks(array('assetmodelnote', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->asset->multidir_output[$object->entity] . "/" . $object->id; +} + +$permissiontoread = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->read) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->read))); +$permissiontoadd = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->asset->write) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->asset->setup_advance->write))); // Used by the include of actions_addupdatedelete.inc.php +$permissionnote = $permissiontoadd; // Used by the include of actions_setnotes.inc.php + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +if ($user->socid > 0) $socid = $user->socid; +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, 'asset', $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { + include DOL_DOCUMENT_ROOT . '/core/actions_setnotes.inc.php'; // Must be include, not include_once +} + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +llxHeader('', $langs->trans('AssetModel'), $help_url); + +if ($id > 0 || !empty($ref)) { + $object->fetch_thirdparty(); + + $head = assetModelPrepareHead($object); + + print dol_get_fiche_head($head, 'note', $langs->trans("AssetModel"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
    '; + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + + + $cssclass = "titlefield"; + include DOL_DOCUMENT_ROOT . '/core/tpl/notes.tpl.php'; + + print '
    '; + + print dol_get_fiche_end(); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/asset/note.php b/htdocs/asset/note.php index ebd340e393d..8de86d49bb7 100644 --- a/htdocs/asset/note.php +++ b/htdocs/asset/note.php @@ -27,7 +27,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/asset.lib.php'; require_once DOL_DOCUMENT_ROOT.'/asset/class/asset.class.php'; // Load translation files required by the page -$langs->loadLangs(array("asset", "companies")); +$langs->loadLangs(array("assets", "companies")); // Get parameters $id = GETPOST('id', 'int'); @@ -40,30 +40,24 @@ $backtopage = GETPOST('backtopage', 'alpha'); $object = new Asset($db); $extrafields = new ExtraFields($db); $diroutputmassaction = $conf->asset->dir_output.'/temp/massgeneration/'.$user->id; -$hookmanager->initHooks(array('assetnote')); // Note that conf->hooks_modules contains array - +$hookmanager->initHooks(array('assetnote', 'globalcard')); // Note that conf->hooks_modules contains array // Fetch optionals attributes and labels $extrafields->fetch_name_optionals_label($object->table_element); -// Security check - Protection if external user -//if ($user->socid > 0) accessforbidden(); -//if ($user->socid > 0) $socid = $user->socid; -//$result = restrictedArea($user, 'asset', $id); - // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals if ($id > 0 || !empty($ref)) { $upload_dir = $conf->asset->multidir_output[$object->entity]."/".$object->id; } -// Security check -if (!empty($user->socid)) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'asset', $id); +$permissionnote = $user->rights->asset->write; // Used by the include of actions_setnotes.inc.php +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php -$permissionnote = 1; -//$permissionnote=$user->rights->asset->creer; // Used by the include of actions_setnotes.inc.php +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->asset->enabled)) accessforbidden(); /* @@ -78,67 +72,28 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once } + /* * View */ $form = new Form($db); -//$help_url='EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes'; $help_url = ''; -llxHeader('', $langs->trans('Assets'), $help_url); +llxHeader('', $langs->trans('Asset'), $help_url); if ($id > 0 || !empty($ref)) { $object->fetch_thirdparty(); - $head = asset_prepare_head($object); + $head = assetPrepareHead($object); - print dol_get_fiche_head($head, 'note', $langs->trans("Asset"), -1, 'generic'); + print dol_get_fiche_head($head, 'note', $langs->trans("Asset"), -1, $object->picto); // Object card // ------------------------------------------------------------ - $linkback = ''.$langs->trans("BackToList").''; + $linkback = '' . $langs->trans("BackToList") . ''; $morehtmlref = '
    '; - /* - // Ref customer - $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); - $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); - // Thirdparty - $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); - // Project - if (! empty($conf->projet->enabled)) - { - $langs->load("projects"); - $morehtmlref.='
    '.$langs->trans('Project') . ' '; - if ($user->rights->asset->creer) - { - if ($action != 'classify') - //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; - $morehtmlref.=' : '; - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.='
    '; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.='
    '; - } else { - $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); - } - } else { - if (! empty($object->fk_project)) { - $proj = new Project($db); - $proj->fetch($object->fk_project); - $morehtmlref.=''; - $morehtmlref.=$proj->ref; - $morehtmlref.=''; - } else { - $morehtmlref.=''; - } - } - }*/ $morehtmlref .= '
    '; @@ -150,7 +105,7 @@ if ($id > 0 || !empty($ref)) { $cssclass = "titlefield"; - include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; + include DOL_DOCUMENT_ROOT . '/core/tpl/notes.tpl.php'; print ''; diff --git a/htdocs/asset/tpl/accountancy_codes_edit.tpl.php b/htdocs/asset/tpl/accountancy_codes_edit.tpl.php new file mode 100644 index 00000000000..bbd2b3d797c --- /dev/null +++ b/htdocs/asset/tpl/accountancy_codes_edit.tpl.php @@ -0,0 +1,81 @@ + + * + * 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 . + * + * Show extrafields. It also show fields from hook formAssetAccountancyCode. Need to have following variables defined: + * $object (asset, assetmodel, ...) + * $assetaccountancycodes + * $action + * $conf + * $langs + * + * $parameters + */ + +// Protection to avoid direct call of template +if (empty($object) || !is_object($object)) { + print "Error, template page can't be called as URL"; + exit; +} + +if (!is_object($form)) { + $form = new Form($db); +} + +if (!empty($conf->accounting->enabled) && !is_object($formaccounting)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php'; + $formaccounting = new FormAccounting($db); +} + + +?> + +executeHooks('formAssetAccountancyCodes', $parameters, $object, $action); +print $hookmanager->resPrint; +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + foreach ($assetaccountancycodes->accountancy_codes_fields as $mode_key => $mode_info) { + //if (empty($object->enabled_modes[$mode_key])) continue; + + print load_fiche_titre($langs->trans($mode_info['label']), '', ''); + print '
    '; + print '
    '; + print ''; + foreach ($mode_info['fields'] as $field_key => $field_info) { + $html_name = $mode_key . '_' . $field_key; + print ''; + } + print '
    ' . $langs->trans($field_info['label']) . ''; + $accountancy_code = GETPOSTISSET($html_name) ? GETPOST($html_name, 'aZ09') : (!empty($assetaccountancycodes->accountancy_codes[$mode_key][$field_key]) ? $assetaccountancycodes->accountancy_codes[$mode_key][$field_key] : ''); + if (!empty($conf->accounting->enabled)) { + print $formaccounting->select_account($accountancy_code, $html_name, 1, null, 1, 1, 'minwidth150 maxwidth300', 1); + } else { + print ''; + } + print '
    '; + print '
    '; + } +} +?> + diff --git a/htdocs/asset/tpl/accountancy_codes_view.tpl.php b/htdocs/asset/tpl/accountancy_codes_view.tpl.php new file mode 100644 index 00000000000..0d92ad8eb37 --- /dev/null +++ b/htdocs/asset/tpl/accountancy_codes_view.tpl.php @@ -0,0 +1,82 @@ + + * + * 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 . + * + * Show extrafields. It also show fields from hook formAssetAccountancyCode. Need to have following variables defined: + * $object (asset, assetmodel, ...) + * $assetaccountancycodes + * $action + * $conf + * $langs + * + * $parameters + */ + +// Protection to avoid direct call of template +if (empty($object) || !is_object($object)) { + print "Error, template page can't be called as URL"; + exit; +} + +if (!is_object($form)) { + $form = new Form($db); +} + + +?> + +executeHooks('formAssetAccountancyCodes', $parameters, $object, $action); +print $hookmanager->resPrint; +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + if (!empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php'; + + foreach ($assetaccountancycodes->accountancy_codes_fields as $mode_key => $mode_info) { + //if (empty($object->enabled_modes[$mode_key])) continue; + + print load_fiche_titre($langs->trans($mode_info['label']), '', ''); + print '
    '; + print '
    '; + print ''; + foreach ($mode_info['fields'] as $field_key => $field_info) { + print ''; + } + print '
    ' . $langs->trans($field_info['label']) . ''; + if (!empty($assetaccountancycodes->accountancy_codes[$mode_key][$field_key])) { + $accountancy_code = $assetaccountancycodes->accountancy_codes[$mode_key][$field_key]; + if (!empty($conf->accounting->enabled)) { + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('', $accountancy_code, 1); + + print $accountingaccount->getNomUrl(0, 1, 1, '', 1); + } else { + print $accountancy_code; + } + } + print '
    '; + print '
    '; + } +} +?> + diff --git a/htdocs/asset/tpl/depreciation_options_edit.tpl.php b/htdocs/asset/tpl/depreciation_options_edit.tpl.php new file mode 100644 index 00000000000..cef22936260 --- /dev/null +++ b/htdocs/asset/tpl/depreciation_options_edit.tpl.php @@ -0,0 +1,228 @@ + + * + * 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 . + * + * Show extrafields. It also show fields from hook formAssetAccountancyCode. Need to have following variables defined: + * $object (asset, assetmodel, ...) + * $assetaccountancycodes + * $action + * $conf + * $langs + * + * $parameters + */ + +// Protection to avoid direct call of template +if (empty($object) || !is_object($object)) { + print "Error, template page can't be called as URL"; + exit; +} + +if (!is_object($form)) { + $form = new Form($db); +} + +if (!is_object($formadmin)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); +} + + +?> + +executeHooks('formAssetDeprecationOptions', $parameters, $object, $action); +print $hookmanager->resPrint; +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + $class_type = get_class($object) == 'Asset' ? 0 : 1; + foreach ($assetdepreciationoptions->deprecation_options_fields as $mode_key => $mode_info) { + if (!empty($mode_info['enabled_field'])) { + $info = explode(':', $mode_info['enabled_field']); + $enabled_field_info[] = array( + 'mode_key' => $info[0], + 'field_key' => $info[1], + 'value' => $info[2], + 'target' => 'block_' . $mode_key, + ); + } + + $assetdepreciationoptions->setInfosForMode($mode_key, $class_type, true); + $prefix_html_name = $mode_key . '_'; + + print '
    '; + print load_fiche_titre($langs->trans($mode_info['label']), '', ''); + print '
    '; + print '
    '; + print '
    '; + print '' . "\n"; + $mode_info['fields'] = dol_sort_array($mode_info['fields'], 'position'); + foreach ($mode_info['fields'] as $field_key => $field_info) { + // Discard if extrafield is a hidden field on form + if (abs($field_info['visible']) != 1 && abs($field_info['visible']) != 3 && abs($field_info['visible']) != 4) { + continue; + } + if (array_key_exists('enabled', $field_info) && isset($field_info['enabled']) && !verifCond($field_info['enabled'])) { + continue; // We don't want this field + } + if (!empty($field_info['column_break'])) { + print '
    '; + + // We close div and reopen for second column + print '
    '; + print '
    '; + + print '
    '; + print ''; + } + + $html_name = $prefix_html_name . $field_key; + if (!empty($field_info['enabled_field'])) { + $info = explode(':', $field_info['enabled_field']); + $enabled_field_info[] = array( + 'mode_key' => $info[0], + 'field_key' => $info[1], + 'value' => $info[2], + 'target' => 'field_' . $html_name, + ); + } + + $more_class = ''; + if (!empty($field_info['required']) || (isset($field_info['notnull']) && $field_info['notnull'] > 0)) { + $more_class .= ' fieldrequired'; + } + if (preg_match('/^(text|html)/', $val['type'])) { + $more_class .= ' tdtop'; + } + + print ''; + if (!empty($field_info['help'])) { + print $form->textwithpicto($langs->trans($field_info['label']), $langs->trans($field_info['help'])); + } else { + print $langs->trans($field_info['label']); + } + print ''; + print ''; + print ''; + } + print '
    '; + if (!empty($field_info['picto'])) { + print img_picto('', $field_info['picto'], '', false, 0, 0, '', 'pictofixedwidth'); + } + if (in_array($field_info['type'], array('int', 'integer'))) { + $value = GETPOSTISSET($html_name) ?GETPOST($html_name, 'int') : $assetdepreciationoptions->$field_key; + } elseif ($field_info['type'] == 'double') { + $value = GETPOSTISSET($html_name) ? price2num(GETPOST($html_name, 'alphanohtml')) : $assetdepreciationoptions->$field_key; + } elseif (preg_match('/^(text|html)/', $field_info['type'])) { + $tmparray = explode(':', $field_info['type']); + if (!empty($tmparray[1])) { + $check = $tmparray[1]; + } else { + $check = 'restricthtml'; + } + $value = GETPOSTISSET($html_name) ? GETPOST($html_name, $check) : $assetdepreciationoptions->$field_key; + } elseif ($field_info['type'] == 'price') { + $value = GETPOSTISSET($html_name) ? price2num(GETPOST($html_name)) : ($assetdepreciationoptions->$field_key ? price2num($assetdepreciationoptions->$field_key) : (!empty($field_info['default']) ? dol_eval($field_info['default'], 1) : 0)); + } elseif ($field_key == 'lang') { + $value = GETPOSTISSET($html_name) ? GETPOST($html_name, 'aZ09') : $assetdepreciationoptions->lang; + } else { + $value = GETPOSTISSET($html_name) ? GETPOST($html_name, 'alpha') : $assetdepreciationoptions->$field_key; + } + if (!empty($field_info['noteditable'])) { + print $assetdepreciationoptions->showOutputField($field_info, $field_key, $value, '', '', $prefix_html_name, 0); + } else { + if ($field_key == 'lang') { + print img_picto('', 'language', 'class="pictofixedwidth"'); + print $formadmin->select_language($value, $html_name, 0, null, 1, 0, 0, 'minwidth300', 2); + } else { + print $assetdepreciationoptions->showInputField($field_info, $field_key, $value, '', '', $prefix_html_name, 0); + } + } + print '
    '; + print '
    '; + print '
    '; + print '
    '; + print '
    '; + } +} + +if (!empty($enabled_field_info)) { + $enabled_field_info = json_encode($enabled_field_info); + print << +SCRIPT; +} + +?> + diff --git a/htdocs/asset/tpl/depreciation_options_view.tpl.php b/htdocs/asset/tpl/depreciation_options_view.tpl.php new file mode 100644 index 00000000000..2660fbbaee7 --- /dev/null +++ b/htdocs/asset/tpl/depreciation_options_view.tpl.php @@ -0,0 +1,154 @@ + + * + * 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 . + * + * Show extrafields. It also show fields from hook formAssetAccountancyCode. Need to have following variables defined: + * $object (asset, assetmodel, ...) + * $assetaccountancycodes + * $action + * $conf + * $langs + * + * $parameters + */ + +// Protection to avoid direct call of template +if (empty($object) || !is_object($object)) { + print "Error, template page can't be called as URL"; + exit; +} + +if (!is_object($form)) { + $form = new Form($db); +} + + +?> + +executeHooks('formAssetDeprecationOptions', $parameters, $object, $action); +print $hookmanager->resPrint; +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + $class_type = get_class($object) == 'Asset' ? 0 : 1; + foreach ($assetdepreciationoptions->deprecation_options_fields as $mode_key => $mode_info) { + if (!empty($mode_info['enabled_field'])) { + $info = explode(':', $mode_info['enabled_field']); + if ($assetdepreciationoptions->deprecation_options[$info[0]][$info[1]] != $info[2]) { + continue; + } + } + + $assetdepreciationoptions->setInfosForMode($mode_key, $class_type, true); + + print load_fiche_titre($langs->trans($mode_info['label']), '', ''); + print '
    '; + print '
    '; + print '
    '; + print '' . "\n"; + $mode_info['fields'] = dol_sort_array($mode_info['fields'], 'position'); + foreach ($mode_info['fields'] as $field_key => $field_info) { + if (!empty($field_info['enabled_field'])) { + $info = explode(':', $field_info['enabled_field']); + if ($assetdepreciationoptions->deprecation_options[$info[0]][$info[1]] != $info[2]) { + continue; + } + } + // Discard if extrafield is a hidden field on form + if (abs($field_info['visible']) != 1 && abs($field_info['visible']) != 3 && abs($field_info['visible']) != 4 && abs($field_info['visible']) != 5) { + continue; + } + if (array_key_exists('enabled', $field_info) && isset($field_info['enabled']) && !verifCond($field_info['enabled'])) { + continue; // We don't want this field + } + if (!empty($field_info['column_break'])) { + print '
    '; + + // We close div and reopen for second column + print '
    '; + print '
    '; + + print '
    '; + print ''; + } + + $key = $mode_key . '_' . $field_key; + $value = $assetdepreciationoptions->deprecation_options[$mode_key][$field_key]; + + print ''; + if (!empty($field_info['help'])) { + print $form->textwithpicto($langs->trans($field_info['label']), $langs->trans($field_info['help'])); + } else { + if (isset($field_info['copytoclipboard']) && $field_info['copytoclipboard'] == 1) { + print showValueWithClipboardCPButton($value, 0, $langs->transnoentitiesnoconv($field_info['label'])); + } else { + print $langs->trans($field_info['label']); + } + } + print ''; + print ''; + print ''; + } + print '
    '; + if (in_array($field_info['type'], array('text', 'html'))) { + print '
    '; + } + if ($field_key == 'lang') { + $langs->load("languages"); + $labellang = ($value ? $langs->trans('Language_' . $value) : ''); + print picto_from_langcode($value, 'class="paddingrightonly saturatemedium opacitylow"'); + print $labellang; + } else { + if (isset($field_info['copytoclipboard']) && $field_info['copytoclipboard'] == 2) { + $out = $assetdepreciationoptions->showOutputField($field_info, $field_key, $value, '', '', $mode_key . '_', 0); + print showValueWithClipboardCPButton($out, 0, $out); + } else { + print $assetdepreciationoptions->showOutputField($field_info, $field_key, $value, '', '', $mode_key . '_', 0); + } + } + if (in_array($field_info['type'], array('text', 'html'))) { + print '
    '; + } + print '
    '; + print '
    '; + print '
    '; + print '
    '; + } +} + +?> + diff --git a/htdocs/asset/tpl/depreciation_view.tpl.php b/htdocs/asset/tpl/depreciation_view.tpl.php new file mode 100644 index 00000000000..2660fbbaee7 --- /dev/null +++ b/htdocs/asset/tpl/depreciation_view.tpl.php @@ -0,0 +1,154 @@ + + * + * 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 . + * + * Show extrafields. It also show fields from hook formAssetAccountancyCode. Need to have following variables defined: + * $object (asset, assetmodel, ...) + * $assetaccountancycodes + * $action + * $conf + * $langs + * + * $parameters + */ + +// Protection to avoid direct call of template +if (empty($object) || !is_object($object)) { + print "Error, template page can't be called as URL"; + exit; +} + +if (!is_object($form)) { + $form = new Form($db); +} + + +?> + +executeHooks('formAssetDeprecationOptions', $parameters, $object, $action); +print $hookmanager->resPrint; +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + $class_type = get_class($object) == 'Asset' ? 0 : 1; + foreach ($assetdepreciationoptions->deprecation_options_fields as $mode_key => $mode_info) { + if (!empty($mode_info['enabled_field'])) { + $info = explode(':', $mode_info['enabled_field']); + if ($assetdepreciationoptions->deprecation_options[$info[0]][$info[1]] != $info[2]) { + continue; + } + } + + $assetdepreciationoptions->setInfosForMode($mode_key, $class_type, true); + + print load_fiche_titre($langs->trans($mode_info['label']), '', ''); + print '
    '; + print '
    '; + print '
    '; + print '' . "\n"; + $mode_info['fields'] = dol_sort_array($mode_info['fields'], 'position'); + foreach ($mode_info['fields'] as $field_key => $field_info) { + if (!empty($field_info['enabled_field'])) { + $info = explode(':', $field_info['enabled_field']); + if ($assetdepreciationoptions->deprecation_options[$info[0]][$info[1]] != $info[2]) { + continue; + } + } + // Discard if extrafield is a hidden field on form + if (abs($field_info['visible']) != 1 && abs($field_info['visible']) != 3 && abs($field_info['visible']) != 4 && abs($field_info['visible']) != 5) { + continue; + } + if (array_key_exists('enabled', $field_info) && isset($field_info['enabled']) && !verifCond($field_info['enabled'])) { + continue; // We don't want this field + } + if (!empty($field_info['column_break'])) { + print '
    '; + + // We close div and reopen for second column + print '
    '; + print '
    '; + + print '
    '; + print ''; + } + + $key = $mode_key . '_' . $field_key; + $value = $assetdepreciationoptions->deprecation_options[$mode_key][$field_key]; + + print ''; + if (!empty($field_info['help'])) { + print $form->textwithpicto($langs->trans($field_info['label']), $langs->trans($field_info['help'])); + } else { + if (isset($field_info['copytoclipboard']) && $field_info['copytoclipboard'] == 1) { + print showValueWithClipboardCPButton($value, 0, $langs->transnoentitiesnoconv($field_info['label'])); + } else { + print $langs->trans($field_info['label']); + } + } + print ''; + print ''; + print ''; + } + print '
    '; + if (in_array($field_info['type'], array('text', 'html'))) { + print '
    '; + } + if ($field_key == 'lang') { + $langs->load("languages"); + $labellang = ($value ? $langs->trans('Language_' . $value) : ''); + print picto_from_langcode($value, 'class="paddingrightonly saturatemedium opacitylow"'); + print $labellang; + } else { + if (isset($field_info['copytoclipboard']) && $field_info['copytoclipboard'] == 2) { + $out = $assetdepreciationoptions->showOutputField($field_info, $field_key, $value, '', '', $mode_key . '_', 0); + print showValueWithClipboardCPButton($out, 0, $out); + } else { + print $assetdepreciationoptions->showOutputField($field_info, $field_key, $value, '', '', $mode_key . '_', 0); + } + } + if (in_array($field_info['type'], array('text', 'html'))) { + print '
    '; + } + print '
    '; + print '
    '; + print '
    '; + print '
    '; + } +} + +?> + diff --git a/htdocs/asset/tpl/linkedobjectblock.tpl.php b/htdocs/asset/tpl/linkedobjectblock.tpl.php new file mode 100644 index 00000000000..59df306c829 --- /dev/null +++ b/htdocs/asset/tpl/linkedobjectblock.tpl.php @@ -0,0 +1,81 @@ + + * Copyright (C) 2013 Juanjo Menent + * Copyright (C) 2014 Marcos GarcĂ­a + * + * 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 . + */ + +// Protection to avoid direct call of template +if (empty($conf) || !is_object($conf)) { + print "Error, template page can't be called as URL"; + exit; +} + +print "\n"; + +global $user; +global $noMoreLinkedObjectBlockAfter; + +$langs = $GLOBALS['langs']; +$linkedObjectBlock = $GLOBALS['linkedObjectBlock']; + +// Load translation files required by the page +$langs->load("assets"); + +$linkedObjectBlock = dol_sort_array($linkedObjectBlock, 'date', 'desc', 0, 0, 1); + +$total = 0; +$ilink = 0; +foreach ($linkedObjectBlock as $key => $objectlink) { + $ilink++; + + $trclass = 'oddeven'; + if ($ilink == count($linkedObjectBlock) && empty($noMoreLinkedObjectBlockAfter) && count($linkedObjectBlock) <= 1) { + $trclass .= ' liste_sub_total'; + } + echo '
    '.$langs->trans("Asset"); + if (!empty($showImportButton) && !empty($conf->global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES)) { + print ' '; + echo ''.$objectlink->getNomUrl(1).''.$objectlink->label.''.dol_print_date($objectlink->date_start, 'day').''; + if ($user->rights->asset->read) { + $total = $total + $objectlink->acquisition_value_ht; + echo price($objectlink->acquisition_value_ht); + } + echo ''.$objectlink->getLibStatut(3).''; + echo ''.img_picto($langs->transnoentitiesnoconv("RemoveLink"), 'unlink').''; + echo '
    '.$langs->trans("Total").''.price($total).'
    '."\n"; - - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print "\n"; - - $assettype = new AssetType($db); - - while ($i < $num) { - $objp = $db->fetch_object($result); - - $assettype->id = $objp->rowid; - $assettype->ref = $objp->rowid; - $assettype->label = $objp->rowid; - - print ''; - print ''; - print ''; - - print ''; - - print ''; - - print ''; - - if ($user->rights->asset->write) { - print ''; - } else { - print ''; - } - print ""; - $i++; - } - - // If no record found - if ($num == 0) { - $colspan = 6; - print ''; - } - - print "
    '.$langs->trans("Ref").''.$langs->trans("Label").''.$langs->trans("AccountancyCodeAsset").''.$langs->trans("AccountancyCodeDepreciationAsset").''.$langs->trans("AccountancyCodeDepreciationExpense").' 
    '; - print $assettype->getNomUrl(1); - //'.img_object($langs->trans("ShowType"),'group').' '.$objp->rowid.' - print ''.dol_escape_htmltag($objp->label).''; - if (!empty($conf->accounting->enabled)) { - $accountingaccount = new AccountingAccount($db); - $accountingaccount->fetch('', $objp->accountancy_code_asset, 1); - - print $accountingaccount->getNomUrl(0, 1, 1, '', 0); - } else { - print $objp->accountancy_code_asset; - } - print ''; - if (!empty($conf->accounting->enabled)) { - $accountingaccount2 = new AccountingAccount($db); - $accountingaccount2->fetch('', $objp->accountancy_code_depreciation_asset, 1); - - print $accountingaccount2->getNomUrl(0, 1, 1, '', 0); - } else { - print $objp->accountancy_code_depreciation_asset; - } - print ''; - if (!empty($conf->accounting->enabled)) { - $accountingaccount3 = new AccountingAccount($db); - $accountingaccount3->fetch('', $objp->accountancy_code_depreciation_expense, 1); - - print $accountingaccount3->getNomUrl(0, 1, 1, '', 0); - } else { - print $objp->accountancy_code_depreciation_expense; - } - print 'rowid.'">'.img_edit().' 
    '.$langs->trans("NoRecordFound").'
    "; - print '
    '; - - print ''; - } else { - dol_print_error($db); - } -} - - -/* ************************************************************************** */ -/* */ -/* Creation mode */ -/* */ -/* ************************************************************************** */ -if ($action == 'create') { - $object = new AssetType($db); - if (!empty($conf->accounting->enabled)) { - $formaccounting = new FormAccounting($db); - } - - print load_fiche_titre($langs->trans("NewAssetType"), '', $object->picto); - - print '
    '; - print ''; - print ''; - - print dol_get_fiche_head(''); - - print ''; - print ''; - - print ''; - - if (!empty($conf->accounting->enabled)) { - // Accountancy_code_asset - print ''; - print ''; - - // Accountancy_code_depreciation_expense - print ''; - print ''; - - // Accountancy_code_depreciation_expense - print ''; - print ''; - } else // For external software - { - // Accountancy_code_asset - print ''; - print ''; - - // Accountancy_code_depreciation_asset - print ''; - print ''; - - // Accountancy_code_depreciation_expense - print ''; - print ''; - } - - print ''; - - // Other attributes - $parameters = array(); - $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - if (empty($reshook)) { - print $object->showOptionals($extrafields, 'create', $parameters); - } - print ''; - print "
    '.$langs->trans("Label").'
    '.$langs->trans("AccountancyCodeAsset").''; - print $formaccounting->select_account($object->accountancy_code_asset, 'accountancy_code_asset', 1, '', 1, 1); - print '
    '.$langs->trans("AccountancyCodeDepreciationAsset").''; - print $formaccounting->select_account($object->accountancy_code_depreciation_asset, 'accountancy_code_depreciation_asset', 1, '', 1, 1); - print '
    '.$langs->trans("AccountancyCodeDepreciationExpense").''; - print $formaccounting->select_account($object->accountancy_code_depreciation_expense, 'accountancy_code_depreciation_expense', 1, '', 1, 1); - print '
    '.$langs->trans("AccountancyCodeAsset").''; - print '
    '.$langs->trans("AccountancyCodeDepreciationAsset").''; - print '
    '.$langs->trans("AccountancyCodeDepreciationExpense").''; - print '
    '.$langs->trans("Description").''; - print '
    \n"; - - print dol_get_fiche_end(); - - print $form->buttonsSaveCancel("Add"); - - print "
    \n"; -} - -/* ************************************************************************** */ -/* */ -/* View mode */ -/* */ -/* ************************************************************************** */ -if ($rowid > 0) { - if ($action != 'edit') { - $object = new AssetType($db); - $object->fetch($rowid); - $object->fetch_optionals(); - - /* - * Confirmation suppression - */ - if ($action == 'delete') { - print $form->formconfirm($_SERVER['PHP_SELF']."?rowid=".$object->id, $langs->trans("DeleteAnAssetType"), $langs->trans("ConfirmDeleteAssetType", $object->label), "confirm_delete", '', 0, 1); - } - - $head = asset_type_prepare_head($object); - - print dol_get_fiche_head($head, 'card', $langs->trans("AssetType"), -1, 'asset'); - - $linkback = ''.$langs->trans("BackToList").''; - - $morehtmlref = '
    '; - // Ref asset type - $morehtmlref .= $form->editfieldkey("Label", 'label', $object->label, $object, $user->rights->asset->write, 'string', '', 0, 1); - $morehtmlref .= $form->editfieldval("Label", 'label', $object->label, $object, $user->rights->asset->write, 'string', '', null, null, '', 1); - $morehtmlref .= '
    '; - - dol_banner_tab($object, 'rowid', $linkback, 1, 'rowid', 'ref', $morehtmlref, '', 0, '', $morehtmlright); - - print '
    '; - print '
    '; - - print ''; - - print ''; - print ''; - print ''; - - print ''; - print ''; - print ''; - - print ''; - print ''; - print ''; - - print '"; - - // Other attributes - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; - - print '
    '; - print $langs->trans("AccountancyCodeAsset"); - print ''; - if (!empty($conf->accounting->enabled)) { - $accountingaccount = new AccountingAccount($db); - $accountingaccount->fetch('', $object->accountancy_code_asset, 1); - - print $accountingaccount->getNomUrl(0, 1, 1, '', 1); - } else { - print $object->accountancy_code_asset; - } - print '
    '; - print $langs->trans("AccountancyCodeDepreciationAsset"); - print ''; - if (!empty($conf->accounting->enabled)) { - $accountingaccount2 = new AccountingAccount($db); - $accountingaccount2->fetch('', $object->accountancy_code_depreciation_asset, 1); - - print $accountingaccount2->getNomUrl(0, 1, 1, '', 1); - } else { - print $object->accountancy_code_depreciation_asset; - } - print '
    '; - print $langs->trans("AccountancyCodeDepreciationExpense"); - print ''; - if (!empty($conf->accounting->enabled)) { - $accountingaccount3 = new AccountingAccount($db); - $accountingaccount3->fetch('', $object->accountancy_code_depreciation_expense, 1); - - print $accountingaccount3->getNomUrl(0, 1, 1, '', 1); - } else { - print $object->accountancy_code_depreciation_expense; - } - print '
    '.$langs->trans("Description").''; - print nl2br($object->note)."
    '; - print '
    '; - - print dol_get_fiche_end(); - - /* - * Buttons - */ - - print '
    '; - - // Edit - if ($user->rights->asset->write) { - print ''; - } - - // Delete - if ($user->rights->asset->write) { - print ''; - } - - print "
    "; - } - - /* ************************************************************************** */ - /* */ - /* Edition mode */ - /* */ - /* ************************************************************************** */ - - if ($action == 'edit') { - $object = new AssetType($db); - $object->fetch($rowid); - $object->fetch_optionals(); - if (!empty($conf->accounting->enabled)) { - $formaccounting = new FormAccounting($db); - } - - $head = asset_type_prepare_head($object); - - print '
    '; - print ''; - print ''; - print ''; - - print dol_get_fiche_head($head, 'card', $langs->trans("AssetsType"), -1, 'setup'); - - print ''; - - print ''; - - print ''; - - if (!empty($conf->accounting->enabled)) { - // Accountancy_code_asset - print ''; - print ''; - - // Accountancy_code_depreciation_expense - print ''; - print ''; - - // Accountancy_code_depreciation_expense - print ''; - print ''; - } else // For external software - { - // Accountancy_code_asset - print ''; - print ''; - - // Accountancy_code_depreciation_asset - print ''; - print ''; - - // Accountancy_code_depreciation_expense - print ''; - print ''; - } - - print ''; - - // Other attributes - $parameters = array(); - $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $act, $action); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - if (empty($reshook)) { - print $object->showOptionals($extrafields, 'edit', $parameters); - } - - // Other attributes - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; - - print '
    '.$langs->trans("Ref").''.$object->id.'
    '.$langs->trans("Label").'
    '.$langs->trans("AccountancyCodeAsset").''; - print $formaccounting->select_account($object->accountancy_code_asset, 'accountancy_code_asset', 1, '', 1, 1); - print '
    '.$langs->trans("AccountancyCodeDepreciationAsset").''; - print $formaccounting->select_account($object->accountancy_code_depreciation_asset, 'accountancy_code_depreciation_asset', 1, '', 1, 1); - print '
    '.$langs->trans("AccountancyCodeDepreciationExpense").''; - print $formaccounting->select_account($object->accountancy_code_depreciation_expense, 'accountancy_code_depreciation_expense', 1, '', 1, 1); - print '
    '.$langs->trans("AccountancyCodeAsset").''; - print '
    '.$langs->trans("AccountancyCodeDepreciationAsset").''; - print '
    '.$langs->trans("AccountancyCodeDepreciationExpense").''; - print '
    '.$langs->trans("Description").''; - print '
    '; - - print dol_get_fiche_end(); - - print $form->buttonsSaveCancel(); - - print "
    "; - } -} - -// End of page -llxFooter(); -$db->close(); diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php index 8663d50e66a..763463d6fb8 100644 --- a/htdocs/barcode/printsheet.php +++ b/htdocs/barcode/printsheet.php @@ -23,7 +23,7 @@ * \brief Page to print sheets with barcodes using the document templates into core/modules/printsheets */ -if (!empty($_POST['mode']) && $_POST['mode'] === 'label') { // Page is called to build a PDF and output, we must ne renew the token. +if (!empty($_POST['mode']) && $_POST['mode'] === 'label') { // Page is called to build a PDF and output, we must not renew the token. if (!defined('NOTOKENRENEWAL')) { define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) } diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 748aea4ddb2..f6e40b511f1 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -148,8 +148,17 @@ if (empty($reshook)) { $error = 0; // Set if we used free entry or predefined product - $idprod = (int) GETPOST('idprod', 'int'); - $bom_child = (int) GETPOST('bom_select', 'int'); + $bom_child_id = (int) GETPOST('bom_id', 'int'); + if ($bom_child_id > 0) { + $bom_child = new BOM($db); + $res = $bom_child->fetch($bom_child_id); + if ($res) { + $idprod = $bom_child->fk_product; + } + } else { + $idprod = (int) GETPOST('idprod', 'int'); + } + $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS'); $disable_stock_change = GETPOST('disable_stock_change', 'int'); @@ -173,7 +182,7 @@ if (empty($reshook)) { $bomline = new BOMLine($db); $bomline->fk_bom = $id; $bomline->fk_product = $idprod; - $bomline->fk_bom_child = $bom_child; + $bomline->fk_bom_child = $bom_child_id; $bomline->qty = $qty; $bomline->qty_frozen = (int) $qty_frozen; $bomline->disable_stock_change = (int) $disable_stock_change; @@ -354,8 +363,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formquestion = array(); if (!empty($conf->bom->enabled)) { $langs->load("mrp"); - require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; - $formproduct = new FormProduct($db); $forcecombo = 0; if ($conf->browser->name == 'ie') { $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy @@ -384,8 +391,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formquestion = array(); if (!empty($conf->bom->enabled)) { $langs->load("mrp"); - require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; - $formproduct = new FormProduct($db); $forcecombo = 0; if ($conf->browser->name == 'ie') { $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy @@ -415,7 +420,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (!empty($conf->bom->enabled)) { $langs->load("mrp"); require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; - $formproduct = new FormProduct($db); $forcecombo = 0; if ($conf->browser->name == 'ie') { $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy @@ -514,7 +518,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Common attributes $keyforbreak = 'duration'; include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; - + $object->calculateCosts(); print ''.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).''.price($object->total_cost).''; print ''.$langs->trans("UnitCost").''.price($object->unit_cost).''; @@ -585,13 +589,14 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $(".collapse_bom").click(function() { console.log("We click on collapse"); var id_bom_line = $(this).attr('id').replace('collapse-', ''); - if($(this).text().indexOf('+') > 0) { + console.log($(this).html().indexOf('folder-open')); + if($(this).html().indexOf('folder-open') <= 0) { $('[parentid="'+ id_bom_line +'"]').show(); - $(this).html('(-) '); + $(this).html(''); } else { $('[parentid="'+ id_bom_line +'"]').hide(); - $(this).html('(+) '); + $(this).html(''); } return false; @@ -601,7 +606,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $("#show_all").click(function() { console.log("We click on show all"); $("[class^=sub_bom_lines]").show(); - $("[class^=collapse_bom]").html('(-) '); + $("[class^=collapse_bom]").html(''); return false; }); @@ -609,7 +614,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $("#hide_all").click(function() { console.log("We click on hide all"); $("[class^=sub_bom_lines]").hide(); - $("[class^=collapse_bom]").html('(+) '); + $("[class^=collapse_bom]").html(''); return false; }); diff --git a/htdocs/bom/bom_net_needs.php b/htdocs/bom/bom_net_needs.php new file mode 100644 index 00000000000..4b2d5cdecab --- /dev/null +++ b/htdocs/bom/bom_net_needs.php @@ -0,0 +1,328 @@ + + * Copyright (C) 2019 FrĂ©dĂ©ric France + * + * 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 . + */ + +/** + * \file htdocs/bom/bom_net_needs.php + * \ingroup bom + * \brief Page to create/edit/view bom + */ + +// Load Dolibarr environment +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; +require_once DOL_DOCUMENT_ROOT.'/bom/lib/bom.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("mrp", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bomnet_needs'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); + + + +// Initialize technical objects +$object = new BOM($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->bom->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('bomnetneeds')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Initialize array of search criterias +$search_all = GETPOST("search_all", 'alpha'); +$search = array(); +foreach ($object->fields as $key => $val) { + if (GETPOST('search_'.$key, 'alpha')) { + $search[$key] = GETPOST('search_'.$key, 'alpha'); + } +} + +if (empty($action) && empty($id) && empty($ref)) { + $action = 'view'; +} + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. +if ($object->id > 0) { + $object->calculateCosts(); +} + + + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +$result = restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); + +$permissionnote = $user->rights->bom->write; // Used by the include of actions_setnotes.inc.php +$permissiondellink = $user->rights->bom->write; // Used by the include of actions_dellink.inc.php +$permissiontoadd = $user->rights->bom->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = $user->rights->bom->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); +$upload_dir = $conf->bom->multidir_output[isset($object->entity) ? $object->entity : 1]; + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + $error = 0; + + $backurlforlist = DOL_URL_ROOT.'/bom/bom_list.php'; + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = DOL_URL_ROOT.'/bom/bom_net_needs.php?id='.($id > 0 ? $id : '__ID__'); + } + } + } + if ($action == 'treeview') $object->getNetNeedsTree($TChildBom, 1); + else $object->getNetNeeds($TChildBom, 1); +} + + +/* + * View + */ + +$form = new Form($db); +$formfile = new FormFile($db); + + +$title = $langs->trans('BOM'); +$help_url ='EN:Module_BOM'; +llxHeader('', $title, $help_url); + + + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { + $head = bomPrepareHead($object); + print dol_get_fiche_head($head, 'net_needs', $langs->trans("BillOfMaterials"), -1, 'bom'); + + $formconfirm = ''; + + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $formconfirm .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $formconfirm = $hookmanager->resPrint; + } + + // Print form confirm + print $formconfirm; + + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + print '
    '; + print ''."\n"; + + // Common attributes + $keyforbreak = 'duration'; + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + + print ''; + print ''; + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + + print '
    '.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).''.price($object->total_cost).'
    '.$langs->trans("UnitCost").''.price($object->unit_cost).'
    '; + print '
    '; + print '
    '; + + print '
    '; + + print dol_get_fiche_end(); + + $viewlink = dolGetButtonTitle($langs->trans('GroupByProduct'), '', 'fa fa-list-alt imgforviewmode', $_SERVER['PHP_SELF'].'?id='.$object->id.'&token='.newToken(), '', 1, array('morecss' => 'reposition '.($action !== 'treeview' ? 'btnTitleSelected':''))); + $viewlink .= dolGetButtonTitle($langs->trans('TreeStructure'), '', 'fa fa-stream imgforviewmode', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=treeview&token='.newToken(), '', 1, array('morecss' => 'reposition marginleftonly '.($action == 'treeview' ? 'btnTitleSelected':''))); + + print load_fiche_titre($langs->trans("BillOfMaterials"), $viewlink, 'cubes'); + + /* + * Lines + */ + $text_stock_options = $langs->trans("RealStockDesc").'
    '; + $text_stock_options .= $langs->trans("RealStockWillAutomaticallyWhen").'
    '; + $text_stock_options .= (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) ? '- '.$langs->trans("DeStockOnShipment").'
    ' : ''); + $text_stock_options .= (! empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) ? '- '.$langs->trans("DeStockOnValidateOrder").'
    ' : ''); + $text_stock_options .= (! empty($conf->global->STOCK_CALCULATE_ON_BILL) ? '- '.$langs->trans("DeStockOnBill").'
    ' : ''); + $text_stock_options .= (! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL) ? '- '.$langs->trans("ReStockOnBill").'
    ' : ''); + $text_stock_options .= (! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? '- '.$langs->trans("ReStockOnValidateOrder").'
    ' : ''); + $text_stock_options .= (! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? '- '.$langs->trans("ReStockOnDispatchOrder").'
    ' : ''); + $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? '- '.$langs->trans("StockOnReception").'
    ' : ''); + + print ''; + print "\n"; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if (! empty($TChildBom)) { + if ($action == 'treeview') { + foreach ($TChildBom as $fk_bom => $TProduct) { + $repeatChar = ' '; + if (! empty($TProduct['bom'])) { + if ($TProduct['parentid'] != $object->id) print ''; + else print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + if (! empty($TProduct['product'])) { + foreach ($TProduct['product'] as $fk_product => $TInfos) { + $prod = new Product($db); + $prod->fetch($fk_product); + $prod->load_virtual_stock(); + if (empty($prod->stock_reel)) $prod->stock_reel = 0; + if ($fk_bom != $object->id) print ''; + else print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + } + } + } else { + foreach ($TChildBom as $fk_product => $qty) { + $prod = new Product($db); + $prod->fetch($fk_product); + $prod->load_virtual_stock(); + if (empty($prod->stock_reel)) $prod->stock_reel = 0; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + } + } + print ''; + print '
    '.$langs->trans('Product'); + if (! empty($conf->global->BOM_SUB_BOM) && $action == 'treeview') { + print '   '.img_picto('', 'folder-open', 'class="paddingright"').$langs->trans("ExpandAll").'  '; + print ''.img_picto('', 'folder', 'class="paddingright"').$langs->trans("UndoExpandAll").' '; + } + print ''.$langs->trans('Quantity').''.$form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1).''.$form->textwithpicto($langs->trans("VirtualStock"), $langs->trans("VirtualStockDesc")).'
    '.str_repeat($repeatChar, $TProduct['level']).$TProduct['bom']->getNomUrl(1); + print ' '; + print img_picto('', 'folder-open'); + print ''; + print ''.$TProduct['qty'].'
    '.str_repeat($repeatChar, $TInfos['level']).$prod->getNomUrl(1).''.$TInfos['qty'].''.$prod->stock_reel.''.$prod->stock_theorique.'
    '.$prod->getNomUrl(1).''.$qty.''.$prod->stock_reel.''.$prod->stock_theorique.'
    '; + + + + /* + * ButAction + */ + print '
    '."\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print '
    '; + + + ?> + + + + close(); diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 0520c76dde2..20ff5fe27b1 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -847,7 +847,7 @@ class BOM extends CommonObject global $action, $hookmanager; $hookmanager->initHooks(array('bomdao')); - $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook > 0) { $result = $hookmanager->resPrint; @@ -1064,26 +1064,89 @@ class BOM extends CommonObject $tmpproduct->cost_price = 0; $tmpproduct->pmp = 0; - $result = $tmpproduct->fetch($line->fk_product, '', '', '', 0, 1, 1); // We discard selling price and language loading - if ($result < 0) { - $this->error = $tmpproduct->error; - return -1; - } - $line->unit_cost = price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp); - if (empty($line->unit_cost)) { - if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) { - $line->unit_cost = $productFournisseur->fourn_unitprice; + if (empty($line->fk_bom_child)) { + $result = $tmpproduct->fetch($line->fk_product, '', '', '', 0, 1, 1); // We discard selling price and language loading + if ($result < 0) { + $this->error = $tmpproduct->error; + return -1; + } + $line->unit_cost = price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp); + if (empty($line->unit_cost)) { + if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) { + $line->unit_cost = $productFournisseur->fourn_unitprice; + } + } + + $line->total_cost = price2num($line->qty * $line->unit_cost, 'MT'); + + $this->total_cost += $line->total_cost; + } else { + $bom_child= new BOM($this->db); + $res = $bom_child->fetch($line->fk_bom_child); + if ($res>0) { + $bom_child->calculateCosts(); + $line->childBom[] = $bom_child; + $this->total_cost += $bom_child->total_cost * $line->qty; + } else { + $this->error = $bom_child->error; + return -2; } } - - $line->total_cost = price2num($line->qty * $line->unit_cost, 'MT'); - - $this->total_cost += $line->total_cost; } $this->total_cost = price2num($this->total_cost, 'MT'); - if ($this->qty) { + if ($this->qty > 0) { $this->unit_cost = price2num($this->total_cost / $this->qty, 'MU'); + } elseif ($this->qty < 0) { + $this->unit_cost = price2num($this->total_cost * $this->qty, 'MU'); + } + } + } + + /** + * Get Net needs by product + * + * @param array $TNetNeeds Array of ChildBom and infos linked to + * @param int $qty qty needed + * @return void + */ + public function getNetNeeds(&$TNetNeeds = array(), $qty = 0) + { + if (! empty($this->lines)) { + foreach ($this->lines as $line) { + if (! empty($line->childBom)) { + foreach ($line->childBom as $childBom) $childBom->getNetNeeds($TNetNeeds, $line->qty*$qty); + } else { + $TNetNeeds[$line->fk_product] += $line->qty*$qty; + } + } + } + } + + /** + * Get Net needs Tree by product or bom + * + * @param array $TNetNeeds Array of ChildBom and infos linked to + * @param int $qty qty needed + * @param int $level level of recursivity + * @return void + */ + public function getNetNeedsTree(&$TNetNeeds = array(), $qty = 0, $level = 0) + { + if (! empty($this->lines)) { + foreach ($this->lines as $line) { + if (! empty($line->childBom)) { + foreach ($line->childBom as $childBom) { + $TNetNeeds[$childBom->id]['bom'] = $childBom; + $TNetNeeds[$childBom->id]['parentid'] = $this->id; + $TNetNeeds[$childBom->id]['qty'] = $line->qty*$qty; + $TNetNeeds[$childBom->id]['level'] = $level; + $childBom->getNetNeedsTree($TNetNeeds, $line->qty*$qty, $level+1); + } + } else { + $TNetNeeds[$this->id]['product'][$line->fk_product]['qty'] += $line->qty * $qty; + $TNetNeeds[$this->id]['product'][$line->fk_product]['level'] = $level; + } } } } @@ -1213,6 +1276,11 @@ class BOMLine extends CommonObjectLine public $unit_cost = 0; + /** + * @var Bom array of Bom in line + */ + public $childBom = array(); + /** * Constructor * @@ -1453,7 +1521,7 @@ class BOMLine extends CommonObjectLine global $action, $hookmanager; $hookmanager->initHooks(array('bomlinedao')); - $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook > 0) { $result = $hookmanager->resPrint; diff --git a/htdocs/bom/lib/bom.lib.php b/htdocs/bom/lib/bom.lib.php index 805ba304c1d..954959d5d7a 100644 --- a/htdocs/bom/lib/bom.lib.php +++ b/htdocs/bom/lib/bom.lib.php @@ -84,6 +84,11 @@ function bomPrepareHead($object) $head[$h][2] = 'card'; $h++; + $head[$h][0] = DOL_URL_ROOT."/bom/bom_net_needs.php?id=".$object->id; + $head[$h][1] = $langs->trans("BOMNetNeeds"); + $head[$h][2] = 'net_needs'; + $h++; + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) { $nbNote = 0; if (!empty($object->note_private)) { diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index 7419c4618e0..0a3a3b34e7a 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -109,7 +109,7 @@ if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { if (!empty($conf->global->BOM_SUB_BOM)) { print '
    '.$langs->trans("or").'
    '.$langs->trans("BOM"); // TODO Add component to select a BOM - print ''; + $form->select_bom(); } print ''; diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 82626c12fec..8040310ea53 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -41,7 +41,7 @@ if (empty($object) || !is_object($object)) { } -global $forceall, $senderissupplier, $inputalsopricewithtax, $outputalsopricetotalwithtax; +global $forceall, $senderissupplier, $inputalsopricewithtax, $outputalsopricetotalwithtax, $langs; if (empty($dateSelector)) { $dateSelector = 0; @@ -83,8 +83,12 @@ $tmpproduct->fetch($line->fk_product); $tmpbom = new BOM($object->db); $res = $tmpbom->fetch($line->fk_bom_child); if ($tmpbom->id > 0) { + print $tmpproduct->getNomUrl(1); + print ' '.$langs->trans("or").' '; print $tmpbom->getNomUrl(1); - print '' . (empty($conf->global->BOM_SHOW_ALL_BOM_BY_DEFAULT) ? '(+)' : '(-)') . ' '; + print ' '; + print (empty($conf->global->BOM_SHOW_ALL_BOM_BY_DEFAULT) ? img_picto('', 'folder') : img_picto('', 'folder-open')); + print ''; } else { print $tmpproduct->getNomUrl(1); print ' - '.$tmpproduct->label; @@ -176,7 +180,8 @@ if ($action == 'selectlines') { print ''; // Select of all the sub-BOM lines -$sql = 'SELECT rowid, fk_bom_child, fk_product FROM '.MAIN_DB_PREFIX.'bom_bomline AS bl'; +// From this pont to the end of the file, we only take care of sub-BOM lines +$sql = 'SELECT rowid, fk_bom_child, fk_product, qty FROM '.MAIN_DB_PREFIX.'bom_bomline AS bl'; $sql.= ' WHERE fk_bom ='. (int) $tmpbom->id; $resql = $object->db->query($sql); @@ -187,7 +192,9 @@ if ($resql) { $sub_bom_product->fetch($obj->fk_product); $sub_bom = new BOM($object->db); - $sub_bom->fetch($obj->fk_bom_child); + if (!empty($obj->fk_bom_child)) { + $sub_bom->fetch($obj->fk_bom_child); + } $sub_bom_line = new BOMLine($object->db); $sub_bom_line->fetch($obj->rowid); @@ -199,21 +206,23 @@ if ($resql) { print ''; } - // Product - print ''.$sub_bom_product->getNomUrl(1).''; - - // Sub-BOM - if ($sub_bom_line->fk_bom_child > 0) { - print ''.$sub_bom->getNomUrl(1).''; + // Product OR BOM + print ''; + if (!empty($obj->fk_bom_child)) { + print $sub_bom_product->getNomUrl(1); + print ' '.$langs->trans('or').' '; + print $sub_bom->getNomUrl(1); } else { - print ' '; + print $sub_bom_product->getNomUrl(1); + print ''; } // Qty - print ''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; if ($sub_bom_line->qty_frozen > 0) { - print ''.$sub_bom_line->qty_frozen.''; + print ''.price($sub_bom_line->qty, 0, '', 0, 0).''; + print ''.$langs->trans('Yes').''; } else { + print ''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; print ' '; } @@ -227,21 +236,26 @@ if ($resql) { // Efficiency print ''.$sub_bom_line->efficiency.''; - // Cost price if it's defined - if ($sub_bom_product->cost_price > 0) { - print ''.price($sub_bom_product->cost_price * $line->qty).''; - $total_cost.= $sub_bom_product->cost_price * $line->qty; + if (!empty($sub_bom->id)) { + $sub_bom->calculateCosts(); + print ''.price($sub_bom->total_cost * $sub_bom_line->qty * $line->qty).''; + $total_cost+= $sub_bom->total_cost * $sub_bom_line->qty * $line->qty; + } elseif ($sub_bom_product->cost_price > 0) { + print ''.price($sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty).''; + $total_cost+= $sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty; } elseif ($sub_bom_product->pmp > 0) { // PMP if cost price isn't defined - print ''.price($sub_bom_product->pmp * $line->qty).''; - $total_cost.= $sub_bom_product->pmp * $line->qty; + print ''.price($sub_bom_product->pmp * $sub_bom_line->qty * $line->qty).''; + $total_cost.= $sub_bom_product->pmp * $sub_bom_line->qty * $line->qty; } else { // Minimum purchase price if cost price and PMP aren't defined - $sql_supplier_price = 'SELECT MIN(price) AS min_price FROM '.MAIN_DB_PREFIX.'product_fournisseur_price'; + $sql_supplier_price = 'SELECT MIN(price) AS min_price, quantity AS qty FROM '.MAIN_DB_PREFIX.'product_fournisseur_price'; $sql_supplier_price.= ' WHERE fk_product = '. (int) $sub_bom_product->id; $resql_supplier_price = $object->db->query($sql_supplier_price); if ($resql_supplier_price) { $obj = $object->db->fetch_object($resql_supplier_price); - print ''.price($obj->min_price * $line->qty).''; - $total_cost+= $obj->min_price * $line->qty; + $line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty * $line->qty; + + print ''.price($line_cost).''; + $total_cost+= $line_cost; } } diff --git a/htdocs/bookmarks/class/bookmark.class.php b/htdocs/bookmarks/class/bookmark.class.php index 9a5b3a53c20..39bb06c2ada 100644 --- a/htdocs/bookmarks/class/bookmark.class.php +++ b/htdocs/bookmarks/class/bookmark.class.php @@ -344,7 +344,7 @@ class Bookmark extends CommonObject global $action, $hookmanager; $hookmanager->initHooks(array('mybookmarkdao')); - $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook > 0) { $result = $hookmanager->resPrint; diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index 5ffed2e5e4b..a3d2dc3e57f 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -10,7 +10,7 @@ * Copyright (C) 2015 Marcos GarcĂ­a * Copyright (C) 2015 RaphaĂ«l Doursenaud * Copyright (C) 2016 Charlie Benke - * Copyright (C) 2018-2019 FrĂ©dĂ©ric France + * Copyright (C) 2018-2022 FrĂ©dĂ©ric France * * 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 @@ -185,7 +185,8 @@ class Categorie extends CommonObject 'contact' => 'socpeople', 'account' => 'bank_account', // old for bank account 'project' => 'projet', - 'warehouse'=> 'entrepot' + 'warehouse'=> 'entrepot', + 'knowledgemanagement' => 'knowledgemanagement_knowledgerecord' ); /** @@ -1612,7 +1613,7 @@ class Categorie extends CommonObject */ public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '') { - global $langs; + global $langs, $hookmanager; $result = ''; $label = $langs->trans("ShowCategory").': '.($this->ref ? $this->ref : $this->label); @@ -1640,6 +1641,15 @@ class Categorie extends CommonObject if ($withpicto != 2) { $result .= $link.dol_trunc(($this->ref ? $this->ref : $this->label), $maxlength).$linkend; } + global $action; + $hookmanager->initHooks(array($this->element . 'dao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } diff --git a/htdocs/categories/edit.php b/htdocs/categories/edit.php index 2b3ffc95c41..518889b85b3 100644 --- a/htdocs/categories/edit.php +++ b/htdocs/categories/edit.php @@ -178,7 +178,9 @@ print ''; // Parent category print ''.$langs->trans("In").''; +print img_picto('', 'category', 'class="pictofixedwidth"'); print $form->select_all_categories($type, $object->fk_parent, 'parent', 64, $object->id); +print ajax_combobox('parent'); print ''; $parameters = array(); diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 1e640f7afbe..a5b4f1d8ce9 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -123,16 +123,17 @@ class ActionComm extends CommonObject */ public $label; + /** + * @var string Agenda event label + * @deprecated Use $label + */ + public $libelle; + /** * @var integer Date creation record (datec) */ public $datec; - /** - * @var integer Date end record (datef) - */ - public $datef; - /** * @var integer Duration (duree) */ @@ -172,6 +173,21 @@ class ActionComm extends CommonObject */ public $datep; + /** + * @var integer Date action end (datef) + */ + public $datef; + + /** + * @var integer This is date start action (datep) but modified to not be outside calendar view. + */ + public $date_start_in_calendar; + + /** + * @var integer This is date end action (datef) but modified to not be outside calendar view. + */ + public $date_end_in_calendar; + /** * @var integer Date action end (datep2) */ @@ -188,6 +204,11 @@ class ActionComm extends CommonObject */ public $fulldayevent = 0; + /** + * @var int 1=??? + */ + public $ponctuel; + /** * @var integer Percentage */ @@ -219,8 +240,7 @@ class ActionComm extends CommonObject public $userownerid; /** - * @var int Id of user done (deprecated) - * @deprecated + * @var int Id of user that has done the event. Used only if AGENDA_ENABLE_DONEBY is set. */ public $userdoneid; @@ -239,20 +259,6 @@ class ActionComm extends CommonObject */ public $reminders = array(); - /** - * @var User Object user of owner - * @deprecated - * @see $userownerid - */ - public $usertodo; - - /** - * @var User Object user that did action - * @deprecated - * @see $userdoneid - */ - public $userdone; - /** * @var int thirdparty id linked to action */ @@ -831,18 +837,17 @@ class ActionComm extends CommonObject $this->usermodid = $obj->fk_user_mod; if (!is_object($this->author)) { - $this->author = new stdClass(); // To avoid warning + $this->author = new User($this->db); // To avoid warning } $this->author->id = $obj->fk_user_author; // deprecated $this->author->firstname = $obj->firstname; // deprecated $this->author->lastname = $obj->lastname; // deprecated if (!is_object($this->usermod)) { - $this->usermod = new stdClass(); // To avoid warning + $this->usermod = new User($this->db); // To avoid warning } $this->usermod->id = $obj->fk_user_mod; // deprecated $this->userownerid = $obj->fk_user_action; - $this->userdoneid = $obj->fk_user_done; $this->priority = $obj->priority; $this->fulldayevent = $obj->fulldayevent; $this->location = $obj->location; @@ -1134,18 +1139,18 @@ class ActionComm extends CommonObject $sql .= ", datep2 = ".(strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : 'null'); $sql .= ", durationp = ".(isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'".$this->db->escape($this->durationp)."'" : "null"); // deprecated $sql .= ", note = '".$this->db->escape($this->note_private)."'"; - $sql .= ", fk_project =".($this->fk_project > 0 ? $this->fk_project : "null"); - $sql .= ", fk_soc =".($socid > 0 ? $socid : "null"); - $sql .= ", fk_contact =".($contactid > 0 ? $contactid : "null"); + $sql .= ", fk_project =".($this->fk_project > 0 ? ((int) $this->fk_project) : "null"); + $sql .= ", fk_soc =".($socid > 0 ? ((int) $socid) : "null"); + $sql .= ", fk_contact =".($contactid > 0 ? ((int) $contactid) : "null"); $sql .= ", priority = '".$this->db->escape($this->priority)."'"; $sql .= ", fulldayevent = '".$this->db->escape($this->fulldayevent)."'"; $sql .= ", location = ".($this->location ? "'".$this->db->escape($this->location)."'" : "null"); $sql .= ", transparency = '".$this->db->escape($this->transparency)."'"; - $sql .= ", fk_user_mod = ".$user->id; - $sql .= ", fk_user_action = ".($userownerid > 0 ? "'".$this->db->escape($userownerid)."'" : "null"); - $sql .= ", fk_user_done = ".($userdoneid > 0 ? "'".$this->db->escape($userdoneid)."'" : "null"); + $sql .= ", fk_user_mod = ".((int) $user->id); + $sql .= ", fk_user_action = ".($userownerid > 0 ? ((int) $userownerid) : "null"); + $sql .= ", fk_user_done = ".($userdoneid > 0 ? ((int) $userdoneid) : "null"); if (!empty($this->fk_element)) { - $sql .= ", fk_element=".($this->fk_element ? $this->db->escape($this->fk_element) : "null"); + $sql .= ", fk_element=".($this->fk_element ? ((int) $this->fk_element) : "null"); } if (!empty($this->elementtype)) { $sql .= ", elementtype=".($this->elementtype ? "'".$this->db->escape($this->elementtype)."'" : "null"); @@ -1443,9 +1448,9 @@ class ActionComm extends CommonObject /** - * Return label of status + * Return the label of the status * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @param int $hidenastatus 1=Show nothing if status is "Not applicable" * @return string String with status */ @@ -1632,41 +1637,39 @@ class ActionComm extends CommonObject } if ($withpicto == 2) { - $libelle = $label; if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { - $libelle = $labeltype; + $label = $labeltype; } - $libelleshort = ''; + $labelshort = ''; } else { - $libelle = (empty($this->libelle) ? $label : $this->libelle.(($label && $label != $this->libelle) ? ' '.$label : '')); - if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && empty($libelle)) { - $libelle = $labeltype; + if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && empty($label)) { + $label = $labeltype; } if ($maxlength < 0) { - $libelleshort = $this->ref; + $labelshort = $this->ref; } else { - $libelleshort = dol_trunc($libelle, $maxlength); + $labelshort = dol_trunc($label, $maxlength); } } if ($withpicto) { if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { // Add code into () if ($labeltype) { - $libelle .= (preg_match('/'.preg_quote($labeltype, '/').'/', $libelle) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')'); + $label .= (preg_match('/'.preg_quote($labeltype, '/').'/', $label) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')'); } } } $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $langs->trans("ShowAction").': '.$libelle), ($overwritepicto ? $overwritepicto : 'action'), (($this->type_color && $overwritepicto) ? 'style="color: #'.$this->type_color.' !important;" ' : '').($notooltip ? 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"' : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $langs->trans("ShowAction").': '.$label), ($overwritepicto ? $overwritepicto : 'action'), (($this->type_color && $overwritepicto) ? 'style="color: #'.$this->type_color.' !important;" ' : '').($notooltip ? 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"' : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); } - $result .= $libelleshort; + $result .= $labelshort; $result .= $linkend; global $action; $hookmanager->initHooks(array('actiondao')); - $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook > 0) { $result = $hookmanager->resPrint; diff --git a/htdocs/comm/action/class/actioncommreminder.class.php b/htdocs/comm/action/class/actioncommreminder.class.php index aa693d2e41f..ff242430b0a 100644 --- a/htdocs/comm/action/class/actioncommreminder.class.php +++ b/htdocs/comm/action/class/actioncommreminder.class.php @@ -205,9 +205,9 @@ class ActionCommReminder extends CommonObject } /** - * Retourne le libelle du status d'un user (actif, inactif) + * Return label of the status of a reminder * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto * @return string Label of status */ public function getLibStatut($mode = 0) diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 81df122f1a9..e8060bc314d 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -847,7 +847,7 @@ if ($resql) { $event->fk_project = $obj->fk_project; - $event->thirdparty_id = $obj->fk_soc; + $event->socid = $obj->fk_soc; $event->contact_id = $obj->fk_contact; // Defined date_start_in_calendar and date_end_in_calendar property @@ -858,10 +858,6 @@ if ($resql) { } else { $event->date_end_in_calendar = $event->datep; } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - } // Check values if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) { @@ -973,7 +969,6 @@ if ($showbirthday) { $event->date_start_in_calendar = $db->jdate($event->datep); $event->date_end_in_calendar = $db->jdate($event->datef); - $event->ponctuel = 0; // Add an entry in eventarray for each day $daycursor = $event->datep; @@ -1316,12 +1311,6 @@ if (count($listofextcals)) { $event->date_end_in_calendar = $event->datep; } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - //print 'x'.$datestart.'-'.$dateend;exit; - } - // Add event into $eventarray if date range are ok. if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) { //print 'x'.$datestart.'-'.$dateend;exit; @@ -1996,7 +1985,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa if ($event->type_code != 'ICALEVENT') { $savlabel = $event->label ? $event->label : $event->libelle; $event->label = $titletoshow; - $event->libelle = $titletoshow; + $event->libelle = $titletoshow; // deprecatd // Note: List of users are inside $event->userassigned. Link may be clickable depending on permissions of user. $titletoshow = (($event->type_picto || $event->type_code) ? $event->getTypePicto() : ''); $titletoshow .= $event->getNomUrl(0, $maxnbofchar, 'cal_event cal_event_title', '', 0, 0); @@ -2028,7 +2017,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa print '
    ('.dol_trunc($event->icalname, $maxnbofchar).')'; } - $thirdparty_id = ($event->thirdparty_id > 0 ? $event->thirdparty_id : ((is_object($event->societe) && $event->societe->id > 0) ? $event->societe->id : 0)); + $thirdparty_id = ($event->socid > 0 ? $event->socid : ((is_object($event->societe) && $event->societe->id > 0) ? $event->societe->id : 0)); $contact_id = ($event->contact_id > 0 ? $event->contact_id : ((is_object($event->contact) && $event->contact->id > 0) ? $event->contact->id : 0)); // If action related to company / contact diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index 43d55424cd3..eee8baa2b20 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -683,10 +683,6 @@ if ($resql) { $event->date_end_in_calendar = $datep; } } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - } // Check values if ($event->date_end_in_calendar < $firstdaytoshow || diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index f74974a26d9..957ccd6e361 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -711,10 +711,6 @@ if ($resql) { $event->date_end_in_calendar = $datep; } } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - } // Check values if ($event->date_end_in_calendar < $firstdaytoshow || diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 90d3ed128f7..eabcb1a55bf 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -214,7 +214,7 @@ if (empty($reshook)) { // assujetissement a la TVA if ($action == 'setassujtva' && $user->rights->societe->creer) { $object->fetch($id); - $object->tva_assuj = $_POST['assujtva_value']; + $object->tva_assuj = GETPOST('assujtva_value'); $result = $object->update($object->id); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); diff --git a/htdocs/comm/contact.php b/htdocs/comm/contact.php index 57a88bef157..62f57c008ba 100644 --- a/htdocs/comm/contact.php +++ b/htdocs/comm/contact.php @@ -157,10 +157,10 @@ if ($resql) { print ''; print ''.img_object($langs->trans("ShowContact"), "contact"); print ' '.$obj->name.''; - print "$obj->firstname"; + print ''.dol_escape_htmltag($obj->firstname).''; print ''.img_object($langs->trans("ShowCompany"), "company").' '; - print "rowid."\">$obj->name\n"; + print ''.$obj->name."\n"; print ''.dol_print_phone($obj->email, $obj->cidp, $obj->rowid, 'AC_EMAIL').''; diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 79faf4b2cd2..f82df06313b 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -745,7 +745,7 @@ if ($action == 'create') { print ''; print ''; print ''; print '
    '.$langs->trans("MailTopic").'
    '.$langs->trans("BackgroundColorByDefault").''; - print $htmlother->selectColor($_POST['bgcolor'], 'bgcolor', '', 0); + print $htmlother->selectColor(GETPOST('bgcolor'), 'bgcolor', '', 0); print '
    '; diff --git a/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php b/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php index cfdca4a1fc2..f4295fa6583 100644 --- a/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php +++ b/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php @@ -230,7 +230,7 @@ class FormAdvTargetEmailing extends Form $InfoFieldList = explode(":", $param_list [0]); // 0 1 : tableName - // 1 2 : label field name Nom du champ contenant le libelle + // 1 2 : label field name Name of field that contains the label // 2 3 : key fields name (if differ of rowid) // 3 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value @@ -304,7 +304,7 @@ class FormAdvTargetEmailing extends Form if ($num) { while ($i < $num) { $obj = $this->db->fetch_object($resql); - // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut + // If a translation exists, we use it, else we use the default label $label = ($langs->trans("Civility".$obj->code) != "Civility".$obj->code ? $langs->trans("Civility".$obj->code) : ($obj->civilite != '-' ? $obj->civilite : '')); $options_array[$obj->code] = $label; diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php index cb900f7ac7b..588faa392e3 100644 --- a/htdocs/comm/mailing/class/mailing.class.php +++ b/htdocs/comm/mailing/class/mailing.class.php @@ -740,7 +740,7 @@ class Mailing extends CommonObject global $action; $hookmanager->initHooks(array('emailingdao')); - $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook > 0) { $result = $hookmanager->resPrint; @@ -754,7 +754,7 @@ class Mailing extends CommonObject /** * Return label of status of emailing (draft, validated, ...) * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @return string Label */ public function getLibStatut($mode = 0) @@ -764,10 +764,10 @@ class Mailing extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Renvoi le libelle d'un statut donne + * Return the label of a given status * * @param int $status Id status - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @return string Label */ public function LibStatut($status, $mode = 0) @@ -792,11 +792,11 @@ class Mailing extends CommonObject /** - * Renvoi le libelle d'un statut donne + * Return the label of a given status of a recipient * TODO Add class mailin_target.class.php * * @param int $status Id status - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @param string $desc Desc error * @return string Label */ diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 9f902c51e29..61ecb966359 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -302,7 +302,7 @@ if (empty($reshook)) { } } } elseif ($action == 'setdate' && $usercancreate) { - $datep = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']); + $datep = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); if (empty($datep)) { $error++; @@ -316,7 +316,7 @@ if (empty($reshook)) { } } } elseif ($action == 'setecheance' && $usercancreate) { - $result = $object->set_echeance($user, dol_mktime(12, 0, 0, $_POST['echmonth'], $_POST['echday'], $_POST['echyear'])); + $result = $object->set_echeance($user, dol_mktime(12, 0, 0, GETPOST('echmonth', 'int'), GETPOST('echday', 'int'), GETPOST('echyear', 'int'))); if ($result >= 0) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; @@ -339,7 +339,7 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'setdate_livraison' && $usercancreate) { - $result = $object->setDeliveryDate($user, dol_mktime(12, 0, 0, $_POST['date_livraisonmonth'], $_POST['date_livraisonday'], $_POST['date_livraisonyear'])); + $result = $object->setDeliveryDate($user, dol_mktime(12, 0, 0, GETPOST('date_livraisonmonth', 'int'), GETPOST('date_livraisonday', 'int'), GETPOST('date_livraisonyear', 'int'))); if ($result < 0) { dol_print_error($db, $object->error); } diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index 41ed388e044..f03d66bae54 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -1,7 +1,9 @@ - * Copyright (C) 2016 Laurent Destailleur - * Copyright (C) 2020 Thibault FOUCART +/* Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2016 Laurent Destailleur + * Copyright (C) 2020 Thibault FOUCART + * Copyright (C) 2022 ATM Consulting + * Copyright (C) 2022 OpenDSI * * 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 @@ -274,14 +276,17 @@ class Proposals extends DolibarrApi /** * Get lines of a commercial proposal * - * @param int $id Id of commercial proposal + * @param int $id Id of commercial proposal + * @param string $sqlfilters Other criteria to filter answers separated by a comma. d is the alias for proposal lines table, p is the alias for product table. "Syntax example "(p.ref:like:'SO-%') and (d.date_start:<:'20220101')" * * @url GET {id}/lines * * @return int */ - public function getLines($id) + public function getLines($id, $sqlfilters = '') { + $filters = ""; + if (!DolibarrApiAccess::$user->rights->propal->lire) { throw new RestException(401); } @@ -294,7 +299,16 @@ class Proposals extends DolibarrApi if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $this->propal->getLinesArray(); + + if (!empty($sqlfilters)) { + if (!DolibarrApi::_checkFilters($sqlfilters)) { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $filters = " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $this->propal->getLinesArray($filters); $result = array(); foreach ($this->propal->lines as $line) { array_push($result, $this->_cleanObjectDatas($line)); @@ -308,7 +322,7 @@ class Proposals extends DolibarrApi * @param int $id Id of commercial proposal to update * @param array $request_data Commercial proposal line data * - * @url POST {id}/lines + * @url POST {id}/line * * @return int */ @@ -368,6 +382,84 @@ class Proposals extends DolibarrApi } } + /** + * Add lines to given commercial proposal + * + * @param int $id Id of commercial proposal to update + * @param array $request_data Commercial proposal line data + * + * @url POST {id}/lines + * + * @return int + */ + public function postLines($id, $request_data = null) + { + if (!DolibarrApiAccess::$user->rights->propal->creer) { + throw new RestException(401); + } + + $result = $this->propal->fetch($id); + if (!$result) { + throw new RestException(404, 'Commercial Proposal not found'); + } + + if (!DolibarrApi::_checkAccessToResource('propal', $this->propal->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $errors = []; + $this->db->begin(); + + foreach ($request_data as $TData) { + if (empty($TData[0])) $TData = array($TData); + + foreach ($TData as $lineData) { + $line = (object) $lineData; + + $updateRes = $this->propal->addline( + $line->desc, + $line->subprice, + $line->qty, + $line->tva_tx, + $line->localtax1_tx, + $line->localtax2_tx, + $line->fk_product, + $line->remise_percent, + 'HT', + 0, + $line->info_bits, + $line->product_type, + $line->rang, + $line->special_code, + $line->fk_parent_line, + $line->fk_fournprice, + $line->pa_ht, + $line->label, + $line->date_start, + $line->date_end, + $line->array_options, + $line->fk_unit, + $line->origin, + $line->origin_id, + $line->multicurrency_subprice, + $line->fk_remise_except + ); + + if ($updateRes < 0) { + $errors['lineLabel'] = $line->label; + $errors['msg'] = $this->propal->errors; + } + } + } + if (empty($errors)) { + $this->db->commit(); + return count($request_data); + } else { + $this->db->rollback(); + throw new RestException(400, implode(", ", $errors)); + } + } + /** * Update a line of given commercial proposal * diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index fd3bbfe7171..029706dfb5d 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1,20 +1,22 @@ - * Copyright (C) 2004 Eric Seigne - * Copyright (C) 2004-2011 Laurent Destailleur - * Copyright (C) 2005 Marc Barilley - * Copyright (C) 2005-2013 Regis Houssin - * Copyright (C) 2006 Andre Cianfarani - * Copyright (C) 2008 Raphael Bertrand - * Copyright (C) 2010-2020 Juanjo Menent - * Copyright (C) 2010-2017 Philippe Grand - * Copyright (C) 2012-2014 Christophe Battarel - * Copyright (C) 2012 Cedric Salvador - * Copyright (C) 2013 Florian Henry - * Copyright (C) 2014-2015 Marcos GarcĂ­a - * Copyright (C) 2018 Nicolas ZABOURI - * Copyright (C) 2018-2021 FrĂ©dĂ©ric France - * Copyright (C) 2018 Ferran Marcet +/* Copyright (C) 2002-2004 Rodolphe Quiedeville + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2005 Marc Barilley + * Copyright (C) 2005-2013 Regis Houssin + * Copyright (C) 2006 Andre Cianfarani + * Copyright (C) 2008 Raphael Bertrand + * Copyright (C) 2010-2020 Juanjo Menent + * Copyright (C) 2010-2017 Philippe Grand + * Copyright (C) 2012-2014 Christophe Battarel + * Copyright (C) 2012 Cedric Salvador + * Copyright (C) 2013 Florian Henry + * Copyright (C) 2014-2015 Marcos GarcĂ­a + * Copyright (C) 2018 Nicolas ZABOURI + * Copyright (C) 2018-2021 FrĂ©dĂ©ric France + * Copyright (C) 2018 Ferran Marcet + * Copyright (C) 2022 ATM Consulting + * Copyright (C) 2022 OpenDSI * * 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 @@ -1246,7 +1248,7 @@ class Propal extends CommonObject break; } // Defined the new fk_parent_line - if ($result > 0 && $line->product_type == 9) { + if ($result > 0) { $fk_parent_line = $result; } } @@ -1714,12 +1716,13 @@ class Propal extends CommonObject /** * Load array lines * - * @param int $only_product Return only physical products - * @param int $loadalsotranslation Return translation for products + * @param int $only_product Return only physical products + * @param int $loadalsotranslation Return translation for products + * @param string $filters Filter on other fields * - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, >0 if OK */ - public function fetch_lines($only_product = 0, $loadalsotranslation = 0) + public function fetch_lines($only_product = 0, $loadalsotranslation = 0, $filters = '') { global $langs, $conf; // phpcs:enable @@ -1738,6 +1741,9 @@ class Propal extends CommonObject if ($only_product) { $sql .= ' AND p.fk_product_type = 0'; } + if ($filters) { + $sql .= $filters; + } $sql .= ' ORDER by d.rang'; dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG); @@ -3563,7 +3569,7 @@ class Propal extends CommonObject */ public function getNomUrl($withpicto = 0, $option = '', $get_params = '', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1) { - global $langs, $conf, $user; + global $langs, $conf, $user, $hookmanager; if (!empty($conf->dol_no_mouse_hover)) { $notooltip = 1; // Force disable tooltips @@ -3684,17 +3690,27 @@ class Propal extends CommonObject } } + global $action; + $hookmanager->initHooks(array($this->element . 'dao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } /** * Retrieve an array of proposal lines + * @param string $filters Filter on other fields * * @return int >0 if OK, <0 if KO */ - public function getLinesArray() + public function getLinesArray($filters = '') { - return $this->fetch_lines(); + return $this->fetch_lines(0, 0, $filters); } /** diff --git a/htdocs/comm/propal/contact.php b/htdocs/comm/propal/contact.php index fedf6a6233d..989dcfe7098 100644 --- a/htdocs/comm/propal/contact.php +++ b/htdocs/comm/propal/contact.php @@ -107,12 +107,6 @@ if ($action == 'addcontact' && $user->rights->propale->creer) { dol_print_error($db); } } -/* -elseif ($action == 'setaddress' && $user->rights->propale->creer) -{ - $result=$object->setDeliveryAddress($_POST['fk_address']); - if ($result < 0) dol_print_error($db,$object->error); -}*/ /* diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index b6977940411..3e790bf6448 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -42,6 +42,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formpropal.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +if (!empty($conf->margin->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmargin.class.php'; +} require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; @@ -223,6 +226,10 @@ $arrayfields = array( 'p.multicurrency_total_invoiced'=>array('label'=>'MulticurrencyAmountInvoicedTTC', 'checked'=>0, 'enabled'=>!empty($conf->multicurrency->enabled) && !empty($conf->global->PROPOSAL_SHOW_INVOICED_AMOUNT)), 'u.login'=>array('label'=>"Author", 'checked'=>1, 'position'=>10), 'sale_representative'=>array('label'=>"SaleRepresentativesOfThirdParty", 'checked'=>-1), + 'total_pa' => array('label' => ($conf->global->MARGIN_TYPE == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => 0, 'position' => 300, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous ? 0 : 1)), + 'total_margin' => array('label' => 'Margin', 'checked' => 0, 'position' => 301, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous ? 0 : 1)), + 'total_margin_rate' => array('label' => 'MarginRate', 'checked' => 0, 'position' => 302, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous || empty($conf->global->DISPLAY_MARGIN_RATES) ? 0 : 1)), + 'total_mark_rate' => array('label' => 'MarkRate', 'checked' => 0, 'position' => 303, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous || empty($conf->global->DISPLAY_MARK_RATES) ? 0 : 1)), 'p.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500), 'p.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500), 'p.date_cloture'=>array('label'=>"DateClosing", 'checked'=>0, 'position'=>500), @@ -486,6 +493,10 @@ $form = new Form($db); $formother = new FormOther($db); $formfile = new FormFile($db); $formpropal = new FormPropal($db); +$formmargin = null; +if (!empty($conf->margin->enabled)) { + $formmargin = new FormMargin($db); +} $companystatic = new Societe($db); $projectstatic = new Project($db); $formcompany = new FormCompany($db); @@ -1244,6 +1255,22 @@ if ($resql) { if (!empty($arrayfields['sale_representative']['checked'])) { print ''; } + if (!empty($arrayfields['total_pa']['checked'])) { + print ''; + print ''; + } + if (!empty($arrayfields['total_margin']['checked'])) { + print ''; + print ''; + } + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''; + print ''; + } + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''; + print ''; + } // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -1392,6 +1419,18 @@ if ($resql) { if (!empty($arrayfields['sale_representative']['checked'])) { print_liste_field_titre($arrayfields['sale_representative']['label'], $_SERVER["PHP_SELF"], "", "", "$param", '', $sortfield, $sortorder); } + if (!empty($arrayfields['total_pa']['checked'])) { + print_liste_field_titre($arrayfields['total_pa']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_margin']['checked'])) { + print_liste_field_titre($arrayfields['total_margin']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print_liste_field_titre($arrayfields['total_margin_rate']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print_liste_field_titre($arrayfields['total_mark_rate']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } $totalarray = array( 'nbfield' => 0, 'val' => array( @@ -1437,7 +1476,21 @@ if ($resql) { $i = 0; $typenArray = null; - while ($i < min($num, $limit)) { + $with_margin_info = false; + if (!empty($conf->margin->enabled) && ( + !empty($arrayfields['total_pa']['checked']) + || !empty($arrayfields['total_margin']['checked']) + || !empty($arrayfields['total_margin_rate']['checked']) + || !empty($arrayfields['total_mark_rate']['checked']) + ) + ) { + $with_margin_info = true; + } + $total_ht = 0; + $total_margin = 0; + + $last_num = min($num, $limit); + while ($i < $last_num) { $obj = $db->fetch_object($resql); $objectstatic->id = $obj->rowid; @@ -1487,6 +1540,14 @@ if ($resql) { } } + $marginInfo = array(); + if ($with_margin_info === true) { + $objectstatic->fetch_lines(); + $marginInfo = $formmargin->getMarginInfosArray($objectstatic); + $total_ht += $obj->total_ht; + $total_margin += $marginInfo['total_margin']; + } + print ''; if (!empty($arrayfields['p.ref']['checked'])) { @@ -1887,6 +1948,49 @@ if ($resql) { } } + // Total buying or cost price + if (!empty($arrayfields['total_pa']['checked'])) { + print ''.price($marginInfo['pa_total']).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total margin + if (!empty($arrayfields['total_margin']['checked'])) { + print ''.price($marginInfo['total_margin']).''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_margin'; + } + $totalarray['val']['total_margin'] = $total_margin; + } + // Total margin rate + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''.(($marginInfo['total_margin_rate'] == '') ? '' : price($marginInfo['total_margin_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total mark rate + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''.(($marginInfo['total_mark_rate'] == '') ? '' : price($marginInfo['total_mark_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; + } + if ($i >= $last_num - 1) { + if (!empty($total_ht)) { + $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); + } else { + $totalarray['val']['total_mark_rate'] = ''; + } + } + } + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook diff --git a/htdocs/comm/prospect/index.php b/htdocs/comm/prospect/index.php index 1e1caa796b5..0bcf2662a44 100644 --- a/htdocs/comm/prospect/index.php +++ b/htdocs/comm/prospect/index.php @@ -77,7 +77,7 @@ if (!empty($conf->propal->enabled)) { * */ -$sql = "SELECT count(*) as cc, st.libelle, st.picto, st.id"; +$sql = "SELECT count(*) as cc, st.libelle as stcomm, st.picto, st.id"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= ", ".MAIN_DB_PREFIX."c_stcomm as st "; if (empty($user->rights->societe->client->voir) && !$socid) { diff --git a/htdocs/comm/remx.php b/htdocs/comm/remx.php index 4404f9758a6..d44093dbab5 100644 --- a/htdocs/comm/remx.php +++ b/htdocs/comm/remx.php @@ -160,7 +160,7 @@ if ($action == 'setremise' && $user->rights->societe->creer) { $amount_ht = price2num(GETPOST('amount_ht', 'alpha')); $desc = GETPOST('desc', 'alpha'); $tva_tx = GETPOST('tva_tx', 'alpha'); - $discount_type = !empty($_POST['discount_type']) ?GETPOST('discount_type', 'alpha') : 0; + $discount_type = GETPOSTISSET('discount_type') ? GETPOST('discount_type', 'alpha') : 0; if ($amount_ht > 0) { $error = 0; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 990ec43c8ae..1470ee210e8 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -421,7 +421,7 @@ if (empty($reshook)) { } // Defined the new fk_parent_line - if ($result > 0 && $lines[$i]->product_type == 9) { + if ($result > 0) { $fk_parent_line = $result; } } @@ -533,7 +533,6 @@ if (empty($reshook)) { } } } elseif ($action == 'setdate' && $usercancreate) { - // print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year']; $date = dol_mktime(0, 0, 0, GETPOST('order_month', 'int'), GETPOST('order_day', 'int'), GETPOST('order_year', 'int')); $result = $object->set_date($user, $date); @@ -541,7 +540,6 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'setdate_livraison' && $usercancreate) { - // print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year']; $date_delivery = dol_mktime(GETPOST('liv_hour', 'int'), GETPOST('liv_min', 'int'), 0, GETPOST('liv_month', 'int'), GETPOST('liv_day', 'int'), GETPOST('liv_year', 'int')); $object->fetch($id); diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 48b7e499dbb..a9ff2e09cf3 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -11,7 +11,7 @@ * Copyright (C) 2014-2015 Marcos GarcĂ­a * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2016-2018 Ferran Marcet - * Copyright (C) 2021 FrĂ©dĂ©ric France + * Copyright (C) 2021-2022 FrĂ©dĂ©ric France * * 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 @@ -495,7 +495,8 @@ class Commande extends CommonOrder $sql .= " SET ref = '".$this->db->escape($num)."',"; $sql .= " fk_statut = ".self::STATUS_VALIDATED.","; $sql .= " date_valid='".$this->db->idate($now)."',"; - $sql .= " fk_user_valid = ".((int) $user->id); + $sql .= " fk_user_valid = ".((int) $user->id).","; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::valid", LOG_DEBUG); @@ -625,7 +626,8 @@ class Commande extends CommonOrder $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."commande"; - $sql .= " SET fk_statut = ".self::STATUS_DRAFT; + $sql .= " SET fk_statut = ".self::STATUS_DRAFT.","; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); if ($this->db->query($sql)) { @@ -699,7 +701,8 @@ class Commande extends CommonOrder $this->db->begin(); $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande'; - $sql .= ' SET fk_statut='.self::STATUS_VALIDATED.', facture=0'; + $sql .= ' SET fk_statut='.self::STATUS_VALIDATED.', facture=0,'; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::set_reopen", LOG_DEBUG); @@ -760,7 +763,8 @@ class Commande extends CommonOrder $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql .= ' SET fk_statut = '.self::STATUS_CLOSED.','; $sql .= ' fk_user_cloture = '.((int) $user->id).','; - $sql .= " date_cloture = '".$this->db->idate($now)."'"; + $sql .= " date_cloture = '".$this->db->idate($now)."',"; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > '.self::STATUS_DRAFT; if ($this->db->query($sql)) { @@ -808,7 +812,8 @@ class Commande extends CommonOrder $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."commande"; - $sql .= " SET fk_statut = ".self::STATUS_CANCELED; + $sql .= " SET fk_statut = ".self::STATUS_CANCELED.","; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); $sql .= " AND fk_statut = ".self::STATUS_VALIDATED; @@ -1051,7 +1056,7 @@ class Commande extends CommonOrder return -1; } // Defined the new fk_parent_line - if ($result > 0 && $line->product_type == 9) { + if ($result > 0) { $fk_parent_line = $result; } } @@ -1784,7 +1789,7 @@ class Commande extends CommonOrder return -1; } - $sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_statut'; + $sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_user_modif, c.fk_statut'; $sql .= ', c.amount_ht, c.total_ht, c.total_ttc, c.total_tva, c.localtax1 as total_localtax1, c.localtax2 as total_localtax2, c.fk_cond_reglement, c.fk_mode_reglement, c.fk_availability, c.fk_input_reason'; $sql .= ', c.fk_account'; $sql .= ', c.date_commande, c.date_valid, c.tms'; @@ -1849,6 +1854,7 @@ class Commande extends CommonOrder $this->user_author_id = $obj->fk_user_author; $this->user_valid = $obj->fk_user_valid; + $this->user_modification = $obj->fk_user_modif; $this->total_ht = $obj->total_ht; $this->total_tva = $obj->total_tva; $this->total_localtax1 = $obj->total_localtax1; @@ -3657,7 +3663,7 @@ class Commande extends CommonOrder */ public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = 0) { - global $conf, $langs, $user; + global $conf, $langs, $user, $hookmanager; if (!empty($conf->dol_no_mouse_hover)) { $notooltip = 1; // Force disable tooltips @@ -3758,6 +3764,15 @@ class Commande extends CommonOrder } } + global $action; + $hookmanager->initHooks(array($this->element . 'dao')); + $parameters = array('id'=>$this->id, 'getnomurl' => &$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } return $result; } diff --git a/htdocs/commande/contact.php b/htdocs/commande/contact.php index a4d857a47fd..b89623fc3a0 100644 --- a/htdocs/commande/contact.php +++ b/htdocs/commande/contact.php @@ -91,13 +91,6 @@ if ($action == 'addcontact' && $user->rights->commande->creer) { setEventMessages($object->error, $object->errors, 'errors'); } } -/* -elseif ($action == 'setaddress' && $user->rights->commande->creer) -{ - $object->fetch($id); - $result=$object->setDeliveryAddress($_POST['fk_address']); - if ($result < 0) dol_print_error($db,$object->error); -}*/ /* diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 48a3c294b26..27391d7a901 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -40,6 +40,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +if (!empty($conf->margin->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmargin.class.php'; +} require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; @@ -187,6 +190,10 @@ $arrayfields = array( 'c.multicurrency_total_ttc'=>array('label'=>'MulticurrencyAmountTTC', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>110), 'u.login'=>array('label'=>"Author", 'checked'=>1, 'position'=>115), 'sale_representative'=>array('label'=>"SaleRepresentativesOfThirdParty", 'checked'=>0, 'position'=>116), + 'total_pa' => array('label' => ($conf->global->MARGIN_TYPE == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => 0, 'position' => 300, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous ? 0 : 1)), + 'total_margin' => array('label' => 'Margin', 'checked' => 0, 'position' => 301, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous ? 0 : 1)), + 'total_margin_rate' => array('label' => 'MarginRate', 'checked' => 0, 'position' => 302, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous || empty($conf->global->DISPLAY_MARGIN_RATES) ? 0 : 1)), + 'total_mark_rate' => array('label' => 'MarkRate', 'checked' => 0, 'position' => 303, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous || empty($conf->global->DISPLAY_MARK_RATES) ? 0 : 1)), 'c.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>120), 'c.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>125), 'c.date_cloture'=>array('label'=>"DateClosing", 'checked'=>0, 'position'=>130), @@ -407,6 +414,10 @@ $now = dol_now(); $form = new Form($db); $formother = new FormOther($db); $formfile = new FormFile($db); +$formmargin = null; +if (!empty($conf->margin->enabled)) { + $formmargin = new FormMargin($db); +} $companystatic = new Societe($db); $formcompany = new FormCompany($db); $projectstatic = new Project($db); @@ -1193,6 +1204,22 @@ if ($resql) { if (!empty($arrayfields['sale_representative']['checked'])) { print ''; } + if (!empty($arrayfields['total_pa']['checked'])) { + print ''; + print ''; + } + if (!empty($arrayfields['total_margin']['checked'])) { + print ''; + print ''; + } + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''; + print ''; + } + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''; + print ''; + } // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; // Fields from hook @@ -1354,6 +1381,18 @@ if ($resql) { if (!empty($arrayfields['sale_representative']['checked'])) { print_liste_field_titre($arrayfields['sale_representative']['label'], $_SERVER["PHP_SELF"], "", "", "$param", '', $sortfield, $sortorder); } + if (!empty($arrayfields['total_pa']['checked'])) { + print_liste_field_titre($arrayfields['total_pa']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_margin']['checked'])) { + print_liste_field_titre($arrayfields['total_margin']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print_liste_field_titre($arrayfields['total_margin_rate']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print_liste_field_titre($arrayfields['total_mark_rate']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } $totalarray = array( 'nbfield' => 0, @@ -1413,7 +1452,22 @@ if ($resql) { $generic_product = new Product($db); $userstatic = new User($db); $i = 0; - while ($i < min($num, $limit)) { + + $with_margin_info = false; + if (!empty($conf->margin->enabled) && ( + !empty($arrayfields['total_pa']['checked']) + || !empty($arrayfields['total_margin']['checked']) + || !empty($arrayfields['total_margin_rate']['checked']) + || !empty($arrayfields['total_mark_rate']['checked']) + ) + ) { + $with_margin_info = true; + } + $total_ht = 0; + $total_margin = 0; + + $last_num = min($num, $limit); + while ($i < $last_num) { $obj = $db->fetch_object($resql); $notshippable = 0; @@ -1455,6 +1509,14 @@ if ($resql) { $projectstatic->ref = $obj->project_ref; $projectstatic->title = $obj->project_label; + $marginInfo = array(); + if ($with_margin_info === true) { + $generic_commande->fetch_lines(); + $marginInfo = $formmargin->getMarginInfosArray($generic_commande); + $total_ht += $obj->total_ht; + $total_margin += $marginInfo['total_margin']; + } + print ''; // Ref @@ -1462,11 +1524,6 @@ if ($resql) { print ''; print $generic_commande->getNomUrl(1, ($search_status != 2 ? 0 : $obj->fk_statut), 0, 0, 0, 1, 1); - // Warning late icon and note - if ($generic_commande->hasDelay()) { - print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning"); - } - $filename = dol_sanitizeFileName($obj->ref); $filedir = $conf->commande->multidir_output[$conf->entity].'/'.dol_sanitizeFileName($obj->ref); $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; @@ -1590,6 +1647,10 @@ if ($resql) { if (!empty($arrayfields['c.date_commande']['checked'])) { print ''; print dol_print_date($db->jdate($obj->date_commande), 'day'); + // Warning late icon and note + if ($generic_commande->hasDelay()) { + print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning"); + } print ''; if (!$i) { $totalarray['nbfield']++; @@ -1792,6 +1853,49 @@ if ($resql) { } } + // Total buying or cost price + if (!empty($arrayfields['total_pa']['checked'])) { + print ''.price($marginInfo['pa_total']).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total margin + if (!empty($arrayfields['total_margin']['checked'])) { + print ''.price($marginInfo['total_margin']).''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_margin'; + } + $totalarray['val']['total_margin'] += $marginInfo['total_margin']; + } + // Total margin rate + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''.(($marginInfo['total_margin_rate'] == '') ? '' : price($marginInfo['total_margin_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total mark rate + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''.(($marginInfo['total_mark_rate'] == '') ? '' : price($marginInfo['total_mark_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; + } + if ($i >= $last_num - 1) { + if (!empty($total_ht)) { + $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); + } else { + $totalarray['val']['total_mark_rate'] = ''; + } + } + } + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook diff --git a/htdocs/compta/ajaxpayment.php b/htdocs/compta/ajaxpayment.php index d22e1a0182a..0332a925f9d 100644 --- a/htdocs/compta/ajaxpayment.php +++ b/htdocs/compta/ajaxpayment.php @@ -47,28 +47,32 @@ $langs->load('compta'); //init var $invoice_type = GETPOST('invoice_type', 'int'); -$amountPayment = $_POST['amountPayment']; -$amounts = $_POST['amounts']; // from text inputs : invoice amount payment (check required) -$remains = $_POST['remains']; // from dolibarr's object (no need to check) -$currentInvId = $_POST['imgClicked']; // from DOM elements : imgId (equals invoice id) +$amountPayment = GETPOST('amountPayment'); +$amounts = GETPOST('amounts'); // from text inputs : invoice amount payment (check required) +$remains = GETPOST('remains'); // from dolibarr's object (no need to check) +$currentInvId = GETPOST('imgClicked'); // from DOM elements : imgId (equals invoice id) // Getting the posted keys=>values, sanitize the ones who are from text inputs $amountPayment = $amountPayment != '' ? (is_numeric(price2num($amountPayment)) ? price2num($amountPayment) : '') : ''; // keep void if not a valid entry // Clean checkamounts -foreach ($amounts as $key => $value) { - $value = price2num($value); - $amounts[$key] = $value; - if (empty($value)) { - unset($amounts[$key]); +if (is_array($amounts)) { + foreach ($amounts as $key => $value) { + $value = price2num($value); + $amounts[$key] = $value; + if (empty($value)) { + unset($amounts[$key]); + } } } // Clean remains -foreach ($remains as $key => $value) { - $value = price2num($value); - $remains[$key] = (($invoice_type) == 2 ?-1 : 1) * $value; - if (empty($value)) { - unset($remains[$key]); +if (is_array($remains)) { + foreach ($remains as $key => $value) { + $value = price2num($value); + $remains[$key] = (($invoice_type) == 2 ?-1 : 1) * $value; + if (empty($value)) { + unset($remains[$key]); + } } } diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index 524d8c79d4a..e991831a6dd 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -1339,14 +1339,15 @@ if ($resql) { $labeltoshow = $langs->trans($reg[1]); } else { if ($objp->label == '(payment_salary)') { - $labeltoshow = dol_trunc($langs->trans("SalaryPayment", 40)); + $labeltoshow = $langs->trans("SalaryPayment"); } else { $labeltoshow = dol_escape_htmltag($objp->label); $titletoshow = $objp->label; } } - print ''; - print $labeltoshow; // Already escaped + + + print ''; // Add info about links after description $cachebankaccount = array(); @@ -1355,70 +1356,70 @@ if ($resql) { if ($links[$key]['type'] == 'withdraw') { $banktransferstatic->id = $links[$key]['url_id']; $banktransferstatic->ref = $links[$key]['label']; - print ' '.$banktransferstatic->getNomUrl(0); + print $banktransferstatic->getNomUrl(0).' '; } elseif ($links[$key]['type'] == 'payment') { $paymentstatic->id = $links[$key]['url_id']; $paymentstatic->ref = $links[$key]['url_id']; // FIXME This is id, not ref of payment $paymentstatic->date = $db->jdate($objp->do); - print ' '.$paymentstatic->getNomUrl(2); + print $paymentstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_supplier') { $paymentsupplierstatic->id = $links[$key]['url_id']; $paymentsupplierstatic->ref = $links[$key]['url_id']; // FIXME This is id, not ref of payment - print ' '.$paymentsupplierstatic->getNomUrl(2); + print $paymentsupplierstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_sc') { $paymentscstatic->id = $links[$key]['url_id']; $paymentscstatic->ref = $links[$key]['url_id']; $paymentscstatic->label = $links[$key]['label']; - print ' '.$paymentscstatic->getNomUrl(2); + print $paymentscstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_vat') { $paymentvatstatic->id = $links[$key]['url_id']; $paymentvatstatic->ref = $links[$key]['url_id']; - print ' '.$paymentvatstatic->getNomUrl(2); + print $paymentvatstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_salary') { $paymentsalstatic->id = $links[$key]['url_id']; $paymentsalstatic->ref = $links[$key]['url_id']; $paymentsalstatic->label = $links[$key]['label']; - print ' '.$paymentsalstatic->getNomUrl(2); + print $paymentsalstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_loan') { print ''; print ' '.img_object($langs->trans('ShowPayment'), 'payment').' '; - print ''; + print ' '; } elseif ($links[$key]['type'] == 'payment_donation') { $paymentdonationstatic->id = $links[$key]['url_id']; $paymentdonationstatic->ref = $links[$key]['url_id']; - print ' '.$paymentdonationstatic->getNomUrl(2); + print $paymentdonationstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_expensereport') { $paymentexpensereportstatic->id = $links[$key]['url_id']; $paymentexpensereportstatic->ref = $links[$key]['url_id']; - print ' '.$paymentexpensereportstatic->getNomUrl(2); + print $paymentexpensereportstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_various') { $paymentvariousstatic->id = $links[$key]['url_id']; $paymentvariousstatic->ref = $links[$key]['url_id']; - print ' '.$paymentvariousstatic->getNomUrl(2); + print $paymentvariousstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'banktransfert') { // Do not show link to transfer since there is no transfer card (avoid confusion). Can already be accessed from transaction detail. if ($objp->amount > 0) { $banklinestatic->fetch($links[$key]['url_id']); $bankstatic->id = $banklinestatic->fk_account; $bankstatic->label = $banklinestatic->bank_account_ref; - print ' ('.$langs->trans("TransferFrom").' '; + print $langs->trans("TransferFrom").' '; print $bankstatic->getNomUrl(1, 'transactions'); print ' '.$langs->trans("toward").' '; $bankstatic->id = $objp->bankid; $bankstatic->label = $objp->bankref; print $bankstatic->getNomUrl(1, ''); - print ')'; + print ' - '; } else { $bankstatic->id = $objp->bankid; $bankstatic->label = $objp->bankref; - print ' ('.$langs->trans("TransferFrom").' '; + print $langs->trans("TransferFrom").' '; print $bankstatic->getNomUrl(1, ''); print ' '.$langs->trans("toward").' '; $banklinestatic->fetch($links[$key]['url_id']); $bankstatic->id = $banklinestatic->fk_account; $bankstatic->label = $banklinestatic->bank_account_ref; print $bankstatic->getNomUrl(1, 'transactions'); - print ')'; + print ' - '; } //var_dump($links); } elseif ($links[$key]['type'] == 'company') { @@ -1430,22 +1431,22 @@ if ($resql) { // Information is already shown using the payment_salary link. No need of this link. } else { // Show link with label $links[$key]['label'] - if (!empty($objp->label) && !empty($links[$key]['label'])) { - print ' - '; - } print ''; if (preg_match('/^\((.*)\)$/i', $links[$key]['label'], $reg)) { // Label generique car entre parentheses. On l'affiche en le traduisant if ($reg[1] == 'paiement') { $reg[1] = 'Payment'; } - print ' '.$langs->trans($reg[1]); + print $langs->trans($reg[1]); } else { - print ' '.$links[$key]['label']; + print $links[$key]['label']; } - print ''; + print ''.($labeltoshow ? ' - ' : ''); } } + + print $labeltoshow; // Already escaped + print ''; if (!$i) { $totalarray['nbfield']++; @@ -1488,7 +1489,7 @@ if ($resql) { // Payment type if (!empty($arrayfields['type']['checked'])) { - print ''; + print ''; $labeltype = ($langs->trans("PaymentTypeShort".$objp->fk_type) != "PaymentTypeShort".$objp->fk_type) ? $langs->trans("PaymentTypeShort".$objp->fk_type) : $langs->getLabelFromKey($db, $objp->fk_type, 'c_paiement', 'code', 'libelle', '', 1); if ($labeltype == 'SOLD') { print ' '; //$langs->trans("InitialBankBalance"); @@ -1514,9 +1515,9 @@ if ($resql) { print ''; $companylinked_id = 0; - $userlinked_id = 0; + $userlinked_id = 0; - //payment line type to define user display and user or company linked + //payment line type to define user display and user or company linked foreach ($links as $key => $value) { if ($links[$key]['type'] == 'payment_sc') { $type_link = 'payment_sc'; diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 8430d9e7440..f8cc88e1be4 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -124,6 +124,7 @@ if (empty($reshook)) { $object->bic = trim(GETPOST("bic")); $object->iban = trim(GETPOST("iban")); $object->domiciliation = trim(GETPOST("domiciliation", "nohtml")); + $object->pti_in_ctti = empty(GETPOST("pti_in_ctti")) ? 0 : 1; $object->proprio = trim(GETPOST("proprio", 'alphanohtml')); $object->owner_address = trim(GETPOST("owner_address", 'nohtml')); @@ -224,6 +225,7 @@ if (empty($reshook)) { $object->bic = trim(GETPOST("bic")); $object->iban = trim(GETPOST("iban")); $object->domiciliation = trim(GETPOST("domiciliation", "nohtml")); + $object->pti_in_ctti = empty(GETPOST("pti_in_ctti")) ? 0 : 1; $object->proprio = trim(GETPOST("proprio", 'alphanohtml')); $object->owner_address = trim(GETPOST("owner_address", 'nohtml')); @@ -283,7 +285,7 @@ if (empty($reshook)) { $categories = GETPOST('categories', 'array'); $object->setCategories($categories); - $_GET["id"] = $_POST["id"]; // Force chargement page en mode visu + $_GET["id"] = GETPOST("id", 'int'); // Force chargement page en mode visu } else { $error++; setEventMessages($object->error, $object->errors, 'errors'); @@ -537,6 +539,13 @@ if ($action == 'create') { print ''.$langs->trans($bickey).''; print ''; + if ($conf->paymentbybanktransfer->enabled) { + print ''.$langs->trans("SEPAXMLPlacePaymentTypeInformationInCreditTransfertransactionInformation").''; + print ' '; + print img_picto($langs->trans("SEPAXMLPlacePaymentTypeInformationInCreditTransfertransactionInformationHelp"), 'info'); + print ''; + } + print ''.$langs->trans("BankAccountDomiciliation").''; print ''; @@ -257,9 +264,12 @@ class DolEditor $out .= ''."\n"; diff --git a/htdocs/core/class/dolreceiptprinter.class.php b/htdocs/core/class/dolreceiptprinter.class.php index 9db069ab290..7653fd24437 100644 --- a/htdocs/core/class/dolreceiptprinter.class.php +++ b/htdocs/core/class/dolreceiptprinter.class.php @@ -242,9 +242,9 @@ class dolReceiptPrinter extends Printer $error = 0; $line = 0; $obj = array(); - $sql = 'SELECT rowid, name, fk_type, fk_profile, parameter'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'printer_receipt'; - $sql .= ' WHERE entity = '.$conf->entity; + $sql = "SELECT rowid, name, fk_type, fk_profile, parameter"; + $sql .= " FROM ".$this->db->prefix()."printer_receipt"; + $sql .= " WHERE entity = ".$conf->entity; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); @@ -310,9 +310,9 @@ class dolReceiptPrinter extends Printer $error = 0; $line = 0; $obj = array(); - $sql = 'SELECT rowid, name, template'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'printer_receipt_template'; - $sql .= ' WHERE entity = '.$conf->entity; + $sql = "SELECT rowid, name, template"; + $sql .= " FROM ".$this->db->prefix()."printer_receipt_template"; + $sql .= " WHERE entity = ".$conf->entity; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); @@ -391,7 +391,7 @@ class dolReceiptPrinter extends Printer { global $conf; $error = 0; - $sql = "INSERT INTO ".MAIN_DB_PREFIX."printer_receipt"; + $sql = "INSERT INTO ".$this->db->prefix()."printer_receipt"; $sql .= " (name, fk_type, fk_profile, parameter, entity)"; $sql .= " VALUES ('".$this->db->escape($name)."', ".((int) $type).", ".((int) $profile).", '".$this->db->escape($parameter)."', ".((int) $conf->entity).")"; $resql = $this->db->query($sql); @@ -417,7 +417,7 @@ class dolReceiptPrinter extends Printer global $conf; $error = 0; - $sql = "UPDATE ".MAIN_DB_PREFIX."printer_receipt"; + $sql = "UPDATE ".$this->db->prefix()."printer_receipt"; $sql .= " SET name='".$this->db->escape($name)."'"; $sql .= ", fk_type=".((int) $type); $sql .= ", fk_profile=".((int) $profile); @@ -442,7 +442,7 @@ class dolReceiptPrinter extends Printer { global $conf; $error = 0; - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'printer_receipt'; + $sql = 'DELETE FROM '.$this->db->prefix().'printer_receipt'; $sql .= ' WHERE rowid='.((int) $printerid); $resql = $this->db->query($sql); if (!$resql) { @@ -463,7 +463,7 @@ class dolReceiptPrinter extends Printer { global $conf; $error = 0; - $sql = "INSERT INTO ".MAIN_DB_PREFIX."printer_receipt_template"; + $sql = "INSERT INTO ".$this->db->prefix()."printer_receipt_template"; $sql .= " (name, template, entity) VALUES ('".$this->db->escape($name)."'"; $sql .= ", '".$this->db->escape($template)."', ".$conf->entity.")"; $resql = $this->db->query($sql); @@ -484,7 +484,7 @@ class dolReceiptPrinter extends Printer { global $conf; $error = 0; - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'printer_receipt_template'; + $sql = 'DELETE FROM '.$this->db->prefix().'printer_receipt_template'; $sql .= " WHERE rowid = ".((int) $templateid); $sql .= " AND entity = ".$conf->entity; $resql = $this->db->query($sql); @@ -508,7 +508,7 @@ class dolReceiptPrinter extends Printer global $conf; $error = 0; - $sql = "UPDATE ".MAIN_DB_PREFIX."printer_receipt_template"; + $sql = "UPDATE ".$this->db->prefix()."printer_receipt_template"; $sql .= " SET name='".$this->db->escape($name)."'"; $sql .= ", template='".$this->db->escape($template)."'"; $sql .= " WHERE rowid=".((int) $templateid); @@ -807,8 +807,8 @@ class dolReceiptPrinter extends Printer case 'DOL_PRINT_PAYMENT': $sql = "SELECT p.pos_change as pos_change, p.datep as date, p.fk_paiement, p.num_paiement as num, pf.amount as amount, pf.multicurrency_amount,"; $sql .= " cp.code"; - $sql .= " FROM ".MAIN_DB_PREFIX."paiement_facture as pf, ".MAIN_DB_PREFIX."paiement as p"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as cp ON p.fk_paiement = cp.id"; + $sql .= " FROM ".$this->db->prefix()."paiement_facture as pf, ".$this->db->prefix()."paiement as p"; + $sql .= " LEFT JOIN ".$this->db->prefix()."c_paiement as cp ON p.fk_paiement = cp.id"; $sql .= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = ".((int) $object->id); $sql .= " ORDER BY p.datep"; $resql = $this->db->query($sql); @@ -834,7 +834,7 @@ class dolReceiptPrinter extends Printer } break; case 'DOL_VALUE_PLACE': - $sql = "SELECT floor, label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $object->ref))); + $sql = "SELECT floor, label FROM ".$this->db->prefix()."takepos_floor_tables where rowid=".((int) str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $object->ref))); $resql = $this->db->query($sql); $obj = $this->db->fetch_object($resql); if ($obj) { @@ -873,10 +873,10 @@ class dolReceiptPrinter extends Printer { global $conf; $error = 0; - $sql = 'SELECT template'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'printer_receipt_template'; - $sql .= ' WHERE rowid = '.((int) $templateid); - $sql .= ' AND entity = '.$conf->entity; + $sql = "SELECT template"; + $sql .= " FROM ".$this->db->prefix()."printer_receipt_template"; + $sql .= " WHERE rowid = ".((int) $templateid); + $sql .= " AND entity = ".$conf->entity; $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_array($resql); @@ -910,10 +910,10 @@ class dolReceiptPrinter extends Printer return; } $error = 0; - $sql = 'SELECT rowid, name, fk_type, fk_profile, parameter'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'printer_receipt'; - $sql .= ' WHERE rowid = '.((int) $printerid); - $sql .= ' AND entity = '.((int) $conf->entity); + $sql = "SELECT rowid, name, fk_type, fk_profile, parameter"; + $sql .= " FROM ".$this->db->prefix()."printer_receipt"; + $sql .= " WHERE rowid = ".((int) $printerid); + $sql .= " AND entity = ".((int) $conf->entity); $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_array($resql); diff --git a/htdocs/core/class/emailsenderprofile.class.php b/htdocs/core/class/emailsenderprofile.class.php index 0ee7eb118ac..517fc953830 100644 --- a/htdocs/core/class/emailsenderprofile.class.php +++ b/htdocs/core/class/emailsenderprofile.class.php @@ -347,9 +347,9 @@ class EmailSenderProfile extends CommonObject */ public function info($id) { - $sql = 'SELECT rowid, date_creation as datec, tms as datem'; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - $sql .= ' WHERE t.rowid = '.((int) $id); + $sql = "SELECT rowid, date_creation as datec, tms as datem"; + $sql .= " FROM ".$this->db->prefix().$this->table_element." as t"; + $sql .= " WHERE t.rowid = ".((int) $id); $result = $this->db->query($sql); if ($result) { if ($this->db->num_rows($result)) { diff --git a/htdocs/core/class/events.class.php b/htdocs/core/class/events.class.php index c8799ebbd5e..63b5e5e494b 100644 --- a/htdocs/core/class/events.class.php +++ b/htdocs/core/class/events.class.php @@ -152,7 +152,7 @@ class Events // extends CommonObject } // Insert request - $sql = "INSERT INTO ".MAIN_DB_PREFIX."events("; + $sql = "INSERT INTO ".$this->db->prefix()."events("; $sql .= "type,"; $sql .= "entity,"; $sql .= "ip,"; @@ -167,7 +167,7 @@ class Events // extends CommonObject $sql .= " '".$this->db->escape(getUserRemoteIP())."',"; $sql .= " ".($this->user_agent ? "'".$this->db->escape(dol_trunc($this->user_agent, 250))."'" : 'NULL').","; $sql .= " '".$this->db->idate($this->dateevent)."',"; - $sql .= " ".($user->id ? "'".$this->db->escape($user->id)."'" : 'NULL').","; + $sql .= " ".($user->id > 0 ? ((int) $user->id) : 'NULL').","; $sql .= " '".$this->db->escape(dol_trunc($this->description, 250))."',"; $sql .= " '".$this->db->escape(dol_getprefix())."'"; $sql .= ")"; @@ -175,7 +175,7 @@ class Events // extends CommonObject dol_syslog(get_class($this)."::create", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."events"); + $this->id = $this->db->last_insert_id($this->db->prefix()."events"); return $this->id; } else { $this->error = "Error ".$this->db->lasterror(); @@ -202,7 +202,7 @@ class Events // extends CommonObject // Put here code to add control on parameters values // Update request - $sql = "UPDATE ".MAIN_DB_PREFIX."events SET"; + $sql = "UPDATE ".$this->db->prefix()."events SET"; $sql .= " type='".$this->db->escape($this->type)."',"; $sql .= " dateevent='".$this->db->idate($this->dateevent)."',"; $sql .= " description='".$this->db->escape($this->description)."'"; @@ -237,7 +237,7 @@ class Events // extends CommonObject $sql .= " t.ip,"; $sql .= " t.user_agent,"; $sql .= " t.prefix_session"; - $sql .= " FROM ".MAIN_DB_PREFIX."events as t"; + $sql .= " FROM ".$this->db->prefix()."events as t"; $sql .= " WHERE t.rowid = ".((int) $id); dol_syslog(get_class($this)."::fetch", LOG_DEBUG); @@ -274,7 +274,7 @@ class Events // extends CommonObject */ public function delete($user) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."events"; + $sql = "DELETE FROM ".$this->db->prefix()."events"; $sql .= " WHERE rowid=".((int) $this->id); dol_syslog(get_class($this)."::delete", LOG_DEBUG); diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 2b827d06f36..b75a6d02f99 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -66,6 +66,11 @@ class ExtraFields */ public $attributes; + /** + * @var array Array with boolean of status of groups + */ + public $expand_display; + /** * @var string Error code (or message) */ @@ -265,10 +270,10 @@ class ExtraFields 'default' => $default_value ); - $result = $this->db->DDLAddField(MAIN_DB_PREFIX.$table, $attrname, $field_desc); + $result = $this->db->DDLAddField($this->db->prefix().$table, $attrname, $field_desc); if ($result > 0) { if ($unique) { - $sql = "ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")"; + $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")"; $resql = $this->db->query($sql, 1, 'dml'); } return 1; @@ -353,7 +358,7 @@ class ExtraFields $params = ''; } - $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields("; + $sql = "INSERT INTO ".$this->db->prefix()."extrafields("; $sql .= " name,"; $sql .= " label,"; $sql .= " type,"; @@ -447,7 +452,7 @@ class ExtraFields if (!$error) { $sql = "SELECT COUNT(rowid) as nb"; - $sql .= " FROM ".MAIN_DB_PREFIX."extrafields"; + $sql .= " FROM ".$this->db->prefix()."extrafields"; $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'"; $sql .= " AND name = '".$this->db->escape($attrname)."'"; //$sql.= " AND entity IN (0,".$conf->entity.")"; Do not test on entity here. We want to see if there is still on field remaning in other entities before deleting field in table @@ -455,7 +460,7 @@ class ExtraFields if ($resql) { $obj = $this->db->fetch_object($resql); if ($obj->nb <= 0) { - $result = $this->db->DDLDropField(MAIN_DB_PREFIX.$table, $attrname); // This also drop the unique key + $result = $this->db->DDLDropField($this->db->prefix().$table, $attrname); // This also drop the unique key if ($result < 0) { $this->error = $this->db->lasterror(); $this->errors[] = $this->db->lasterror(); @@ -492,7 +497,7 @@ class ExtraFields } if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."extrafields"; + $sql = "DELETE FROM ".$this->db->prefix()."extrafields"; $sql .= " WHERE name = '".$this->db->escape($attrname)."'"; $sql .= " AND entity IN (0,".$conf->entity.')'; $sql .= " AND elementtype = '".$this->db->escape($elementtype)."'"; @@ -597,7 +602,7 @@ class ExtraFields } if ($type != 'separate') { // No table update when separate type - $result = $this->db->DDLUpdateField(MAIN_DB_PREFIX.$table, $attrname, $field_desc); + $result = $this->db->DDLUpdateField($this->db->prefix().$table, $attrname, $field_desc); } if ($result > 0 || $type == 'separate') { if ($label) { @@ -606,12 +611,16 @@ class ExtraFields if ($result > 0) { $sql = ''; if ($unique) { - $sql = "ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")"; + $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")"; } else { - $sql = "ALTER TABLE ".MAIN_DB_PREFIX.$table." DROP INDEX uk_".$table."_".$attrname; + $sql = "ALTER TABLE ".$this->db->prefix().$table." DROP INDEX IF EXISTS uk_".$table."_".$attrname; } dol_syslog(get_class($this).'::update', LOG_DEBUG); $resql = $this->db->query($sql, 1, 'dml'); + /*if ($resql < 0) { + $this->error = $this->db->lasterror(); + return -1; + }*/ return 1; } else { $this->error = $this->db->lasterror(); @@ -699,20 +708,20 @@ class ExtraFields if ($entity === '' || $entity != '0') { // We dont want on all entities, we delete all and current - $sql_del = "DELETE FROM ".MAIN_DB_PREFIX."extrafields"; + $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields"; $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'"; $sql_del .= " AND entity IN (0, ".($entity === '' ? $conf->entity : $entity).")"; $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'"; } else { // We want on all entities ($entities = '0'), we delete on all only (we keep setup specific to each entity) - $sql_del = "DELETE FROM ".MAIN_DB_PREFIX."extrafields"; + $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields"; $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'"; $sql_del .= " AND entity = 0"; $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'"; } $resql1 = $this->db->query($sql_del); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields("; + $sql = "INSERT INTO ".$this->db->prefix()."extrafields("; $sql .= " name,"; // This is code $sql .= " entity,"; $sql .= " label,"; @@ -804,15 +813,12 @@ class ExtraFields if ($elementtype == 'order_supplier') { $elementtype = 'commande_fournisseur'; } - if ($elementtype == 'stock_mouvement') { - $elementtype = 'movement'; - } $array_name_label = array(); // We should not have several time this request. If we have, there is some optimization to do by calling a simple $extrafields->fetch_optionals() in top of code and not into subcode $sql = "SELECT rowid, name, label, type, size, elementtype, fieldunique, fieldrequired, param, pos, alwayseditable, perms, langs, list, printable, totalizable, fielddefault, fieldcomputed, entity, enabled, help"; - $sql .= " FROM ".MAIN_DB_PREFIX."extrafields"; + $sql .= " FROM ".$this->db->prefix()."extrafields"; //$sql.= " WHERE entity IN (0,".$conf->entity.")"; // Filter is done later if ($elementtype) { $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'"; // Filed with object->table_element @@ -1139,7 +1145,7 @@ class ExtraFields $sqlwhere = ''; $sql = "SELECT ".$keyList; - $sql .= ' FROM '.MAIN_DB_PREFIX.$InfoFieldList[0]; + $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0]; if (!empty($InfoFieldList[4])) { // can use curent entity filter if (strpos($InfoFieldList[4], '$ENTITY$') !== false) { @@ -1158,7 +1164,7 @@ class ExtraFields } //We have to join on extrafield table if (strpos($InfoFieldList[4], 'extra') !== false) { - $sql .= ' as main, '.MAIN_DB_PREFIX.$InfoFieldList[0].'_extrafields as extra'; + $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra'; $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4]; } else { $sqlwhere .= " WHERE ".$InfoFieldList[4]; @@ -1307,7 +1313,7 @@ class ExtraFields $sqlwhere = ''; $sql = "SELECT ".$keyList; - $sql .= ' FROM '.MAIN_DB_PREFIX.$InfoFieldList[0]; + $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0]; if (!empty($InfoFieldList[4])) { // can use SELECT request if (strpos($InfoFieldList[4], '$SEL$') !== false) { @@ -1370,7 +1376,7 @@ class ExtraFields // We have to join on extrafield table if (strpos($InfoFieldList[4], 'extra.') !== false) { - $sql .= ' as main, '.MAIN_DB_PREFIX.$InfoFieldList[0].'_extrafields as extra'; + $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra'; $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4]; } else { $sqlwhere .= " WHERE ".$InfoFieldList[4]; @@ -1595,7 +1601,7 @@ class ExtraFields } $sql = "SELECT ".$keyList; - $sql .= ' FROM '.MAIN_DB_PREFIX.$InfoFieldList[0]; + $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0]; if (!empty($InfoFieldList[4]) && strpos($InfoFieldList[4], 'extra') !== false) { $sql .= ' as main'; } @@ -1699,7 +1705,7 @@ class ExtraFields } $sql = "SELECT ".$keyList; - $sql .= " FROM ".MAIN_DB_PREFIX.$InfoFieldList[0]; + $sql .= " FROM ".$this->db->prefix().$InfoFieldList[0]; if (strpos($InfoFieldList[4], 'extra') !== false) { $sql .= ' as main'; } @@ -1865,56 +1871,63 @@ class ExtraFields $colspan=0; } + $extrafield_param = $this->attributes[$object->table_element]['param'][$key]; + $extrafield_param_list = array(); + if (!empty($extrafield_param) && is_array($extrafield_param)) { + $extrafield_param_list = array_keys($extrafield_param['options']); + } + $extrafield_collapse_display_value = -1; + $expand_display = false; + if (is_array($extrafield_param_list) && count($extrafield_param_list) > 0) { + $extrafield_collapse_display_value = intval($extrafield_param_list[0]); + $expand_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) || GETPOST('ignorecollapsesetup', 'int')) ? ($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key] ? true : false) : ($extrafield_collapse_display_value == 2 ? false : true)); + } + $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'">'; $out .= '<'.$tagtype_dyn.' '.(!empty($colspan)?'colspan="' . $colspan . '"':'').'>'; // Some js code will be injected here to manage the collapsing of extrafields - $out .=''; + $out .= ' '; + $out .= ''; $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]); $out .= ''; $out .= ''; $out .= ''; - $extrafield_param = $this->attributes[$object->table_element]['param'][$key]; - if (!empty($extrafield_param) && is_array($extrafield_param)) { - $extrafield_param_list = array_keys($extrafield_param['options']); + $collapse_group = $key.(!empty($object->id) ? '_'.$object->id : ''); + //$extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:''); - if (count($extrafield_param_list) > 0) { - $extrafield_collapse_display_value = intval($extrafield_param_list[0]); - if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) { - // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup. - $collapse_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) || GETPOST('ignorecollapsesetup', 'int')) ? ($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key] ? true : false) : ($extrafield_collapse_display_value == 2 ? false : true)); - $extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:''); + if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) { + // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup. + $this->expand_display[$collapse_group] = $expand_display; - if (!empty($conf->use_javascript_ajax)) { - $out .= ''."\n"; - $out .= ''."\n"; - } + if (!empty($conf->use_javascript_ajax)) { + $out .= ''."\n"; + $out .= ''."\n"; } + } else { + $this->expand_display[$collapse_group] = 1; } return $out; @@ -1947,8 +1960,8 @@ class ExtraFields if (!empty($onlykey) && $onlykey != '@GETPOSTISSET' && $key != $onlykey) { continue; } - if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && $this->attributes[$object->table_element]['type'][$key] != 'boolean') { - //when unticking boolean field, it's not set in POST + + if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && (! in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'chkbxlst')))) { continue; } diff --git a/htdocs/core/class/fiscalyear.class.php b/htdocs/core/class/fiscalyear.class.php index 0edae298f46..772c67ff282 100644 --- a/htdocs/core/class/fiscalyear.class.php +++ b/htdocs/core/class/fiscalyear.class.php @@ -134,7 +134,7 @@ class Fiscalyear extends CommonObject $this->db->begin(); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."accounting_fiscalyear ("; + $sql = "INSERT INTO ".$this->db->prefix()."accounting_fiscalyear ("; $sql .= "label"; $sql .= ", date_start"; $sql .= ", date_end"; @@ -155,7 +155,7 @@ class Fiscalyear extends CommonObject dol_syslog(get_class($this)."::create", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."accounting_fiscalyear"); + $this->id = $this->db->last_insert_id($this->db->prefix()."accounting_fiscalyear"); $result = $this->update($user); if ($result > 0) { @@ -191,7 +191,7 @@ class Fiscalyear extends CommonObject $this->db->begin(); - $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_fiscalyear"; + $sql = "UPDATE ".$this->db->prefix()."accounting_fiscalyear"; $sql .= " SET label = '".$this->db->escape($this->label)."'"; $sql .= ", date_start = '".$this->db->idate($this->date_start)."'"; $sql .= ", date_end = ".($this->date_end ? "'".$this->db->idate($this->date_end)."'" : "null"); @@ -221,7 +221,7 @@ class Fiscalyear extends CommonObject public function fetch($id) { $sql = "SELECT rowid, label, date_start, date_end, statut"; - $sql .= " FROM ".MAIN_DB_PREFIX."accounting_fiscalyear"; + $sql .= " FROM ".$this->db->prefix()."accounting_fiscalyear"; $sql .= " WHERE rowid = ".((int) $id); dol_syslog(get_class($this)."::fetch", LOG_DEBUG); @@ -253,7 +253,7 @@ class Fiscalyear extends CommonObject { $this->db->begin(); - $sql = "DELETE FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE rowid = ".((int) $id); + $sql = "DELETE FROM ".$this->db->prefix()."accounting_fiscalyear WHERE rowid = ".((int) $id); dol_syslog(get_class($this)."::delete", LOG_DEBUG); $result = $this->db->query($sql); @@ -414,10 +414,10 @@ class Fiscalyear extends CommonObject */ public function info($id) { - $sql = 'SELECT fy.rowid, fy.datec, fy.fk_user_author, fy.fk_user_modif,'; - $sql .= ' fy.tms'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'accounting_fiscalyear as fy'; - $sql .= ' WHERE fy.rowid = '.((int) $id); + $sql = "SELECT fy.rowid, fy.datec, fy.fk_user_author, fy.fk_user_modif,"; + $sql .= " fy.tms"; + $sql .= " FROM ".$this->db->prefix()."accounting_fiscalyear as fy"; + $sql .= " WHERE fy.rowid = ".((int) $id); dol_syslog(get_class($this)."::fetch info", LOG_DEBUG); $result = $this->db->query($sql); @@ -464,7 +464,7 @@ class Fiscalyear extends CommonObject } $sql = "SELECT count(DISTINCT piece_num) as nb"; - $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping"; + $sql .= " FROM ".$this->db->prefix()."accounting_bookkeeping"; $sql .= " WHERE entity IN (".getEntity('bookkeeping', 0).")"; $sql .= " AND doc_date >= '".$this->db->idate($datestart)."' and doc_date <= '".$this->db->idate($dateend)."'"; @@ -498,7 +498,7 @@ class Fiscalyear extends CommonObject } $sql = "SELECT count(rowid) as nb"; - $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping "; + $sql .= " FROM ".$this->db->prefix()."accounting_bookkeeping "; $sql .= " WHERE entity IN (".getEntity('bookkeeping', 0).")"; $sql .= " AND doc_date >= '".$this->db->idate($datestart)."' and doc_date <= '".$this->db->idate($dateend)."'"; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index f25c9aad9d3..1bdd1161770 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -141,7 +141,7 @@ class Form } } } else { - if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) { + if (empty($notabletag) && $perm) { $ret .= ''; } - if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) { + if (empty($notabletag) && $perm) { $ret .= ''; } - if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) { + if (empty($notabletag) && $perm) { $ret .= '
    '; } if ($fieldrequired) { @@ -158,10 +158,10 @@ class Form if (!empty($notabletag)) { $ret .= ' '; } - if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) { + if (empty($notabletag) && $perm) { $ret .= ''; } if ($htmlname && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) { @@ -173,10 +173,10 @@ class Form if (!empty($notabletag) && $notabletag == 3) { $ret .= ' '; } - if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) { + if (empty($notabletag) && $perm) { $ret .= '
    '; } } @@ -204,7 +204,7 @@ class Form */ public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 0, $formatfunc = '', $paramid = 'id') { - global $conf, $langs, $db; + global $conf, $langs; $ret = ''; @@ -886,7 +886,7 @@ class Form $atleastonefavorite = 0; $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite, eec"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_country"; + $sql .= " FROM ".$this->db->prefix()."c_country"; $sql .= " WHERE active > 0"; //$sql.= " ORDER BY code ASC"; @@ -1009,7 +1009,7 @@ class Form $incotermArray = array(); $sql = "SELECT rowid, code"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_incoterms"; + $sql .= " FROM ".$this->db->prefix()."c_incoterms"; $sql .= " WHERE active > 0"; $sql .= " ORDER BY code ASC"; @@ -1088,7 +1088,7 @@ class Form public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0) { // phpcs:enable - global $db, $langs, $user, $conf; + global $langs, $conf; // If product & services are enabled or both disabled. if ($forceall == 1 || (empty($forceall) && !empty($conf->product->enabled) && !empty($conf->service->enabled)) @@ -1155,7 +1155,7 @@ class Form $langs->load("trips"); $sql = "SELECT c.code, c.label"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_type_fees as c"; + $sql .= " FROM ".$this->db->prefix()."c_type_fees as c"; $sql .= " WHERE active > 0"; $resql = $this->db->query($sql); @@ -1344,12 +1344,12 @@ class Form $sql .= ", s.address, s.zip, s.town"; $sql .= ", dictp.code as country_code"; } - $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; + $sql .= " FROM ".$this->db->prefix()."societe as s"; if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as dictp ON dictp.rowid = s.fk_pays"; + $sql .= " LEFT JOIN ".$this->db->prefix()."c_country as dictp ON dictp.rowid = s.fk_pays"; } if (empty($user->rights->societe->client->voir) && !$user->socid) { - $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql .= ", ".$this->db->prefix()."societe_commerciaux as sc"; } $sql .= " WHERE s.entity IN (".getEntity('societe').")"; if (!empty($user->socid)) { @@ -1523,7 +1523,7 @@ class Form // On recherche les remises $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,"; $sql .= " re.description, re.fk_facture_source"; - $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re"; + $sql .= " FROM ".$this->db->prefix()."societe_remise_except as re"; $sql .= " WHERE re.fk_soc = ".(int) $socid; $sql .= " AND re.entity = ".$conf->entity; if ($filter) { @@ -1668,9 +1668,9 @@ class Form if ($showsoc > 0 || !empty($conf->global->CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST)) { $sql .= ", s.nom as company, s.town AS company_town"; } - $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as sp"; + $sql .= " FROM ".$this->db->prefix()."socpeople as sp"; if ($showsoc > 0 || !empty($conf->global->CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST)) { - $sql .= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid=sp.fk_soc"; + $sql .= " LEFT OUTER JOIN ".$this->db->prefix()."societe as s ON s.rowid=sp.fk_soc"; } $sql .= " WHERE sp.entity IN (".getEntity('socpeople').")"; if ($socid > 0 || $socid == -1) { @@ -1690,11 +1690,16 @@ class Form $out .= ''; + + $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'bom_bom as b'; + $sql.= ' WHERE b.entity IN ('.getEntity('bom').')'; + if (!empty($status)) $sql.= ' AND status = '. (int) $status; + if (!empty($type)) $sql.= ' AND status = '. (int) $type; + if (!empty($limit)) $sql.= 'LIMIT '. (int) $limit; + $resql = $db->query($sql); + if ($resql) { + if ($showempty) { + $out .= ''; + $out .= ''; + } + } else { + $error++; + dol_print_error($db); + } + if (empty($nooutput)) { + print $out; + } else { + return $out; + } + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of products for a customer. @@ -2386,12 +2455,13 @@ class Form * 'warehouseopen' = count products from open warehouses, * 'warehouseclosed' = count products from closed warehouses, * 'warehouseinternal' = count products from warehouses for internal correct/transfer only + * @param int $status_purchase Purchase status -1=Return all products, 0=Products not on purchase, 1=Products on purchase * @return array Array of keys for json */ - public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '') + public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $status_purchase = -1) { // phpcs:enable - global $langs, $conf, $user, $db; + global $langs, $conf; $out = ''; $outarray = array(); @@ -2427,9 +2497,9 @@ class Form if (!empty($conf->global->PRODUCT_SORT_BY_CATEGORY)) { //Product category - $sql .= ", (SELECT ".MAIN_DB_PREFIX."categorie_product.fk_categorie - FROM ".MAIN_DB_PREFIX."categorie_product - WHERE ".MAIN_DB_PREFIX."categorie_product.fk_product=p.rowid + $sql .= ", (SELECT ".$this->db->prefix()."categorie_product.fk_categorie + FROM ".$this->db->prefix()."categorie_product + WHERE ".$this->db->prefix()."categorie_product.fk_product=p.rowid LIMIT 1 ) AS categorie_product_id "; } @@ -2455,13 +2525,13 @@ class Form } // Price by quantity if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { - $sql .= ", (SELECT pp.rowid FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid"; + $sql .= ", (SELECT pp.rowid FROM ".$this->db->prefix()."product_price as pp WHERE pp.fk_product = p.rowid"; if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { $sql .= " AND price_level = ".((int) $price_level); } $sql .= " ORDER BY date_price"; $sql .= " DESC LIMIT 1) as price_rowid"; - $sql .= ", (SELECT pp.price_by_qty FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid"; // price_by_qty is 1 if some prices by qty exists in subtable + $sql .= ", (SELECT pp.price_by_qty FROM ".$this->db->prefix()."product_price as pp WHERE pp.fk_product = p.rowid"; // price_by_qty is 1 if some prices by qty exists in subtable if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { $sql .= " AND price_level = ".((int) $price_level); } @@ -2469,32 +2539,32 @@ class Form $sql .= " DESC LIMIT 1) as price_by_qty"; $selectFields .= ", price_rowid, price_by_qty"; } - $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; + $sql .= " FROM ".$this->db->prefix()."product as p"; if (count($warehouseStatusArray)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (".getEntity('stock').")"; + $sql .= " LEFT JOIN ".$this->db->prefix()."product_stock as ps on ps.fk_product = p.rowid"; + $sql .= " LEFT JOIN ".$this->db->prefix()."entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (".getEntity('stock').")"; $sql .= ' AND e.statut IN ('.$this->db->sanitize($this->db->escape(implode(',', $warehouseStatusArray))).')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0. } // include search in supplier ref if (!empty($conf->global->MAIN_SEARCH_PRODUCT_BY_FOURN_REF)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; + $sql .= " LEFT JOIN ".$this->db->prefix()."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; } //Price by customer if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".((int) $socid)." AND pcp.fk_product=p.rowid"; + $sql .= " LEFT JOIN ".$this->db->prefix()."product_customer_price as pcp ON pcp.fk_soc=".((int) $socid)." AND pcp.fk_product=p.rowid"; } // Units if (!empty($conf->global->PRODUCT_USE_UNITS)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_units u ON u.rowid = p.fk_unit"; + $sql .= " LEFT JOIN ".$this->db->prefix()."c_units u ON u.rowid = p.fk_unit"; } // Multilang : we add translation if (!empty($conf->global->MAIN_MULTILANGS)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid "; + $sql .= " LEFT JOIN ".$this->db->prefix()."product_lang as pl ON pl.fk_product = p.rowid "; if (!empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE) && !empty($socid)) { require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; - $soc = new Societe($db); + $soc = new Societe($this->db); $result = $soc->fetch($socid); if ($result > 0 && !empty($soc->default_lang)) { $sql .= " AND pl.lang = '".$this->db->escape($soc->default_lang)."'"; @@ -2507,7 +2577,7 @@ class Form } if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination pac ON pac.fk_product_child = p.rowid"; + $sql .= " LEFT JOIN ".$this->db->prefix()."product_attribute_combination pac ON pac.fk_product_child = p.rowid"; } $sql .= ' WHERE p.entity IN ('.getEntity('product').')'; @@ -2526,6 +2596,9 @@ class Form } elseif ($status >= 0) { $sql .= " AND p.tosell = ".((int) $status); } + if ($status_purchase >= 0) { + $sql .= " AND p.tobuy = ".((int) $status_purchase); + } // Filter by product type if (strval($filtertype) != '') { $sql .= " AND p.fk_product_type = ".((int) $filtertype); @@ -2635,7 +2708,7 @@ class Form if ((!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && !empty($objp->price_by_qty) && $objp->price_by_qty == 1) { // Price by quantity will return many prices for the same product $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type"; - $sql .= " FROM ".MAIN_DB_PREFIX."product_price_by_qty"; + $sql .= " FROM ".$this->db->prefix()."product_price_by_qty"; $sql .= " WHERE fk_product_price = ".((int) $objp->price_rowid); $sql .= " ORDER BY quantity ASC"; @@ -2708,7 +2781,7 @@ class Form } return $outarray; } else { - dol_print_error($db); + dol_print_error($this->db); } } @@ -2729,7 +2802,7 @@ class Form */ protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0) { - global $langs, $conf, $user, $db; + global $langs, $conf, $user; $outkey = ''; $outval = ''; @@ -2875,7 +2948,7 @@ class Form // If we need a particular price level (from 1 to n) if (empty($hidepriceinlabel) && $price_level >= 1 && (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES))) { $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code"; - $sql .= " FROM ".MAIN_DB_PREFIX."product_price"; + $sql .= " FROM ".$this->db->prefix()."product_price"; $sql .= " WHERE fk_product = ".((int) $objp->rowid); $sql .= " AND entity IN (".getEntity('productprice').")"; $sql .= " AND price_level = ".((int) $price_level); @@ -3106,7 +3179,7 @@ class Form public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0, $placeholder = '') { // phpcs:enable - global $langs, $conf, $db, $user; + global $langs, $conf, $user; $out = ''; $outarray = array(); @@ -3136,15 +3209,15 @@ class Form if (!empty($conf->barcode->enabled)) { $sql .= ", pfp.barcode"; } - $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (".getEntity('product').") )"; + $sql .= " FROM ".$this->db->prefix()."product as p"; + $sql .= " LEFT JOIN ".$this->db->prefix()."product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (".getEntity('product').") )"; if ($socid > 0) { $sql .= " AND pfp.fk_soc = ".((int) $socid); } - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid"; + $sql .= " LEFT JOIN ".$this->db->prefix()."societe as s ON pfp.fk_soc = s.rowid"; // Units if (!empty($conf->global->PRODUCT_USE_UNITS)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_units u ON u.rowid = p.fk_unit"; + $sql .= " LEFT JOIN ".$this->db->prefix()."c_units u ON u.rowid = p.fk_unit"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; if ($statut != -1) { @@ -3486,9 +3559,9 @@ class Form $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,"; $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,"; $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name"; - $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid"; + $sql .= " FROM ".$this->db->prefix()."product as p"; + $sql .= " LEFT JOIN ".$this->db->prefix()."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; + $sql .= " LEFT JOIN ".$this->db->prefix()."societe as s ON pfp.fk_soc = s.rowid"; $sql .= " WHERE pfp.entity IN (".getEntity('productsupplierprice').")"; $sql .= " AND p.tobuy = 1"; $sql .= " AND s.fournisseur = 1"; @@ -3584,7 +3657,7 @@ class Form // phpcs:enable // looking for users $sql = "SELECT a.rowid, a.label"; - $sql .= " FROM ".MAIN_DB_PREFIX."societe_address as a"; + $sql .= " FROM ".$this->db->prefix()."societe_address as a"; $sql .= " WHERE a.fk_soc = ".((int) $socid); $sql .= " ORDER BY a.label ASC"; @@ -3636,7 +3709,7 @@ class Form dol_syslog(__METHOD__, LOG_DEBUG); $sql = "SELECT rowid, code, libelle as label"; - $sql .= " FROM ".MAIN_DB_PREFIX.'c_payment_term'; + $sql .= " FROM ".$this->db->prefix().'c_payment_term'; $sql .= " WHERE entity IN (".getEntity('c_payment_term').")"; $sql .= " AND active > 0"; $sql .= " ORDER BY sortorder"; @@ -3685,7 +3758,7 @@ class Form $langs->load('propal'); $sql = "SELECT rowid, code, label, position"; - $sql .= " FROM ".MAIN_DB_PREFIX.'c_availability'; + $sql .= " FROM ".$this->db->prefix().'c_availability'; $sql .= " WHERE active > 0"; $resql = $this->db->query($sql); @@ -3765,7 +3838,7 @@ class Form } $sql = "SELECT rowid, code, label"; - $sql .= " FROM ".MAIN_DB_PREFIX.'c_input_reason'; + $sql .= " FROM ".$this->db->prefix().'c_input_reason'; $sql .= " WHERE active > 0"; $resql = $this->db->query($sql); @@ -3865,7 +3938,7 @@ class Form $this->cache_types_paiements = array(); $sql = "SELECT id, code, libelle as label, type, active"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_paiement"; + $sql .= " FROM ".$this->db->prefix()."c_paiement"; $sql .= " WHERE entity IN (".getEntity('c_paiement').")"; $resql = $this->db->query($sql); @@ -3897,7 +3970,7 @@ class Form // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Return list of payment modes. + * print 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. * @@ -3912,8 +3985,28 @@ class Form public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '') { // phpcs:enable - global $langs, $user, $conf; + print $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss); + } + + /** + * 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 + * @param int $filtertype Not used + * @param int $addempty Add an empty entry + * @param int $noinfoadmin 0=Add admin info, 1=Disable admin info + * @param string $morecss Add more CSS on select tag + * @return void + */ + public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '') + { + + global $langs, $user, $conf; + $out = ''; dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG); $this->load_cache_conditions_paiements(); @@ -3923,24 +4016,25 @@ class Form $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID; } - print ''; if ($addempty) { - print ''; + $out.= ''; } foreach ($this->cache_conditions_paiements as $id => $arrayconditions) { if ($selected == $id) { - print ''; + $out.= $arrayconditions['label']; + $out.= ''; } - print ''; + $out.= ''; if ($user->admin && empty($noinfoadmin)) { - print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); + $out.= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } - print ajax_combobox($htmlname); + $out.= ajax_combobox($htmlname); + return $out; } @@ -4106,7 +4200,7 @@ class Form $this->cache_transport_mode = array(); $sql = "SELECT rowid, code, label, active"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_transport_mode"; + $sql .= " FROM ".$this->db->prefix()."c_transport_mode"; $sql .= " WHERE entity IN (".getEntity('c_transport_mode').")"; $resql = $this->db->query($sql); @@ -4224,7 +4318,7 @@ class Form $langs->load("deliveries"); $sql = "SELECT rowid, code, libelle as label"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_shipment_mode"; + $sql .= " FROM ".$this->db->prefix()."c_shipment_mode"; $sql .= " WHERE active > 0"; if ($filtre) { $sql .= " AND ".$filtre; @@ -4277,7 +4371,7 @@ class Form */ public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0) { - global $langs, $db; + global $langs; $langs->load("deliveries"); @@ -4290,7 +4384,7 @@ class Form print ''; } else { if ($selected) { - $code = $langs->getLabelFromKey($db, $selected, 'c_shipment_mode', 'rowid', 'code'); + $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code'); print $langs->trans("SendingMethod".strtoupper($code)); } else { print " "; @@ -4312,9 +4406,9 @@ class Form $langs->load('bills'); - $opt = ''; - $sql = 'SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'facture'; + $opt = ''; + $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc"; + $sql .= ' FROM '.$this->db->prefix().'facture'; $sql .= ' WHERE entity IN ('.getEntity('invoice').')'; $sql .= ' AND situation_counter >= 1'; $sql .= ' AND fk_soc = '.(int) $socid; @@ -4369,7 +4463,7 @@ class Form $return = ''; if ($showempty) { $textforempty = ' '; - if (!empty($conf->use_javascript_ajax)) { - $textforempty = ' '; // If we use ajaxcombo, we need   here to avoid to have an empty element that is too small. - } if (!is_numeric($showempty)) { $textforempty = $showempty; } + if (!empty($conf->use_javascript_ajax) && $textforempty == ' ') { + $textforempty = ' '; // If we use ajaxcombo, we need   here to avoid to have an empty element that is too small. + } $out .= ''."\n"; } // Get list of users allowed to be viewed $sql_usr = "SELECT u.rowid, u.lastname, u.firstname, u.statut as status, u.login, u.photo, u.gender, u.entity, u.admin"; - $sql_usr .= " FROM ".MAIN_DB_PREFIX."user as u"; + $sql_usr .= " FROM ".$this->db->prefix()."user as u"; if (!empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { if (!empty($user->admin) && empty($user->entity) && $conf->entity == 1) { $sql_usr .= " WHERE u.entity IS NOT NULL"; // Show all users } else { - $sql_usr .= " WHERE EXISTS (SELECT ug.fk_user FROM ".MAIN_DB_PREFIX."usergroup_user as ug WHERE u.rowid = ug.fk_user AND ug.entity IN (".getEntity('usergroup')."))"; + $sql_usr .= " WHERE EXISTS (SELECT ug.fk_user FROM ".$this->db->prefix()."usergroup_user as ug WHERE u.rowid = ug.fk_user AND ug.entity IN (".getEntity('usergroup')."))"; $sql_usr .= " OR u.entity = 0"; // Show always superadmin } } else { @@ -520,13 +520,13 @@ class FormOther if (empty($user->rights->user->user->lire) && $user->socid) { $sql_usr .= " UNION "; $sql_usr .= "SELECT u2.rowid, u2.lastname, u2.firstname, u2.statut as status, u2.login, u2.photo, u2.gender, u2.entity, u2.admin"; - $sql_usr .= " FROM ".MAIN_DB_PREFIX."user as u2, ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql_usr .= " FROM ".$this->db->prefix()."user as u2, ".$this->db->prefix()."societe_commerciaux as sc"; if (!empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { if (!empty($user->admin) && empty($user->entity) && $conf->entity == 1) { $sql_usr .= " WHERE u2.entity IS NOT NULL"; // Show all users } else { - $sql_usr .= " WHERE EXISTS (SELECT ug2.fk_user FROM ".MAIN_DB_PREFIX."usergroup_user as ug2 WHERE u2.rowid = ug2.fk_user AND ug2.entity IN (".getEntity('usergroup')."))"; + $sql_usr .= " WHERE EXISTS (SELECT ug2.fk_user FROM ".$this->db->prefix()."usergroup_user as ug2 WHERE u2.rowid = ug2.fk_user AND ug2.entity IN (".getEntity('usergroup')."))"; } } else { $sql_usr .= " WHERE u2.entity IN (".getEntity('user').")"; @@ -907,8 +907,7 @@ class FormOther '; } $out .= ''; - } else // In most cases, this is not used. We used instead function with no specific list of colors - { + } else { // In most cases, this is not used. We used instead function with no specific list of colors if (empty($conf->dol_use_jmobile) && !empty($conf->use_javascript_ajax)) { $out .= ''; $out .= ''; @@ -1399,7 +1398,7 @@ class FormOther $langs->load("admin"); $sql = "SELECT rowid, ".$keyfield.", ".$labelfield; - $sql .= " FROM ".MAIN_DB_PREFIX.$dictionarytable; + $sql .= " FROM ".$this->db->prefix().$dictionarytable; $sql .= " ORDER BY ".$labelfield; dol_syslog(get_class($this)."::select_dictionary", LOG_DEBUG); @@ -1481,69 +1480,18 @@ class FormOther * @param array $search_groupby Array of preselected fields * @param array $arrayofgroupby Array of groupby to fill * @param string $morecss More CSS + * @param string $showempty '1' or 'text' * @return string HTML string component */ - public function selectGroupByField($object, $search_groupby, &$arrayofgroupby, $morecss = 'minwidth200 maxwidth250') + public function selectGroupByField($object, $search_groupby, &$arrayofgroupby, $morecss = 'minwidth200 maxwidth250', $showempty = '1') { global $langs, $extrafields, $form; - $YYYY = substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1); - $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1); - $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1); - $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1); - $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1); - $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1); - - foreach ($object->fields as $key => $val) { - if (!$val['measure']) { - if (in_array($key, array( - 'id', 'ref_int', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams', - 'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) { - continue; - } - if (isset($val['enabled']) && !dol_eval($val['enabled'], 1)) { - continue; - } - if (isset($val['visible']) && !dol_eval($val['visible'], 1)) { - continue; - } - if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) { - continue; - } - if (preg_match('/^pass/', $key)) { - continue; - } - if (in_array($val['type'], array('html', 'text'))) { - continue; - } - if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) { - $arrayofgroupby['t.'.$key.'-year'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.')', 'position' => $val['position'].'-y'); - $arrayofgroupby['t.'.$key.'-month'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', 'position' => $val['position'].'-m'); - $arrayofgroupby['t.'.$key.'-day'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', 'position' => $val['position'].'-d'); - } else { - $arrayofgroupby['t.'.$key] = array('label' => $langs->trans($val['label']), 'position' => (int) $val['position']); - } - } - } - // Add extrafields to Group by - if ($object->isextrafieldmanaged) { - foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { - if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') { - continue; - } - if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) { - continue; - } - $arrayofgroupby['te.'.$key] = array('label' => $langs->trans($extrafields->attributes[$object->table_element]['label'][$key]), 'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key]); - } - } - - $arrayofgroupby = dol_sort_array($arrayofgroupby, 'position', 'asc', 0, 0, 1); $arrayofgroupbylabel = array(); foreach ($arrayofgroupby as $key => $val) { $arrayofgroupbylabel[$key] = $val['label']; } - $result = $form->selectarray('search_groupby', $arrayofgroupbylabel, $search_groupby, 1, 0, 0, '', 0, 0, 0, '', $morecss, 1); + $result = $form->selectarray('search_groupby', $arrayofgroupbylabel, $search_groupby, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1); return $result; } @@ -1554,72 +1502,18 @@ class FormOther * @param mixed $object Object analyzed * @param array $search_xaxis Array of preselected fields * @param array $arrayofxaxis Array of groupby to fill - * @return string HTML string component + * @param string $showempty '1' or 'text' + * @return string HTML string component */ - public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis) + public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1') { - global $langs, $extrafields, $form; - - $YYYY = substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1); - $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1); - $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1); - $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1); - $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1); - $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1); - - - foreach ($object->fields as $key => $val) { - if (!$val['measure']) { - if (in_array($key, array( - 'id', 'ref_int', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams', - 'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) { - continue; - } - if (isset($val['enabled']) && !dol_eval($val['enabled'], 1)) { - continue; - } - if (isset($val['visible']) && !dol_eval($val['visible'], 1)) { - continue; - } - if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) { - continue; - } - if (preg_match('/^pass/', $key)) { - continue; - } - if (in_array($val['type'], array('html', 'text'))) { - continue; - } - if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) { - $arrayofxaxis['t.'.$key.'-year'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.')', 'position' => $val['position'].'-y'); - $arrayofxaxis['t.'.$key.'-month'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', 'position' => $val['position'].'-m'); - $arrayofxaxis['t.'.$key.'-day'] = array('label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', 'position' => $val['position'].'-d'); - } else { - $arrayofxaxis['t.'.$key] = array('label' => $langs->trans($val['label']), 'position' => (int) $val['position']); - } - } - } - - // Add extrafields to X-Axis - if ($object->isextrafieldmanaged) { - foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { - if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') { - continue; - } - if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) { - continue; - } - $arrayofxaxis['te.'.$key] = array('label' => $langs->trans($extrafields->attributes[$object->table_element]['label'][$key]), 'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key]); - } - } - - $arrayofxaxis = dol_sort_array($arrayofxaxis, 'position', 'asc', 0, 0, 1); + global $form; $arrayofxaxislabel = array(); foreach ($arrayofxaxis as $key => $val) { $arrayofxaxislabel[$key] = $val['label']; } - $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, 1, 0, 0, '', 0, 0, 0, '', 'minwidth250', 1); + $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', 'minwidth250 maxwidth500', 1); return $result; } diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index 5f2029410ab..aa7a38969be 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -164,8 +164,8 @@ class FormProjets } // Search all projects - $sql = 'SELECT p.rowid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, s.nom as name, s.name_alias'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as p LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON s.rowid = p.fk_soc'; + $sql = "SELECT p.rowid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, s.nom as name, s.name_alias"; + $sql .= " FROM ".$this->db->prefix()."projet as p LEFT JOIN ".$this->db->prefix()."societe as s ON s.rowid = p.fk_soc"; $sql .= " WHERE p.entity IN (".getEntity('project').")"; if ($projectsListId !== false) { $sql .= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")"; @@ -338,12 +338,12 @@ class FormProjets } // Search all projects - $sql = 'SELECT t.rowid, t.ref as tref, t.label as tlabel, t.progress,'; - $sql .= ' p.rowid as pid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, p.usage_task,'; - $sql .= ' s.nom as name'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as p'; - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON s.rowid = p.fk_soc,'; - $sql .= ' '.MAIN_DB_PREFIX.'projet_task as t'; + $sql = "SELECT t.rowid, t.ref as tref, t.label as tlabel, t.progress,"; + $sql .= " p.rowid as pid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, p.usage_task,"; + $sql .= " s.nom as name"; + $sql .= " FROM ".$this->db->prefix()."projet as p"; + $sql .= " LEFT JOIN ".$this->db->prefix()."societe as s ON s.rowid = p.fk_soc,"; + $sql .= " ".$this->db->prefix()."projet_task as t"; $sql .= " WHERE p.entity IN (".getEntity('project').")"; $sql .= " AND t.fk_projet = p.rowid"; if ($projectsListId) { @@ -566,7 +566,7 @@ class FormProjets $sql = "SELECT t.rowid, t.ref"; break; case 'stock_mouvement': - $sql = 'SELECT t.rowid, t.label as ref'; + $sql = "SELECT t.rowid, t.label as ref"; $projectkey = 'fk_origin'; break; case "payment_salary": @@ -583,9 +583,9 @@ class FormProjets if ($linkedtothirdparty) { $sql .= ", s.nom as name"; } - $sql .= " FROM ".MAIN_DB_PREFIX.$table_element." as t"; + $sql .= " FROM ".$this->db->prefix().$table_element." as t"; if ($linkedtothirdparty) { - $sql .= ", ".MAIN_DB_PREFIX."societe as s"; + $sql .= ", ".$this->db->prefix()."societe as s"; } $sql .= " WHERE ".$projectkey." is null"; if (!empty($socid) && $linkedtothirdparty) { @@ -666,7 +666,7 @@ class FormProjets global $conf, $langs, $user; $sql = "SELECT rowid, code, label, percent"; - $sql .= " FROM ".MAIN_DB_PREFIX.'c_lead_status'; + $sql .= " FROM ".$this->db->prefix().'c_lead_status'; $sql .= " WHERE active = 1"; $sql .= " ORDER BY position"; diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index 733f7a0c478..87919141727 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -81,7 +81,7 @@ class FormPropal } else { $prefix = "PropalStatus"; - $sql = "SELECT id, code, label, active FROM ".MAIN_DB_PREFIX."c_propalst"; + $sql = "SELECT id, code, label, active FROM ".$this->db->prefix()."c_propalst"; $sql .= " WHERE active = 1"; dol_syslog(get_class($this)."::selectProposalStatus", LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/core/class/html.formsocialcontrib.class.php b/htdocs/core/class/html.formsocialcontrib.class.php index 3455b572888..ea325a4b591 100644 --- a/htdocs/core/class/html.formsocialcontrib.class.php +++ b/htdocs/core/class/html.formsocialcontrib.class.php @@ -74,13 +74,13 @@ class FormSocialContrib if (!empty($mysoc->country_id)) { $sql = "SELECT c.id, c.libelle as type"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_chargesociales as c"; + $sql .= " FROM ".$this->db->prefix()."c_chargesociales as c"; $sql .= " WHERE c.active = 1"; $sql .= " AND c.fk_pays = ".((int) $mysoc->country_id); $sql .= " ORDER BY c.libelle ASC"; } else { $sql = "SELECT c.id, c.libelle as type"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_chargesociales as c, ".MAIN_DB_PREFIX."c_country as co"; + $sql .= " FROM ".$this->db->prefix()."c_chargesociales as c, ".$this->db->prefix()."c_country as co"; $sql .= " WHERE c.active = 1 AND c.fk_pays = co.rowid"; $sql .= " AND co.code = '".$this->db->escape($mysoc->country_code)."'"; $sql .= " ORDER BY c.libelle ASC"; diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 6866bfa8356..aba62587fa1 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -762,13 +762,13 @@ class FormTicket $child_id=GETPOST($htmlname.'_child_id', 'aZ09')?GETPOST($htmlname.'_child_id', 'aZ09'):0; if (!empty($groupticket)) { $tmpgroupticket = $groupticket; - $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code FROM ".MAIN_DB_PREFIX."c_ticket_category as ctc WHERE ctc.code = '".$this->db->escape($tmpgroupticket)."'"; + $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code FROM ".$this->db->prefix()."c_ticket_category as ctc WHERE ctc.code = '".$this->db->escape($tmpgroupticket)."'"; $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_object($resql); $selectedgroups[] = $obj->code; while ($obj->fk_parent > 0) { - $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code FROM ".MAIN_DB_PREFIX."c_ticket_category as ctc WHERE ctc.rowid ='".$this->db->escape($obj->fk_parent)."'"; + $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code FROM ".$this->db->prefix()."c_ticket_category as ctc WHERE ctc.rowid ='".$this->db->escape($obj->fk_parent)."'"; $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_object($resql); @@ -788,7 +788,7 @@ class FormTicket $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, "; $sql .= $this->db->ifsql("ctc.rowid NOT IN (SELECT ctcfather.rowid FROM llx_c_ticket_category as ctcfather JOIN llx_c_ticket_category as ctcjoin ON ctcfather.rowid = ctcjoin.fk_parent)", "'NOTPARENT'", "'PARENT'")." as isparent"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_category as ctc"; + $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc"; $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity); if ($filtertype == 'public=1') { $sql .= " AND ctc.public = 1"; @@ -847,8 +847,8 @@ class FormTicket $stringtoprint .= ''; $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ctcjoin.code as codefather"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_category as ctc"; - $sql .= " JOIN ".MAIN_DB_PREFIX."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid"; + $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc"; + $sql .= " JOIN ".$this->db->prefix()."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid"; $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity); $sql .= " AND ctc.rowid NOT IN (".$this->db->sanitize(join(',', $arrayidusedconcat)).")"; @@ -1364,7 +1364,7 @@ class FormTicket } elseif (!dol_textishtml($defaultmessage) && dol_textishtml($this->substit['__USER_SIGNATURE__'])) { $defaultmessage = dol_nl2br($defaultmessage); } - if (GETPOSTISSET("message") && !$_POST['modelselected']) { + if (GETPOSTISSET("message") && !GETPOST('modelselected')) { $defaultmessage = GETPOST('message', 'restricthtml'); } else { $defaultmessage = make_substitutions($defaultmessage, $this->substit); diff --git a/htdocs/core/class/html.formwebsite.class.php b/htdocs/core/class/html.formwebsite.class.php index a4db07f95c0..083e571cf35 100644 --- a/htdocs/core/class/html.formwebsite.class.php +++ b/htdocs/core/class/html.formwebsite.class.php @@ -64,7 +64,7 @@ class FormWebsite $out = ''; $sql = "SELECT rowid, ref"; - $sql .= " FROM ".MAIN_DB_PREFIX."website"; + $sql .= " FROM ".$this->db->prefix()."website"; $sql .= " WHERE 1 = 1"; $sql .= " ORDER BY rowid"; $result = $this->db->query($sql); @@ -114,7 +114,7 @@ class FormWebsite $langs->load("admin"); $sql = "SELECT rowid, code, label, entity"; - $sql .= " FROM ".MAIN_DB_PREFIX.'c_type_container'; + $sql .= " FROM ".$this->db->prefix().'c_type_container'; $sql .= " WHERE active = 1 AND entity IN (".getEntity('c_type_container').")"; $sql .= " ORDER BY label"; diff --git a/htdocs/core/class/infobox.class.php b/htdocs/core/class/infobox.class.php index 0cd34e13193..f3f28abe149 100644 --- a/htdocs/core/class/infobox.class.php +++ b/htdocs/core/class/infobox.class.php @@ -83,7 +83,7 @@ class InfoBox /** * Return array of boxes qualified for area and user * - * @param DoliDB $dbs Database handler + * @param DoliDB $dbs Database handler * @param string $mode 'available' or 'activated' * @param int $zone Name or area (-1 for all, 0 for Homepage, 1 for Accountancy, 2 for xxx, ...) * @param User|null $user Object user to filter @@ -100,7 +100,7 @@ class InfoBox if ($mode == 'activated') { // activated $sql = "SELECT b.rowid, b.position, b.box_order, b.fk_user,"; $sql .= " d.rowid as box_id, d.file, d.note, d.tms"; - $sql .= " FROM ".MAIN_DB_PREFIX."boxes as b, ".MAIN_DB_PREFIX."boxes_def as d"; + $sql .= " FROM ".$dbs->prefix()."boxes as b, ".$dbs->prefix()."boxes_def as d"; $sql .= " WHERE b.box_id = d.rowid"; $sql .= " AND b.entity IN (0,".$conf->entity.")"; if ($zone >= 0) { @@ -114,7 +114,7 @@ class InfoBox $sql .= " ORDER BY b.box_order"; } else { // available $sql = "SELECT d.rowid as box_id, d.file, d.note, d.tms"; - $sql .= " FROM ".MAIN_DB_PREFIX."boxes_def as d"; + $sql .= " FROM ".$dbs->prefix()."boxes_def as d"; $sql .= " WHERE d.entity IN (0, ".$conf->entity.")"; } @@ -251,7 +251,7 @@ class InfoBox } // Delete all lines - $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes"; + $sql = "DELETE FROM ".$dbs->prefix()."boxes"; $sql .= " WHERE entity = ".$conf->entity; $sql .= " AND fk_user = ".((int) $userid); $sql .= " AND position = ".((int) $zone); @@ -274,7 +274,7 @@ class InfoBox $i++; $ii = sprintf('%02d', $i); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes"; + $sql = "INSERT INTO ".$dbs->prefix()."boxes"; $sql .= "(box_id, position, box_order, fk_user, entity)"; $sql .= " values ("; $sql .= " ".((int) $id).","; diff --git a/htdocs/core/class/link.class.php b/htdocs/core/class/link.class.php index f69dcb2874d..239c527ec53 100644 --- a/htdocs/core/class/link.class.php +++ b/htdocs/core/class/link.class.php @@ -97,7 +97,7 @@ class Link extends CommonObject $this->db->begin(); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."links (entity, datea, url, label, objecttype, objectid)"; + $sql = "INSERT INTO ".$this->db->prefix()."links (entity, datea, url, label, objecttype, objectid)"; $sql .= " VALUES (".$conf->entity.", '".$this->db->idate($this->datea)."'"; $sql .= ", '".$this->db->escape($this->url)."'"; $sql .= ", '".$this->db->escape($this->label)."'"; @@ -107,7 +107,7 @@ class Link extends CommonObject dol_syslog(get_class($this)."::create", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."links"); + $this->id = $this->db->last_insert_id($this->db->prefix()."links"); if ($this->id > 0) { // Call trigger @@ -175,7 +175,7 @@ class Link extends CommonObject $this->db->begin(); - $sql = "UPDATE ".MAIN_DB_PREFIX."links SET "; + $sql = "UPDATE ".$this->db->prefix()."links SET "; $sql .= "entity = ".$conf->entity; $sql .= ", datea = '".$this->db->idate(dol_now())."'"; $sql .= ", url = '".$this->db->escape($this->url)."'"; @@ -233,7 +233,7 @@ class Link extends CommonObject { global $conf; - $sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid FROM ".MAIN_DB_PREFIX."links"; + $sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid FROM ".$this->db->prefix()."links"; $sql .= " WHERE objecttype = '".$this->db->escape($objecttype)."' AND objectid = ".((int) $objectid); if ($conf->entity != 0) { $sql .= " AND entity = ".$conf->entity; @@ -274,7 +274,7 @@ class Link extends CommonObject /** * Return nb of links * - * @param DoliDb $dbs Database handler + * @param DoliDb $dbs Database handler * @param string $objecttype Type of the associated object in dolibarr * @param int $objectid Id of the associated object in dolibarr * @return int Nb of links, -1 if error @@ -283,7 +283,7 @@ class Link extends CommonObject { global $conf; - $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."links"; + $sql = "SELECT COUNT(rowid) as nb FROM ".$dbs->prefix()."links"; $sql .= " WHERE objecttype = '".$dbs->escape($objecttype)."' AND objectid = ".((int) $objectid); if ($conf->entity != 0) { $sql .= " AND entity = ".$conf->entity; @@ -313,7 +313,7 @@ class Link extends CommonObject $rowid = $this->id; } - $sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid FROM ".MAIN_DB_PREFIX."links"; + $sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid FROM ".$this->db->prefix()."links"; $sql .= " WHERE rowid = ".((int) $rowid); if ($conf->entity != 0) { $sql .= " AND entity = ".$conf->entity; @@ -364,7 +364,7 @@ class Link extends CommonObject // End call triggers // Remove link - $sql = "DELETE FROM ".MAIN_DB_PREFIX."links"; + $sql = "DELETE FROM ".$this->db->prefix()."links"; $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::delete", LOG_DEBUG); diff --git a/htdocs/core/class/menubase.class.php b/htdocs/core/class/menubase.class.php index 6f024c91b0b..6b45cd08f98 100644 --- a/htdocs/core/class/menubase.class.php +++ b/htdocs/core/class/menubase.class.php @@ -213,7 +213,7 @@ class Menubase // may use an already used value because its internal cursor does not increase when we do // an insert with a forced id. if (in_array($this->db->type, array('pgsql'))) { - $sql = "SELECT MAX(rowid) as maxrowid FROM ".MAIN_DB_PREFIX."menu"; + $sql = "SELECT MAX(rowid) as maxrowid FROM ".$this->db->prefix()."menu"; $resqlrowid = $this->db->query($sql); if ($resqlrowid) { $obj = $this->db->fetch_object($resqlrowid); @@ -224,7 +224,7 @@ class Menubase $maxrowid = 1; } - $sql = "SELECT setval('".MAIN_DB_PREFIX."menu_rowid_seq', ".($maxrowid).")"; + $sql = "SELECT setval('".$this->db->prefix()."menu_rowid_seq', ".($maxrowid).")"; //print $sql; exit; $resqlrowidset = $this->db->query($sql); if (!$resqlrowidset) { @@ -237,7 +237,7 @@ class Menubase // Check that entry does not exists yet on key menu_handler-fk_menu-position-url-entity, to avoid errors with postgresql $sql = "SELECT count(*)"; - $sql .= " FROM ".MAIN_DB_PREFIX."menu"; + $sql .= " FROM ".$this->db->prefix()."menu"; $sql .= " WHERE menu_handler = '".$this->db->escape($this->menu_handler)."'"; $sql .= " AND fk_menu = ".((int) $this->fk_menu); $sql .= " AND position = ".((int) $this->position); @@ -250,7 +250,7 @@ class Menubase if ($row[0] == 0) { // If not found // Insert request - $sql = "INSERT INTO ".MAIN_DB_PREFIX."menu("; + $sql = "INSERT INTO ".$this->db->prefix()."menu("; $sql .= "menu_handler,"; $sql .= "entity,"; $sql .= "module,"; @@ -293,7 +293,7 @@ class Menubase dol_syslog(get_class($this)."::create", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."menu"); + $this->id = $this->db->last_insert_id($this->db->prefix()."menu"); dol_syslog(get_class($this)."::create record added has rowid=".((int) $this->id), LOG_DEBUG); return $this->id; @@ -346,7 +346,7 @@ class Menubase // Put here code to add control on parameters values // Update request - $sql = "UPDATE ".MAIN_DB_PREFIX."menu SET"; + $sql = "UPDATE ".$this->db->prefix()."menu SET"; $sql .= " menu_handler='".$this->db->escape($this->menu_handler)."',"; $sql .= " module='".$this->db->escape($this->module)."',"; $sql .= " type='".$this->db->escape($this->type)."',"; @@ -409,7 +409,7 @@ class Menubase $sql .= " t.enabled,"; $sql .= " t.usertype as user,"; $sql .= " t.tms"; - $sql .= " FROM ".MAIN_DB_PREFIX."menu as t"; + $sql .= " FROM ".$this->db->prefix()."menu as t"; $sql .= " WHERE t.rowid = ".((int) $id); dol_syslog(get_class($this)."::fetch", LOG_DEBUG); @@ -460,7 +460,7 @@ class Menubase { //global $conf, $langs; - $sql = "DELETE FROM ".MAIN_DB_PREFIX."menu"; + $sql = "DELETE FROM ".$this->db->prefix()."menu"; $sql .= " WHERE rowid=".((int) $this->id); dol_syslog(get_class($this)."::delete", LOG_DEBUG); @@ -635,7 +635,7 @@ class Menubase $leftmenu = $myleftmenu; // To export to dol_eval function $sql = "SELECT m.rowid, m.type, m.module, m.fk_menu, m.fk_mainmenu, m.fk_leftmenu, m.url, m.titre, m.prefix, m.langs, m.perms, m.enabled, m.target, m.mainmenu, m.leftmenu, m.position"; - $sql .= " FROM ".MAIN_DB_PREFIX."menu as m"; + $sql .= " FROM ".$this->db->prefix()."menu as m"; $sql .= " WHERE m.entity IN (0,".$conf->entity.")"; $sql .= " AND m.menu_handler IN ('".$this->db->escape($menu_handler)."','all')"; if ($type_user == 0) { diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index 85b622f62ad..853de6d0a41 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -208,10 +208,10 @@ class Notify if (!$error) { if ($socid >= 0 && in_array('thirdparty', $scope)) { $sql = "SELECT a.code, c.email, c.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."notify_def as n,"; - $sql .= " ".MAIN_DB_PREFIX."socpeople as c,"; - $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a,"; - $sql .= " ".MAIN_DB_PREFIX."societe as s"; + $sql .= " FROM ".$this->db->prefix()."notify_def as n,"; + $sql .= " ".$this->db->prefix()."socpeople as c,"; + $sql .= " ".$this->db->prefix()."c_action_trigger as a,"; + $sql .= " ".$this->db->prefix()."societe as s"; $sql .= " WHERE n.fk_contact = c.rowid"; $sql .= " AND a.rowid = n.fk_action"; $sql .= " AND n.fk_soc = s.rowid"; @@ -248,9 +248,9 @@ class Notify if (!$error) { if ($userid >= 0 && in_array('user', $scope)) { $sql = "SELECT a.code, c.email, c.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."notify_def as n,"; - $sql .= " ".MAIN_DB_PREFIX."user as c,"; - $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a"; + $sql .= " FROM ".$this->db->prefix()."notify_def as n,"; + $sql .= " ".$this->db->prefix()."user as c,"; + $sql .= " ".$this->db->prefix()."c_action_trigger as a"; $sql .= " WHERE n.fk_user = c.rowid"; $sql .= " AND a.rowid = n.fk_action"; $sql .= $sqlnotifcode; @@ -395,10 +395,10 @@ class Notify if (!empty($object->socid) && $object->socid > 0) { $sql .= "SELECT 'tocontactid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.default_lang,"; $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.type"; - $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as c,"; - $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a,"; - $sql .= " ".MAIN_DB_PREFIX."notify_def as n,"; - $sql .= " ".MAIN_DB_PREFIX."societe as s"; + $sql .= " FROM ".$this->db->prefix()."socpeople as c,"; + $sql .= " ".$this->db->prefix()."c_action_trigger as a,"; + $sql .= " ".$this->db->prefix()."notify_def as n,"; + $sql .= " ".$this->db->prefix()."societe as s"; $sql .= " WHERE n.fk_contact = c.rowid AND a.rowid = n.fk_action"; $sql .= " AND n.fk_soc = s.rowid"; $sql .= " AND c.statut = 1"; @@ -415,9 +415,9 @@ class Notify // Check notification per user $sql .= "SELECT 'touserid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.lang as default_lang,"; $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.type"; - $sql .= " FROM ".MAIN_DB_PREFIX."user as c,"; - $sql .= " ".MAIN_DB_PREFIX."c_action_trigger as a,"; - $sql .= " ".MAIN_DB_PREFIX."notify_def as n"; + $sql .= " FROM ".$this->db->prefix()."user as c,"; + $sql .= " ".$this->db->prefix()."c_action_trigger as a,"; + $sql .= " ".$this->db->prefix()."notify_def as n"; $sql .= " WHERE n.fk_user = c.rowid AND a.rowid = n.fk_action"; $sql .= " AND c.statut = 1"; if (is_numeric($notifcode)) { @@ -644,10 +644,10 @@ class Notify if ($mailfile->sendfile()) { if ($obj->type_target == 'touserid') { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_user, type, objet_type, type_target, objet_id, email)"; + $sql = "INSERT INTO ".$this->db->prefix()."notify (daten, fk_action, fk_soc, fk_user, type, objet_type, type_target, objet_id, email)"; $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".((int) $notifcodedefid).", ".($object->socid > 0 ? ((int) $object->socid) : 'null').", ".((int) $obj->cid).", '".$this->db->escape($obj->type)."', '".$this->db->escape($object_type)."', '".$this->db->escape($obj->type_target)."', ".((int) $object->id).", '".$this->db->escape($obj->email)."')"; } else { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, type_target, objet_id, email)"; + $sql = "INSERT INTO ".$this->db->prefix()."notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, type_target, objet_id, email)"; $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".((int) $notifcodedefid).", ".($object->socid > 0 ? ((int) $object->socid) : 'null').", ".((int) $obj->cid).", '".$this->db->escape($obj->type)."', '".$this->db->escape($object_type)."', '".$this->db->escape($obj->type_target)."', ".((int) $object->id).", '".$this->db->escape($obj->email)."')"; } if (!$this->db->query($sql)) { @@ -879,7 +879,7 @@ class Notify ); if ($mailfile->sendfile()) { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify (daten, fk_action, fk_soc, fk_contact, type, type_target, objet_type, objet_id, email)"; + $sql = "INSERT INTO ".$this->db->prefix()."notify (daten, fk_action, fk_soc, fk_contact, type, type_target, objet_type, objet_id, email)"; $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".((int) $notifcodedefid).", ".($object->socid > 0 ? ((int) $object->socid) : 'null').", null, 'email', 'tofixedemail', '".$this->db->escape($object_type)."', ".((int) $object->id).", '".$this->db->escape($conf->global->$param)."')"; if (!$this->db->query($sql)) { dol_print_error($this->db); diff --git a/htdocs/core/class/openid.class.php b/htdocs/core/class/openid.class.php index dd7f864b4d6..79cf9137a99 100644 --- a/htdocs/core/class/openid.class.php +++ b/htdocs/core/class/openid.class.php @@ -323,43 +323,6 @@ class SimpleOpenID } } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * CURL_Request - * - * @param string $url URL - * @param string $method Method - * @param string $params Params - * @return string - */ - public function CURL_Request($url, $method = "GET", $params = "") - { - // phpcs:enable - // Remember, SSL MUST BE SUPPORTED - if (is_array($params)) { - $params = $this->array2url($params); - } - - $curl = curl_init($url.($method == "GET" && $params != "" ? "?".$params : "")); - @curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($curl, CURLOPT_HEADER, false); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($curl, CURLOPT_HTTPGET, ($method == "GET")); - curl_setopt($curl, CURLOPT_POST, ($method == "POST")); - if ($method == "POST") { - curl_setopt($curl, CURLOPT_POSTFIELDS, $params); - } - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - $response = curl_exec($curl); - - if (curl_errno($curl) == 0) { - $response; - } else { - $this->ErrorStore('OPENID_CURL', curl_error($curl)); - } - return $response; - } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * HTML2OpenIDServer @@ -372,6 +335,8 @@ class SimpleOpenID // phpcs:enable $get = array(); + $matches1 = array(); $matches2 = array(); + // Get details of their OpenID server and (optional) delegate preg_match_all('/]*rel=[\'"]openid.server[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1); preg_match_all('/]*href=\'"([^\'"]+)[\'"][^>]*rel=[\'"]openid.server[\'"][^>]*\/?>/i', $content, $matches2); @@ -495,7 +460,15 @@ class SimpleOpenID if ($openid_server == false) { return false; } - $response = $this->CURL_Request($openid_server, 'POST', $params); + + if (is_array($params)) { + $params = $this->array2url($params); + } + + $result = getURLContent($openid_server, 'POST', $params); + + $response = $result['content']; + $data = $this->splitResponse($response); if ($data['is_valid'] == "true") { return true; diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index f881447cd67..8be6f77251c 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -480,7 +480,7 @@ class Translate if (!$found && !empty($conf->global->MAIN_ENABLE_OVERWRITE_TRANSLATION)) { // Overwrite translation with database read - $sql = "SELECT transkey, transvalue FROM ".MAIN_DB_PREFIX."overwrite_trans where lang='".$db->escape($this->defaultlang)."' OR lang IS NULL"; + $sql = "SELECT transkey, transvalue FROM ".$db->prefix()."overwrite_trans where lang='".$db->escape($this->defaultlang)."' OR lang IS NULL"; $sql .= " AND entity IN (0, ".getEntity('overwrite_trans').")"; $sql .= $db->order("lang", "DESC"); $resql = $db->query($sql); @@ -980,7 +980,7 @@ class Translate // Not found in loaded language file nor in cache. So we will take the label into database. $sql = "SELECT ".$fieldlabel." as label"; - $sql .= " FROM ".MAIN_DB_PREFIX.$tablename; + $sql .= " FROM ".$db->prefix().$tablename; $sql .= " WHERE ".$fieldkey." = '".$db->escape($keyforselect ? $keyforselect : $key)."'"; if ($filteronentity) { $sql .= " AND entity IN (".getEntity($tablename).')'; @@ -1067,7 +1067,7 @@ class Translate } $sql = "SELECT code_iso, label, unicode"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_currencies"; + $sql .= " FROM ".$db->prefix()."c_currencies"; $sql .= " WHERE active = 1"; if (!empty($currency_code)) { $sql .= " AND code_iso = '".$db->escape($currency_code)."'"; diff --git a/htdocs/core/class/validate.class.php b/htdocs/core/class/validate.class.php index 61251167c21..d3aa5707c05 100644 --- a/htdocs/core/class/validate.class.php +++ b/htdocs/core/class/validate.class.php @@ -262,7 +262,7 @@ class Validate * Check for all values in db * * @param array $values Boolean to validate - * @param string $table the db table name without MAIN_DB_PREFIX + * @param string $table the db table name without $this->db->prefix() * @param string $col the target col * @return boolean Validity is ok or not * @throws Exception @@ -281,7 +281,7 @@ class Validate } foreach ($value_arr as $val) { - $sql = "SELECT ".$col." FROM ".MAIN_DB_PREFIX.$table." WHERE ".$col." = '".$this->db->escape($val)."'"; // nore quick than count(*) to check existing of a row + $sql = "SELECT ".$col." FROM ".$this->db->prefix().$table." WHERE ".$col." = '".$this->db->escape($val)."'"; // nore quick than count(*) to check existing of a row $resql = $this->db->getRow($sql); if ($resql) { continue; diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index fafd1c015e8..fd1b8069264 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -99,7 +99,8 @@ $arrayoftype = array( 'order' => array('label' => 'Orders', 'ObjectClassName' => 'Commande', 'enabled' => $conf->commande->enabled, 'ClassPath' => "/commande/class/commande.class.php"), 'invoice' => array('label' => 'Invoices', 'ObjectClassName' => 'Facture', 'enabled' => $conf->facture->enabled, 'ClassPath' => "/compta/facture/class/facture.class.php"), 'invoice_template'=>array('label' => 'PredefinedInvoices', 'ObjectClassName' => 'FactureRec', 'enabled' => $conf->facture->enabled, 'ClassPath' => "/compta/class/facturerec.class.php", 'langs'=>'bills'), - 'contract' => array('label' => 'Contracts', 'ObjectClassName' => 'Contrat', 'enabled' => $conf->contrat->enabled, 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contract'), + 'contract' => array('label' => 'Contracts', 'ObjectClassName' => 'Contrat', 'enabled' => $conf->contrat->enabled, 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'), + 'contractdet' => array('label' => 'ContractLines', 'ObjectClassName' => 'ContratLigne', 'enabled' => $conf->contrat->enabled, 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'), 'bom' => array('label' => 'BOM', 'ObjectClassName' => 'Bom', 'enabled' => $conf->bom->enabled), 'mo' => array('label' => 'MO', 'ObjectClassName' => 'Mo', 'enabled' => $conf->mrp->enabled, 'ClassPath' => "/mrp/class/mo.class.php"), 'ticket' => array('label' => 'Ticket', 'ObjectClassName' => 'Ticket', 'enabled' => $conf->ticket->enabled), @@ -159,6 +160,11 @@ $search_array_options = $extrafields->getOptionalsFromPost($object->table_elemen $search_component_params = array(''); $search_component_params_hidden = GETPOST('search_component_params_hidden', 'alphanohtml'); +// For the case we enter a criteria manually, the search_component_params_input will be defined and must be used in priority +if (GETPOST('search_component_params_input', 'alphanohtml')) { + $search_component_params_hidden = GETPOST('search_component_params_input', 'alphanohtml'); +} + $MAXUNIQUEVALFORGROUP = 20; $MAXMEASURESINBARGRAPH = 20; @@ -169,13 +175,18 @@ $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1); $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1); $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1); -$arrayofmesures = array('t.count'=>'Count'); +$arrayofmesures = array(); $arrayofxaxis = array(); $arrayofgroupby = array(); $arrayofyaxis = array(); $arrayofvaluesforgroupby = array(); -restrictedArea($user, $object->element, 0, ''); +$features = $object->element; +if (!empty($object->element_for_permission)) { + $features = $object->element_for_permission; +} + +restrictedArea($user, $features, 0, ''); $error = 0; @@ -400,42 +411,31 @@ print $form->searchComponent(array($object->element => $object->fields), $search print ''; // Add measures into array +$count = 0; +$arrayofmesures = fillArrayOfMeasures($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofmesures, 0, $count); +//var_dump($arrayofmesures); print '
    '; -foreach ($object->fields as $key => $val) { - if (!empty($val['isameasure']) && (!isset($val['enabled']) || dol_eval($val['enabled'], 1))) { - $arrayofmesures['t.'.$key.'-sum'] = $langs->trans($val['label']).' ('.$langs->trans("Sum").')'; - $arrayofmesures['t.'.$key.'-average'] = $langs->trans($val['label']).' ('.$langs->trans("Average").')'; - $arrayofmesures['t.'.$key.'-min'] = $langs->trans($val['label']).' ('.$langs->trans("Minimum").')'; - $arrayofmesures['t.'.$key.'-max'] = $langs->trans($val['label']).' ('.$langs->trans("Maximum").')'; - } -} -// Add extrafields to Measures -if ($object->isextrafieldmanaged) { - foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { - if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key]) && (!isset($extrafields->attributes[$object->table_element]['enabled'][$key]) || dol_eval($extrafields->attributes[$object->table_element]['enabled'][$key], 1))) { - $arrayofmesures['te.'.$key.'-sum'] = $langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Sum").')'; - $arrayofmesures['te.'.$key.'-average'] = $langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Average").')'; - $arrayofmesures['te.'.$key.'-min'] = $langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Minimum").')'; - $arrayofmesures['te.'.$key.'-max'] = $langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Maximum").')'; - } - } -} -print '
    '.$langs->trans("Measures").'
    '; -print $form->multiselectarray('search_measures', $arrayofmesures, $search_measures, 0, 0, 'minwidth400', 1); +print '
    '; +print $form->multiselectarray('search_measures', $arrayofmesures, $search_measures, 0, 0, 'minwidth400', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields print '
    '; - // XAxis +$count = 0; +$arrayofxaxis = fillArrayOfXAxis($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofxaxis, 0, $count); +$arrayofxaxis = dol_sort_array($arrayofxaxis, 'position', 'asc', 0, 0, 1); print '
    '; -print '
    '.$langs->trans("XAxis").'
    '; -print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis); +print '
    '; +//var_dump($arrayofxaxis); +print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis")); // Fill the array $arrayofxaxis with possible fields print '
    '; - // Group by +$count = 0; +$arrayofgroupby = fillArrayOfGroupBy($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofgroupby, 0, $count); +$arrayofgroupby = dol_sort_array($arrayofgroupby, 'position', 'asc', 0, 0, 1); print '
    '; -print '
    '.$langs->trans("GroupBy").'
    '; -print $formother->selectGroupByField($object, $search_groupby, $arrayofgroupby); +print '
    '; +print $formother->selectGroupByField($object, $search_groupby, $arrayofgroupby, 'minwidth200 maxwidth250', $langs->trans("GroupBy")); // Fill the array $arrayofgroupby with possible fields print '
    '; @@ -561,7 +561,7 @@ if (!empty($search_measures) && !empty($search_xaxis)) { $sql .= ' AND entity IN ('.getEntity($object->element).')'; } // Add the where here - $sqlfilters = GETPOST('search_component_params_hidden', 'alphanohtml'); + $sqlfilters = $search_component_params_hidden; if ($sqlfilters) { $errormessage = ''; if (dolCheckFilters($sqlfilters, $errormessage)) { @@ -835,3 +835,276 @@ if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) { llxFooter(); $db->close(); + + + + + +/** + * Fill arrayofmesures for an object + * + * @param mixed $object Any object + * @param string $tablealias Alias of table + * @param string $labelofobject Label of object + * @param array $arrayofmesures Array of mesures already filled + * @param int $level Level + * @param int $count Count + * @return array Array of mesures + */ +function fillArrayOfMeasures($object, $tablealias, $labelofobject, &$arrayofmesures, $level = 0, &$count = 0) +{ + global $langs, $extrafields, $db; + + if ($level > 10) { // Protection against infinite loop + return $arrayofmesures; + } + + if ($level == 0) { + // Add the count of record only for the main/first level object. Parents are necessarly unique for each record. + $arrayofmesures[$tablealias.'.count'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': Count'; + } + + // Add main fields of object + foreach ($object->fields as $key => $val) { + if (!empty($val['isameasure']) && (!isset($val['enabled']) || dol_eval($val['enabled'], 1))) { + $arrayofmesures[$tablealias.'.'.$key.'-sum'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Sum").')'; + $arrayofmesures[$tablealias.'.'.$key.'-average'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Average").')'; + $arrayofmesures[$tablealias.'.'.$key.'-min'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Minimum").')'; + $arrayofmesures[$tablealias.'.'.$key.'-max'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Maximum").')'; + } + } + // Add extrafields to Measures + if ($object->isextrafieldmanaged) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key]) && (!isset($extrafields->attributes[$object->table_element]['enabled'][$key]) || dol_eval($extrafields->attributes[$object->table_element]['enabled'][$key], 1))) { + $arrayofmesures[$tablealias.'e.'.$key.'-sum'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Sum").')'; + $arrayofmesures[$tablealias.'e.'.$key.'-average'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Average").')'; + $arrayofmesures[$tablealias.'e.'.$key.'-min'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Minimum").')'; + $arrayofmesures[$tablealias.'e.'.$key.'-max'] = img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' ('.$langs->trans("Maximum").')'; + } + } + } + // Add fields for parent objects + foreach ($object->fields as $key => $val) { + if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) { + $tmptype = explode(':', $val['type'], 4); + if ($tmptype[0] = 'integer' && $tmptype[1] && $tmptype[2]) { + $newobject = $tmptype[1]; + dol_include_once($tmptype[2]); + if (class_exists($newobject)) { + $tmpobject = new $newobject($db); + /*var_dump($val['label']); + var_dump($tmptype); + var_dump($arrayofmesures); + var_dump('t-'.$key);*/ + $count++; + $arrayofmesures = fillArrayOfMeasures($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofmesures, $level + 1, $count); + } else { + print 'Failed to find '.$newobject.' class for field '.$key.' of object '.$object->element."\n"; + } + } + } + } + + return $arrayofmesures; +} + + +/** + * Fill arrayofmesures for an object + * + * @param mixed $object Any object + * @param string $tablealias Alias of table + * @param string $labelofobject Label of object + * @param array $arrayofxaxis Array of xaxis already filled + * @param int $level Level + * @param int $count Count + * @return array Array of xaxis + */ +function fillArrayOfXAxis($object, $tablealias, $labelofobject, &$arrayofxaxis, $level = 0, &$count = 0) +{ + global $langs, $extrafields, $db; + + if ($level > 10) { // Protection against infinite loop + return $arrayofxaxis; + } + + if ($level >= 2) { + return $arrayofxaxis; + } + + $YYYY = substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1); + $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1); + $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1); + $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1); + $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1); + $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1); + + // Add main fields of object + foreach ($object->fields as $key => $val) { + if (empty($val['measure'])) { + if (in_array($key, array( + 'id', 'ref_int', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams', + 'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) { + continue; + } + if (isset($val['enabled']) && !dol_eval($val['enabled'], 1)) { + continue; + } + if (isset($val['visible']) && !dol_eval($val['visible'], 1)) { + continue; + } + if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) { + continue; + } + if (preg_match('/^pass/', $key)) { + continue; + } + if (in_array($val['type'], array('html', 'text'))) { + continue; + } + if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) { + $arrayofxaxis[$tablealias.'.'.$key.'-year'] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.')', 'position' => ($val['position']+($count * 100000)).'.1'); + $arrayofxaxis[$tablealias.'.'.$key.'-month'] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', 'position' => ($val['position']+($count * 100000)).'.2'); + $arrayofxaxis[$tablealias.'.'.$key.'-day'] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', 'position' => ($val['position']+($count * 100000)).'.3'); + } else { + $arrayofxaxis[$tablealias.'.'.$key] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']), 'position' => ($val['position']+($count * 100000))); + } + } + } + // Add extrafields to X-Axis + if ($object->isextrafieldmanaged) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') { + continue; + } + if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) { + continue; + } + $arrayofxaxis[$tablealias.'e.'.$key] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]), 'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key] + ($count * 100000)); + } + } + // Add fields for parent objects + foreach ($object->fields as $key => $val) { + if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) { + $tmptype = explode(':', $val['type'], 4); + if ($tmptype[0] = 'integer' && $tmptype[1] && $tmptype[2]) { + $newobject = $tmptype[1]; + dol_include_once($tmptype[2]); + if (class_exists($newobject)) { + $tmpobject = new $newobject($db); + /*var_dump($val['label']); + var_dump($tmptype); + var_dump($arrayofmesures); + var_dump('t-'.$key);*/ + $count++; + $arrayofxaxis = fillArrayOfXAxis($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofxaxis, $level + 1, $count); + } else { + print 'Failed to find '.$newobject.' class for field '.$key.' of object '.$object->element."\n"; + } + } + } + } + + return $arrayofxaxis; +} + + +/** + * Fill arrayofgrupby for an object + * + * @param mixed $object Any object + * @param string $tablealias Alias of table + * @param string $labelofobject Label of object + * @param array $arrayofgroupby Array of groupby already filled + * @param int $level Level + * @param int $count Count + * @return array Array of groupby + */ +function fillArrayOfGroupBy($object, $tablealias, $labelofobject, &$arrayofgroupby, $level = 0, &$count = 0) +{ + global $langs, $extrafields, $db; + + if ($level > 10) { // Protection against infinite loop + return $arrayofgroupby; + } + + if ($level >= 2) { + return $arrayofgroupby; + } + + $YYYY = substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1); + $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1); + $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1); + $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1); + $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1); + $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1); + + // Add main fields of object + foreach ($object->fields as $key => $val) { + if (!$val['isameasure']) { + if (in_array($key, array( + 'id', 'ref_int', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams', + 'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) { + continue; + } + if (isset($val['enabled']) && !dol_eval($val['enabled'], 1)) { + continue; + } + if (isset($val['visible']) && !dol_eval($val['visible'], 1)) { + continue; + } + if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) { + continue; + } + if (preg_match('/^pass/', $key)) { + continue; + } + if (in_array($val['type'], array('html', 'text'))) { + continue; + } + if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) { + $arrayofgroupby[$tablealias.'.'.$key.'-year'] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.')', 'position' => ($val['position']+($count * 100000)).'.1'); + $arrayofgroupby[$tablealias.'.'.$key.'-month'] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', 'position' => ($val['position']+($count * 100000)).'.2'); + $arrayofgroupby[$tablealias.'.'.$key.'-day'] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', 'position' => ($val['position']+($count * 100000)).'.3'); + } else { + $arrayofgroupby[$tablealias.'.'.$key] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']), 'position' => ($val['position']+($count * 100000))); + } + } + } + // Add extrafields to Group by + if ($object->isextrafieldmanaged) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') { + continue; + } + if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) { + continue; + } + $arrayofgroupby[$tablealias.'e.'.$key] = array('label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]), 'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key] + ($count * 100000)); + } + } + // Add fields for parent objects + foreach ($object->fields as $key => $val) { + if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) { + $tmptype = explode(':', $val['type'], 4); + if ($tmptype[0] = 'integer' && $tmptype[1] && $tmptype[2]) { + $newobject = $tmptype[1]; + dol_include_once($tmptype[2]); + if (class_exists($newobject)) { + $tmpobject = new $newobject($db); + /*var_dump($val['label']); + var_dump($tmptype); + var_dump($arrayofmesures); + var_dump('t-'.$key);*/ + $count++; + $arrayofgroupby = fillArrayOfGroupBy($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofgroupby, $level + 1, $count); + } else { + print 'Failed to find '.$newobject.' class for field '.$key.' of object '.$object->element."\n"; + } + } + } + } + + return $arrayofgroupby; +} diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index 68bb8236d72..1e9b53b1424 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -562,7 +562,7 @@ function setConstant(url, code, input, entity, strict, forcereload, userid, toke value: value }, function() { /* handler for success of post */ - console.log("url request success forcereload="+forcereload+" value="+value); + console.log("Ajax url request to set constant is a success. Make complementary actions and then forcereload="+forcereload+" value="+value); if (value == 0) { $("#set_" + code).show(); $("#del_" + code).hide(); @@ -615,9 +615,19 @@ function setConstant(url, code, input, entity, strict, forcereload, userid, toke } }); if (forcereload) { - location.reload(); + var url = window.location.href; + if (url.indexOf('dol_resetcache') < 0) { + if (url.indexOf('?') > -1) { + url = url + "&dol_resetcache=1"; + } else { + url = url + "?dol_resetcache=1"; + } + } + window.location.href = url; + //location.reload(); + return false; } - }).fail(function(error) { location.reload(); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */ + }).fail(function(error) { console.log("Error, we force reload"); location.reload(); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */ } /* @@ -642,7 +652,7 @@ function delConstant(url, code, input, entity, strict, forcereload, userid, toke token: token }, function() { - console.log("url request success forcereload="+forcereload); + console.log("Ajax url request to delete constant is success. Make complementary actions and then forcereload="+forcereload); $("#del_" + code).hide(); $("#set_" + code).show(); $.each(input, function(type, data) { @@ -686,9 +696,19 @@ function delConstant(url, code, input, entity, strict, forcereload, userid, toke } }); if (forcereload) { - location.reload(); + var url = window.location.href; + if (url.indexOf('dol_resetcache') < 0) { + if (url.indexOf('?') > -1) { + url = url + "&dol_resetcache=1"; + } else { + url = url + "?dol_resetcache=1"; + } + } + window.location.href = url; + //location.reload(); + return false; } - }).fail(function(error) { location.reload(); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */ + }).fail(function(error) { console.log("Error, we force reload"); location.reload(); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */ } /* diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index a068f5fb5f5..6054b05aab3 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -320,6 +320,7 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle // Loop on each request to execute request $cursorinsert = 0; $listofinsertedrowid = array(); + $keyforsql = md5($sqlfile); foreach ($arraysql as $i => $sql) { if ($sql) { // Replace the prefix tables @@ -335,7 +336,7 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle // Add log of request if (!$silent) { - print ''.$langs->trans("Request").' '.($i + 1)." sql='".dol_htmlentities($newsql, ENT_NOQUOTES)."'\n"; + print ''.$langs->trans("Request").' '.($i + 1)." sql='".dol_htmlentities($newsql, ENT_NOQUOTES)."'\n"; } dol_syslog('Admin.lib::run_sql Request '.($i + 1), LOG_DEBUG); $sqlmodified = 0; @@ -454,18 +455,18 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle //if (!empty($conf->use_javascript_ajax)) { // use_javascript_ajax is not defined print ''; - print ' - '.$langs->trans("ShowHideDetails").''; + print ' - '.$langs->trans("ShowHideDetails").''; //} print ''."\n"; diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 903bb08f655..e7bea722e0c 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -563,9 +563,9 @@ function ajax_constantonoff($code, $input = array(), $entity = null, $revertonof if (empty($conf->use_javascript_ajax) || $forcenoajax) { if (empty($conf->global->$code)) { - print ''.img_picto($langs->trans("Disabled"), 'off').''; + print ''.img_picto($langs->trans("Disabled"), 'off').''; } else { - print ''.img_picto($langs->trans("Enabled"), 'on').''; + print ''.img_picto($langs->trans("Enabled"), 'on').''; } } else { $out = "\n".' @@ -573,10 +573,10 @@ function ajax_constantonoff($code, $input = array(), $entity = null, $revertonof $(document).ready(function() { var input = '.json_encode($input).'; var url = \''.DOL_URL_ROOT.'/core/ajax/constantonoff.php\'; - var code = \''.$code.'\'; - var entity = \''.$entity.'\'; - var strict = \''.$strict.'\'; - var userid = \''.$user->id.'\'; + var code = \''.dol_escape_js($code).'\'; + var entity = \''.dol_escape_js($entity).'\'; + var strict = \''.dol_escape_js($strict).'\'; + var userid = \''.dol_escape_js($user->id).'\'; var yesButton = \''.dol_escape_js($langs->transnoentities("Yes")).'\'; var noButton = \''.dol_escape_js($langs->transnoentities("No")).'\'; var token = \''.currentToken().'\'; @@ -588,7 +588,7 @@ function ajax_constantonoff($code, $input = array(), $entity = null, $revertonof if (input.alert.set.noButton) noButton = input.alert.set.noButton; confirmConstantAction("set", url, code, input, input.alert.set, entity, yesButton, noButton, strict, userid, token); } else { - setConstant(url, code, input, entity, 0, '.$forcereload.', userid, token); + setConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token); } }); @@ -600,9 +600,9 @@ function ajax_constantonoff($code, $input = array(), $entity = null, $revertonof confirmConstantAction("del", url, code, input, input.alert.del, entity, yesButton, noButton, strict, userid, token); } else {'; if (empty($setzeroinsteadofdel)) { - $out .=' delConstant(url, code, input, entity, 0, '.$forcereload.', userid, token);'; + $out .=' delConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token);'; } else { - $out .=' setConstant(url, code, input, entity, 0, '.$forcereload.', userid, token, 0);'; + $out .=' setConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token, 0);'; } $out .= ' } }); diff --git a/htdocs/core/lib/asset.lib.php b/htdocs/core/lib/asset.lib.php index 840aca1339a..9d71e2b38f1 100644 --- a/htdocs/core/lib/asset.lib.php +++ b/htdocs/core/lib/asset.lib.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2018-2022 OpenDSI * * 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 @@ -26,7 +26,7 @@ * * @return array head array with tabs */ -function asset_admin_prepare_head() +function assetAdminPrepareHead() { global $langs, $conf; @@ -43,90 +43,118 @@ function asset_admin_prepare_head() // Show more tabs from modules // Entries must be declared in modules descriptor with line //$this->tabs = array( - // 'entity:+tabname:Title:@assets:/asset/mypage.php?id=__ID__' + // 'entity:+tabname:Title:@asset:/asset/mypage.php?id=__ID__' //); // to add new tab //$this->tabs = array( - // 'entity:-tabname:Title:@assets:/asset/mypage.php?id=__ID__' + // 'entity:-tabname:Title:@asset:/asset/mypage.php?id=__ID__' //); // to remove a tab - complete_head_from_modules($conf, $langs, null, $head, $h, 'assets_admin'); + complete_head_from_modules($conf, $langs, null, $head, $h, 'asset_admin'); - $head[$h][0] = DOL_URL_ROOT.'/asset/admin/assets_extrafields.php'; + $head[$h][0] = DOL_URL_ROOT.'/asset/admin/asset_extrafields.php'; $head[$h][1] = $langs->trans("ExtraFields"); - $head[$h][2] = 'attributes'; + $head[$h][2] = 'asset_extrafields'; $h++; - $head[$h][0] = DOL_URL_ROOT.'/asset/admin/assets_type_extrafields.php'; - $head[$h][1] = $langs->trans("ExtraFieldsAssetsType"); - $head[$h][2] = 'attributes_type'; + $head[$h][0] = DOL_URL_ROOT.'/asset/admin/assetmodel_extrafields.php'; + $head[$h][1] = $langs->trans("ExtraFieldsAssetModel"); + $head[$h][2] = 'assetmodel_extrafields'; $h++; - complete_head_from_modules($conf, $langs, null, $head, $h, 'assets_admin', 'remove'); + complete_head_from_modules($conf, $langs, null, $head, $h, 'asset_admin', 'remove'); return $head; } /** - * Prepare admin pages header + * Prepare array of tabs for Asset * - * @param Contrat $object Object related to tabs - * @return array head array with tabs + * @param Asset $object Asset + * @return array Array of tabs */ -function asset_prepare_head(Asset $object) +function assetPrepareHead(Asset $object) { global $db, $langs, $conf; - $langs->load("assets"); + $langs->load("assets", "admin"); $h = 0; $head = array(); - $head[$h][0] = DOL_URL_ROOT.'/asset/card.php?id='.$object->id; + $head[$h][0] = DOL_URL_ROOT . '/asset/card.php?id=' . $object->id; $head[$h][1] = $langs->trans("Card"); $head[$h][2] = 'card'; $h++; + if (empty($object->not_depreciated)) { + $head[$h][0] = DOL_URL_ROOT . '/asset/depreciation_options.php?id=' . $object->id; + $head[$h][1] = $langs->trans("AssetDepreciationOptions"); + $head[$h][2] = 'depreciation_options'; + $h++; + } + + $head[$h][0] = DOL_URL_ROOT . '/asset/accountancy_codes.php?id=' . $object->id; + $head[$h][1] = $langs->trans("AssetAccountancyCodes"); + $head[$h][2] = 'accountancy_codes'; + $h++; + + if (empty($object->not_depreciated)) { + $head[$h][0] = DOL_URL_ROOT . '/asset/depreciation.php?id=' . $object->id; + $head[$h][1] = $langs->trans("AssetDepreciation"); + $head[$h][2] = 'depreciation'; + $h++; + } + + if (isset($object->disposal_date) && $object->disposal_date !== "") { + $head[$h][0] = DOL_URL_ROOT . '/asset/disposal.php?id=' . $object->id; + $head[$h][1] = $langs->trans("AssetDisposal"); + $head[$h][2] = 'disposal'; + $h++; + } + + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) { + $nbNote = 0; + if (!empty($object->note_private)) { + $nbNote++; + } + if (!empty($object->note_public)) { + $nbNote++; + } + $head[$h][0] = DOL_URL_ROOT . '/asset/note.php?id=' . $object->id; + $head[$h][1] = $langs->trans('Notes'); + if ($nbNote > 0) { + $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' . $nbNote . '' : ''); + } + $head[$h][2] = 'note'; + $h++; + } + + require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php'; + $upload_dir = $conf->asset->dir_output . "/asset/" . dol_sanitizeFileName($object->ref); + $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); + $nbLinks = Link::count($db, $object->element, $object->id); + $head[$h][0] = DOL_URL_ROOT . '/asset/document.php?id=' . $object->id; + $head[$h][1] = $langs->trans('Documents'); + if (($nbFiles + $nbLinks) > 0) { + $head[$h][1] .= '' . ($nbFiles + $nbLinks) . ''; + } + $head[$h][2] = 'document'; + $h++; + + $head[$h][0] = DOL_URL_ROOT . '/asset/agenda.php?id=' . $object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + // Show more tabs from modules // Entries must be declared in modules descriptor with line //$this->tabs = array( - // 'entity:+tabname:Title:@assets:/asset/mypage.php?id=__ID__' + // 'entity:+tabname:Title:@asset:/asset/mypage.php?id=__ID__' //); // to add new tab //$this->tabs = array( - // 'entity:-tabname:Title:@assets:/asset/mypage.php?id=__ID__' + // 'entity:-tabname:Title:@asset:/asset/mypage.php?id=__ID__' //); // to remove a tab - complete_head_from_modules($conf, $langs, $object, $head, $h, 'assets'); - - require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; - $upload_dir = $conf->assets->dir_output.'/'.dol_sanitizeFileName($object->ref); - $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); - $nbLinks = Link::count($db, $object->element, $object->id); - $head[$h][0] = DOL_URL_ROOT.'/asset/document.php?id='.$object->id; - $head[$h][1] = $langs->trans('Documents'); - if (($nbFiles + $nbLinks) > 0) { - $head[$h][1] .= ''.($nbFiles + $nbLinks).''; - } - $head[$h][2] = 'documents'; - $h++; - - $nbNote = 0; - if (!empty($object->note_private)) { - $nbNote++; - } - if (!empty($object->note_public)) { - $nbNote++; - } - $head[$h][0] = DOL_URL_ROOT.'/asset/note.php?id='.$object->id; - $head[$h][1] = $langs->trans("Notes"); - if ($nbNote > 0) { - $head[$h][1] .= ''.$nbNote.''; - } - $head[$h][2] = 'note'; - $h++; - - $head[$h][0] = DOL_URL_ROOT.'/asset/info.php?id='.$object->id; - $head[$h][1] = $langs->trans("Info"); - $head[$h][2] = 'info'; - $h++; + complete_head_from_modules($conf, $langs, $object, $head, $h, 'asset'); complete_head_from_modules($conf, $langs, $object, $head, $h, 'asset', 'remove'); @@ -134,30 +162,69 @@ function asset_prepare_head(Asset $object) } /** - * Return array head with list of tabs to view object informations + * Prepare array of tabs for AssetModel * - * @param AssetType $object Asset - * @return array head + * @param AssetModel $object AssetModel + * @return array Array of tabs */ -function asset_type_prepare_head(AssetType $object) +function assetModelPrepareHead($object) { - global $langs, $conf, $user; + global $langs, $conf; + + $langs->load("assets", "admin"); $h = 0; $head = array(); - $head[$h][0] = DOL_URL_ROOT.'/asset/type.php?rowid='.$object->id; + $head[$h][0] = DOL_URL_ROOT . '/asset/model/card.php?id=' . $object->id; $head[$h][1] = $langs->trans("Card"); $head[$h][2] = 'card'; $h++; + $head[$h][0] = DOL_URL_ROOT . '/asset/model/depreciation_options.php?id=' . $object->id; + $head[$h][1] = $langs->trans("AssetDepreciationOptions"); + $head[$h][2] = 'depreciation_options'; + $h++; + + $head[$h][0] = DOL_URL_ROOT . '/asset/model/accountancy_codes.php?id=' . $object->id; + $head[$h][1] = $langs->trans("AssetAccountancyCodes"); + $head[$h][2] = 'accountancy_codes'; + $h++; + + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) { + $nbNote = 0; + if (!empty($object->note_private)) { + $nbNote++; + } + if (!empty($object->note_public)) { + $nbNote++; + } + $head[$h][0] = DOL_URL_ROOT . '/asset/model/note.php?id=' . $object->id; + $head[$h][1] = $langs->trans('Notes'); + if ($nbNote > 0) { + $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' . $nbNote . '' : ''); + } + $head[$h][2] = 'note'; + $h++; + } + + $head[$h][0] = DOL_URL_ROOT . '/asset/model/agenda.php?id=' . $object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + + // Show more tabs from modules // Entries must be declared in modules descriptor with line - // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab - complete_head_from_modules($conf, $langs, $object, $head, $h, 'assettype'); + //$this->tabs = array( + // 'entity:+tabname:Title:@asset:/asset/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@asset:/asset/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'assetmodel'); - complete_head_from_modules($conf, $langs, $object, $head, $h, 'assettype', 'remove'); + complete_head_from_modules($conf, $langs, $object, $head, $h, 'assetmodel', 'remove'); return $head; } diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index c60cb0c8c18..5a0c6c376fb 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -57,6 +57,40 @@ function contact_prepare_head(Contact $object) $head[$tab][2] = 'perso'; $tab++; + if (!empty($conf->projet->enabled) && (!empty($user->rights->projet->lire))) { + $nbProject = 0; + // Enable caching of thirdrparty count projects + require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; + $cachekey = 'count_projects_contact_'.$object->id; + $dataretrieved = dol_getcache($cachekey); + + if (!is_null($dataretrieved)) { + $nbProject = $dataretrieved; + } else { + $sql = 'SELECT COUNT(n.rowid) as nb'; + $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as n'; + $sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'element_contact as cc ON (n.rowid = cc.element_id)'; + $sql .= ' WHERE cc.fk_socpeople = '.((int) $object->id); + $sql .= ' AND cc.fk_c_type_contact IN (SELECT rowid FROM '.MAIN_DB_PREFIX.'c_type_contact WHERE element="project" AND source="external")'; + $sql .= ' AND n.entity IN ('.getEntity('project').')'; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + $nbProject = $obj->nb; + } else { + dol_print_error($db); + } + dol_setcache($cachekey, $nbProject, 120); // If setting cache fails, this is not a problem, so we do not test result. + } + $head[$tab][0] = DOL_URL_ROOT.'/contact/project.php?id='.$object->id; + $head[$tab][1] = $langs->trans("Projects"); + if ($nbProject > 0) { + $head[$tab][1] .= ''.$nbProject.''; + } + $head[$tab][2] = 'project'; + $tab++; + } + // Related items if (!empty($conf->commande->enabled) || !empty($conf->propal->enabled) || !empty($conf->facture->enabled) || !empty($conf->ficheinter->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { $head[$tab][0] = DOL_URL_ROOT.'/contact/consumption.php?id='.$object->id; @@ -117,3 +151,131 @@ function contact_prepare_head(Contact $object) return $head; } + +/** + * Show html area for list of projects + * + * @param Conf $conf Object conf + * @param Translate $langs Object langs + * @param DoliDB $db Database handler + * @param Object $object Third party object + * @param string $backtopage Url to go once contact is created + * @param int $nocreatelink 1=Hide create project link + * @param string $morehtmlright More html on right of title + * @return int + */ +function show_contacts_projects($conf, $langs, $db, $object, $backtopage = '', $nocreatelink = 0, $morehtmlright = '') +{ + global $user; + + $i = -1; + + if (!empty($conf->projet->enabled) && $user->rights->projet->lire) { + $langs->load("projects"); + + $newcardbutton = ''; + if (!empty($conf->projet->enabled) && $user->rights->projet->creer && empty($nocreatelink)) { + $newcardbutton .= dolGetButtonTitle($langs->trans('AddProject'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/card.php?socid='.$object->id.'&action=create&backtopage='.urlencode($backtopage)); + } + + print "\n"; + print load_fiche_titre($langs->trans("ProjectsHavingThisContact"), $newcardbutton.$morehtmlright, ''); + print '
    '; + print "\n".''; + + $sql = 'SELECT p.rowid as id, p.entity, p.title, p.ref, p.public, p.dateo as do, p.datee as de, p.fk_statut as status, p.fk_opp_status, p.opp_amount, p.opp_percent, p.tms as date_update, p.budget_amount'; + $sql .= ', cls.code as opp_status_code, ctc.libelle'; + $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as p'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_lead_status as cls on p.fk_opp_status = cls.rowid'; + $sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'element_contact as cc ON (p.rowid = cc.element_id)'; + $sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_contact as ctc ON (ctc.rowid = cc.fk_c_type_contact)'; + $sql .= ' WHERE cc.fk_socpeople = '.((int) $object->id); + $sql .= ' AND ctc.element="project" AND ctc.source="external"'; + $sql .= ' AND p.entity IN ('.getEntity('project').')'; + $sql .= ' ORDER BY p.dateo DESC'; + + $result = $db->query($sql); + if ($result) { + $num = $db->num_rows($result); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + if ($num > 0) { + require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + + $projecttmp = new Project($db); + + $i = 0; + + while ($i < $num) { + $obj = $db->fetch_object($result); + $projecttmp->fetch($obj->id); + + // To verify role of users + $userAccess = $projecttmp->restrictedProjectArea($user); + + if ($user->rights->projet->lire && $userAccess > 0) { + print ''; + + // Ref + print ''; + + // Label + print ''; + print ''; + // Date start + print ''; + // Date end + print ''; + // Opp amount + print ''; + // Opp status + print ''; + // Opp percent + print ''; + // Status + print ''; + + print ''; + } + $i++; + } + } else { + print ''; + } + $db->free($result); + } else { + dol_print_error($db); + } + print "
    '.$langs->trans("Ref").''.$langs->trans("Name").''.$langs->trans("ContactType").''.$langs->trans("DateStart").''.$langs->trans("DateEnd").''.$langs->trans("OpportunityAmountShort").''.$langs->trans("OpportunityStatusShort").''.$langs->trans("OpportunityProbabilityShort").''.$langs->trans("Status").'
    '; + print $projecttmp->getNomUrl(1); + print ''.$obj->title.''.$obj->libelle.''.dol_print_date($db->jdate($obj->do), "day").''.dol_print_date($db->jdate($obj->de), "day").''; + if ($obj->opp_status_code) { + print price($obj->opp_amount, 1, '', 1, -1, -1, ''); + } + print ''; + if ($obj->opp_status_code) { + print $langs->trans("OppStatus".$obj->opp_status_code); + } + print ''; + if ($obj->opp_percent) { + print price($obj->opp_percent, 1, '', 1, 0).'%'; + } + print ''.$projecttmp->getLibStatut(5).'
    '.$langs->trans("None").'
    "; + print '
    '; + + print "
    \n"; + } + + return $i; +} diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 04c3a481d00..efde963d077 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2348,15 +2348,15 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $accessallowed = ($user->admin && basename($original_file) == $original_file && preg_match('/^dolibarr.*\.log$/', basename($original_file))); $original_file = $dolibarr_main_data_root.'/'.$original_file; } elseif ($modulepart == 'doctemplates' && !empty($dolibarr_main_data_root)) { - // Wrapping for *.log files, like when used with url http://.../document.php?modulepart=logs&file=dolibarr.log + // Wrapping for doctemplates $accessallowed = $user->admin; $original_file = $dolibarr_main_data_root.'/doctemplates/'.$original_file; } elseif ($modulepart == 'doctemplateswebsite' && !empty($dolibarr_main_data_root)) { - // Wrapping for *.zip files, like when used with url http://.../document.php?modulepart=packages&file=module_myfile.zip + // Wrapping for doctemplates of websites $accessallowed = ($fuser->rights->website->write && preg_match('/\.jpg$/i', basename($original_file))); $original_file = $dolibarr_main_data_root.'/doctemplates/websites/'.$original_file; } elseif ($modulepart == 'packages' && !empty($dolibarr_main_data_root)) { - // Wrapping for *.zip files, like when used with url http://.../document.php?modulepart=packages&file=module_myfile.zip + // Wrapping for *.zip package files, like when used with url http://.../document.php?modulepart=packages&file=module_myfile.zip // Dir for custom dirs $tmp = explode(',', $dolibarr_main_document_root_alt); $dirins = $tmp[0]; @@ -2369,7 +2369,10 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $original_file = $conf->mycompany->dir_output.'/'.$original_file; } elseif ($modulepart == 'userphoto' && !empty($conf->user->dir_output)) { // Wrapping for users photos - $accessallowed = 1; + $accessallowed = 0; + if (preg_match('/^\d+\/photos\//', $original_file)) { + $accessallowed = 1; + } $original_file = $conf->user->dir_output.'/'.$original_file; } elseif (($modulepart == 'companylogo') && !empty($conf->mycompany->dir_output)) { // Wrapping for users logos @@ -2377,7 +2380,10 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $original_file = $conf->mycompany->dir_output.'/logos/'.$original_file; } elseif ($modulepart == 'memberphoto' && !empty($conf->adherent->dir_output)) { // Wrapping for members photos - $accessallowed = 1; + $accessallowed = 0; + if (preg_match('/^\d+\/photos\//', $original_file)) { + $accessallowed = 1; + } $original_file = $conf->adherent->dir_output.'/'.$original_file; } elseif ($modulepart == 'apercufacture' && !empty($conf->facture->multidir_output[$entity])) { // Wrapping pour les apercu factures @@ -2452,7 +2458,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } $original_file = $conf->expensereport->dir_output.'/'.$original_file; } elseif (($modulepart == 'apercuexpensereport') && !empty($conf->expensereport->dir_output)) { - // Wrapping pour les apercu supplier invoice + // Wrapping pour les apercu expense report if ($fuser->rights->expensereport->{$lire}) { $accessallowed = 1; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 7668489c8ea..65abec7b253 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -17,6 +17,7 @@ * Copyright (C) 2019 Thibault Foucart * Copyright (C) 2020 Open-Dsi * Copyright (C) 2021 Gauthier VERDOL + * Copyright (C) 2022 Anthony Berton * * 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 @@ -352,12 +353,14 @@ function GETPOSTISSET($paramname) } } } - // If there is saved contextpage, page or limit + // If there is saved contextpage, limit, page or mode if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_'.$relativepathstring])) { $isset = true; + } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring])) { + $isset = true; } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring])) { $isset = true; - } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring])) { + } elseif ($paramname == 'mode' && !empty($_SESSION['lastsearch_mode_'.$relativepathstring])) { $isset = true; } } else { @@ -447,10 +450,12 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null // If there is saved contextpage, page or limit if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_'.$relativepathstring])) { $out = $_SESSION['lastsearch_contextpage_'.$relativepathstring]; - } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring])) { - $out = $_SESSION['lastsearch_page_'.$relativepathstring]; } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring])) { $out = $_SESSION['lastsearch_limit_'.$relativepathstring]; + } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring])) { + $out = $_SESSION['lastsearch_page_'.$relativepathstring]; + } elseif ($paramname == 'mode' && !empty($_SESSION['lastsearch_mode_'.$relativepathstring])) { + $out = $_SESSION['lastsearch_mode_'.$relativepathstring]; } } elseif (!isset($_GET['sortfield'])) { // Else, retrieve default values if we are not doing a sort @@ -660,16 +665,16 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null } // Sanitizing for special parameters. - // Note: There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. + // Note: There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. Only relative URLs are allowed. if ($paramname == 'backtopage' || $paramname == 'backtolist' || $paramname == 'backtourl') { - $out = str_replace('\\', '/', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. - $out = str_replace(array(':', ';', '@'), '', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. + $out = str_replace('\\', '/', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. + $out = str_replace(array(':', ';', '@', "\t", ' '), '', $out); // Can be before the loop because only 1 char is replaced. No risk to retreive it after other replacements. do { $oldstringtoclean = $out; $out = str_ireplace(array('javascript', 'vbscript', '&colon', '&#'), '', $out); + $out = preg_replace(array('/^[^\?]*%/'), '', $out); // We remove any % chars before the ?. Example in url: '/product/stock/card.php?action=create&backtopage=%2Fdolibarr_dev%2Fhtdocs%2Fpro%25duct%2Fcard.php%3Fid%3Dabc' + $out = preg_replace(array('/^[a-z]*\/\s*\/+/i'), '', $out); // We remove schema*// to remove external URL } while ($oldstringtoclean != $out); - - $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); // We remove schema*// to remove external URL } // Code for search criteria persistence. @@ -708,11 +713,11 @@ function GETPOSTINT($paramname, $method = 0) /** * Return a value after checking on a rule. A sanitization may also have been done. * - * @param string $out Value to check/clear. - * @param string $check Type of check/sanitizing - * @param int $filter Filter to apply when $check is set to 'custom'. (See http://php.net/manual/en/filter.filters.php for détails) - * @param mixed $options Options to pass to filter_var when $check is set to 'custom' - * @return string|array Value sanitized (string or array). It may be '' if format check fails. + * @param string|array $out Value to check/clear. + * @param string $check Type of check/sanitizing + * @param int $filter Filter to apply when $check is set to 'custom'. (See http://php.net/manual/en/filter.filters.php for détails) + * @param mixed $options Options to pass to filter_var when $check is set to 'custom' + * @return string|array Value sanitized (string or array). It may be '' if format check fails. */ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = null) { @@ -782,7 +787,7 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = // keep lines feed } break; - case 'alphawithlgt': // No " and no ../ but we keep balanced < > tags with no special chars inside. Can be used for email string like "Name " + case 'alphawithlgt': // No " and no ../ but we keep balanced < > tags with no special chars inside. Can be used for email string like "Name ". Less secured than 'alphanohtml' if (!is_array($out)) { $out = trim($out); do { @@ -865,31 +870,32 @@ if (!function_exists('dol_getprefix')) { * Return a prefix to use for this Dolibarr instance, for session/cookie names or email id. * The prefix is unique for instance and avoid conflict between multi-instances, even when having two instances with same root dir * or two instances in same virtual servers. + * This function must not use dol_hash (that is used for password hash) and need to have all context $conf loaded. * * @param string $mode '' (prefix for session name) or 'email' (prefix for email id) * @return string A calculated prefix */ function dol_getprefix($mode = '') { - // If prefix is for email (we need to have $conf alreayd loaded for this case) + // If prefix is for email (we need to have $conf already loaded for this case) if ($mode == 'email') { global $conf; - if (!empty($conf->global->MAIL_PREFIX_FOR_EMAIL_ID)) { // If MAIL_PREFIX_FOR_EMAIL_ID is set (a value initialized with a random value is recommended) + if (!empty($conf->global->MAIL_PREFIX_FOR_EMAIL_ID)) { // If MAIL_PREFIX_FOR_EMAIL_ID is set if ($conf->global->MAIL_PREFIX_FOR_EMAIL_ID != 'SERVER_NAME') { return $conf->global->MAIL_PREFIX_FOR_EMAIL_ID; - } elseif (isset($_SERVER["SERVER_NAME"])) { + } elseif (isset($_SERVER["SERVER_NAME"])) { // If MAIL_PREFIX_FOR_EMAIL_ID is set to 'SERVER_NAME' return $_SERVER["SERVER_NAME"]; } } - // The recommended value (may be not defined for old versions) + // The recommended value if MAIL_PREFIX_FOR_EMAIL_ID is not defined (may be not defined for old versions) if (!empty($conf->file->instance_unique_id)) { - return $conf->file->instance_unique_id; + return sha1('dolibarr'.$conf->file->instance_unique_id); } - // For backward compatibility - return dol_hash(DOL_DOCUMENT_ROOT.DOL_URL_ROOT, '3'); + // For backward compatibility when instance_unique_id is not set + return sha1(DOL_DOCUMENT_ROOT.DOL_URL_ROOT); } // If prefix is for session (no need to have $conf loaded) @@ -898,15 +904,15 @@ if (!function_exists('dol_getprefix')) { // The recommended value (may be not defined for old versions) if (!empty($tmp_instance_unique_id)) { - return $tmp_instance_unique_id; + return sha1('dolibarr'.$tmp_instance_unique_id); } - // For backward compatibility + // For backward compatibility when instance_unique_id is not set if (isset($_SERVER["SERVER_NAME"]) && isset($_SERVER["DOCUMENT_ROOT"])) { - return dol_hash($_SERVER["SERVER_NAME"].$_SERVER["DOCUMENT_ROOT"].DOL_DOCUMENT_ROOT.DOL_URL_ROOT, '3'); + return sha1($_SERVER["SERVER_NAME"].$_SERVER["DOCUMENT_ROOT"].DOL_DOCUMENT_ROOT.DOL_URL_ROOT); + } else { + return sha1(DOL_DOCUMENT_ROOT.DOL_URL_ROOT); } - - return dol_hash(DOL_DOCUMENT_ROOT.DOL_URL_ROOT, '3'); } } @@ -1099,6 +1105,7 @@ function dol_sanitizeFileName($str, $newstr = '_', $unaccent = 1) $tmp = dol_string_nospecial($unaccent ? dol_string_unaccent($str) : $str, $newstr, $filesystem_forbidden_chars); $tmp = preg_replace('/\-\-+/', '_', $tmp); $tmp = preg_replace('/\s+\-([^\s])/', ' _$1', $tmp); + $tmp = str_replace('..', '', $tmp); return $tmp; } @@ -1122,6 +1129,7 @@ function dol_sanitizePathName($str, $newstr = '_', $unaccent = 1) $tmp = dol_string_nospecial($unaccent ? dol_string_unaccent($str) : $str, $newstr, $filesystem_forbidden_chars); $tmp = preg_replace('/\-\-+/', '_', $tmp); $tmp = preg_replace('/\s+\-([^\s])/', ' _$1', $tmp); + $tmp = str_replace('..', '', $tmp); return $tmp; } @@ -1665,7 +1673,11 @@ function dol_get_fiche_head($links = array(), $active = '', $title = '', $notab $limittitle = 30; $out .= ''; if ($picto) { - $out .= img_picto($title, ($pictoisfullpath ? '' : 'object_').$picto, '', $pictoisfullpath, 0, 0, '', 'imgTabTitle').' '; + $noprefix = $pictoisfullpath; + if (strpos($picto, 'fontawesome_') !== false) { + $noprefix = 1; + } + $out .= img_picto($title, ($noprefix ? '' : 'object_').$picto, '', $pictoisfullpath, 0, 0, '', 'imgTabTitle').' '; } $out .= ''.dol_escape_htmltag(dol_trunc($title, $limittitle)).''; $out .= ''; @@ -2019,10 +2031,14 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi $width = 14; $cssclass = 'photorefcenter'; $picto = $object->picto; + $prefix = 'object_'; if ($object->element == 'project' && !$object->public) { $picto = 'project'; // instead of projectpub } - $nophoto = img_picto('No photo', 'object_'.$picto); + if (strpos($picto, 'fontawesome_') !== false) { + $prefix = ''; + } + $nophoto = img_picto('No photo', $prefix.$picto); } $morehtmlleft .= ''; $morehtmlleft .= '
    '; @@ -2913,6 +2929,38 @@ function dol_print_socialnetworks($value, $cid, $socid, $type, $dictsocialnetwor return $htmllink; } +/** + * Format profIDs according to country + * + * @param string $profID Value of profID to format + * @param string $profIDtype Type of profID to format ('1', '2', '3', '4', '5', '6' or 'VAT') + * @param string $countrycode Country code to use for formatting + * @param int $addcpButton Add button to copy to clipboard (1 => show only on hoover ; 2 => always display ) + * @param string $separ Separation between numbers for a better visibility example : xxx xxx xxx xxxxx + * @return string Formated profID + */ +function dol_print_profids($profID, $profIDtype, $countrycode = '', $addcpButton = 1, $separ = ' ') +{ + global $mysoc; + + if (empty($profID) || empty($profIDtype)) { + return ''; + } + if (empty($countrycode)) $countrycode = $mysoc->country_code; + $newProfID = $profID; + $id = substr($profIDtype, -1); + $ret = ''; + if (strtoupper($countrycode) == 'FR') { + // France + if ($id == 1 && dol_strlen($newProfID) == 9) $newProfID = substr($newProfID, 0, 3).$separ.substr($newProfID, 3, 3).$separ.substr($newProfID, 6, 3); + if ($id == 2 && dol_strlen($newProfID) == 14) $newProfID = substr($newProfID, 0, 3).$separ.substr($newProfID, 3, 3).$separ.substr($newProfID, 6, 3).$separ.substr($newProfID, 9, 5); + if ($profIDtype === 'VAT' && dol_strlen($newProfID) == 13) $newProfID = substr($newProfID, 0, 4).$separ.substr($newProfID, 4, 3).$separ.substr($newProfID, 7, 3).$separ.substr($newProfID, 10, 3); + } + if (!empty($addcpButton)) $ret = showValueWithClipboardCPButton(dol_escape_htmltag($profID), ($addcpButton == 1 ? 1 : 0), $newProfID); + else $ret = $newProfID; + return $ret; +} + /** * Format phone numbers according to country * @@ -3605,6 +3653,7 @@ function dol_trunc($string, $size = 40, $trunc = 'right', $stringencoding = 'UTF * Example: picto.png if picto.png is stored into htdocs/theme/mytheme/img * Example: picto.png@mymodule if picto.png is stored into htdocs/mymodule/img * Example: /mydir/mysubdir/picto.png if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1) + * Example: fontawesome_envelope-open-text_fas_red_1em if you want to use fontaweseome icons: fontawesome__