diff --git a/.github/workflows/pr-18-autolabel.yaml b/.github/workflows/pr-18-autolabel.yaml index 4524d02815b54..feb9ee17c9702 100644 --- a/.github/workflows/pr-18-autolabel.yaml +++ b/.github/workflows/pr-18-autolabel.yaml @@ -18,3 +18,4 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} configuration-path: .github/changed-lines-count-labeler.yml + continue-on-error: true diff --git a/build/phpstan/phpstan-baseline.neon b/build/phpstan/phpstan-baseline.neon index d88e33d2e26cf..1c7672653e5b6 100644 --- a/build/phpstan/phpstan-baseline.neon +++ b/build/phpstan/phpstan-baseline.neon @@ -463,7 +463,7 @@ parameters: path: ../../htdocs/accountancy/class/accountingaccount.class.php - - message: '#^Call to function array_key_exists\(\) with ''error'' and array\{ref\: mixed, label\: mixed, acquisition_value_ht\: mixed, depreciation\: non\-empty\-array\\}\>, disposal\?\: array\{date\: mixed, amount\: mixed, subject_to_vat\: bool\}\} will always evaluate to false\.$#' + message: '#^Call to function array_key_exists\(\) with ''error'' and array\{ref\: mixed, label\: mixed, acquisition_value_ht\: mixed, depreciation\: non\-empty\-array\\}\>, disposal\?\: array\{date\: mixed, amount\: mixed, subject_to_vat\: bool\}\} will always evaluate to false\.$#' identifier: function.impossibleType count: 1 path: ../../htdocs/accountancy/class/accountingjournal.class.php @@ -625,7 +625,7 @@ parameters: path: ../../htdocs/accountancy/class/lettering.class.php - - message: '#^Parameter \#1 \$link_by_element of method Lettering\:\:getGroupElements\(\) expects array\\>, array\\> given\.$#' + message: '#^Parameter \#1 \$link_by_element of method Lettering\:\:getGroupElements\(\) expects array\\>, array\\> given\.$#' identifier: argument.type count: 1 path: ../../htdocs/accountancy/class/lettering.class.php @@ -894,10 +894,16 @@ parameters: count: 1 path: ../../htdocs/adherents/card.php + - + message: '#^Call to function is_array\(\) with array will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: ../../htdocs/adherents/class/adherent.class.php + - message: '#^Call to function is_array\(\) with array\ will always evaluate to true\.$#' identifier: function.alreadyNarrowedType - count: 2 + count: 1 path: ../../htdocs/adherents/class/adherent.class.php - @@ -3343,7 +3349,7 @@ parameters: path: ../../htdocs/categories/class/categorie.class.php - - message: '#^Method Categorie\:\:get_full_arbo\(\) should return \-1\|array\ but returns array\\.$#' + message: '#^Method Categorie\:\:get_full_arbo\(\) should return \-1\|array\ but returns array\\.$#' identifier: return.type count: 1 path: ../../htdocs/categories/class/categorie.class.php @@ -3361,7 +3367,7 @@ parameters: path: ../../htdocs/categories/class/categorie.class.php - - message: '#^Property Categorie\:\:\$cats \(array\\) does not accept array\\.$#' + message: '#^Property Categorie\:\:\$cats \(array\\) does not accept array\\.$#' identifier: assign.propertyType count: 2 path: ../../htdocs/categories/class/categorie.class.php @@ -5311,7 +5317,7 @@ parameters: path: ../../htdocs/compta/cashcontrol/class/cashcontrol.class.php - - message: '#^Call to function is_array\(\) with non\-empty\-array\ will always evaluate to true\.$#' + message: '#^Call to function is_array\(\) with non\-empty\-array\<\(float\|int\)\> will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: ../../htdocs/compta/cashcontrol/report.php @@ -6601,7 +6607,7 @@ parameters: path: ../../htdocs/compta/resultat/index.php - - message: '#^Call to function is_array\(\) with non\-empty\-array\\}\> will always evaluate to true\.$#' + message: '#^Call to function is_array\(\) with non\-empty\-array\\}\> will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: ../../htdocs/compta/resultat/result.php @@ -7969,7 +7975,7 @@ parameters: path: ../../htdocs/core/actions_linkedfiles.inc.php - - message: '#^Call to function is_array\(\) with non\-empty\-array\ will always evaluate to true\.$#' + message: '#^Call to function is_array\(\) with non\-empty\-array\ will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: ../../htdocs/core/actions_massactions.inc.php @@ -10537,7 +10543,7 @@ parameters: path: ../../htdocs/core/class/notify.class.php - - message: '#^Call to function is_array\(\) with non\-empty\-array\ will always evaluate to true\.$#' + message: '#^Call to function is_array\(\) with non\-empty\-array\ will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: ../../htdocs/core/class/openid.class.php @@ -13597,7 +13603,7 @@ parameters: path: ../../htdocs/core/modules/hrm/mod_evaluation_standard.php - - message: '#^Call to function is_array\(\) with non\-empty\-array will always evaluate to true\.$#' + message: '#^Call to function is_array\(\) with non\-empty\-list\ will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: ../../htdocs/core/modules/import/import_csv.modules.php @@ -23299,7 +23305,7 @@ parameters: path: ../../htdocs/master.inc.php - - message: '#^Call to function is_array\(\) with array\ will always evaluate to true\.$#' + message: '#^Call to function is_array\(\) with array\ will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: ../../htdocs/modulebuilder/index.php @@ -30312,12 +30318,6 @@ parameters: count: 1 path: ../../htdocs/salaries/list.php - - - message: '#^Variable \$resteapayer might not be defined\.$#' - identifier: variable.undefined - count: 1 - path: ../../htdocs/salaries/list.php - - message: '#^Variable \$selected might not be defined\.$#' identifier: variable.undefined @@ -30336,12 +30336,6 @@ parameters: count: 2 path: ../../htdocs/salaries/paiement_salary.php - - - message: '#^Variable \$sumpaid might not be defined\.$#' - identifier: variable.undefined - count: 3 - path: ../../htdocs/salaries/paiement_salary.php - - message: '#^Negated boolean expression is always false\.$#' identifier: booleanNot.alwaysFalse @@ -30432,24 +30426,6 @@ parameters: count: 1 path: ../../htdocs/societe/ajax/company.php - - - message: '#^Variable \$canvas might not be defined\.$#' - identifier: variable.undefined - count: 1 - path: ../../htdocs/societe/canvas/company/tpl/card_create.tpl.php - - - - message: '#^Variable \$canvas might not be defined\.$#' - identifier: variable.undefined - count: 1 - path: ../../htdocs/societe/canvas/company/tpl/card_edit.tpl.php - - - - message: '#^Variable \$canvas might not be defined\.$#' - identifier: variable.undefined - count: 2 - path: ../../htdocs/societe/canvas/company/tpl/card_view.tpl.php - - message: '#^Variable \$db might not be defined\.$#' identifier: variable.undefined @@ -30937,7 +30913,7 @@ parameters: path: ../../htdocs/societe/notify/card.php - - message: '#^Call to function is_array\(\) with array\ will always evaluate to true\.$#' + message: '#^Call to function is_array\(\) with array\ will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: ../../htdocs/societe/paymentmodes.php diff --git a/dev/tools/apstats.php b/dev/tools/apstats.php index fa27133329a5a..825257dadbe62 100755 --- a/dev/tools/apstats.php +++ b/dev/tools/apstats.php @@ -883,7 +883,7 @@ $html .= '
'."\n"; $html .= '
'."\n"; $html .= ''."\n"; -$html .= ''."\n"; +$html .= ''."\n"; foreach ($arrayofalerts as $key => $alert) { $cve = ''; $yogosha = empty($alert['issueidyogosha']) ? '' : $alert['issueidyogosha']; diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index d69db0e405ea5..6d3df7446b45b 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -17,7 +17,7 @@ return [ // PhanTypeMismatchProperty : 130+ occurrences // PhanPluginUnknownArrayMethodParamType : 120+ occurrences // PhanPluginUnknownPropertyType : 110+ occurrences - // PhanPossiblyUndeclaredVariable : 80+ occurrences + // PhanPossiblyUndeclaredVariable : 65+ occurrences // PhanRedefineFunction : 45+ occurrences // PhanTypeExpectedObjectPropAccess : 45+ occurrences // PhanTypeMismatchArgumentNullableInternal : 40+ occurrences @@ -507,7 +507,7 @@ return [ 'htdocs/recruitment/admin/setup_candidatures.php' => ['PhanEmptyForeach'], 'htdocs/recruitment/class/recruitmentcandidature.class.php' => ['PhanUndeclaredProperty'], 'htdocs/recruitment/class/recruitmentjobposition.class.php' => ['PhanUndeclaredProperty'], - 'htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php' => ['PhanPossiblyUndeclaredVariable', 'PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'], + 'htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php' => ['PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'], 'htdocs/recruitment/core/modules/recruitment/mod_recruitmentcandidature_advanced.php' => ['PhanPluginSuspiciousParamOrder', 'PhanUndeclaredProperty'], 'htdocs/recruitment/core/modules/recruitment/mod_recruitmentjobposition_advanced.php' => ['PhanPluginSuspiciousParamOrder', 'PhanUndeclaredProperty'], 'htdocs/recruitment/index.php' => ['PhanUndeclaredGlobalVariable'], @@ -523,7 +523,7 @@ return [ 'htdocs/salaries/card.php' => ['PhanPossiblyUndeclaredGlobalVariable'], 'htdocs/salaries/class/api_salaries.class.php' => ['PhanPluginUnknownArrayMethodParamType', 'PhanPluginUnknownArrayMethodReturnType'], 'htdocs/salaries/list.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredGlobalVariable'], - 'htdocs/salaries/paiement_salary.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'], + 'htdocs/salaries/paiement_salary.php' => ['PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'], 'htdocs/salaries/virement_request.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/societe/admin/societe.php' => ['PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredMethod'], 'htdocs/societe/ajax/company.php' => ['PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'], diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 53e6efa493495..f8573c3f75e71 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -3,7 +3,8 @@ * Copyright (C) 2015-2022 Alexandre Spangaro * Copyright (C) 2015-2020 Florian Henry * Copyright (C) 2018-2024 Frédéric France - * Copyright (C) 2024 MDW + * Copyright (C) 2024 MDW + * Copyright (C) 2024 Jose MARTINEZ * * 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 @@ -68,7 +69,7 @@ class BookKeeping extends CommonObject public $doc_date; /** - * @var int Deadline for payment + * @var int|null|'' Deadline for payment */ public $date_lim_reglement; @@ -324,7 +325,7 @@ public function create(User $user, $notrigger = 0) $this->piece_num = 0; // First check if line not yet already in bookkeeping. - // Note that we must include 'doc_type - fk_doc - numero_compte - label' to be sure to have unicity of line (because we may have several lines + // Note that we must include 'doc_type - fk_doc - numero_compte - label - subledger_account (if not empty)' to be sure to have unicity of line (because we may have several lines // with same doc_type, fk_doc, numero_compte for 1 invoice line when using localtaxes with same account) // WARNING: This is not reliable, label may have been modified. This is just a small protection. // The page that make transfer make the test on couple (doc_type - fk_doc) only. @@ -338,6 +339,9 @@ public function create(User $user, $notrigger = 0) } $sql .= " AND numero_compte = '".$this->db->escape($this->numero_compte)."'"; $sql .= " AND label_operation = '".$this->db->escape($this->label_operation)."'"; + if (!empty($this->subledger_account)) { + $sql .= " AND subledger_account = '".$this->db->escape($this->subledger_account)."'"; + } $sql .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features $resql = $this->db->query($sql); @@ -2863,10 +2867,8 @@ public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $sep $sql = 'SELECT'; $sql .= " t.numero_compte,"; - $sql .= " t.label_compte,"; if ($separate_auxiliary_account) { - $sql .= " t.subledger_account,"; - $sql .= " t.subledger_label,"; + $sql .= " NULLIF(t.subledger_account, '') as subledger_account,"; // fix db issues with Null or "" values } $sql .= " aa.pcg_type,"; $sql .= " (SUM(t.credit) - SUM(t.debit)) as opening_balance"; @@ -2878,10 +2880,11 @@ public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $sep $sql .= ' AND aa.pcg_type IN (' . $this->db->sanitize(implode(',', $pcg_type_filter), 1) . ')'; $sql .= " AND DATE(t.doc_date) >= '" . $this->db->idate($fiscal_period->date_start) . "'"; $sql .= " AND DATE(t.doc_date) <= '" . $this->db->idate($fiscal_period->date_end) . "'"; - $sql .= ' GROUP BY t.numero_compte, t.label_compte, aa.pcg_type'; + $sql .= ' GROUP BY t.numero_compte, aa.pcg_type'; if ($separate_auxiliary_account) { - $sql .= ' ,t.subledger_account, t.subledger_label'; + $sql .= " , NULLIF(t.subledger_account, '')"; } + $sql .= ' HAVING (SUM(t.credit) - SUM(t.debit)) != 0 '; // Exclude rows with opening_balance = 0 $sql .= $this->db->order("t.numero_compte", "ASC"); $resql = $this->db->query($sql); @@ -2902,24 +2905,41 @@ public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $sep $bookkeeping = new BookKeeping($this->db); $bookkeeping->doc_date = $new_fiscal_period->date_start; - $bookkeeping->date_lim_reglement = 0; - $bookkeeping->doc_ref = $new_fiscal_period->label; + + $bookkeeping->date_lim_reglement = ''; + $bookkeeping->doc_ref = $fiscal_period->label; + $bookkeeping->date_creation = $now; $bookkeeping->doc_type = 'closure'; - $bookkeeping->fk_doc = $new_fiscal_period->id; + $bookkeeping->fk_doc = $fiscal_period->id; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = ''; if ($separate_auxiliary_account) { $bookkeeping->subledger_account = $obj->subledger_account; - $bookkeeping->subledger_label = $obj->subledger_label; + $sql = 'SELECT'; + $sql .= " subledger_label"; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " WHERE subledger_account = '" . $this->db->escape($obj->subledger_account) . "'"; + $sql .= " ORDER BY doc_date DESC"; + $sql .= " LIMIT 1"; + $result = $this->db->query($sql); + if (!$result) { + $this->errors[] = 'Error: ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + $error++; + } + $objtmp = $this->db->fetch_object($result); + $bookkeeping->subledger_label = $objtmp->subledger_label; // latest subledger label used } else { - $bookkeeping->subledger_account = ''; - $bookkeeping->subledger_label = ''; + $bookkeeping->subledger_account = null; + $bookkeeping->subledger_label = null; } $bookkeeping->numero_compte = $obj->numero_compte; - $bookkeeping->label_compte = $obj->label_compte; + $accountingaccount = new AccountingAccount($this->db); + $accountingaccount->fetch(0, $obj->numero_compte); + $bookkeeping->label_compte = $accountingaccount->label; // latest account label used $bookkeeping->label_operation = $new_fiscal_period->label; $bookkeeping->montant = $mt; @@ -2933,8 +2953,7 @@ public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $sep $result = $bookkeeping->create($user); if ($result < 0) { - $this->error = $bookkeeping->error; - $this->errors = $bookkeeping->errors; + $this->setErrorsFromObject($bookkeeping); $error++; break; } @@ -2949,21 +2968,35 @@ public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $sep $bookkeeping = new BookKeeping($this->db); $bookkeeping->doc_date = $new_fiscal_period->date_start; - $bookkeeping->date_lim_reglement = 0; - $bookkeeping->doc_ref = $new_fiscal_period->label; + + $bookkeeping->date_lim_reglement = ''; + $bookkeeping->doc_ref = $fiscal_period->label; + $bookkeeping->date_creation = $now; $bookkeeping->doc_type = 'closure'; - $bookkeeping->fk_doc = $new_fiscal_period->id; + $bookkeeping->fk_doc = $fiscal_period->id; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = ''; if ($separate_auxiliary_account) { - $bookkeeping->subledger_label = ''; $bookkeeping->subledger_account = $obj->subledger_account; - $bookkeeping->subledger_label = $obj->subledger_label; + $sql = 'SELECT'; + $sql .= " subledger_label"; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " WHERE subledger_account = '" . $this->db->escape($obj->subledger_account) . "'"; + $sql .= " ORDER BY doc_date DESC"; + $sql .= " LIMIT 1"; + $result = $this->db->query($sql); + if (!$result) { + $this->errors[] = 'Error: ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + $error++; + } + $objtmp = $this->db->fetch_object($result); + $bookkeeping->subledger_label = $objtmp->subledger_label; // latest subledger label used } else { - $bookkeeping->subledger_account = ''; - $bookkeeping->subledger_label = ''; + $bookkeeping->subledger_account = null; + $bookkeeping->subledger_label = null; } $bookkeeping->numero_compte = $accountingaccount->account_number; @@ -2981,8 +3014,7 @@ public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $sep $result = $bookkeeping->create($user); if ($result < 0) { - $this->error = $bookkeeping->error; - $this->errors = $bookkeeping->errors; + $this->setErrorsFromObject($bookkeeping); $error++; } } diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index e7f8a9b1139a9..2e02f37ebec26 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1546,8 +1546,8 @@ function init_repeat() $listofuserid[$firstelem['id']]['transparency'] = (GETPOSTISSET('transparency') ? GETPOST('transparency', 'alpha') : 0); // 0 by default when refreshing } } - print '
'; - print $form->select_dolusers_forevent(($action == 'create' ? 'add' : 'update'), 'assignedtouser', 1, array(), 0, '', array(), 0, 0, 0, 'AND u.statut != 0', 1, $listofuserid, $listofcontactid, $listofotherid); + print '
'; + print $form->select_dolusers_forevent(($action == 'create' ? 'add' : 'update'), 'assignedtouser', 1, array(), 0, '', array(), 0, 0, 0, 'u.statut:<>:0', 1, $listofuserid, $listofcontactid, $listofotherid); print '
'; print ''; @@ -1811,7 +1811,7 @@ function init_repeat() print "\n".''; +//print 'Click'; + print "\n"; diff --git a/htdocs/core/triggers/interface_95_modZapier_ZapierTriggers.class.php b/htdocs/core/triggers/interface_95_modZapier_ZapierTriggers.class.php index 87fd49d1f0eeb..d6ed6a6383f77 100644 --- a/htdocs/core/triggers/interface_95_modZapier_ZapierTriggers.class.php +++ b/htdocs/core/triggers/interface_95_modZapier_ZapierTriggers.class.php @@ -224,7 +224,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf case 'ORDER_CLASSIFY_BILLED': case 'ORDER_SETDRAFT': case 'LINEORDER_INSERT': - case 'LINEORDER_UPDATE': + case 'LINEORDER_MODIFY': case 'LINEORDER_DELETE': break; // Supplier orders @@ -239,7 +239,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // case 'ORDER_SUPPLIER_RECEIVE': // case 'LINEORDER_SUPPLIER_DISPATCH': // case 'LINEORDER_SUPPLIER_CREATE': - // case 'LINEORDER_SUPPLIER_UPDATE': + // case 'LINEORDER_SUPPLIER_MODIFY': // Proposals // case 'PROPAL_CREATE': @@ -251,7 +251,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // case 'PROPAL_CLOSE_REFUSED': // case 'PROPAL_DELETE': // case 'LINEPROPAL_INSERT': - // case 'LINEPROPAL_UPDATE': + // case 'LINEPROPAL_MODIFY': // case 'LINEPROPAL_DELETE': // SupplierProposal @@ -264,7 +264,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // case 'SUPPLIER_PROPOSAL_CLOSE_REFUSED': // case 'SUPPLIER_PROPOSAL_DELETE': // case 'LINESUPPLIER_PROPOSAL_INSERT': - // case 'LINESUPPLIER_PROPOSAL_UPDATE': + // case 'LINESUPPLIER_PROPOSAL_MODIFY': // case 'LINESUPPLIER_PROPOSAL_DELETE': // Contracts @@ -274,7 +274,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // case 'CONTRACT_CLOSE': // case 'CONTRACT_DELETE': // case 'LINECONTRACT_INSERT': - // case 'LINECONTRACT_UPDATE': + // case 'LINECONTRACT_MODIFY': // case 'LINECONTRACT_DELETE': // Bills @@ -288,19 +288,19 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // case 'BILL_DELETE': // case 'BILL_PAYED': // case 'LINEBILL_INSERT': - // case 'LINEBILL_UPDATE': + // case 'LINEBILL_MODIFY': // case 'LINEBILL_DELETE': //Supplier Bill // case 'BILL_SUPPLIER_CREATE': - // case 'BILL_SUPPLIER_UPDATE': + // case 'BILL_SUPPLIER_MODIFY': // case 'BILL_SUPPLIER_DELETE': // case 'BILL_SUPPLIER_PAYED': // case 'BILL_SUPPLIER_UNPAYED': // case 'BILL_SUPPLIER_VALIDATE': // case 'BILL_SUPPLIER_UNVALIDATE': // case 'LINEBILL_SUPPLIER_CREATE': - // case 'LINEBILL_SUPPLIER_UPDATE': + // case 'LINEBILL_SUPPLIER_MODIFY': // case 'LINEBILL_SUPPLIER_DELETE': // Payments @@ -316,7 +316,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // Donation // case 'DON_CREATE': - // case 'DON_UPDATE': + // case 'DON_MODIFY': // case 'DON_DELETE': // Interventions @@ -325,7 +325,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // case 'FICHINTER_VALIDATE': // case 'FICHINTER_DELETE': // case 'LINEFICHINTER_CREATE': - // case 'LINEFICHINTER_UPDATE': + // case 'LINEFICHINTER_MODIFY': // case 'LINEFICHINTER_DELETE': // Members diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 2fe1ac92ddde2..56d300c9b8f1a 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1875,7 +1875,7 @@ print ''; } - if ($object->status == $object::STATUS_CLOSED) { + if ($object->status == ExpenseReport::STATUS_CLOSED) { /* TODO this fields are not yet filled print '
'; print ''; @@ -2615,12 +2615,12 @@ // Unit price net print ''; // Unit price with tax print ''; // Quantity diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index f9757c4f77943..b502bfe6ad7ce 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -1943,7 +1943,7 @@ public function addline($qty = 0, $up = 0, $fk_c_type_fees = 0, $vatrate = 0, $d dol_syslog(get_class($this)."::addline qty=$qty, up=$up, fk_c_type_fees=$fk_c_type_fees, vatrate=$vatrate, date=$date, fk_project=$fk_project, type=$type, comments=$comments", LOG_DEBUG); - if ($this->status == self::STATUS_DRAFT) { + if ($this->status == self::STATUS_DRAFT || $this->status == self::STATUS_REFUSED) { if (empty($qty)) { $qty = 0; } @@ -2037,7 +2037,7 @@ public function addline($qty = 0, $up = 0, $fk_c_type_fees = 0, $vatrate = 0, $d } } else { dol_syslog(get_class($this)."::addline status of expense report must be Draft to allow use of ->addline()", LOG_ERR); - $this->error = 'ErrorExpenseNotDraft'; + $this->error = 'ErrorExpenseNotDraftAndNotRefused'; return -3; } } diff --git a/htdocs/exports/export.php b/htdocs/exports/export.php index 61042abf3dea4..72d260e152502 100644 --- a/htdocs/exports/export.php +++ b/htdocs/exports/export.php @@ -474,7 +474,7 @@ // Affiche les modules d'exports print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table - print '
Commit IDDateReported on
Yogosha
Reported on
GIT
Reported on
CVE
TitleBranch of fix
Commit IDDateReported on
Yogosha
Reported on
GIT
Reported on
CVE
TitleBranch of fix
'.$langs->trans("AUTHORPAIEMENT").''; - print ''; + print ''; print ''; - print ''; + print ''; print '
'; + print '
'; print ''; print ''; print ''; @@ -486,16 +486,17 @@ //var_dump($objexport->array_export_code_for_sort); //$sortedarrayofmodules = dol_sort_array($objexport->array_export_module, 'module_position', 'asc', 0, 0, 1); foreach ($objexport->array_export_code_for_sort as $key => $value) { - print '
'.$langs->trans("Module").''.$langs->trans("ExportableDatas").'
'; - //print img_object($objexport->array_export_module[$key]->getName(),$export->array_export_module[$key]->picto).' '; - print $objexport->array_export_module[$key]->getName(); + $titleofmodule = $objexport->array_export_module[$key]->getName(); + print '
'; + print dolPrintHTML($titleofmodule); print ''; $entity = preg_replace('/:.*$/', '', $objexport->array_export_icon[$key]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); $label = $objexport->array_export_label[$key]; - //print $value.'-'.$icon.'-'.$label."
"; - print img_object($objexport->array_export_module[$key]->getName(), $entityicon).' '; - print $label; + print '
'; + print img_object($objexport->array_export_module[$key]->getName(), $entityicon, 'class="pictofixedwidth"'); + print dolPrintHTML($label); + print '
'; print '
'; if ($objexport->array_export_perms[$key]) { print ''.img_picto($langs->trans("NewExport"), 'next', 'class="fa-15"').''; diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index 5a259070df15b..d7db51a8523a1 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -1025,7 +1025,7 @@ public function find_min_price_product_fournisseur($prodid, $qty = 0, $socid = 0 } } - if ($fourn_unitprice < $min || $min == -1) { + if ($fourn_unitprice_with_discount < $min || $min == -1) { $this->id = $prodid; $this->product_fourn_price_id = $record["product_fourn_price_id"]; $this->ref_supplier = $record["ref_fourn"]; @@ -1050,7 +1050,7 @@ public function find_min_price_product_fournisseur($prodid, $qty = 0, $socid = 0 $this->fourn_multicurrency_id = $record["fk_multicurrency"]; $this->fourn_multicurrency_code = $record["multicurrency_code"]; - $min = $fourn_unitprice; + $min = $fourn_unitprice_with_discount; } } } diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 34349e99a910b..1506bc57e1736 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -844,7 +844,7 @@ $object->fk_incoterms = GETPOSTINT('incoterm_id'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha'); - $object->multicurrency_tx = GETPOSTINT('originmulticurrency_tx'); + $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx'); $object->transport_mode_id = GETPOSTINT('transport_mode_id'); // Proprietes particulieres a facture de replacement @@ -4063,7 +4063,7 @@ function setRadioForTypeOfInvoice() { } // Reverse back money or convert to reduction - if ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE || $object->type == FactureFournisseur::TYPE_DEPOSIT || $object->type == FactureFournisseur::TYPE_STANDARD) { + if ($object->status != FactureFournisseur::STATUS_DRAFT && ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE || $object->type == FactureFournisseur::TYPE_DEPOSIT || $object->type == FactureFournisseur::TYPE_STANDARD)) { // For credit note only if ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE && $object->status == 1 && $object->paid == 0) { if ($resteapayer == 0) { diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index 1e9d77989f4bb..4d42caf99def5 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -351,7 +351,7 @@ // Affiche les modules d'imports print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table - print ''; + print '
'; print ''; print ''; print ''; @@ -362,18 +362,21 @@ $sortedarrayofmodules = dol_sort_array($objimport->array_import_module, 'position_of_profile', 'asc', 0, 0, 1); foreach ($sortedarrayofmodules as $key => $value) { //var_dump($key.' '.$value['position_of_profile'].' '.$value['import_code'].' '.$objimport->array_import_module[$key]['module']->getName().' '.$objimport->array_import_code[$key]); - print ''; diff --git a/htdocs/societe/canvas/company/tpl/card_create.tpl.php b/htdocs/societe/canvas/company/tpl/card_create.tpl.php index 379abf2e8ccda..dc2ef93fc6fb2 100644 --- a/htdocs/societe/canvas/company/tpl/card_create.tpl.php +++ b/htdocs/societe/canvas/company/tpl/card_create.tpl.php @@ -1,6 +1,6 @@ - * Copyright (C) 2010-2012 Laurent Destailleur +/* Copyright (C) 2010 Regis Houssin + * Copyright (C) 2010-2012 Laurent Destailleur * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -18,10 +18,13 @@ */ /** + * @var Canvas $this * @var Conf $conf * @var CommonObject $this * @var Translate $langs * @var User $user + * + * @var string $canvas */ // Protection to avoid direct call of template if (empty($conf) || !is_object($conf)) { diff --git a/htdocs/societe/canvas/company/tpl/card_edit.tpl.php b/htdocs/societe/canvas/company/tpl/card_edit.tpl.php index 5143b84ea73d5..03a353f7eb85c 100644 --- a/htdocs/societe/canvas/company/tpl/card_edit.tpl.php +++ b/htdocs/societe/canvas/company/tpl/card_edit.tpl.php @@ -18,10 +18,12 @@ */ /** + * @var Canvas $this * @var Conf $conf * @var CommonObject $this * @var Translate $langs * @var User $user + * @var string $canvas */ // Protection to avoid direct call of template if (empty($conf) || !is_object($conf)) { diff --git a/htdocs/societe/canvas/company/tpl/card_view.tpl.php b/htdocs/societe/canvas/company/tpl/card_view.tpl.php index 82191b9faa0f2..f1246e4bb662f 100644 --- a/htdocs/societe/canvas/company/tpl/card_view.tpl.php +++ b/htdocs/societe/canvas/company/tpl/card_view.tpl.php @@ -16,10 +16,13 @@ * along with this program. If not, see . */ /** + * @var Canvas $this * @var Conf $conf * @var CommonObject $this * @var Translate $langs * @var User $user + * + * @var string $canvas */ // Protection to avoid direct call of template if (empty($conf) || !is_object($conf)) { @@ -37,17 +40,16 @@ print dol_get_fiche_head($head, 'card', $langs->trans("ThirdParty"), 0, 'company'); -?> - -control->tpl['error']) { +if ($this->control->tpl['error']) { echo $this->control->tpl['error']; -} ?> -control->tpl['action_delete']) { +} +if ($this->control->tpl['action_delete']) { echo $this->control->tpl['action_delete']; -} ?> -control->tpl['js_checkVatPopup']) { +} +if ($this->control->tpl['js_checkVatPopup']) { echo $this->control->tpl['js_checkVatPopup']; -} ?> +} +?>
'.$langs->trans("Module").''.$langs->trans("ImportableDatas").'
'; $titleofmodule = $objimport->array_import_module[$key]['module']->getName(); + print '
'; // Special case for import common to module/services if (in_array($objimport->array_import_code[$key], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } - print $titleofmodule; + print dolPrintHTML($titleofmodule); print ''; $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[$key]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); - print img_object($objimport->array_import_module[$key]['module']->getName(), $entityicon).' '; - print $objimport->array_import_label[$key]; + $label = $objimport->array_import_label[$key]; + print '
'; + print img_object($objimport->array_import_module[$key]['module']->getName(), $entityicon, 'class="pictofixedwidth"'); + print dolPrintHtml($label); + print '
'; print '
'; if ($objimport->array_import_perms[$key]) { print ''.img_picto($langs->trans("NewImport"), 'next', 'class="fa-15"').''; diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index ad0813153e104..bff22a33e9fe6 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -383,8 +383,8 @@ ExportCardToFormat=Export card to format ContactNotLinkedToCompany=Contact not linked to any third party DolibarrLogin=Dolibarr login NoDolibarrAccess=No Dolibarr access -ExportDataset_company_1=Third-parties (companies/foundations/physical people) and their properties -ExportDataset_company_2=Contacts and their properties +ExportDataset_company_1=Third-parties (organizations/natural persons) and attributes +ExportDataset_company_2=Third-parties additional contacts/addresses and attributes ExportDataset_company_3=Third-parties payment modes (bank accounts) ImportDataset_company_1=Third-parties and their properties ImportDataset_company_2=Third-parties additional contacts/addresses and attributes diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 16db52a977034..4099d76274578 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -798,7 +798,7 @@ Notes=Notes AddNewLine=Add new line AddFile=Add file FreeZone=Free-text product -FreeLineOfType=Free-text item, type: +FreeLineOfType=Free-text item, type CloneMainAttributes=Clone object with its main attributes ReGeneratePDF=Re-generate PDF PDFMerge=PDF Merge diff --git a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php index 89e4ed53480d6..b9391aa6afacb 100644 --- a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php +++ b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php @@ -143,7 +143,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //case 'ORDER_CLASSIFY_UNBILLED': // TODO Replace it with ORDER_UNBILLED //case 'ORDER_SETDRAFT': //case 'LINEORDER_INSERT': - //case 'LINEORDER_UPDATE': + //case 'LINEORDER_MODIFY': //case 'LINEORDER_DELETE': // Supplier orders @@ -160,7 +160,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //case 'ORDER_SUPPLIER_RECEIVE': //case 'LINEORDER_SUPPLIER_DISPATCH': //case 'LINEORDER_SUPPLIER_CREATE': - //case 'LINEORDER_SUPPLIER_UPDATE': + //case 'LINEORDER_SUPPLIER_MODIFY': //case 'LINEORDER_SUPPLIER_DELETE': // Proposals @@ -174,7 +174,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //case 'PROPAL_CLOSE_REFUSED': //case 'PROPAL_DELETE': //case 'LINEPROPAL_INSERT': - //case 'LINEPROPAL_UPDATE': + //case 'LINEPROPAL_MODIFY': //case 'LINEPROPAL_DELETE': // SupplierProposal @@ -186,7 +186,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //case 'SUPPLIER_PROPOSAL_CLOSE_REFUSED': //case 'SUPPLIER_PROPOSAL_DELETE': //case 'LINESUPPLIER_PROPOSAL_INSERT': - //case 'LINESUPPLIER_PROPOSAL_UPDATE': + //case 'LINESUPPLIER_PROPOSAL_MODIFY': //case 'LINESUPPLIER_PROPOSAL_DELETE': // Contracts @@ -197,7 +197,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //case 'CONTRACT_CLOSE': //case 'CONTRACT_DELETE': //case 'LINECONTRACT_INSERT': - //case 'LINECONTRACT_UPDATE': + //case 'LINECONTRACT_MODIFY': //case 'LINECONTRACT_DELETE': // Bills @@ -210,7 +210,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //case 'BILL_DELETE': //case 'BILL_PAYED': //case 'LINEBILL_INSERT': - //case 'LINEBILL_UPDATE': + //case 'LINEBILL_MODIFY': //case 'LINEBILL_DELETE': // Recurring Bills @@ -222,14 +222,14 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //Supplier Bill //case 'BILL_SUPPLIER_CREATE': - //case 'BILL_SUPPLIER_UPDATE': + //case 'BILL_SUPPLIER_MODIFY': //case 'BILL_SUPPLIER_DELETE': //case 'BILL_SUPPLIER_PAYED': //case 'BILL_SUPPLIER_UNPAYED': //case 'BILL_SUPPLIER_VALIDATE': //case 'BILL_SUPPLIER_UNVALIDATE': //case 'LINEBILL_SUPPLIER_CREATE': - //case 'LINEBILL_SUPPLIER_UPDATE': + //case 'LINEBILL_SUPPLIER_MODIFY': //case 'LINEBILL_SUPPLIER_DELETE': // Payments @@ -245,7 +245,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf // Donation //case 'DON_CREATE': - //case 'DON_UPDATE': + //case 'DON_MODIFY': //case 'DON_DELETE': // Interventions @@ -256,7 +256,7 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf //case 'FICHINTER_CLASSIFY_UNBILLED': // TODO Replace it with FICHINTER_UNBILLED //case 'FICHINTER_DELETE': //case 'LINEFICHINTER_CREATE': - //case 'LINEFICHINTER_UPDATE': + //case 'LINEFICHINTER_MODIFY': //case 'LINEFICHINTER_DELETE': // Members diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index a94aa6d490ac4..141b9b79054c3 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1544,7 +1544,7 @@ public function update($id, $user, $notrigger = 0, $action = 'update', $updatety $sql .= ", sell_or_eat_by_mandatory = ".((empty($this->sell_or_eat_by_mandatory) || $this->sell_or_eat_by_mandatory < 0) ? 0 : (int) $this->sell_or_eat_by_mandatory); $sql .= ", batch_mask = '".$this->db->escape($this->batch_mask)."'"; - $sql .= ", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished == '') ? "null" : (int) $this->finished); + $sql .= ", finished = ".((!isset($this->finished) || $this->finished < 0 || $this->finished === '') ? "null" : (int) $this->finished); $sql .= ", fk_default_bom = ".((!isset($this->fk_default_bom) || $this->fk_default_bom < 0 || $this->fk_default_bom == '') ? "null" : (int) $this->fk_default_bom); $sql .= ", net_measure = ".($this->net_measure != '' ? "'".$this->db->escape($this->net_measure)."'" : 'null'); $sql .= ", net_measure_units = ".($this->net_measure_units != '' ? "'".$this->db->escape($this->net_measure_units)."'" : 'null'); @@ -3078,7 +3078,7 @@ public function fetch($id = 0, $ref = '', $ref_ext = '', $barcode = '', $ignore_ // Load multiprices array if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && empty($ignore_price_load)) { // prices per segment - $produit_multiprices_limit = getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT'); + $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { $sql = "SELECT price, price_ttc, price_min, price_min_ttc,"; $sql .= " price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly"; @@ -3195,7 +3195,7 @@ public function fetch($id = 0, $ref = '', $ref_ext = '', $barcode = '', $ignore_ return -1; } } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && empty($ignore_price_load)) { // prices per customer and quantity - $produit_multiprices_limit = getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT'); + $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { $sql = "SELECT price, price_ttc, price_min, price_min_ttc,"; $sql .= " price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly"; diff --git a/htdocs/public/ticket/list.php b/htdocs/public/ticket/list.php index 03dba86959abb..c835bdd1cf26a 100644 --- a/htdocs/public/ticket/list.php +++ b/htdocs/public/ticket/list.php @@ -98,7 +98,6 @@ } - /* * Actions */ diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index 86e8d046ff987..22c1ad326ba7f 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -647,8 +647,7 @@ public function valid($user, $notrigger = 0) if (intval($result) < 0) { $error++; - $this->errors[] = $mouvS->error; - $this->errors = array_merge($this->errors, $mouvS->errors); + $this->setErrorsFromObject($mouvS); break; } } else { @@ -661,8 +660,7 @@ public function valid($user, $notrigger = 0) if (intval($result) < 0) { $error++; - $this->errors[] = $mouvS->error; - $this->errors = array_merge($this->errors, $mouvS->errors); + $this->setErrorsFromObject($mouvS); break; } } @@ -809,8 +807,7 @@ public function getStatusDispatch() $ret = $supplierorderdispatch->fetchAll('', '', 0, 0, $filter); if ($ret < 0) { - $this->error = $supplierorderdispatch->error; - $this->errors = $supplierorderdispatch->errors; + $this->setErrorsFromObject($supplierorderdispatch); return $ret; } else { // build array with quantity received by product in all supplier orders (origin) @@ -895,8 +892,7 @@ public function addline($entrepot_id, $id, $qty, $array_options = [], $comment = $supplierorderline = new CommandeFournisseurLigne($this->db); $result = $supplierorderline->fetch($id); if ($result <= 0) { - $this->error = $supplierorderline->error; - $this->errors = $supplierorderline->errors; + $this->setErrorsFromObject($supplierorderline); return -1; } diff --git a/htdocs/salaries/class/salary.class.php b/htdocs/salaries/class/salary.class.php index a70fce80e077f..e0d3abf655cd0 100644 --- a/htdocs/salaries/class/salary.class.php +++ b/htdocs/salaries/class/salary.class.php @@ -120,6 +120,7 @@ class Salary extends CommonObject /** * @var int + * @deprecated see $accountid * @see $accountid */ public $fk_account; @@ -154,7 +155,7 @@ class Salary extends CommonObject const STATUS_PAID = 1; /** - * @var string + * @var float amount remain to pay */ public $resteapayer; diff --git a/htdocs/salaries/list.php b/htdocs/salaries/list.php index c26a609536be2..f72c3a4512fb7 100644 --- a/htdocs/salaries/list.php +++ b/htdocs/salaries/list.php @@ -193,8 +193,8 @@ $objecttmp = new Salary($db); $result = $objecttmp->fetch($toselectid); if ($result > 0) { - $totalpaid = $objecttmp->getSommePaiement(); - $objecttmp->resteapayer = price2num((float) $objecttmp->amount - $totalpaid, 'MT'); + $totalpaid = (float) $objecttmp->getSommePaiement(); + $objecttmp->resteapayer = (float) price2num((float) $objecttmp->amount - $totalpaid, 'MT'); // hook to finalize the remaining amount, considering e.g. cash discount agreements $parameters = array('remaintopay' => $objecttmp->resteapayer); @@ -211,7 +211,7 @@ if ($objecttmp->status == Salary::STATUS_PAID || $objecttmp->resteapayer == 0) { $error++; setEventMessages($langs->trans("Salary").' '.$objecttmp->ref.' : '.$langs->trans("AlreadyPaid"), $objecttmp->errors, 'errors'); - } elseif ($resteapayer < 0) { + } elseif ($objecttmp->resteapayer < 0) { $error++; setEventMessages($langs->trans("Salary").' '.$objecttmp->ref.' : '.$langs->trans("AmountMustBePositive"), $objecttmp->errors, 'errors'); } diff --git a/htdocs/salaries/paiement_salary.php b/htdocs/salaries/paiement_salary.php index fcb4cb9ad53f6..f084e5e1a07d4 100644 --- a/htdocs/salaries/paiement_salary.php +++ b/htdocs/salaries/paiement_salary.php @@ -167,6 +167,7 @@ llxHeader('', '', $help_url); $salary = $object; +$sumpaid = 0.0; // Formulaire de creation d'un paiement de charge if ($action == 'create') { @@ -214,7 +215,7 @@ $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $sumpaid = $obj->total; + $sumpaid = (float) $obj->total; $db->free($resql); } /*print '
'.$langs->trans("AlreadyPaid").''.price($sumpaid,0,$outputlangs,1,-1,-1,$conf->currency).'
diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index e4a3c6c47d5ec..9e149817d8308 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1960,7 +1960,7 @@ function manageprospectcustomer(element) { print ''; print ''; print ''; print ''; } +if (!empty($arrayfields['s.ref_ext']['checked'])) { + print ''; +} // Barcode if (!empty($arrayfields['s.barcode']['checked'])) { print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } // Barcode if (!empty($arrayfields['s.barcode']['checked'])) { print ''; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index b198e461b824b..e6b4e156a26e7 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -748,8 +748,12 @@ /* CSS for placeholder */ .placeholder { color: #ccc; } +select.placeholder { color: #ccc; } ::-webkit-input-placeholder { color: #ccc; } input:-moz-placeholder { color: #ccc; } +select.placeholder option:not(.opacitymediumbycolor):not(.opacitymedium) { + color: var(--colortext); +} input[name=price], input[name=weight], input[name=volume], input[name=surface], input[name=sizeheight], input[name=net_measure], select[name=incoterm_id] { margin-right: 6px; } fieldset { @@ -766,6 +770,7 @@ opacity: 0.7; } + .formconsumeproduce { background: #f3f3f3; padding: 20px 0px 0px 0px; @@ -1712,7 +1717,7 @@ -webkit-line-clamp: 2; overflow: hidden; } -.twolinesmax { +.twolinesmax, .twolinesmax-normallineheight { /* To be used into a
into a td for example */ display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; @@ -1720,6 +1725,9 @@ height: auto !important; word-break: break-word; } +.twolinesmax-normallineheight { + line-height: normal; +} .tenlinesmax { display: -webkit-box; -webkit-box-orient: vertical; @@ -4481,8 +4489,8 @@ } table.liste td, table.noborder td, div.noborder form div, table.tableforservicepart1 td, table.tableforservicepart2 td { padding: 6px 10px 6px 12px; /* t r b l */ - /* line-height: 22px; This create trouble on cell login on list of last events of a contract*/ - height: 30px; + /* line-height: 22px; This create trouble on cell login on list of last events of a contract */ + height: 32px; } table.liste tr.trkanban td { padding: 12px 15px 12px 15px; /* t r b l */ diff --git a/htdocs/theme/md/main_menu_fa_icons.inc.php b/htdocs/theme/md/main_menu_fa_icons.inc.php index d5373467280d8..a08b85c27c12d 100644 --- a/htdocs/theme/md/main_menu_fa_icons.inc.php +++ b/htdocs/theme/md/main_menu_fa_icons.inc.php @@ -107,14 +107,15 @@ text-align: center; } -.menu_titre .em092 { + +.em092 { font-size: 0.92em; } -.menu_titre .em088 { +.em088 { font-size: 0.88em; } -.menu_titre .em080 { +.em080 { font-size: 0.80em; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index c1c1ff04592ad..b333f13f1cad1 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -933,11 +933,15 @@ /* CSS for placeholder */ .placeholder { color: #ccc; } +select.placeholder { color: #ccc; } ::-webkit-input-placeholder { color:#ccc; } :-moz-placeholder { color:#bbb; } /* firefox 18- */ ::-moz-placeholder { color:#bbb; } /* firefox 19+ */ :-ms-input-placeholder { color:#ccc; } /* ie */ input:-moz-placeholder { color:#ccc; } +select.placeholder option:not(.opacitymediumbycolor):not(.opacitymedium) { + color: var(--colortext); +} input[name=price], input[name=weight], input[name=volume], input[name=surface], input[name=sizeheight], input[name=net_measure], select[name=incoterm_id] { margin-right: 6px; } fieldset { @@ -1863,7 +1867,7 @@ -webkit-line-clamp: 2; overflow: hidden; } -.twolinesmax { +.twolinesmax, .twolinesmax-normallineheight { /* To be used into a
into a td for example */ display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; @@ -1871,6 +1875,9 @@ height: auto !important; word-break: break-word; } +.twolinesmax-normallineheight { + line-height: normal; +} .tenlinesmax { display: -webkit-box; -webkit-box-orient: vertical; @@ -4487,7 +4494,7 @@ padding-top: 4px; padding-bottom: 3px; } -.liste_titre_create td, .liste_titre_create th, .liste_titre_create .tagtd +.liste_titre_create td:not(.linecoldescription), .liste_titre_create th, .liste_titre_create .tagtd { border-top-width: 1px; border-top-color: var(--colortopbordertitle1); @@ -4509,13 +4516,17 @@ border-top-style: solid; } +td.linecoldescription { + padding: 6px 10px 6px 12px !important; /* t r b l */ +} + table.liste th, table.noborder th, table.noborder tr.liste_titre td, table.noborder tr.box_titre td { padding: 8px 8px 8px 10px; /* t r b l */ } table.liste td, table.noborder td, div.noborder form div, table.tableforservicepart1 td, table.tableforservicepart2 td { padding: 4px 8px 4px 10px; /* t r b l */ - height: 22px; + height: 28px; } table.liste tr.trkanban td { padding: 12px 15px 12px 15px; /* t r b l */ diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index adc2322e5261f..b7c9d5e3c454f 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -550,13 +550,13 @@ public function updateProperties(Product $parent, User $user) // MultiPrix if (getDolGlobalString('PRODUIT_MULTIPRICES')) { - $produit_multiprices_limit = getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT'); + $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { if ($parent->multiprices[$i] != '' || isset($this->combination_price_levels[$i]->variation_price)) { $new_type = empty($parent->multiprices_base_type[$i]) ? 'HT' : $parent->multiprices_base_type[$i]; $new_min_price = $parent->multiprices_min[$i]; $variation_price = (float) (!isset($this->combination_price_levels[$i]->variation_price) ? $this->variation_price : $this->combination_price_levels[$i]->variation_price); - $variation_price_percentage = (float) (!isset($this->combination_price_levels[$i]->variation_price_percentage) ? $this->variation_price_percentage : $this->combination_price_levels[$i]->variation_price_percentage); + $variation_price_percentage = (bool) (!isset($this->combination_price_levels[$i]->variation_price_percentage) ? $this->variation_price_percentage : $this->combination_price_levels[$i]->variation_price_percentage); if ($parent->prices_by_qty_list[$i]) { $new_psq = 1; @@ -867,14 +867,14 @@ public function createProductCombination(User $user, Product $product, array $co $newproduct->description .= ''.$prodattr->label.': '.$prodattrval->value; } - $newcomb->variation_price_percentage = $price_var_percent[1]; + $newcomb->variation_price_percentage = (bool) $price_var_percent[1]; $newcomb->variation_price = $price_impact[1]; $newcomb->variation_weight = $weight_impact; $newcomb->variation_ref_ext = $this->db->escape($ref_ext); // Init price level if (getDolGlobalString('PRODUIT_MULTIPRICES')) { - $produit_multiprices_limit = getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT'); + $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { $productCombinationLevel = new ProductCombinationLevel($this->db); $productCombinationLevel->fk_product_attribute_combination = $newcomb->id; @@ -882,7 +882,7 @@ public function createProductCombination(User $user, Product $product, array $co $productCombinationLevel->variation_price = $price_impact[$i]; if (is_array($price_var_percent)) { - $productCombinationLevel->variation_price_percentage = (empty($price_var_percent[$i]) ? false : $price_var_percent[$i]); + $productCombinationLevel->variation_price_percentage = (bool) $price_var_percent[$i] ; } else { $productCombinationLevel->variation_price_percentage = $price_var_percent; } diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index 0e31f37cba9e1..e32143113c6ae 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -302,7 +302,8 @@ if (getDolGlobalString('PRODUIT_MULTIPRICES')) { $prodcomb->combination_price_levels = array(); - for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) { + $maxi = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); + for ($i = 1; $i <= $maxi; $i++) { $productCombinationLevel = new ProductCombinationLevel($db); $productCombinationLevel->fk_product_attribute_combination = $prodcomb->id; $productCombinationLevel->fk_price_level = $i; @@ -723,14 +724,16 @@
fetchCombinationPriceLevels(); - for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) { + $maxi = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); + for ($i = 1; $i <= $maxi; $i++) { $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$i; $text = $langs->trans('ImpactOnPriceLevel', $i).' - '.getDolGlobalString($keyforlabel); print ''; @@ -740,7 +743,7 @@ } print ''; print ''; print ''; @@ -767,7 +770,7 @@ let priceImpact = $( "#level_price_impact_1" ).val(); let priceImpactPrecent = $( "#level_price_impact_percent_1" ).prop("checked"); - var multipricelimit = global->PRODUIT_MULTIPRICES_LIMIT); ?> + let multipricelimit = for (let i = 2; i <= multipricelimit; i++) { $( "#level_price_impact_" + i ).val(priceImpact); diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index 12e58357aa479..ae5b2c0359574 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -134,6 +134,8 @@ public static function suite() $suite->addTestSuite('SecurityTest'); require_once dirname(__FILE__).'/SecurityGETPOSTTest.php'; $suite->addTestSuite('SecurityGETPOSTTest'); + require_once dirname(__FILE__).'/SecurityLoginTest.php'; + $suite->addTestSuite('SecurityLoginTest'); require_once dirname(__FILE__).'/UserTest.php'; $suite->addTestSuite('UserTest'); diff --git a/test/phpunit/SecurityLoginTest.php b/test/phpunit/SecurityLoginTest.php new file mode 100644 index 0000000000000..2e4d190567c3b --- /dev/null +++ b/test/phpunit/SecurityLoginTest.php @@ -0,0 +1,106 @@ + + * Copyright (C) 2023 Alexandre Janniaux + * Copyright (C) 2024 Frédéric France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file test/phpunit/SecurityTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; + +if (! defined('NOREQUIRESOC')) { + define('NOREQUIRESOC', '1'); +} +if (! defined('NOCSRFCHECK')) { + define('NOCSRFCHECK', '1'); +} +if (! defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); +} +if (! defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); // If there is no menu to show +} +if (! defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +} +if (! defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (! defined("NOLOGIN")) { + define("NOLOGIN", '1'); // If this page is public (can be called outside logged session) +} +if (! defined("NOSESSION")) { + define("NOSESSION", '1'); +} + +require_once dirname(__FILE__).'/../../htdocs/main.inc.php'; // We force include of main.inc.php instead of master.inc.php even if we are in CLI mode because it contains a lot of security components we want to test. +require_once dirname(__FILE__).'/../../htdocs/core/lib/security.lib.php'; +require_once dirname(__FILE__).'/../../htdocs/core/lib/security2.lib.php'; +require_once dirname(__FILE__).'/CommonClassTest.class.php'; + +if (empty($user->id)) { + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->loadRights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS = 1; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class SecurityLoginTest extends CommonClassTest +{ + /** + * testCheckLoginPassEntity + * + * @return void + */ + public function testCheckLoginPassEntity() + { + $login = checkLoginPassEntity('loginbidon', 'passwordbidon', 1, array('dolibarr')); + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, ''); + + $login = checkLoginPassEntity('admin', 'passwordbidon', 1, array('dolibarr')); + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, ''); + + $login = checkLoginPassEntity('admin', 'admin', 1, array('dolibarr')); // Should works because admin/admin exists + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, 'admin', 'The test to check if pass of user "admin" is "admin" has failed'); + + $login = checkLoginPassEntity('admin', 'admin', 1, array('http','dolibarr')); // Should work because of second authentication method + print __METHOD__." login=".$login."\n"; + $this->assertEquals($login, 'admin'); + + $login = checkLoginPassEntity('admin', 'admin', 1, array('forceuser')); + print __METHOD__." login=".$login."\n"; + $this->assertEquals('', $login, 'Error'); // Expected '' because should failed because login 'auto' does not exists + } +} diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 294d1596fec84..9b5db827bc3b5 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -636,13 +636,13 @@ public function testDolEval() $this->assertEquals('Bad string syntax to evaluate: new __forbiddenstring__(\'abc\')', $result); - $result = (string) dol_eval('$a=function() { }; $a;', 1, 1, '0'); - print "result5 = ".$result."\n"; - $this->assertStringContainsString('Bad string syntax to evaluate', $result); + $result = dol_eval('$a=function() { }; $a', 1, 1, '0'); // result of dol_eval may be an object Closure + print "result5 = ".json_encode($result)."\n"; + $this->assertStringContainsString('Bad string syntax to evaluate', json_encode($result)); - $result = (string) dol_eval('$a=function() { }; $a;', 1, 1, '1'); - print "result6 = ".$result."\n"; - $this->assertStringContainsString('Bad string syntax to evaluate', $result); + $result = dol_eval('$a=function() { }; $a();', 1, 1, '1'); + print "result6 = ".json_encode($result)."\n"; + $this->assertStringContainsString('Bad string syntax to evaluate', json_encode($result)); $result = (string) dol_eval('$a=exec("ls");', 1, 1); print "result7 = ".$result."\n"; @@ -723,6 +723,11 @@ public function testDolEval() $result = (string) dol_eval('($a = "ex") && ($b = "ec") && ($cmd = "$a$b") && $cmd ("curl localhost:5555")', 1, 0); print "result22 = ".$result."\n"; $this->assertStringContainsString('Bad string syntax to evaluate', $result, 'Test 22'); + + + $result = (string) dol_eval('\'exec\'("aaa")', 1, 0); + print "result1 = ".$result."\n"; + $this->assertStringContainsString('Bad string syntax to evaluate', json_encode($result), 'Cant find the string Bad string syntaxwhen i should'); } /** @@ -966,33 +971,4 @@ public function testDolHtmlWithNoJs() return 0; } - - - /** - * testCheckLoginPassEntity - * - * @return void - */ - public function testCheckLoginPassEntity() - { - $login = checkLoginPassEntity('loginbidon', 'passwordbidon', 1, array('dolibarr')); - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, ''); - - $login = checkLoginPassEntity('admin', 'passwordbidon', 1, array('dolibarr')); - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, ''); - - $login = checkLoginPassEntity('admin', 'admin', 1, array('dolibarr')); // Should works because admin/admin exists - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, 'admin', 'The test to check if pass of user "admin" is "admin" has failed'); - - $login = checkLoginPassEntity('admin', 'admin', 1, array('http','dolibarr')); // Should work because of second authentication method - print __METHOD__." login=".$login."\n"; - $this->assertEquals($login, 'admin'); - - $login = checkLoginPassEntity('admin', 'admin', 1, array('forceuser')); - print __METHOD__." login=".$login."\n"; - $this->assertEquals('', $login, 'Error'); // Expected '' because should failed because login 'auto' does not exists - } } diff --git a/test/phpunit/WebsiteTest.php b/test/phpunit/WebsiteTest.php index 6ccccb17b23cd..bbf80cad4c59e 100644 --- a/test/phpunit/WebsiteTest.php +++ b/test/phpunit/WebsiteTest.php @@ -65,11 +65,11 @@ print "Load permissions for admin user nb 1\n"; $user->fetch(1); $user->loadRights(); - - if (empty($user->rights->website)) { - $user->rights->website = new stdClass(); - } } +if (empty($user->rights->website)) { + $user->rights->website = new stdClass(); +} + $conf->global->MAIN_DISABLE_ALL_MAILS = 1; @@ -132,22 +132,61 @@ public function testDolStripPhpCode() */ public function testCheckPHPCode() { - global $user; + global $conf, $user; // Force permission so this is not the permission that will affect result of checkPHPCode $user->rights->website->writephp = 1; + // Legitimate + + $t = ''; + $s = ''; + $result = checkPHPCode($t, $s); + print __METHOD__." result checkPHPCode=".$result."\n"; + $this->assertEquals($result, 0, 'checkPHPCode detect string as dangerous when it is legitimate'); + + + // Dangerous + $t = ''; $s = ''; $result = checkPHPCode($t, $s); print __METHOD__." result checkPHPCode=".$result."\n"; $this->assertEquals($result, 1, 'checkPHPCode did not detect the string was dangerous'); + $t = ''; + $s = ''; + $result = checkPHPCode($t, $s); + print __METHOD__." result checkPHPCode=".$result."\n"; + $this->assertEquals($result, 1, 'checkPHPCode did not detect the string was dangerous'); + + $t = ''; + $s = ''; + $result = checkPHPCode($t, $s); + print __METHOD__." result checkPHPCode=".$result."\n"; + $this->assertEquals($result, 1, 'checkPHPCode did not detect the string was dangerous'); + + $t = ''; + $s = ''; + $result = checkPHPCode($t, $s); + print __METHOD__." result checkPHPCode=".$result."\n"; + $this->assertEquals($result, 1, 'checkPHPCode did not detect the string was dangerous'); + $t = ''; $s = ';").($_^"/"); ?>'; $result = checkPHPCode($t, $s); print __METHOD__." result checkPHPCode=".$result."\n"; $this->assertEquals($result, 1, 'checkPHPCode did not detect the string was dangerous'); + + // Dangerous but legitimate due to option WEBSITE_PHP_ALLOW_EXEC + + $conf->global->WEBSITE_PHP_ALLOW_EXEC = 1; + + $t = ''; + $s = ''; + $result = checkPHPCode($t, $s); + print __METHOD__." result checkPHPCode=".$result."\n"; + $this->assertEquals($result, 0, 'checkPHPCode did not accept the exec. it should when WEBSITE_PHP_ALLOW_EXEC is set.'); } /**
'.$form->editfieldkey('AllocateCommercial', 'commercial_id', '', $object, 0).''; // TODO Use select_doluser in multiselect mode - $userlist = $form->select_dolusers($selected, '', 0, null, 0, '', '', '0', 0, 0, 'AND u.statut = 1', 0, '', '', 0, 2); + $userlist = $form->select_dolusers($selected, '', 0, null, 0, '', '', '0', 0, 0, 'u.statut:=:1', 0, '', '', 0, 2); // Note: If user has no right to "see all thirdparties", we force selection of sale representative to him, so after creation he can see the record. $selected = (GETPOSTISARRAY('commercial') ? GETPOST('commercial', 'array:int') : (GETPOSTINT('commercial') > 0 ? array(GETPOSTINT('commercial')) : array($user->id))); print img_picto('', 'user').$form->multiselectarray('commercial', $userlist, $selected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); @@ -2812,7 +2812,7 @@ function init_check_no_email(input) { print '
'.$form->editfieldkey('AllocateCommercial', 'commercial_id', '', $object, 0).''; - $userlist = $form->select_dolusers('', '', 0, null, 0, '', '', 0, 0, 0, 'AND u.statut = 1', 0, '', '', 0, 1); + $userlist = $form->select_dolusers('', '', 0, null, 0, '', '', 0, 0, 0, 'u.statut:=:1', 0, '', '', 0, 1); $arrayselected = GETPOST('commercial', 'array'); if (empty($arrayselected)) { $arrayselected = $object->getSalesRepresentatives($user, 1); diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index 0af1d485070a8..365d2968f0b35 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2019 Frédéric France + * Copyright (C) 2019-2024 Frédéric France * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify @@ -194,9 +194,6 @@ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $sql = "SELECT t.rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as t"; - if ($category > 0) { - $sql .= ", ".MAIN_DB_PREFIX."categorie_contact as c"; - } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople_extrafields as te ON te.fk_object = t.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON t.fk_soc = s.rowid"; $sql .= ' WHERE t.entity IN ('.getEntity('contact').')'; @@ -213,8 +210,37 @@ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, } // Select contacts of given category if ($category > 0) { - $sql .= " AND c.fk_categorie = ".((int) $category); - $sql .= " AND c.fk_socpeople = t.rowid "; + // Search Contact Categories + $searchCategoryContactList = $category ? array($category) : array(); + // $searchCategoryContactOperator = 0; + // Search for tag/category ($searchCategoryContactList is an array of ID) + if (!empty($searchCategoryContactList)) { + $searchCategoryContactSqlList = array(); + // $listofcategoryid = ''; + foreach ($searchCategoryContactList as $searchCategoryContact) { + if (intval($searchCategoryContact) == -2) { + $searchCategoryContactSqlList[] = "NOT EXISTS (SELECT ck.fk_socpeople FROM ".MAIN_DB_PREFIX."categorie_contact as ck WHERE t.rowid = ck.fk_socpeople)"; + } elseif (intval($searchCategoryContact) > 0) { + // if ($searchCategoryContactOperator == 0) { + $searchCategoryContactSqlList[] = " EXISTS (SELECT ck.fk_socpeople FROM ".MAIN_DB_PREFIX."categorie_contact as ck WHERE t.rowid = ck.fk_socpeople AND ck.fk_categorie = ".((int) $searchCategoryContact).")"; + // } else { + // $listofcategoryid .= ($listofcategoryid ? ', ' : '') .((int) $searchCategoryContact); + // } + } + } + // if ($listofcategoryid) { + // $searchCategoryContactSqlList[] = " EXISTS (SELECT ck.fk_socpeople FROM ".MAIN_DB_PREFIX."categorie_contact as ck WHERE t.rowid = ck.fk_socpeople AND ck.fk_categorie IN (".$this->db->sanitize($listofcategoryid)."))"; + // } + // if ($searchCategoryContactOperator == 1) { + // if (!empty($searchCategoryContactSqlList)) { + // $sql .= " AND (".implode(' OR ', $searchCategoryContactSqlList).")"; + // } + // } else { + if (!empty($searchCategoryContactSqlList)) { + $sql .= " AND (".implode(' AND ', $searchCategoryContactSqlList).")"; + } + // } + } } // Add sql filters diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 6a81aeede43e4..70fe8a2f34f33 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -85,6 +85,7 @@ $search_nom = trim(GETPOST("search_nom", 'restricthtml')); $search_alias = trim(GETPOST("search_alias", 'restricthtml')); $search_nom_only = trim(GETPOST("search_nom_only", 'restricthtml')); +$search_ref_ext = trim(GETPOST("search_ref_ext", 'restricthtml')); $search_barcode = trim(GETPOST("search_barcode", 'alpha')); $search_customer_code = trim(GETPOST('search_customer_code', 'alpha')); $search_supplier_code = trim(GETPOST('search_supplier_code', 'alpha')); @@ -287,7 +288,8 @@ 's.rowid' => array('label' => "TechnicalID", 'position' => 1, 'checked' => -1, 'enabled' => 1), 's.nom' => array('label' => "ThirdPartyName", 'position' => 2, 'checked' => 1), 's.name_alias' => array('label' => "AliasNameShort", 'position' => 3, 'checked' => 1), - 's.barcode' => array('label' => "Gencod", 'position' => 5, 'checked' => 1, 'enabled' => (isModEnabled('barcode'))), + 's.ref_ext' => array('label' => "RefExt", 'position' => 4, 'checked' => -1, 'enabled' => getDolGlobalInt('MAIN_LIST_SHOW_REF_EXT')), + 's.barcode' => array('label' => "Gencod", 'position' => 5, 'checked' => 1, 'enabled' => isModEnabled('barcode')), 's.code_client' => array('label' => "CustomerCodeShort", 'position' => 10, 'checked' => $checkedcustomercode), 's.code_fournisseur' => array('label' => "SupplierCodeShort", 'position' => 11, 'checked' => $checkedsuppliercode, 'enabled' => (isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))), 's.code_compta' => array('label' => "CustomerAccountancyCodeShort", 'position' => 13, 'checked' => $checkedcustomeraccountcode), @@ -411,6 +413,7 @@ $search_id = ''; $search_nom = ''; $search_alias = ''; + $search_ref_ext = ''; $search_categ_cus = 0; $search_categ_sup = 0; $searchCategoryCustomerOperator = 0; @@ -562,7 +565,7 @@ // Build and execute select // -------------------------------------------------------------------- -$sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.barcode, s.address, s.town, s.zip, s.datec, s.code_client, s.code_fournisseur, s.logo,"; +$sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.ref_ext, s.barcode, s.address, s.town, s.zip, s.datec, s.code_client, s.code_fournisseur, s.logo,"; $sql .= " s.entity,"; $sql .= " st.libelle as stcomm, st.picto as stcomm_picto, s.fk_stcomm as stcomm_id, s.fk_prospectlevel, s.prefix_comm, s.client, s.fournisseur, s.canvas, s.status as status, s.note_private, s.note_public,"; $sql .= " s.email, s.phone, s.phone_mobile, s.fax, s.url, s.siren as idprof1, s.siret as idprof2, s.ape as idprof3, s.idprof4 as idprof4, s.idprof5 as idprof5, s.idprof6 as idprof6, s.tva_intra, s.fk_pays,"; @@ -715,6 +718,9 @@ if ($search_nom_only) { $sql .= natural_search("s.nom", $search_nom_only); } +if ($search_ref_ext) { + $sql .= natural_search("s.ref_ext", $search_ref_ext); +} if ($search_customer_code) { $sql .= natural_search("s.code_client", $search_customer_code); } @@ -970,6 +976,9 @@ if ($search_alias != '') { $param .= "&search_alias=".urlencode($search_alias); } +if ($search_ref_ext != '') { + $param .= "&search_ref_ext=".urlencode($search_ref_ext); +} if ($search_address != '') { $param .= '&search_address='.urlencode($search_address); } @@ -1281,7 +1290,7 @@ } // If the user can view prospects other than his' -$userlist = $form->select_dolusers('', '', 0, null, 0, '', '', 0, 0, 0, 'AND u.statut = 1', 0, '', '', 0, 1); +$userlist = $form->select_dolusers('', '', 0, null, 0, '', '', 0, 0, 0, 'u.statut:=:1', 0, '', '', 0, 1); $userlist[-2] = $langs->trans("NoSalesRepresentativeAffected"); if ($user->hasRight("societe", "client", "voir") || $socid) { $moreforfilter .= '
'; @@ -1335,6 +1344,11 @@ print ''; print '
'; + print ''; + print ''; @@ -1619,6 +1633,11 @@ print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, "", $sortfield, $sortorder); $totalarray['nbfield']++; } +if (!empty($arrayfields['s.ref_ext']['checked'])) { + // @phan-suppress-next-line PhanTypeInvalidDimOffset + print_liste_field_titre($arrayfields['s.ref_ext']['label'], $_SERVER["PHP_SELF"], "s.ref_ext", "", $param, "", $sortfield, $sortorder); + $totalarray['nbfield']++; +} if (!empty($arrayfields['s.barcode']['checked'])) { print_liste_field_titre($arrayfields['s.barcode']['label'], $_SERVER["PHP_SELF"], "s.barcode", $param, '', '', $sortfield, $sortorder); $totalarray['nbfield']++; @@ -1807,6 +1826,7 @@ $companystatic->id = $obj->rowid; $companystatic->name = $obj->name; $companystatic->name_alias = $obj->name_alias; + $companystatic->ref_ext = $obj->ref_ext; $companystatic->logo = $obj->logo; $companystatic->barcode = $obj->barcode; $companystatic->canvas = $obj->canvas; @@ -1899,6 +1919,15 @@ $totalarray['nbfield']++; } } + // Ref ext + if (!empty($arrayfields['s.ref_ext']['checked'])) { + print ''; + print dol_escape_htmltag($companystatic->ref_ext); + print "'.dol_escape_htmltag($companystatic->barcode).'
- > + + >
'; - print 'combination_price_levels[$i]->variation_price_percentage) ? ' checked' : '').'> '; + print 'combination_price_levels[$i]->variation_price_percentage ? ' checked' : '').'> '; print '