diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 68fe9de68d6..d7463d62172 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -26,8 +26,9 @@ Default **language here is english**. So please prepare your contributions in en 1. [Fork](https://help.github.com/articles/fork-a-repo) the [GitHub repository](https://github.com/Dolibarr/dolibarr). 2. Clone your fork. 3. Choose a branch(See the [Branches](#branches) section below). -4. Commit and push your changes. -5. [Make a pull request](https://help.github.com/articles/creating-a-pull-request). +4. Read our developer documentation on the [Dolibarr Wiki](https://wiki.dolibarr.org/index.php?title=Developer_documentation). +5. Commit and push your changes. +6. [Make a pull request](https://help.github.com/articles/creating-a-pull-request). ### Branches diff --git a/.travis.yml b/.travis.yml index b48a3667bb0..5d7eb7a1678 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ jobs: php: nightly env: DB=mysql - stage: PHP Dev - if: type = push AND branch = 14.0 + if: type = push AND branch = 15.0 php: nightly env: DB=mysql @@ -411,6 +411,12 @@ script: php upgrade.php 13.0.0 14.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade13001400.log php upgrade2.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-2.log php step5.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-3.log + 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/ChangeLog b/ChangeLog index 8c52db8af69..a8211da486a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -138,6 +138,8 @@ NEW: Hidden option API_DISABLE_COMPRESSION is now visible in API setup page. NEW: Add hook printUnderHeaderPDFline on invoice PDF templates (can be used for example to add a barcode or more information on header of invoices). Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: +* ALL EXTERNAL MODULES THAT WERE NOT CORRECTLY DEVELOPPED WILL NOT WORK ON V15 (All modules that forgot to manage the security token field + into forms will be broken. The security token field is expected since Dolibarr v9 but a lot of external modules did not implement it). * Update hook 'printOriginObjectLine', removed check on product type and special code. Need now reshook. * Old deprecated module "SimplePOS" has been completely removed. Use module "TakePOS" is you need a Point Of Sale. * The method static ActionComm::getActions($db, ...) is no more static. Use $actioncomm->getActions(...) instead (without $db param). diff --git a/README.md b/README.md index b0f7a2c3761..4e120a4cb91 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ ![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/develop.svg) [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg?style=flat-square)](https://php.net/) [![GitHub release](https://img.shields.io/github/v/release/Dolibarr/dolibarr)](https://github.com/Dolibarr/dolibarr) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5521/badge)](https://bestpractices.coreinfrastructure.org/projects/5521) Dolibarr ERP & CRM is a modern software package that helps manage your organization's activity (contacts, suppliers, invoices, orders, stocks, agenda…). diff --git a/SECURITY.md b/SECURITY.md index 9c28e2874b9..cadd4a23791 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,13 +6,14 @@ This file contains some policies about the security reports on Dolibarr ERP CRM | Version | Supported | | ---------- | ---------------------- | -| <= 14.0.1 | :x: | -| >= 14.0.2+ | :white_check_mark: except CSRF attacks| +| <= 14.0.4 | :x: | +| >= 14.0.5+ | :white_check_mark: except CSRF attacks| | >= develop | :white_check_mark: | ## Reporting a Vulnerability -To report a vulnerability, please use GitHub security advisory at [https://github.com/Dolibarr/dolibarr/security/advisories/new](https://github.com/Dolibarr/dolibarr/security/advisories/new) (if you have permissions) or alternatively send an email to security@dolibarr.org (for everybody) +To report a vulnerability, for a private report, please use GitHub security advisory at [https://github.com/Dolibarr/dolibarr/security/advisories/new](https://github.com/Dolibarr/dolibarr/security/advisories/new) (if you have permissions). +Alternatively send an email to security@dolibarr.org (for everybody) ## Hunting vulnerabilities on Dolibarr @@ -66,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/htdocs/accountancy/admin/journals_list.php b/htdocs/accountancy/admin/journals_list.php index 8af707c4626..7f000290e1c 100644 --- a/htdocs/accountancy/admin/journals_list.php +++ b/htdocs/accountancy/admin/journals_list.php @@ -58,8 +58,8 @@ $listoffset = GETPOST('listoffset', 'alpha'); $listlimit = GETPOST('listlimit', 'int') > 0 ?GETPOST('listlimit', 'int') : 1000; $active = 1; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index 8503f3acfd6..847891c949b 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -80,8 +80,8 @@ if (empty($accounting_product_mode)) { } $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php index 29a0171fe08..a563b653ac1 100644 --- a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php +++ b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php @@ -48,8 +48,8 @@ $socid = GETPOSTINT("socid"); // if ($user->socid) $socid=$user->socid; $limit = GETPOSTISSET('limit') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == - 1) { $page = 0; @@ -157,7 +157,7 @@ $sql = "SELECT bk.rowid, bk.doc_date, bk.doc_type, bk.doc_ref, "; $sql .= " bk.subledger_account, bk.numero_compte , bk.label_compte, bk.debit, "; $sql .= " bk.credit, bk.montant, bk.sens, bk.code_journal, bk.piece_num, bk.lettering_code"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as bk"; -$sql .= " WHERE (bk.subledger_account = '".$db->escape($object->code_compta)."' AND bk.numero_compte = '".$db->escape($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER)."' )"; +$sql .= " WHERE (bk.subledger_account = '".$db->escape($object->code_compta)."' AND bk.numero_compte = '".$db->escape($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER)."' )"; /* if (dol_strlen($search_date_start) || dol_strlen($search_date_end)) { diff --git a/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php b/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php index d62a1e9fc25..5c315bee9fc 100644 --- a/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php +++ b/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php @@ -48,8 +48,8 @@ $socid = GETPOSTINT("socid"); $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == - 1) { $page = 0; diff --git a/htdocs/accountancy/class/accountingaccount.class.php b/htdocs/accountancy/class/accountingaccount.class.php index a42439b1597..a4dcac8c1ad 100644 --- a/htdocs/accountancy/class/accountingaccount.class.php +++ b/htdocs/accountancy/class/accountingaccount.class.php @@ -29,6 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + /** * Class to manage accounting accounts */ @@ -566,7 +567,7 @@ class AccountingAccount extends CommonObject /** * Information on record * - * @param int $id of record + * @param int $id ID of record * @return void */ public function info($id) @@ -850,8 +851,8 @@ class AccountingAccount extends CommonObject // Level 3 (define $code_t): Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) if (!empty($conf->global->ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY)) { - if (!empty($buyer->code_compta)) { - $code_t = $buyer->code_compta; + if (!empty($buyer->code_compta_product)) { + $code_t = $buyer->code_compta_product; $suggestedid = $accountingAccount['thirdparty']; $suggestedaccountingaccountfor = 'thridparty'; } diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 42fb42b89fa..e96cf9e0997 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -2114,15 +2114,26 @@ class BookKeepingLine public $montant; /** - * @var float Amount + * @var float Amount */ public $amount; + /** + * @var float Multicurrency amount + */ + public $multicurrency_amount; + + /** + * @var float Multicurrency code + */ + public $multicurrency_code; + /** * @var string Sens */ public $sens; public $lettering_code; + public $date_lettering; /** * @var int ID @@ -2153,4 +2164,9 @@ class BookKeepingLine * @var integer|string $date_validation; */ public $date_validation; + + /** + * @var integer|string $date_lim_reglement; + */ + public $date_lim_reglement; } diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index b7ec854fd7c..7ce226f99d8 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -153,9 +153,9 @@ if ($action == 'validatehistory') { $sql .= " co.code as country_code, co.label as country_label,"; $sql .= " s.tva_intra,"; if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { - $sql .= " spe.accountancy_code_sell as company_code_sell"; + $sql .= " spe.accountancy_code_sell as company_code_sell"; // accounting code for product but stored on thirdparty } else { - $sql .= " s.accountancy_code_sell as company_code_sell"; + $sql .= " s.accountancy_code_sell as company_code_sell"; // accounting code for product but stored on thirdparty } $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; @@ -215,7 +215,7 @@ if ($action == 'validatehistory') { $thirdpartystatic->email = $objp->email; $thirdpartystatic->country_code = $objp->country_code; $thirdpartystatic->tva_intra = $objp->tva_intra; - $thirdpartystatic->code_compta = $objp->company_code_sell; + $thirdpartystatic->code_compta_product = $objp->company_code_sell; // The accounting account for product stored on thirdparty object (for level3 suggestion) $product_static->ref = $objp->product_ref; $product_static->id = $objp->product_id; diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index 582877d3599..56f904e79ef 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -539,13 +539,14 @@ if ($result) { $thirdpartystatic->client = $objp->client; $thirdpartystatic->fournisseur = $objp->fournisseur; $thirdpartystatic->code_client = $objp->code_client; + $thirdpartystatic->code_compta = $objp->code_compta_client; // For backward compatibility $thirdpartystatic->code_compta_client = $objp->code_compta_client; $thirdpartystatic->code_fournisseur = $objp->code_fournisseur; $thirdpartystatic->code_compta_fournisseur = $objp->code_compta_fournisseur; $thirdpartystatic->email = $objp->email; $thirdpartystatic->country_code = $objp->country_code; $thirdpartystatic->tva_intra = $objp->tva_intra; - $thirdpartystatic->code_compta_company = $objp->company_code_sell; + $thirdpartystatic->code_compta_product = $objp->company_code_sell; // The accounting account for product stored on thirdparty object (for level3 suggestion) $product_static->ref = $objp->product_ref; $product_static->id = $objp->product_id; diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index 51c9e66cebe..70434a470f1 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -211,7 +211,7 @@ if ($action == 'validatehistory') { $thirdpartystatic->email = $objp->email; $thirdpartystatic->country_code = $objp->country_code; $thirdpartystatic->tva_intra = $objp->tva_intra; - $thirdpartystatic->code_compta = $objp->company_code_sell; + $thirdpartystatic->code_compta_product = $objp->company_code_buy; // The accounting account for product stored on thirdparty object (for level3 suggestion) $product_static->ref = $objp->product_ref; $product_static->id = $objp->product_id; @@ -230,7 +230,7 @@ if ($action == 'validatehistory') { $facture_static->ref = $objp->ref; $facture_static->id = $objp->facid; $facture_static->type = $objp->ftype; - $facture_static->datef = $objp->datef; + $facture_static->date = $objp->datef; $facture_static_det->id = $objp->rowid; $facture_static_det->total_ht = $objp->total_ht; diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index f88c1dd8ccc..6364ce914c6 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -547,7 +547,7 @@ if ($result) { $thirdpartystatic->email = $objp->email; $thirdpartystatic->country_code = $objp->country_code; $thirdpartystatic->tva_intra = $objp->tva_intra; - $thirdpartystatic->code_compta_company = $objp->company_code_buy; + $thirdpartystatic->code_compta_product = $objp->company_code_buy; // The accounting account for product stored on thirdparty object (for level3 suggestion) $product_static->ref = $objp->product_ref; $product_static->id = $objp->product_id; diff --git a/htdocs/adherents/agenda.php b/htdocs/adherents/agenda.php index 4b59039d313..cb942ba3176 100644 --- a/htdocs/adherents/agenda.php +++ b/htdocs/adherents/agenda.php @@ -39,8 +39,8 @@ $langs->loadLangs(array("companies", "members")); $id = GETPOST('id', 'int') ?GETPOST('id', 'int') : GETPOST('rowid', 'int'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index d7d72f70540..a2e3779d52b 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -949,7 +949,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print load_fiche_titre($langs->trans("NewMember"), '', $object->picto); if ($conf->use_javascript_ajax) { - print "\n".''."\n"; + $urlforjs = dol_buildpath($jsfile, 1); + if ($urlforjs && $urlforjs != '/') { + print ''."\n".''."\n"; + } else { + dol_syslog("Warning: module ".$modjs." declared a js path file for a file we can't find.", LOG_WARNING); + } } } } @@ -2929,7 +2941,7 @@ function left_menu($menu_array_before, $helppagename = '', $notused = '', $menu_ */ function main_area($title = '') { - global $conf, $langs; + global $conf, $langs, $hookmanager; if (empty($conf->dol_hide_leftmenu)) { print '
'; @@ -2939,14 +2951,17 @@ function main_area($title = '') print ''."\n".'
'."\n"; + $hookmanager->initHooks(array('main')); + $parameters = array(); + $reshook = $hookmanager->executeHooks('printMainArea', $parameters); // Note that $action and $object may have been modified by some hooks + print $hookmanager->resPrint; + if (!empty($conf->global->MAIN_ONLY_LOGIN_ALLOWED)) { print info_admin($langs->trans("WarningYouAreInMaintenanceMode", $conf->global->MAIN_ONLY_LOGIN_ALLOWED), 0, 0, 1, 'warning maintenancemode'); } // Permit to add user company information on each printed document by setting SHOW_SOCINFO_ON_PRINT if (!empty($conf->global->SHOW_SOCINFO_ON_PRINT) && GETPOST('optioncss', 'aZ09') == 'print' && empty(GETPOST('disable_show_socinfo_on_print', 'az09'))) { - global $hookmanager; - $hookmanager->initHooks(array('main')); $parameters = array(); $reshook = $hookmanager->executeHooks('showSocinfoOnPrint', $parameters); if (empty($reshook)) { diff --git a/htdocs/margin/customerMargins.php b/htdocs/margin/customerMargins.php index 7fe151b93f7..290a94908c0 100644 --- a/htdocs/margin/customerMargins.php +++ b/htdocs/margin/customerMargins.php @@ -129,8 +129,8 @@ if ($socid > 0) { print ''; } -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); if (!$sortorder) { $sortorder = "ASC"; } diff --git a/htdocs/margin/tabs/productMargins.php b/htdocs/margin/tabs/productMargins.php index 062462be267..93895b01e2f 100644 --- a/htdocs/margin/tabs/productMargins.php +++ b/htdocs/margin/tabs/productMargins.php @@ -43,8 +43,8 @@ if (!empty($user->socid)) { $object = new Product($db); $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/margin/tabs/thirdpartyMargins.php b/htdocs/margin/tabs/thirdpartyMargins.php index 43e9c87c6e6..c69c0443e28 100644 --- a/htdocs/margin/tabs/thirdpartyMargins.php +++ b/htdocs/margin/tabs/thirdpartyMargins.php @@ -35,8 +35,8 @@ if (!empty($user->socid)) { } $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index 7a92402224b..aa836842e71 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -32,7 +32,8 @@ * This script reads the conf file, init $lang, $db and and empty $user */ -// Declaration of variables. May have been already require by main.inc.php. But may not by scripts. So, here the require_once must be kept. +// Include the conf.php and functions.lib.php and security.lib.php. This defined the constants like DOL_DOCUMENT_ROOT, DOL_DATA_ROOT, DOL_URL_ROOT... +// This file may have been already required by main.inc.php. But may not by scripts. So, here the require_once must be kept. require_once 'filefunc.inc.php'; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index ac7522fed2e..4e66e655f5e 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -767,7 +767,7 @@ if ($dirins && $action == 'addlanguage' && !empty($module)) { // remove/delete File if ($dirins && $action == 'confirm_removefile' && !empty($module)) { - $relativefilename = dol_sanitizePathName(GETPOST('file', 'none')); + $relativefilename = dol_sanitizePathName(GETPOST('file', 'restricthtml')); if ($relativefilename) { $dirnametodelete = dirname($relativefilename); $filetodelete = $dirins.'/'.$relativefilename; diff --git a/htdocs/modulebuilder/template/lib/mymodule.lib.php b/htdocs/modulebuilder/template/lib/mymodule.lib.php index 32ae980e946..ab8a647efe4 100644 --- a/htdocs/modulebuilder/template/lib/mymodule.lib.php +++ b/htdocs/modulebuilder/template/lib/mymodule.lib.php @@ -62,7 +62,7 @@ function mymoduleAdminPrepareHead() //); // to remove a tab complete_head_from_modules($conf, $langs, null, $head, $h, 'mymodule@mymodule'); - complete_head_from_modules($conf, $langs, $object, $head, $h, 'mymodule@mymodule', 'remove'); + complete_head_from_modules($conf, $langs, null, $head, $h, 'mymodule@mymodule', 'remove'); return $head; } diff --git a/htdocs/modulebuilder/template/myobject_agenda.php b/htdocs/modulebuilder/template/myobject_agenda.php index b7d3fcfaa80..5eb4f6e3028 100644 --- a/htdocs/modulebuilder/template/myobject_agenda.php +++ b/htdocs/modulebuilder/template/myobject_agenda.php @@ -102,8 +102,8 @@ if (GETPOST('actioncode', 'array')) { $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'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/modulebuilder/template/myobject_document.php b/htdocs/modulebuilder/template/myobject_document.php index e77fec58167..3db0271dd01 100644 --- a/htdocs/modulebuilder/template/myobject_document.php +++ b/htdocs/modulebuilder/template/myobject_document.php @@ -92,8 +92,8 @@ $ref = GETPOST('ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/modulebuilder/template/scripts/mymodule.php b/htdocs/modulebuilder/template/scripts/mymodule.php index f0a7ca715a4..3f117a51094 100644 --- a/htdocs/modulebuilder/template/scripts/mymodule.php +++ b/htdocs/modulebuilder/template/scripts/mymodule.php @@ -40,7 +40,6 @@ //if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value //if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler //if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message -//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies //if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET //if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification if (!defined('NOSESSION')) define('NOSESSION', '1'); // On CLI mode, no need to use web sessions diff --git a/htdocs/mrp/index.php b/htdocs/mrp/index.php index c4480f76ed0..d9ee0e39cc6 100644 --- a/htdocs/mrp/index.php +++ b/htdocs/mrp/index.php @@ -155,7 +155,7 @@ print '
'; $max = 5; -$sql = "SELECT a.rowid, a.status, a.ref, a.tms as datem, a.status"; +$sql = "SELECT a.rowid, a.status, a.ref, a.tms as datem, a.status, a.fk_product"; $sql .= " FROM ".MAIN_DB_PREFIX."bom_bom as a"; $sql .= " WHERE a.entity IN (".getEntity('bom').")"; $sql .= $db->order("a.tms", "DESC"); @@ -176,6 +176,7 @@ if ($resql) { $staticbom->id = $obj->rowid; $staticbom->ref = $obj->ref; + $staticbom->fk_product = $obj->fk_product; $staticbom->date_modification = $obj->datem; $staticbom->status = $obj->status; diff --git a/htdocs/mrp/mo_agenda.php b/htdocs/mrp/mo_agenda.php index 95dab4e62ab..e1b19d87ad0 100644 --- a/htdocs/mrp/mo_agenda.php +++ b/htdocs/mrp/mo_agenda.php @@ -55,8 +55,8 @@ if (GETPOST('actioncode', 'array')) { $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'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/mrp/mo_document.php b/htdocs/mrp/mo_document.php index c81ed1f995e..acb5cb3e1c4 100644 --- a/htdocs/mrp/mo_document.php +++ b/htdocs/mrp/mo_document.php @@ -44,8 +44,8 @@ $ref = GETPOST('ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/mrp/mo_movements.php b/htdocs/mrp/mo_movements.php index f0fe25eddb6..10e430479cf 100644 --- a/htdocs/mrp/mo_movements.php +++ b/htdocs/mrp/mo_movements.php @@ -65,8 +65,8 @@ $search_type_mouvement = GETPOST('search_type_mouvement', 'int'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 diff --git a/htdocs/multicurrency/multicurrency_rate.php b/htdocs/multicurrency/multicurrency_rate.php index 2c32e0b03e8..73cff1b4502 100644 --- a/htdocs/multicurrency/multicurrency_rate.php +++ b/htdocs/multicurrency/multicurrency_rate.php @@ -55,8 +55,8 @@ $dateinput = dol_mktime(0, 0, 0, GETPOST('dateinputmonth', 'int'), GETPOST('d $rateinput = price2num(GETPOST('rateinput', 'alpha')); $optioncss = GETPOST('optioncss', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = (GETPOST("page", 'int') ?GETPOST("page", 'int') : 0); if (empty($page) || $page == -1) { diff --git a/htdocs/partnership/partnership_agenda.php b/htdocs/partnership/partnership_agenda.php index f154e1b9f5b..4c68a83d4e2 100644 --- a/htdocs/partnership/partnership_agenda.php +++ b/htdocs/partnership/partnership_agenda.php @@ -53,8 +53,8 @@ if (GETPOST('actioncode', 'array')) { $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'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/partnership/partnership_document.php b/htdocs/partnership/partnership_document.php index 79b7be0057a..f96eb6e58ec 100644 --- a/htdocs/partnership/partnership_document.php +++ b/htdocs/partnership/partnership_document.php @@ -43,8 +43,8 @@ $ref = GETPOST('ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/agenda.php b/htdocs/product/agenda.php index 815014e259f..40d451653e7 100644 --- a/htdocs/product/agenda.php +++ b/htdocs/product/agenda.php @@ -54,8 +54,8 @@ if ($user->socid) { } $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index e230d148026..32c4c83378c 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -47,7 +47,7 @@ if (empty($_GET['keysearch']) && !defined('NOREQUIREHTML')) { require '../../main.inc.php'; -$htmlname = GETPOST('htmlname', 'alpha'); +$htmlname = GETPOST('htmlname', 'aZ09'); $socid = GETPOST('socid', 'int'); $type = GETPOST('type', 'int'); $mode = GETPOST('mode', 'int'); @@ -73,7 +73,7 @@ restrictedArea($user, 'produit|service', 0, 'product&product'); // print ''."\n"; // print_r($_GET); -if (!empty($action) && $action == 'fetch' && !empty($id)) { +if ($action == 'fetch' && !empty($id)) { // action='fetch' is used to get product information on a product. So when action='fetch', id must be the product id. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; @@ -242,7 +242,7 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) { // Filter on the product to search can be: // Into an array with key $htmlname123 (we take first one found). Which page use this ? // Into a var with name $htmlname can be 'prodid', 'productid', ... - $match = preg_grep('/('.$htmlname.'[0-9]+)/', array_keys($_GET)); + $match = preg_grep('/('.preg_quote($htmlname, '/').'[0-9]+)/', array_keys($_GET)); sort($match); $idprod = (empty($match[0]) ? '' : $match[0]); // Take first key found into GET array with matching $htmlname123 diff --git a/htdocs/product/document.php b/htdocs/product/document.php index 230f8375538..79ff858ba6e 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -58,8 +58,8 @@ $hookmanager->initHooks(array('productdocuments')); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index b79fe5fb843..98ab414a8c3 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -63,10 +63,9 @@ $error = 0; $extrafields = new ExtraFields($db); // If socid provided by ajax company selector -if (!empty($_REQUEST['search_fourn_id'])) { +if (GETPOST('search_fourn_id', 'int')) { $_GET['id_fourn'] = GETPOST('search_fourn_id', 'int'); $_POST['id_fourn'] = GETPOST('search_fourn_id', 'int'); - $_REQUEST['id_fourn'] = GETPOST('search_fourn_id', 'int'); } // Security check @@ -81,8 +80,8 @@ if (empty($user->rights->fournisseur->lire)) { } $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = (GETPOST("page", 'int') ?GETPOST("page", 'int') : 0); if (empty($page) || $page == -1) { $page = 0; @@ -518,7 +517,7 @@ if ($id > 0 || $ref) { } else { $events = array(); $events[] = array('method' => 'getVatRates', 'url' => dol_buildpath('/core/ajax/vatrates.php', 1), 'htmlname' => 'tva_tx', 'params' => array()); - print $form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', 'fournisseur=1', 'SelectThirdParty', 0, 0, $events); + print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', 'fournisseur=1', 'SelectThirdParty', 0, 0, $events); $parameters = array('filtre'=>"fournisseur=1", 'html_name'=>'id_fourn', 'selected'=>GETPOST("id_fourn"), 'showempty'=>1, 'prod_id'=>$object->id); $reshook = $hookmanager->executeHooks('formCreateThirdpartyOptions', $parameters, $object, $action); diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 949158289a0..778565dd2cb 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -65,7 +65,12 @@ $search_barcode = GETPOST("search_barcode", 'alpha'); $search_label = GETPOST("search_label", 'alpha'); $search_type = GETPOST("search_type", 'int'); $search_vatrate = GETPOST("search_vatrate", 'alpha'); -$searchCategoryProductOperator = (GETPOST('search_category_product_operator', 'int') ? GETPOST('search_category_product_operator', 'int') : 0); +$searchCategoryProductOperator = 0; +if (GETPOSTISSET('formfilteraction')) { + $searchCategoryProductOperator = GETPOST('search_category_product_operator', 'int'); +} elseif (!empty($conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT)) { + $searchCategoryProductOperator = $conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT; +} $searchCategoryProductList = GETPOST('search_category_product_list', 'array'); $search_tosell = GETPOST("search_tosell", 'int'); $search_tobuy = GETPOST("search_tobuy", 'int'); @@ -94,8 +99,8 @@ if (!empty($conf->variants->enabled) && !empty($conf->global->PRODUIT_ATTRIBUTES $diroutputmassaction = $conf->product->dir_output.'/temp/massgeneration/'.$user->id; $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$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')) { $page = 0; diff --git a/htdocs/product/popuprop.php b/htdocs/product/popuprop.php index 9028e81a757..707f95d2202 100644 --- a/htdocs/product/popuprop.php +++ b/htdocs/product/popuprop.php @@ -44,8 +44,8 @@ if (!empty($user->socid)) { } $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 309853a7bb6..d21574e696e 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -143,15 +143,35 @@ if (empty($reshook)) { $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; - $sql .= " AND t.code ='".$db->escape($vatratecode)."'"; + $sql .= " AND t.code = '".$db->escape($vatratecode)."'"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $npr = $obj->recuperableonly; - $localtax1 = $obj->localtax1; - $localtax2 = $obj->localtax2; - $localtax1_type = $obj->localtax1_type; - $localtax2_type = $obj->localtax2_type; + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } + } + } else { + // Get record with empty code + $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; + $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; + $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; + $sql .= " AND t.code = ''"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } } } @@ -258,11 +278,37 @@ if (empty($reshook)) { $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $npr = $obj->recuperableonly; - $localtax1 = $obj->localtax1; - $localtax2 = $obj->localtax2; - $localtax1_type = $obj->localtax1_type; - $localtax2_type = $obj->localtax2_type; + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } + + // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. + if (in_array($mysoc->country_code, array('ES'))) { + $localtax1 = get_localtax($tva_tx, 1); + $localtax2 = get_localtax($tva_tx, 2); + } + } + } else { + // Get record with empty code + $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; + $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; + $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; + $sql .= " AND t.code = ''"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } } } @@ -311,19 +357,40 @@ if (empty($reshook)) { $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $npr = $obj->recuperableonly; - $localtax1 = $obj->localtax1; - $localtax2 = $obj->localtax2; - $localtax1_type = $obj->localtax1_type; - $localtax2_type = $obj->localtax2_type; + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } - // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule + // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. if (in_array($mysoc->country_code, array('ES'))) { $localtax1 = get_localtax($tva_tx, 1); $localtax2 = get_localtax($tva_tx, 2); } } + } else { + // Get record with empty code + $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; + $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; + $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; + $sql .= " AND t.code = ''"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } + } } + $pricestoupdate[0] = array( 'price' => $newprice, 'price_min' => $newprice_min, @@ -534,11 +601,37 @@ if (empty($reshook)) { $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $npr = $obj->recuperableonly; - $localtax1 = $obj->localtax1; - $localtax2 = $obj->localtax2; - $localtax1_type = $obj->localtax1_type; - $localtax2_type = $obj->localtax2_type; + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } + + // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. + if (in_array($mysoc->country_code, array('ES'))) { + $localtax1 = get_localtax($tva_tx, 1); + $localtax2 = get_localtax($tva_tx, 2); + } + } + } else { + // Get record with empty code + $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; + $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; + $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; + $sql .= " AND t.code = ''"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } } } @@ -627,11 +720,37 @@ if (empty($reshook)) { $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $npr = $obj->recuperableonly; - $localtax1 = $obj->localtax1; - $localtax2 = $obj->localtax2; - $localtax1_type = $obj->localtax1_type; - $localtax2_type = $obj->localtax2_type; + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } + + // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. + if (in_array($mysoc->country_code, array('ES'))) { + $localtax1 = get_localtax($tva_tx, 1); + $localtax2 = get_localtax($tva_tx, 2); + } + } + } else { + // Get record with empty code + $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; + $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; + $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; + $sql .= " AND t.code = ''"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $npr = $obj->recuperableonly; + $localtax1 = $obj->localtax1; + $localtax2 = $obj->localtax2; + $localtax1_type = $obj->localtax1_type; + $localtax2_type = $obj->localtax2_type; + } } } @@ -829,22 +948,23 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ } // TVA + print ''; print ''.$langs->trans("DefaultTaxRate").''; $positiverates = ''; if (price2num($object->tva_tx)) { - $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx); + $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx); } if (price2num($object->localtax1_type)) { - $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx); + $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx); } if (price2num($object->localtax2_type)) { - $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx); + $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } - echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), '%', $object->tva_npr); + print vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr, 1); /* if ($object->default_vat_code) { @@ -1671,8 +1791,8 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { $prodcustprice = new Productcustomerprice($db); $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; - $sortfield = GETPOST("sortfield", 'alpha'); - $sortorder = GETPOST("sortorder", 'alpha'); + $sortfield = GETPOST('sortfield', 'aZ09comma'); + $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = (GETPOST("page", 'int') ?GETPOST("page", 'int') : 0); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index b0a1ce87ddd..62bfd626f82 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -48,8 +48,8 @@ $tobuy = GETPOST("tobuy"); $fourn_id = GETPOST("fourn_id", 'int'); $sbarcode = GETPOST("sbarcode", 'int'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page < 0) { $page = 0; diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index e75d1504267..2bd62b2ce22 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -52,8 +52,8 @@ $tobuy = GETPOST("tobuy"); $fourn_id = GETPOST("fourn_id", 'int'); $sbarcode = GETPOST("sbarcode", 'int'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page < 0) { $page = 0; diff --git a/htdocs/product/stats/bom.php b/htdocs/product/stats/bom.php index ef4923e89be..b7c4321dfd1 100644 --- a/htdocs/product/stats/bom.php +++ b/htdocs/product/stats/bom.php @@ -50,8 +50,8 @@ $option = ''; // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; @@ -129,11 +129,11 @@ if ($id > 0 || !empty($ref)) { //Calcul total qty and amount for global if full scan list $total_qty_toconsume = 0; $total_qty_toproduce = 0; + $product_cache=array(); $bom_data_result = array(); - //Qauntity to produce - $sql = "SELECT b.rowid as rowid, b.ref, b.status, b.date_valid,"; + $sql = "SELECT b.rowid as rowid, b.ref, b.status, b.date_valid, b.fk_product,"; $sql .= " b.qty as qty_toproduce"; $sql .= " FROM ".MAIN_DB_PREFIX."bom_bom as b"; $sql .= " WHERE "; @@ -166,7 +166,20 @@ if ($id > 0 || !empty($ref)) { $objp = $db->fetch_object($result); $bomtmp->id = $objp->rowid; $bomtmp->ref = $objp->ref; + $product = new Product($db); + if (!empty($objp->fk_product)) { + if (!array_key_exists($product->id, $product_cache)) { + $resultFetch = $product->fetch($objp->fk_product); + if ($resultFetch < 0) { + setEventMessages($product->error, $product->errors, 'errors'); + } else { + $product_cache[$product->id] = $product; + } + } + } + $bomtmp->fk_product = $objp->fk_product; $bom_data_result[$objp->rowid]['link'] = $bomtmp->getNomUrl(1, 'production'); + $bom_data_result[$objp->rowid]['product'] = (array_key_exists($objp->fk_product, $product_cache)? $product_cache[$objp->fk_product]->getNomUrl(1): ''); $bom_data_result[$objp->rowid]['qty_toproduce'] += ($objp->qty_toproduce > 0 ? $objp->qty_toproduce : 0); $bom_data_result[$objp->rowid]['qty_toconsume'] = 0; $bom_data_result[$objp->rowid]['date_valid'] = dol_print_date($db->jdate($objp->date_valid), 'dayhour'); @@ -180,7 +193,7 @@ if ($id > 0 || !empty($ref)) { $db->free($result); //Qauntity to consume - $sql = "SELECT b.rowid as rowid, b.ref, b.status, b.date_valid,"; + $sql = "SELECT b.rowid as rowid, b.ref, b.status, b.date_valid, b.fk_product,"; $sql .= " SUM(bl.qty) as qty_toconsume"; $sql .= " FROM ".MAIN_DB_PREFIX."bom_bom as b"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."bom_bomline as bl ON bl.fk_bom=b.rowid"; @@ -214,9 +227,22 @@ if ($id > 0 || !empty($ref)) { $objp = $db->fetch_object($result); $bomtmp->id = $objp->rowid; $bomtmp->ref = $objp->ref; + $product = new Product($db); + if (!empty($objp->fk_product)) { + if (!array_key_exists($product->id, $product_cache)) { + $resultFetch = $product->fetch($objp->fk_product); + if ($resultFetch < 0) { + setEventMessages($product->error, $product->errors, 'errors'); + } else { + $product_cache[$product->id] = $product; + } + } + } + $bomtmp->fk_product = $objp->fk_product; if (!array_key_exists($objp->rowid, $bom_data_result)) { $bom_data_result[$objp->rowid]['link'] = $bomtmp->getNomUrl(1, 'production'); + $bom_data_result[$objp->rowid]['product'] = (array_key_exists($objp->fk_product, $product_cache)? $product_cache[$objp->fk_product]->getNomUrl(1): ''); $bom_data_result[$objp->rowid]['qty_toproduce'] = 0; $bom_data_result[$objp->rowid]['qty_toconsume'] += ($objp->qty_toconsume > 0 ? $objp->qty_toconsume : 0); $bom_data_result[$objp->rowid]['date_valid'] = dol_print_date($db->jdate($objp->date_valid), 'dayhour'); @@ -232,7 +258,6 @@ if ($id > 0 || !empty($ref)) { } $db->free($result); - if ($limit > 0 && $limit != $conf->liste_limit) { $option .= '&limit='.urlencode($limit); } @@ -265,6 +290,7 @@ if ($id > 0 || !empty($ref)) { print ''; print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "b.rowid", "", "&id=".$product->id, '', $sortfield, $sortorder); + print_liste_field_titre("Product", $_SERVER["PHP_SELF"], "b.fk_product", "", "&id=".$product->id, '', $sortfield, $sortorder); print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "b.date_valid", "", "&id=".$product->id, 'align="center"', $sortfield, $sortorder); print_liste_field_titre("RowMaterial", $_SERVER["PHP_SELF"], "", "", "&id=".$product->id, '', $sortfield, $sortorder, 'center '); print_liste_field_titre("Finished", $_SERVER["PHP_SELF"], "", "", "&id=".$product->id, '', $sortfield, $sortorder, 'center '); @@ -277,6 +303,9 @@ if ($id > 0 || !empty($ref)) { print ''; print $data['link']; print "\n"; + print ''; + print $data['product']; + print "\n"; print ""; print $data['date_valid'].""; print ''.$data['qty_toconsume'].''; diff --git a/htdocs/product/stats/commande.php b/htdocs/product/stats/commande.php index abfd329dfa4..9f38f68ee33 100644 --- a/htdocs/product/stats/commande.php +++ b/htdocs/product/stats/commande.php @@ -49,8 +49,8 @@ $hookmanager->initHooks(array('productstatsorder')); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/stats/contrat.php b/htdocs/product/stats/contrat.php index e44619d1b19..0c569d3530c 100644 --- a/htdocs/product/stats/contrat.php +++ b/htdocs/product/stats/contrat.php @@ -46,8 +46,8 @@ $hookmanager->initHooks(array('productstatscontract')); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/stats/facture.php b/htdocs/product/stats/facture.php index 8da6e97f55c..13c6329b34f 100644 --- a/htdocs/product/stats/facture.php +++ b/htdocs/product/stats/facture.php @@ -52,8 +52,8 @@ $showmessage = GETPOST('showmessage'); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/stats/facture_fournisseur.php b/htdocs/product/stats/facture_fournisseur.php index d61b6de9491..9db71e92148 100644 --- a/htdocs/product/stats/facture_fournisseur.php +++ b/htdocs/product/stats/facture_fournisseur.php @@ -50,8 +50,8 @@ $hookmanager->initHooks(array('productstatssupplierinvoice')); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/stats/mo.php b/htdocs/product/stats/mo.php index c63034e95a6..693f1fbae03 100644 --- a/htdocs/product/stats/mo.php +++ b/htdocs/product/stats/mo.php @@ -46,8 +46,8 @@ $hookmanager->initHooks(array('productstatsmo')); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php index ffa593639b5..18a394559a3 100644 --- a/htdocs/product/stock/card.php +++ b/htdocs/product/stock/card.php @@ -54,8 +54,8 @@ $id = GETPOST('id', 'int'); $socid = GETPOST('socid', 'int'); $ref = GETPOST('ref', 'alpha'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); if (!$sortfield) { $sortfield = "p.ref"; } diff --git a/htdocs/product/stock/movement_card.php b/htdocs/product/stock/movement_card.php index f9c0778eea4..ebe8f0552ce 100644 --- a/htdocs/product/stock/movement_card.php +++ b/htdocs/product/stock/movement_card.php @@ -75,8 +75,8 @@ $search_type_mouvement = GETPOST('search_type_mouvement', 'int'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php index ed5896ca6cc..405528a3480 100644 --- a/htdocs/product/stock/movement_list.php +++ b/htdocs/product/stock/movement_list.php @@ -84,14 +84,19 @@ $search_fk_projet=GETPOST("search_fk_projet", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); $type = GETPOST("type", "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'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); -if (empty($page) || $page == -1) { +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + // If $page is not defined, or '' or -1 or if we click on clear filters $page = 0; -} // If $page is not defined, or '' or -1 +} $offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + if (!$sortfield) { $sortfield = "m.datem"; } @@ -103,8 +108,10 @@ $pdluoid = GETPOST('pdluoid', 'int'); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $object = new MouvementStock($db); -$hookmanager->initHooks(array('movementlist')); $extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->stock->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('movementlist')); + $formfile = new FormFile($db); // fetch optionals attributes and labels @@ -156,6 +163,8 @@ if (!$user->rights->stock->mouvement->lire) { accessforbidden(); } +$uploaddir = $conf->stock->dir_output.'/movements'; + $permissiontoread = $user->rights->stock->mouvement->lire; $permissiontoadd = $user->rights->stock->mouvement->creer; $permissiontodelete = $user->rights->stock->mouvement->creer; // There is no deletion permission for stock movement as we shoul dnever delete @@ -172,7 +181,8 @@ $error = 0; */ if (GETPOST('cancel', 'alpha')) { - $action = 'list'; $massaction = ''; + $action = 'list'; + $massaction = ''; } if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; @@ -185,9 +195,10 @@ if ($reshook < 0) { } if (empty($reshook)) { + // Selection of new fields include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; - // Do we click on purge search criteria ? + // Purge search criteria if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // Both test are required to be compatible with all browsers $search_date_startday = ''; $search_date_startmonth = ''; @@ -212,11 +223,92 @@ if (empty($reshook)) { $toselect = ''; $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 = 'MouvementStock'; $objectlabel = 'MouvementStock'; - $uploaddir = $conf->stock->dir_output; + + if (!$error && $massaction == "builddoc" && $permissiontoread && !GETPOST('button_search')) { + if (empty($diroutputmassaction)) { + dol_print_error(null, 'include of actions_massactions.inc.php is done but var $diroutputmassaction was not defined'); + exit; + } + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + + $objecttmp = new $objectclass($db); + $listofobjectid = array(); + foreach ($toselect as $toselectid) { + $objecttmp = new $objectclass($db); // must create new instance because instance is saved into $listofobjectref array for future use + $result = $objecttmp->fetch($toselectid); + if ($result > 0) { + $listofobjectid[$toselectid] = $toselectid; + } + } + + $arrayofinclusion = array(); + foreach ($listofobjectref as $tmppdf) { + $arrayofinclusion[] = '^'.preg_quote(dol_sanitizeFileName($tmppdf), '/').'\.pdf$'; + } + foreach ($listofobjectref as $tmppdf) { + $arrayofinclusion[] = '^'.preg_quote(dol_sanitizeFileName($tmppdf), '/').'_[a-zA-Z0-9-_]+\.pdf$'; // To include PDF generated from ODX files + } + $listoffiles = dol_dir_list($uploaddir, 'all', 1, implode('|', $arrayofinclusion), '\.meta$|\.png', 'date', SORT_DESC, 0, true); + + // Define output language (Here it is not used because we do only merging existing PDF) + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); + } + //elseif ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($objecttmp->thirdparty)) { // On massaction, we can have several values for $objecttmp->thirdparty + // $newlang = $objecttmp->thirdparty->default_lang; + //} + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + + // Create output dir if not exists + dol_mkdir($diroutputmassaction); + + // Defined name of merged file + $filename = strtolower(dol_sanitizeFileName($langs->transnoentities($objectlabel))); + $filename = preg_replace('/\s/', '_', $filename); + + // Save merged file + /* + if ($year) { + $filename .= '_'.$year; + } + if ($month) { + $filename .= '_'.$month; + } + */ + $now = dol_now(); + $file = $diroutputmassaction.'/'.$filename.'_'.dol_print_date($now, 'dayhourlog').'.pdf'; + + + // Create PDF + // TODO Create the pdf including list of movement ids found into $listofobjectid + // ... + + + if (!$error) { + $langs->load("exports"); + setEventMessages($langs->trans('FileSuccessfullyBuilt', $filename.'_'.dol_print_date($now, 'dayhourlog')), null, 'mesgs'); + } + + $massaction = ''; + $action = ''; + } + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } @@ -482,6 +574,8 @@ if (!empty($conf->projet->enabled)) { $formproject = new FormProjets($db); } +// Build and execute select +// -------------------------------------------------------------------- $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tosell, p.tobuy, p.tobatch, p.fk_product_type as type, p.entity,"; $sql .= " e.ref as warehouse_ref, e.rowid as entrepot_id, e.lieu, e.fk_parent, e.statut,"; $sql .= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,"; @@ -499,7 +593,8 @@ if (!empty($extrafields->attributes[$object->table_element]['label'])) { // Add fields from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook -$sql .= $hookmanager->resPrint; +$sql .= preg_replace('/^,/', '', $hookmanager->resPrint); +$sql = preg_replace('/,\s*$/', '', $sql); $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,"; $sql .= " ".MAIN_DB_PREFIX."product as p,"; $sql .= " ".MAIN_DB_PREFIX."stock_mouvement as m"; @@ -572,6 +667,31 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // 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)) { @@ -589,20 +709,19 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { $resql = $db->query($sqlforcount); $objforcount = $db->fetch_object($resql); $nbtotalofrecords = $objforcount->nbtotalofrecords; - if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 + 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); } -//print $sql; - $resql = $db->query($sql); if (!$resql) { dol_print_error($db); @@ -624,20 +743,24 @@ if ($id > 0 || $ref) { $num = $db->num_rows($resql); -$arrayofselected = is_array($toselect) ? $toselect : array(); +// Output page +// -------------------------------------------------------------------- $i = 0; $help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; if ($msid) { - $texte = $langs->trans('StockMovementForId', $msid); + $title = $langs->trans('StockMovementForId', $msid); } else { - $texte = $langs->trans("ListOfStockMovements"); + $title = $langs->trans("ListOfStockMovements"); if ($id) { - $texte .= ' ('.$langs->trans("ForThisWarehouse").')'; + $title .= ' ('.$langs->trans("ForThisWarehouse").')'; } } -llxHeader("", $texte, $help_url); + +llxHeader('', $title, $help_url); + +$arrayofselected = is_array($toselect) ? $toselect : array(); /* * Show tab only if we ask a particular warehouse @@ -774,26 +897,20 @@ if ($object->id > 0) { } -/* - * Correct stock - */ +// Correct stock if ($action == "correction") { include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stockcorrection.tpl.php'; print '
'; } -/* - * Transfer of units - */ +// Transfer of units if ($action == "transfert") { include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stocktransfer.tpl.php'; print '
'; } -/* - * Action bar - */ +// Action bar if ((empty($action) || $action == 'list') && $id > 0) { print "
\n"; @@ -867,12 +984,11 @@ if ($idproduct > 0) { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; // List of mass actions available -$arrayofmassactions = array( - 'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), -// 'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), -// 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), -); -// By default, we should never accept deletion of stock movement. +$arrayofmassactions = array(); +if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { + $arrayofmassactions['builddoc'] = img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("GeneratePDF"); +} +// By default, we should never accept deletion of stock movement if (!empty($conf->global->STOCK_ALLOW_DELETE_OF_MOVEMENT) && $permissiontodelete) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } @@ -881,7 +997,7 @@ if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'pr } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); -print '
'; +print ''."\n"; if ($optioncss != '') { print ''; } @@ -891,15 +1007,16 @@ print ''; print ''; print ''; print ''; +print ''; print ''; if ($id > 0) { print ''; } if ($id > 0) { - print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1); + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1); } else { - print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1); + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1); } // Add code for pre mass action (confirmation or email presend form) @@ -919,7 +1036,7 @@ if ($sall) { $moreforfilter = ''; $parameters = array('arrayfields'=>&$arrayfields); -$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $moreforfilter .= $hookmanager->resPrint; } else { @@ -934,12 +1051,14 @@ if (!empty($moreforfilter)) { $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 '
'; -print ''."\n"; +print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print '
'."\n"; // Fields title search -print ''; +// -------------------------------------------------------------------- +print ''; if (!empty($arrayfields['m.rowid']['checked'])) { // Ref print ''; } -// Actions +// Action column print ''; -print "\n"; +print ''."\n"; + +// Fields title label +// -------------------------------------------------------------------- print ''; if (!empty($arrayfields['m.rowid']['checked'])) { print_liste_field_titre($arrayfields['m.rowid']['label'], $_SERVER["PHP_SELF"], 'm.rowid', '', $param, '', $sortfield, $sortorder); @@ -1127,7 +1249,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; // Hook fields $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); -$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; if (!empty($arrayfields['m.datec']['checked'])) { print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap '); @@ -1135,32 +1257,39 @@ if (!empty($arrayfields['m.datec']['checked'])) { if (!empty($arrayfields['m.tms']['checked'])) { print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); } +// Action column print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); -print "\n"; +print ''."\n"; $arrayofuniqueproduct = array(); + +// Loop on record +// -------------------------------------------------------------------- $i = 0; $totalarray = array(); $totalarray['nbfield'] = 0; -while ($i < min($num, $limit)) { - $objp = $db->fetch_object($resql); +while ($i < ($limit ? min($num, $limit) : $num)) { + $obj = $db->fetch_object($resql); + if (empty($obj)) { + break; // Should not happen + } - $userstatic->id = $objp->fk_user_author; - $userstatic->login = $objp->login; - $userstatic->lastname = $objp->lastname; - $userstatic->firstname = $objp->firstname; - $userstatic->photo = $objp->photo; - $userstatic->email = $objp->user_email; - $userstatic->statut = $objp->user_status; + $userstatic->id = $obj->fk_user_author; + $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->photo = $obj->photo; + $userstatic->email = $obj->user_email; + $userstatic->statut = $obj->user_status; // Multilangs if (!empty($conf->global->MAIN_MULTILANGS)) { // If multilang is enabled // TODO Use a cache $sql = "SELECT label"; $sql .= " FROM ".MAIN_DB_PREFIX."product_lang"; - $sql .= " WHERE fk_product = ".((int) $objp->rowid); + $sql .= " WHERE fk_product = ".((int) $obj->rowid); $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'"; $sql .= " LIMIT 1"; @@ -1168,37 +1297,37 @@ while ($i < min($num, $limit)) { if ($result) { $objtp = $db->fetch_object($result); if (!empty($objtp->label)) { - $objp->produit = $objtp->label; + $obj->produit = $objtp->label; } } } - $productstatic->id = $objp->rowid; - $productstatic->ref = $objp->product_ref; - $productstatic->label = $objp->produit; - $productstatic->type = $objp->type; - $productstatic->entity = $objp->entity; - $productstatic->status = $objp->tosell; - $productstatic->status_buy = $objp->tobuy; - $productstatic->status_batch = $objp->tobatch; + $productstatic->id = $obj->rowid; + $productstatic->ref = $obj->product_ref; + $productstatic->label = $obj->produit; + $productstatic->type = $obj->type; + $productstatic->entity = $obj->entity; + $productstatic->status = $obj->tosell; + $productstatic->status_buy = $obj->tobuy; + $productstatic->status_batch = $obj->tobatch; - $productlot->id = $objp->lotid; - $productlot->batch = $objp->batch; - $productlot->eatby = $objp->eatby; - $productlot->sellby = $objp->sellby; + $productlot->id = $obj->lotid; + $productlot->batch = $obj->batch; + $productlot->eatby = $obj->eatby; + $productlot->sellby = $obj->sellby; - $warehousestatic->id = $objp->entrepot_id; - $warehousestatic->ref = $objp->warehouse_ref; - $warehousestatic->label = $objp->warehouse_ref; - $warehousestatic->lieu = $objp->lieu; - $warehousestatic->fk_parent = $objp->fk_parent; - $warehousestatic->statut = $objp->statut; + $warehousestatic->id = $obj->entrepot_id; + $warehousestatic->ref = $obj->warehouse_ref; + $warehousestatic->label = $obj->warehouse_ref; + $warehousestatic->lieu = $obj->lieu; + $warehousestatic->fk_parent = $obj->fk_parent; + $warehousestatic->statut = $obj->statut; - $movement->type = $objp->type_mouvement; + $movement->type = $obj->type_mouvement; - $arrayofuniqueproduct[$objp->rowid] = $objp->produit; - if (!empty($objp->fk_origin)) { - $origin = $movement->get_origin($objp->fk_origin, $objp->origintype); + $arrayofuniqueproduct[$obj->rowid] = $obj->produit; + if (!empty($obj->fk_origin)) { + $origin = $movement->get_origin($obj->fk_origin, $obj->origintype); } else { $origin = ''; } @@ -1208,12 +1337,12 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['m.rowid']['checked'])) { print ''; // This is primary not movement id } if (!empty($arrayfields['m.datem']['checked'])) { // Date - print ''; + print ''; } if (!empty($arrayfields['p.ref']['checked'])) { // Product ref @@ -1237,10 +1366,10 @@ while ($i < min($num, $limit)) { print ''; } if (!empty($arrayfields['pl.eatby']['checked'])) { - print ''; + print ''; } if (!empty($arrayfields['pl.sellby']['checked'])) { - print ''; + print ''; } // Warehouse if (!empty($arrayfields['e.ref']['checked'])) { @@ -1256,11 +1385,11 @@ while ($i < min($num, $limit)) { } if (!empty($arrayfields['m.inventorycode']['checked'])) { // Inventory code - print ''; + print ''; } if (!empty($arrayfields['m.label']['checked'])) { // Label of movement - print ''; + print ''; } if (!empty($arrayfields['origin']['checked'])) { // Origin of movement @@ -1269,8 +1398,8 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['m.fk_projet']['checked'])) { // fk_project print ''; } @@ -1283,14 +1412,14 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['m.value']['checked'])) { // Qty print ''; @@ -1298,8 +1427,8 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['m.price']['checked'])) { // Price print ''; } @@ -1307,25 +1436,26 @@ while ($i < min($num, $limit)) { // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'objp'=>$objp, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by 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"; + print ''."\n"; + $i++; } @@ -1365,6 +1495,26 @@ if (count($arrayofuniqueproduct) == 1 && is_numeric($year)) { //print ''; } +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_mymodule', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); +} + // End of page llxFooter(); $db->close(); diff --git a/htdocs/product/stock/productlot_document.php b/htdocs/product/stock/productlot_document.php index 4f695f990e4..789b03aa6ce 100644 --- a/htdocs/product/stock/productlot_document.php +++ b/htdocs/product/stock/productlot_document.php @@ -58,8 +58,8 @@ $hookmanager->initHooks(array('productlotdocuments')); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 695e4356582..23e93aba785 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -623,7 +623,7 @@ if (empty($reshook)) { } print '
'; -print ''; +print ''; print '
'; print ''; diff --git a/htdocs/product/stock/replenishorders.php b/htdocs/product/stock/replenishorders.php index 91ff0b40fbc..1eba8556753 100644 --- a/htdocs/product/stock/replenishorders.php +++ b/htdocs/product/stock/replenishorders.php @@ -37,11 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; // Load translation files required by the page $langs->loadLangs(array('products', 'stocks', 'orders')); -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'produit|service'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'replenishorders'; // To manage different context of search $sall = GETPOST('search_all', 'alphanohtml'); $sref = GETPOST('search_ref', 'alpha'); @@ -56,8 +52,8 @@ $search_dateday = GETPOST('search_dateday', 'int'); $search_date = dol_mktime(0, 0, 0, $search_datemonth, $search_dateday, $search_dateyear); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); if (!$sortorder) { $sortorder = 'DESC'; } @@ -70,6 +66,12 @@ if ($page < 0) { } $offset = $limit * $page; +// Security check +if ($user->socid) { + $socid = $user->socid; +} +$result = restrictedArea($user, 'produit|service'); + /* * Actions @@ -171,9 +173,10 @@ if ($resql) { $num = $db->num_rows($resql); $i = 0; - print ''.$langs->trans("ReplenishmentOrdersDesc").'

'; + print ''; + print ''; - print ''; + print ''.$langs->trans("ReplenishmentOrdersDesc").'
'; print_barre_liste('', $page, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, '', $num, 0, ''); @@ -209,6 +212,7 @@ if ($resql) { $param .= '&optioncss='.urlencode($optioncss); } + print '
'; print '
'; @@ -1052,7 +1171,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; // Fields from hook $parameters = array('arrayfields'=>$arrayfields); -$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Date creation if (!empty($arrayfields['m.datec']['checked'])) { @@ -1064,13 +1183,16 @@ if (!empty($arrayfields['m.tms']['checked'])) { print ''; print ''; -$searchpicto = $form->showFilterAndCheckAddButtons(0); +$searchpicto = $form->showFilterButtons(); print $searchpicto; print '
'; print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"'); - print $objp->mid; + print $obj->mid; print ''.dol_print_date($db->jdate($objp->datem), 'dayhour', 'tzuserrel').''.dol_print_date($db->jdate($obj->datem), 'dayhour', 'tzuserrel').''.dol_print_date($objp->eatby, 'day').''.dol_print_date($obj->eatby, 'day').''.dol_print_date($objp->sellby, 'day').''.dol_print_date($obj->sellby, 'day').'inventorycode.'$').'&search_type_mouvement='.urlencode($objp->type_mouvement).'">'.$objp->inventorycode.'inventorycode.'$').'&search_type_mouvement='.urlencode($obj->type_mouvement).'">'.$obj->inventorycode.''.$objp->label.''.$obj->label.''; - if ($objp->fk_project != 0) { - print $movement->get_origin($objp->fk_project, 'project'); + if ($obj->fk_project != 0) { + print $movement->get_origin($obj->fk_project, 'project'); } print ''; - if ($objp->qty > 0) { + if ($obj->qty > 0) { print ''; print '+'; - print $objp->qty; + print $obj->qty; print ''; } else { print ''; - print $objp->qty; + print $obj->qty; print ''; } print ''; - if ($objp->price != 0) { - print price($objp->price); + if ($obj->price != 0) { + print price($obj->price); } 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($objp->mid, $arrayofselected)) { + if (in_array($obj->mid, $arrayofselected)) { $selected = 1; } - print ''; + print ''; } print '
'; print ''; @@ -347,6 +351,8 @@ if ($resql) { $i++; } print '
'; + print '
'; + print ''; $db->free($resql); diff --git a/htdocs/product/stock/valo.php b/htdocs/product/stock/valo.php index 7f7f9610d1f..926b0c01634 100644 --- a/htdocs/product/stock/valo.php +++ b/htdocs/product/stock/valo.php @@ -36,8 +36,8 @@ $sref = GETPOST("sref", 'alpha'); $snom = GETPOST("snom", 'alpha'); $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); if (!$sortfield) { $sortfield = "e.ref"; } diff --git a/htdocs/projet/activity/perday.php b/htdocs/projet/activity/perday.php index 32e8fc40381..b743dffbc53 100644 --- a/htdocs/projet/activity/perday.php +++ b/htdocs/projet/activity/perday.php @@ -77,8 +77,8 @@ $search_project_ref = GETPOST('search_project_ref', 'alpha'); $search_thirdparty = GETPOST('search_thirdparty', 'alpha'); $search_declared_progress = GETPOST('search_declared_progress', 'alpha'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $monthofday = GETPOST('addtimemonth'); $dayofday = GETPOST('addtimeday'); diff --git a/htdocs/projet/activity/perweek.php b/htdocs/projet/activity/perweek.php index f84a7112504..763ecefe650 100644 --- a/htdocs/projet/activity/perweek.php +++ b/htdocs/projet/activity/perweek.php @@ -77,8 +77,8 @@ $search_project_ref = GETPOST('search_project_ref', 'alpha'); $search_thirdparty = GETPOST('search_thirdparty', 'alpha'); $search_declared_progress = GETPOST('search_declared_progress', 'alpha'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $startdayarray = dol_get_first_day_week($day, $month, $year); diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index dac2afa4834..d0b27caf326 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -165,6 +165,11 @@ class Task extends CommonObject $this->label = trim($this->label); $this->description = trim($this->description); + if (!empty($this->date_start) && !empty($this->date_end) && $this->date_start > $this->date_end) { + $this->errors[] = $langs->trans('StartDateCannotBeAfterEndDate'); + return -1; + } + // Check parameters // Put here code to add control on parameters values @@ -384,6 +389,11 @@ class Task extends CommonObject $this->budget_amount = trim($this->budget_amount); } + if (!empty($this->date_start) && !empty($this->date_end) && $this->date_start > $this->date_end) { + $this->errors[] = $langs->trans('StartDateCannotBeAfterEndDate'); + return -1; + } + // Check parameters // Put here code to add control on parameters values diff --git a/htdocs/projet/document.php b/htdocs/projet/document.php index 1bfbb9aa4a6..9e8d3a6ce8e 100644 --- a/htdocs/projet/document.php +++ b/htdocs/projet/document.php @@ -53,8 +53,8 @@ if ($id > 0 || !empty($ref)) { // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/projet/index.php b/htdocs/projet/index.php index e1f86bcffc9..51e78f23d57 100644 --- a/htdocs/projet/index.php +++ b/htdocs/projet/index.php @@ -56,8 +56,8 @@ if (!$user->rights->projet->lire) { accessforbidden(); } -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT; diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 4078afb20c0..6019011956a 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -198,6 +198,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; // Add non object fields to fields for list $arrayfields['s.nom'] = array('label'=>$langs->trans("ThirdParty"), 'checked'=>1, 'position'=>21, 'enabled'=>(empty($conf->societe->enabled) ? 0 : 1)); $arrayfields['commercial'] = array('label'=>$langs->trans("SaleRepresentativesOfThirdParty"), 'checked'=>0, 'position'=>23); +$arrayfields['c.assigned'] = array('label'=>$langs->trans("AssignedTo"), 'checked'=>-1, 'position'=>120); $arrayfields['opp_weighted_amount'] = array('label'=>$langs->trans('OpportunityWeightedAmountShort'), 'checked'=>0, 'position'=> 116, 'enabled'=>(empty($conf->global->PROJECT_USE_OPPORTUNITIES) ? 0 : 1), 'position'=>106); // Force some fields according to search_usage filter... if (GETPOST('search_usage_opportunity')) { @@ -911,7 +912,7 @@ if (!empty($arrayfields['p.public']['checked'])) { // Opp status if (!empty($arrayfields['p.fk_opp_status']['checked'])) { print ''; - print $formproject->selectOpportunityStatus('search_opp_status', $search_opp_status, 1, 0, 1, 0, 'maxwidth100'); + print $formproject->selectOpportunityStatus('search_opp_status', $search_opp_status, 1, 0, 1, 0, 'maxwidth100', 1); print ''; } if (!empty($arrayfields['p.opp_amount']['checked'])) { @@ -933,6 +934,10 @@ if (!empty($arrayfields['p.budget_amount']['checked'])) { print ''; print ''; } +if (!empty($arrayfields['c.assigned']['checked'])) { + print ''; + print ''; +} if (!empty($arrayfields['p.usage_opportunity']['checked'])) { print ''; print $form->selectyesno('search_usage_opportunity', $search_usage_opportunity, 1, false, 1); @@ -1003,7 +1008,7 @@ if (!empty($arrayfields['p.fk_statut']['checked'])) { $arrayofstatus[$key] = $langs->trans($val); } $arrayofstatus['99'] = $langs->trans("NotClosed").' ('.$langs->trans('Draft').' + '.$langs->trans('Opened').')'; - print $form->selectarray('search_status', $arrayofstatus, $search_status, 1, 0, 0, '', 0, 0, 0, '', 'minwidth75imp maxwidth150 selectarrowonleft'); + print $form->selectarray('search_status', $arrayofstatus, $search_status, 1, 0, 0, '', 0, 0, 0, '', 'minwidth75imp maxwidth125 selectarrowonleft'); print ajax_combobox('search_status'); print ''; } @@ -1052,6 +1057,9 @@ if (!empty($arrayfields['opp_weighted_amount']['checked'])) { if (!empty($arrayfields['p.budget_amount']['checked'])) { print_liste_field_titre($arrayfields['p.budget_amount']['label'], $_SERVER["PHP_SELF"], 'p.budget_amount', "", $param, '', $sortfield, $sortorder, 'right '); } +if (!empty($arrayfields['c.assigned']['checked'])) { + print_liste_field_titre($arrayfields['c.assigned']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', ''); +} if (!empty($arrayfields['p.usage_opportunity']['checked'])) { print_liste_field_titre($arrayfields['p.usage_opportunity']['label'], $_SERVER["PHP_SELF"], 'p.usage_opportunity', "", $param, '', $sortfield, $sortorder, 'right '); } @@ -1312,6 +1320,41 @@ while ($i < min($num, $limit)) { $totalarray['pos'][$totalarray['nbfield']] = 'p.budget_amount'; } } + // Contacts of project + if (!empty($arrayfields['c.assigned']['checked'])) { + print ''; + $ifisrt = 1; + foreach (array('internal', 'external') as $source) { + $tab = $object->liste_contact(-1, $source); + $numcontact = count($tab); + if (!empty($numcontact)) { + foreach ($tab as $contactproject) { + //var_dump($contacttask); + if ($source == 'internal') { + $c = new User($db); + } else { + $c = new Contact($db); + } + $c->fetch($contactproject['id']); + if (!empty($c->photo)) { + if (get_class($c) == 'User') { + print $c->getNomUrl(-2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst')); + } else { + print $c->getNomUrl(-2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst')); + } + } else { + if (get_class($c) == 'User') { + print $c->getNomUrl(2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst')); + } else { + print $c->getNomUrl(2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst')); + } + } + $ifisrt = 0; + } + } + } + print ''; + } // Usage opportunity if (!empty($arrayfields['p.usage_opportunity']['checked'])) { print ''; diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index e8c938d2156..dc482c1c60c 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -811,9 +811,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third $linktocreatetask = dolGetButtonTitle($langs->trans('AddTask'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/tasks.php?action=create'.$param.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$object->id), '', $linktocreatetaskUserRight, $linktocreatetaskParam); print '
'; - if ($optioncss != '') { - print ''; - } + print ''; print ''; print ''; print ''; diff --git a/htdocs/projet/tasks/document.php b/htdocs/projet/tasks/document.php index c60e3324741..155cb261040 100644 --- a/htdocs/projet/tasks/document.php +++ b/htdocs/projet/tasks/document.php @@ -46,8 +46,8 @@ $project_ref = GETPOST('project_ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index 1553c58683f..697969c6060 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -115,8 +115,8 @@ if (!$user->rights->projet->lire) { $diroutputmassaction = $conf->projet->dir_output.'/tasks/temp/massgeneration/'.$user->id; $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index 8feb682f023..8e773f92788 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -117,6 +117,7 @@ if ($action == 'update' && !GETPOST("cancel") && $user->rights->projet->creer) { $result = $object->update($user); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); + $action = 'edit'; } } } else { diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index f9f3a2aca43..bbf33b620c4 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -82,8 +82,8 @@ if (!$user->rights->projet->lire) { } $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/public/members/public_list.php b/htdocs/public/members/public_list.php index 80e092f2951..4bf2a6b94bf 100644 --- a/htdocs/public/members/public_list.php +++ b/htdocs/public/members/public_list.php @@ -92,8 +92,8 @@ function llxFooterVierge() } -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index 3aaa3676663..8bd95d23c8d 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -448,10 +448,8 @@ if ($action == "dosign" && empty($cancel)) { $("#clearsignature").on("click",function(){ $("#signature").jSignature("clear"); $("#signbutton").attr("disabled",true); - /* $("#clearsignature").css("display","none"); */ }); - /* $("#clearsignature").css("display","none"); */ $("#signbutton").attr("disabled",true); }); '; diff --git a/htdocs/public/ticket/create_ticket.php b/htdocs/public/ticket/create_ticket.php index 9efa561341e..6a3fd1aa688 100644 --- a/htdocs/public/ticket/create_ticket.php +++ b/htdocs/public/ticket/create_ticket.php @@ -173,7 +173,7 @@ if (empty($reshook) && $action == 'create_ticket' && GETPOST('save', 'alpha')) { // Check Captcha code if is enabled if (!empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA)) { $sessionkey = 'dol_antispam_value'; - $ok = (array_key_exists($sessionkey, $_SESSION) === true && (strtolower($_SESSION[$sessionkey]) === strtolower(GETPOST('code', 'none')))); + $ok = (array_key_exists($sessionkey, $_SESSION) === true && (strtolower($_SESSION[$sessionkey]) === strtolower(GETPOST('code', 'restricthtml')))); if (!$ok) { $error++; array_push($object->errors, $langs->trans("ErrorBadValueForCode")); diff --git a/htdocs/public/ticket/list.php b/htdocs/public/ticket/list.php index ef16b716db2..8a353eea881 100644 --- a/htdocs/public/ticket/list.php +++ b/htdocs/public/ticket/list.php @@ -294,8 +294,8 @@ if ($action == "view_ticketlist") { require DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; - $sortfield = GETPOST("sortfield", 'alpha'); - $sortorder = GETPOST("sortorder", 'alpha'); + $sortfield = GETPOST('sortfield', 'aZ09comma'); + $sortorder = GETPOST('sortorder', 'aZ09comma'); if (!$sortfield) { $sortfield = 't.datec'; diff --git a/htdocs/reception/document.php b/htdocs/reception/document.php index 9093f645e48..f592dba452a 100644 --- a/htdocs/reception/document.php +++ b/htdocs/reception/document.php @@ -47,8 +47,8 @@ $ref = GETPOST('ref'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index 00c59e47336..70775e112f6 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -75,7 +75,7 @@ $pagenext = $page + 1; // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $contextpage = 'receptionlist'; -$search_status = GETPOST('search_status'); +$search_status = GETPOST('search_status', 'intcomma'); $object = new Reception($db); diff --git a/htdocs/recruitment/class/api_recruitment.class.php b/htdocs/recruitment/class/api_recruitment.class.php new file mode 100644 index 00000000000..e0c2cb5da11 --- /dev/null +++ b/htdocs/recruitment/class/api_recruitment.class.php @@ -0,0 +1,647 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use Luracast\Restler\RestException; + +dol_include_once('/recruitment/class/recruitmentjobposition.class.php'); +dol_include_once('/recruitment/class/recruitmentcandidature.class.php'); + + + +/** + * \file recruitment/class/api_recruitment.class.php + * \ingroup recruitment + * \brief File for API management of recruitment. + */ + +/** + * API class for recruitment + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class Recruitment extends DolibarrApi +{ + /** + * @var jobposition $jobposition {@type jobposition} + */ + public $jobposition; + public $candidature; + + /** + * Constructor + * + * @url GET / + * + */ + public function __construct() + { + global $db, $conf; + $this->db = $db; + $this->jobposition = new RecruitmentJobPosition($this->db); + $this->candidature = new RecruitmentCandidature($this->db); + } + + /** + * Get properties of a jobposition object + * + * Return an array with jobposition informations + * + * @param int $id ID of jobposition + * @return array|mixed data without useless information + * + * @url GET jobposition/{id} + * + * @throws RestException 401 Not allowed + * @throws RestException 404 Not found + */ + public function getJobPosition($id) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->read) { + throw new RestException(401); + } + + $result = $this->jobposition->fetch($id); + if (!$result) { + throw new RestException(404, 'JobPosition not found'); + } + + if (!DolibarrApi::_checkAccessToResource('recruitment', $this->jobposition->id, 'recruitment_recruitmentjobposition')) { + throw new RestException(401, 'Access to instance id='.$this->jobposition->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->jobposition); + } + + /** + * Get properties of a candidature object + * + * Return an array with candidature informations + * + * @param int $id ID of candidature + * @return array|mixed data without useless information + * + * @url GET candidature/{id} + * + * @throws RestException 401 Not allowed + * @throws RestException 404 Not found + */ + public function getCandidature($id) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->read) { + throw new RestException(401); + } + + $result = $this->candidature->fetch($id); + if (!$result) { + throw new RestException(404, 'Candidature not found'); + } + + if (!DolibarrApi::_checkAccessToResource('recruitment', $this->candidature->id, 'recruitment_recruitmentcandidature')) { + throw new RestException(401, 'Access to instance id='.$this->candidature->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->candidature); + } + + + /** + * List jobpositions + * + * Get a list of jobpositions + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @return array Array of order objects + * + * @throws RestException + * + * @url GET /jobposition/ + */ + public function indexJobPosition($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') + { + global $db, $conf; + + $obj_ret = array(); + $tmpobject = new RecruitmentJobPosition($this->db); + + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->read) { + throw new RestException(401); + } + + $socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : ''; + + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object + + // If the internal user must only see his customers, force searching by him + $search_sale = 0; + if ($restrictonsocid && !DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) { + $search_sale = DolibarrApiAccess::$user->id; + } + + $sql = "SELECT t.rowid"; + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + } + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + } + $sql .= " WHERE 1 = 1"; + + // Example of use $mode + //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; + //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; + + if ($tmpobject->ismultientitymanaged) { + $sql .= ' AND t.entity IN ('.getEntity($tmpobject->element).')'; + } + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= " AND t.fk_soc = sc.fk_soc"; + } + if ($restrictonsocid && $socid) { + $sql .= " AND t.fk_soc = ".((int) $socid); + } + if ($restrictonsocid && $search_sale > 0) { + $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + } + // Insert sale filter + if ($restrictonsocid && $search_sale > 0) { + $sql .= " AND sc.fk_user = ".((int) $search_sale); + } + if ($sqlfilters) { + $errormessage = ''; + if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { + throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql .= $this->db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + + $sql .= $this->db->plimit($limit + 1, $offset); + } + + $result = $this->db->query($sql); + $i = 0; + if ($result) { + $num = $this->db->num_rows($result); + while ($i < $num) { + $obj = $this->db->fetch_object($result); + $tmp_object = new RecruitmentJobPosition($this->db); + if ($tmp_object->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($tmp_object); + } + $i++; + } + } else { + throw new RestException(503, 'Error when retrieving jobposition list: '.$this->db->lasterror()); + } + if (!count($obj_ret)) { + throw new RestException(404, 'No jobposition found'); + } + return $obj_ret; + } + + /** + * List candatures + * + * Get a list of candidatures + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @return array Array of order objects + * + * @throws RestException + * + * @url GET /candidature/ + */ + public function indexCandidature($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') + { + global $db, $conf; + + $obj_ret = array(); + $tmpobject = new RecruitmentCandidature($this->db); + + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->read) { + throw new RestException(401); + } + + $socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : ''; + + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object + + // If the internal user must only see his customers, force searching by him + $search_sale = 0; + if ($restrictonsocid && !DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) { + $search_sale = DolibarrApiAccess::$user->id; + } + + $sql = "SELECT t.rowid"; + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + } + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + } + $sql .= " WHERE 1 = 1"; + + // Example of use $mode + //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; + //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; + + if ($tmpobject->ismultientitymanaged) { + $sql .= ' AND t.entity IN ('.getEntity($tmpobject->element).')'; + } + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= " AND t.fk_soc = sc.fk_soc"; + } + if ($restrictonsocid && $socid) { + $sql .= " AND t.fk_soc = ".((int) $socid); + } + if ($restrictonsocid && $search_sale > 0) { + $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + } + // Insert sale filter + if ($restrictonsocid && $search_sale > 0) { + $sql .= " AND sc.fk_user = ".((int) $search_sale); + } + if ($sqlfilters) { + $errormessage = ''; + if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { + throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql .= $this->db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + + $sql .= $this->db->plimit($limit + 1, $offset); + } + + $result = $this->db->query($sql); + $i = 0; + if ($result) { + $num = $this->db->num_rows($result); + while ($i < $num) { + $obj = $this->db->fetch_object($result); + $tmp_object = new RecruitmentCandidature($this->db); + if ($tmp_object->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($tmp_object); + } + $i++; + } + } else { + throw new RestException(503, 'Error when retrieving candidature list: '.$this->db->lasterror()); + } + if (!count($obj_ret)) { + throw new RestException(404, 'No candidature found'); + } + return $obj_ret; + } + + /** + * Create jobposition object + * + * @param array $request_data Request datas + * @return int ID of jobposition + * + * @throws RestException + * + * @url POST jobposition/ + */ + public function postJobPosition($request_data = null) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->write) { + throw new RestException(401); + } + + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach ($request_data as $field => $value) { + $this->jobposition->$field = $this->_checkValForAPI($field, $value, $this->jobposition); + } + + // Clean data + // $this->jobposition->abc = checkVal($this->jobposition->abc, 'alphanohtml'); + + if ($this->jobposition->create(DolibarrApiAccess::$user)<0) { + throw new RestException(500, "Error creating jobposition", array_merge(array($this->jobposition->error), $this->jobposition->errors)); + } + return $this->jobposition->id; + } + + /** + * Create candidature object + * + * @param array $request_data Request datas + * @return int ID of candidature + * + * @throws RestException + * + * @url POST candidature/ + */ + public function postCandidature($request_data = null) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->write) { + throw new RestException(401); + } + + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach ($request_data as $field => $value) { + $this->jobposition->$field = $this->_checkValForAPI($field, $value, $this->jobposition); + } + + // Clean data + // $this->jobposition->abc = checkVal($this->jobposition->abc, 'alphanohtml'); + + if ($this->candidature->create(DolibarrApiAccess::$user)<0) { + throw new RestException(500, "Error creating candidature", array_merge(array($this->candidature->error), $this->candidature->errors)); + } + return $this->candidature->id; + } + + /** + * Update jobposition + * + * @param int $id Id of jobposition to update + * @param array $request_data Datas + * @return int + * + * @throws RestException + * + * @url PUT jobposition/{id} + */ + public function putJobPosition($id, $request_data = null) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->write) { + throw new RestException(401); + } + + $result = $this->jobposition->fetch($id); + if (!$result) { + throw new RestException(404, 'jobposition not found'); + } + + if (!DolibarrApi::_checkAccessToResource('recruitment', $this->jobposition->id, 'recruitment_recruitmentjobposition')) { + throw new RestException(401, 'Access to instance id='.$this->jobposition->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach ($request_data as $field => $value) { + if ($field == 'id') { + continue; + } + $this->jobposition->$field = $this->_checkValForAPI($field, $value, $this->jobposition); + } + + // Clean data + // $this->jobposition->abc = checkVal($this->jobposition->abc, 'alphanohtml'); + + if ($this->jobposition->update(DolibarrApiAccess::$user, false) > 0) { + return $this->get($id); + } else { + throw new RestException(500, $this->jobposition->error); + } + } + + /** + * Update candidature + * + * @param int $id Id of candidature to update + * @param array $request_data Datas + * @return int + * + * @throws RestException + * + * @url PUT candidature/{id} + */ + public function putCandidature($id, $request_data = null) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->write) { + throw new RestException(401); + } + + $result = $this->candidature->fetch($id); + if (!$result) { + throw new RestException(404, 'candidature not found'); + } + + if (!DolibarrApi::_checkAccessToResource('recruitment', $this->candidature->id, 'recruitment_recruitmentcandidature')) { + throw new RestException(401, 'Access to instance id='.$this->candidature->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach ($request_data as $field => $value) { + if ($field == 'id') { + continue; + } + $this->candidature->$field = $this->_checkValForAPI($field, $value, $this->candidature); + } + + // Clean data + // $this->jobposition->abc = checkVal($this->jobposition->abc, 'alphanohtml'); + + if ($this->candidature->update(DolibarrApiAccess::$user, false) > 0) { + return $this->get($id); + } else { + throw new RestException(500, $this->candidature->error); + } + } + + + /** + * Delete jobposition + * + * @param int $id jobposition ID + * @return array + * + * @throws RestException + * + * @url DELETE jobposition/{id} + */ + public function deleteJobPosition($id) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->delete) { + throw new RestException(401); + } + $result = $this->jobposition->fetch($id); + if (!$result) { + throw new RestException(404, 'jobposition not found'); + } + + if (!DolibarrApi::_checkAccessToResource('recruitment', $this->jobposition->id, 'recruitment_recruitmentjobposition')) { + throw new RestException(401, 'Access to instance id='.$this->jobposition->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (!$this->jobposition->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when deleting jobposition : '.$this->jobposition->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'jobposition deleted' + ) + ); + } + + /** + * Delete candidature + * + * @param int $id candidature ID + * @return array + * + * @throws RestException + * + * @url DELETE candidature/{id} + */ + public function deleteCandidature($id) + { + if (!DolibarrApiAccess::$user->rights->recruitment->recruitmentjobposition->delete) { + throw new RestException(401); + } + $result = $this->candidature->fetch($id); + if (!$result) { + throw new RestException(404, 'candidature not found'); + } + + if (!DolibarrApi::_checkAccessToResource('recruitment', $this->candidature->id, 'recruitment_recruitmentcandidature')) { + throw new RestException(401, 'Access to instance id='.$this->candidature->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (!$this->candidature->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when deleting candidature : '.$this->candidature->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'candidature deleted' + ) + ); + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Clean sensible object datas + * + * @param Object $object Object to clean + * @return Object Object with cleaned properties + */ + protected function _cleanObjectDatas($object) + { + // phpcs:enable + $object = parent::_cleanObjectDatas($object); + + unset($object->rowid); + unset($object->canvas); + + /*unset($object->name); + unset($object->lastname); + unset($object->firstname); + unset($object->civility_id); + unset($object->statut); + unset($object->state); + unset($object->state_id); + unset($object->state_code); + unset($object->region); + unset($object->region_code); + unset($object->country); + unset($object->country_id); + unset($object->country_code); + unset($object->barcode_type); + unset($object->barcode_type_code); + unset($object->barcode_type_label); + unset($object->barcode_type_coder); + unset($object->total_ht); + unset($object->total_tva); + unset($object->total_localtax1); + unset($object->total_localtax2); + unset($object->total_ttc); + unset($object->fk_account); + unset($object->comments); + unset($object->note); + unset($object->mode_reglement_id); + unset($object->cond_reglement_id); + unset($object->cond_reglement); + unset($object->shipping_method_id); + unset($object->fk_incoterms); + unset($object->label_incoterms); + unset($object->location_incoterms); + */ + + // If object has lines, remove $db property + if (isset($object->lines) && is_array($object->lines) && count($object->lines) > 0) { + $nboflines = count($object->lines); + for ($i = 0; $i < $nboflines; $i++) { + $this->_cleanObjectDatas($object->lines[$i]); + + unset($object->lines[$i]->lines); + unset($object->lines[$i]->note); + } + } + + return $object; + } + + /** + * Validate fields before create or update object + * + * @param array $data Array of data to validate + * @return array + * + * @throws RestException + */ + private function _validate($data) + { + $jobposition = array(); + foreach ($this->jobposition->fields as $field => $propfield) { + if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) { + continue; // Not a mandatory field + } + if (!isset($data[$field])) { + throw new RestException(400, "$field field missing"); + } + $jobposition[$field] = $data[$field]; + } + return $jobposition; + } +} diff --git a/htdocs/recruitment/recruitmentcandidature_agenda.php b/htdocs/recruitment/recruitmentcandidature_agenda.php index 79795472b4e..9cc259c21e1 100644 --- a/htdocs/recruitment/recruitmentcandidature_agenda.php +++ b/htdocs/recruitment/recruitmentcandidature_agenda.php @@ -81,8 +81,8 @@ if (GETPOST('actioncode', 'array')) { $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'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/recruitment/recruitmentcandidature_document.php b/htdocs/recruitment/recruitmentcandidature_document.php index dcd29c88118..792b413b5e4 100644 --- a/htdocs/recruitment/recruitmentcandidature_document.php +++ b/htdocs/recruitment/recruitmentcandidature_document.php @@ -71,8 +71,8 @@ $ref = GETPOST('ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/recruitment/recruitmentjobposition_agenda.php b/htdocs/recruitment/recruitmentjobposition_agenda.php index 4c3e642a224..3f9e76d4dcf 100644 --- a/htdocs/recruitment/recruitmentjobposition_agenda.php +++ b/htdocs/recruitment/recruitmentjobposition_agenda.php @@ -81,8 +81,8 @@ if (GETPOST('actioncode', 'array')) { $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'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/recruitment/recruitmentjobposition_document.php b/htdocs/recruitment/recruitmentjobposition_document.php index 14355aeb0e3..e9615777ade 100644 --- a/htdocs/recruitment/recruitmentjobposition_document.php +++ b/htdocs/recruitment/recruitmentjobposition_document.php @@ -71,8 +71,8 @@ $ref = GETPOST('ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/resource/agenda.php b/htdocs/resource/agenda.php index bf300141bc4..363f334a7eb 100644 --- a/htdocs/resource/agenda.php +++ b/htdocs/resource/agenda.php @@ -55,8 +55,8 @@ if (GETPOST('actioncode', 'array')) { $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'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/resource/list.php b/htdocs/resource/list.php index 025ec2fbf70..97d55c7bb33 100644 --- a/htdocs/resource/list.php +++ b/htdocs/resource/list.php @@ -38,7 +38,7 @@ $element = GETPOST('element', 'alpha'); $element_id = GETPOST('element_id', 'int'); $resource_id = GETPOST('resource_id', 'int'); -$sortorder = GETPOST('sortorder', 'alpha'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $sortfield = GETPOST('sortfield', 'aZ09comma'); $optioncss = GETPOST('optioncss', 'alpha'); diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 89676e50140..689a2664c0a 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -277,7 +277,7 @@ if ($action == 'add' && empty($cancel)) { $paiement->amounts = array($object->id=>$amount); // Tableau de montant $paiement->paiementtype = $type_payment; $paiement->num_payment = GETPOST("num_payment", 'alphanohtml'); - $paiement->note = GETPOST("note", 'none'); + $paiement->note = GETPOST("note", 'restricthtml'); if (!$error) { $paymentid = $paiement->create($user, (int) GETPOST('closepaidsalary')); diff --git a/htdocs/salaries/paiement_salary.php b/htdocs/salaries/paiement_salary.php index d4465103308..221e5cf2c0e 100644 --- a/htdocs/salaries/paiement_salary.php +++ b/htdocs/salaries/paiement_salary.php @@ -110,8 +110,8 @@ if ($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm == 'y $paiement->amounts = $amounts; // Tableau de montant $paiement->paiementtype = GETPOST("paiementtype", 'alphanohtml'); $paiement->num_payment = GETPOST("num_payment", 'alphanohtml'); - $paiement->note = GETPOST("note", 'none'); - $paiement->note_private = GETPOST("note", 'none'); + $paiement->note = GETPOST("note", 'restricthtml'); + $paiement->note_private = GETPOST("note", 'restricthtml'); if (!$error) { $paymentid = $paiement->create($user, (GETPOST('closepaidsalary') == 'on' ? 1 : 0)); diff --git a/htdocs/societe/agenda.php b/htdocs/societe/agenda.php index ec59482b345..1aa7093299d 100644 --- a/htdocs/societe/agenda.php +++ b/htdocs/societe/agenda.php @@ -52,8 +52,8 @@ if ($user->socid) { $result = restrictedArea($user, 'societe', $socid, '&societe'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/societe/ajax/company.php b/htdocs/societe/ajax/company.php index 7edd00db4d5..9dfe3909393 100644 --- a/htdocs/societe/ajax/company.php +++ b/htdocs/societe/ajax/company.php @@ -44,7 +44,7 @@ if (!defined('NOCSRFCHECK')) { require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; -$htmlname = GETPOST('htmlname', 'alpha'); +$htmlname = GETPOST('htmlname', 'aZ09'); $filter = GETPOST('filter', 'alpha'); $outjson = (GETPOST('outjson', 'int') ? GETPOST('outjson', 'int') : 0); $action = GETPOST('action', 'aZ09'); @@ -102,7 +102,7 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) { // Filter on the company to search can be: // Into an array with key $htmlname123 (we take first one found). Which page use this ? // Into a var with name $htmlname can be 'prodid', 'productid', ... - $match = preg_grep('/('.$htmlname.'[0-9]+)/', array_keys($_GET)); + $match = preg_grep('/('.preg_quote($htmlname, '/').'[0-9]+)/', array_keys($_GET)); sort($match); $id = (!empty($match[0]) ? $match[0] : ''); // Take first key found into GET array with matching $htmlname123 diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index d75d9256b34..b6c483fc026 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1765,10 +1765,11 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if (GETPOSTISSET('name')) { // We overwrite with values if posted $object->name = GETPOST('name', 'alphanohtml'); - $object->prefix_comm = GETPOST('prefix_comm', 'alphanohtml'); + $object->name_alias = GETPOST('name_alias', 'alphanohtml'); + $object->prefix_comm = GETPOST('prefix_comm', 'alphanohtml'); $object->client = GETPOST('client', 'int'); - $object->code_client = GETPOST('customer_code', 'alpha'); - $object->fournisseur = GETPOST('fournisseur', 'int'); + $object->code_client = GETPOST('customer_code', 'alpha'); + $object->fournisseur = GETPOST('fournisseur', 'int'); $object->code_fournisseur = GETPOST('supplier_code', 'alpha'); $object->address = GETPOST('address', 'alphanohtml'); $object->zip = GETPOST('zipcode', 'alphanohtml'); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 315bdb9af13..7490fca0265 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -554,13 +554,14 @@ class Societe extends CommonObject * Accounting code for client * @var string */ - public $code_compta; + public $code_compta_client; /** - * Accounting code for client + * Duplicate of code_compta_client (for backward compatibility) * @var string */ - public $code_compta_client; + public $code_compta; + /** * Accounting code for customer @@ -580,6 +581,14 @@ class Societe extends CommonObject */ public $accountancy_code_supplier; + + /** + * Accounting code for product (for level 3 of suggestion of prouct accounting account) + * @var string + */ + public $code_compta_product; + + /** * @var string * @deprecated Note is split in public and private notes @@ -1822,7 +1831,8 @@ class Societe extends CommonObject $this->code_client = $obj->code_client; $this->code_fournisseur = $obj->code_fournisseur; - $this->code_compta = $obj->code_compta; + $this->code_compta = $obj->code_compta; // For backward compatibility + $this->code_compta_client = $obj->code_compta; $this->code_compta_fournisseur = $obj->code_compta_fournisseur; $this->barcode = $obj->barcode; diff --git a/htdocs/societe/consumption.php b/htdocs/societe/consumption.php index d9abbd61c22..596f9b6f3c6 100644 --- a/htdocs/societe/consumption.php +++ b/htdocs/societe/consumption.php @@ -47,8 +47,8 @@ if ($socid > 0) { // Sort & Order fields $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); diff --git a/htdocs/societe/document.php b/htdocs/societe/document.php index 9ce01c64638..707c573f116 100644 --- a/htdocs/societe/document.php +++ b/htdocs/societe/document.php @@ -41,8 +41,8 @@ $ref = GETPOST('ref', 'alpha'); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index dbb380bd405..da056ec33da 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -111,8 +111,8 @@ $place = GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : '0'; // $place is $diroutputmassaction = $conf->societe->dir_output.'/temp/massgeneration/'.$user->id; $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (!$sortorder) { $sortorder = "ASC"; diff --git a/htdocs/societe/notify/card.php b/htdocs/societe/notify/card.php index 4ed16e948c5..8729ed3b46e 100644 --- a/htdocs/societe/notify/card.php +++ b/htdocs/societe/notify/card.php @@ -45,8 +45,8 @@ if ($user->socid) { $result = restrictedArea($user, 'societe', '', ''); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (!$sortorder) { $sortorder = "DESC"; diff --git a/htdocs/societe/price.php b/htdocs/societe/price.php index 72246fdf9cb..75818a34f72 100644 --- a/htdocs/societe/price.php +++ b/htdocs/societe/price.php @@ -245,8 +245,8 @@ print dol_get_fiche_end(); if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { $prodcustprice = new Productcustomerprice($db); - $sortfield = GETPOST("sortfield", 'alpha'); - $sortorder = GETPOST("sortorder", 'alpha'); + $sortfield = GETPOST('sortfield', 'aZ09comma'); + $sortorder = GETPOST('sortorder', 'aZ09comma'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { diff --git a/htdocs/societe/societecontact.php b/htdocs/societe/societecontact.php index d0511d53a1f..82d815f0ac4 100644 --- a/htdocs/societe/societecontact.php +++ b/htdocs/societe/societecontact.php @@ -40,8 +40,8 @@ $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (!$sortorder) { $sortorder = "ASC"; diff --git a/htdocs/societe/website.php b/htdocs/societe/website.php index 108a4bdf34a..bc93d72d60e 100644 --- a/htdocs/societe/website.php +++ b/htdocs/societe/website.php @@ -43,8 +43,6 @@ $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'web $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') -$search_status = GETPOST('search_status'); - // Security check $id = GETPOST('id', 'int') ?GETPOST('id', 'int') : GETPOST('socid', 'int'); if ($user->socid) { @@ -53,8 +51,8 @@ if ($user->socid) { $result = restrictedArea($user, 'societe', $socid, '&societe'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/stripe/charge.php b/htdocs/stripe/charge.php index c6a07593a04..49db54b444f 100644 --- a/htdocs/stripe/charge.php +++ b/htdocs/stripe/charge.php @@ -42,8 +42,8 @@ if ($user->socid) { $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $rowid = GETPOST("rowid", 'alpha'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index a520e83f0ee..18ebce96f8b 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -607,9 +607,6 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_BANCONTACT)) { $paymentmethodtypes[] = "bancontact"; } - if (!empty($conf->global->STRIPE_KLARNA)) { - $paymentmethodtypes[] = "klarna"; - } if (!empty($conf->global->STRIPE_IDEAL)) { $paymentmethodtypes[] = "ideal"; } diff --git a/htdocs/stripe/payout.php b/htdocs/stripe/payout.php index 75c24ef0561..34b4ea1dc4f 100644 --- a/htdocs/stripe/payout.php +++ b/htdocs/stripe/payout.php @@ -42,8 +42,8 @@ if ($user->socid) { $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $rowid = GETPOST("rowid", 'alpha'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/stripe/transaction.php b/htdocs/stripe/transaction.php index 0d43c830e8e..6bab8459d18 100644 --- a/htdocs/stripe/transaction.php +++ b/htdocs/stripe/transaction.php @@ -42,8 +42,8 @@ if ($user->socid) { $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $rowid = GETPOST("rowid", 'alpha'); -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/supplier_proposal/document.php b/htdocs/supplier_proposal/document.php index 884519a4f9a..fa73ec22fa8 100644 --- a/htdocs/supplier_proposal/document.php +++ b/htdocs/supplier_proposal/document.php @@ -52,8 +52,8 @@ $result = restrictedArea($user, 'supplier_proposal', $id); // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index 1a1110fba1c..ad35c8f9914 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -103,8 +103,8 @@ $mesg = (GETPOST("msg") ? GETPOST("msg") : GETPOST("mesg")); $optioncss = GETPOST('optioncss', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1 || !empty($search_btn) || !empty($search_remove_btn) || (empty($toselect) && $massaction === '0')) { $page = 0; diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 6cfbf4b3c1a..58c1906cd42 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -53,6 +53,8 @@ if (empty($user->rights->takepos->run)) { accessforbidden(); } +// Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks +$hookmanager->initHooks(array('takeposproductsearch')); /* * View @@ -109,13 +111,30 @@ if ($action == 'getProducts') { } } - $sql = 'SELECT rowid, ref, label, tosell, tobuy, barcode, price FROM '.MAIN_DB_PREFIX.'product as p'; + $sql = 'SELECT rowid, ref, label, tosell, tobuy, barcode, price' ; + // Add fields from hooks + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + + $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; + + // Add tables from hooks + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListTables', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + $sql .= ' WHERE entity IN ('.getEntity('product').')'; if ($filteroncategids) { $sql .= ' AND EXISTS (SELECT cp.fk_product FROM '.MAIN_DB_PREFIX.'categorie_product as cp WHERE cp.fk_product = p.rowid AND cp.fk_categorie IN ('.$db->sanitize($filteroncategids).'))'; } $sql .= ' AND tosell = 1'; $sql .= natural_search(array('ref', 'label', 'barcode'), $term); + // 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; + $resql = $db->query($sql); if ($resql) { $rows = array(); diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 2c44acdaae2..0b159e96a38 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -335,7 +335,11 @@ function LoadProducts(position, issubcat) { var titlestring = ; global->TAKEPOS_HIDE_PRODUCT_IMAGES) { echo '$("#prodivdesc"+ishow).show();'; - echo '$("#prodesc"+ishow).text(data[parseInt(idata)][\'label\']);'; + if ($conf->global->TAKEPOS_SHOW_PRODUCT_REFERENCE == 1) { + echo '$("#prodesc"+ishow).html(data[parseInt(idata)][\'ref\'].bold() + \' - \' + data[parseInt(idata)][\'label\']);'; + } else { + echo '$("#prodesc"+ishow).text(data[parseInt(idata)][\'label\']);'; + } echo '$("#proimg"+ishow).attr("title", titlestring);'; echo '$("#proimg"+ishow).attr("src", "genimg/index.php?query=pro&id="+data[idata][\'id\']);'; } else { @@ -401,7 +405,12 @@ function MoreProducts(moreorless) { else if ((data[idata]['status']) == "1") { //Only show products with status=1 (for sell) $("#prodivdesc"+ishow).show(); - $("#prodesc"+ishow).text(data[parseInt(idata)]['label']); + global->TAKEPOS_SHOW_PRODUCT_REFERENCE == 1) { ?> + $("#prodesc"+ishow).html(data[parseInt(idata)]['ref'].bold() + ' - ' + data[parseInt(idata)]['label']); + + $("#prodesc"+ishow).text(data[parseInt(idata)]['label']); + $("#probutton"+ishow).text(data[parseInt(idata)]['label']); $("#probutton"+ishow).show(); if (data[parseInt(idata)]['price_formated']) { @@ -579,7 +588,12 @@ function Search2(keyCodeForEnter) { $titlestring .= " + ' - ".dol_escape_js($langs->trans("Barcode").': ')."' + data[i]['barcode']"; ?> var titlestring = ; - $("#prodesc" + i).text(data[i]['label']); + global->TAKEPOS_SHOW_PRODUCT_REFERENCE == 1) { ?> + $("#prodesc" + i).html(data[i]['ref'].bold() + ' - ' + data[i]['label']); + + $("#prodesc" + i).text(data[i]['label']); + $("#prodivdesc" + i).show(); $("#probutton" + i).text(data[i]['label']); $("#probutton" + i).show(); @@ -1203,11 +1217,15 @@ if (!empty($conf->global->TAKEPOS_WEIGHING_SCALE)) { } ?>"> -
- + global->TAKEPOS_HIDE_CATEGORIES == 1) { + print '