diff --git a/htdocs/accountancy/admin/export.php b/htdocs/accountancy/admin/export.php index 23a16340c0b..30cc0144a1f 100644 --- a/htdocs/accountancy/admin/export.php +++ b/htdocs/accountancy/admin/export.php @@ -269,9 +269,9 @@ if ($num2) { // Value print ''; if (is_array($key['param'])) { - print $form->selectarray($label, $key['param'], $conf->global->$label, 0); + print $form->selectarray($label, $key['param'], getDolGlobalString($label), 0); } else { - print ''; + print ''; } print ''; diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index e9ac1dfa28f..942d4d2e75e 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -101,8 +101,8 @@ if (GETPOST('datep')) { // Security check $socid = GETPOST('socid', 'int'); $id = GETPOST('id', 'int'); -if ($user->socid) { - $socid = $user->socid; +if ($user->socid && ($socid != $user->socid)) { + accessforbidden(); } $error = GETPOST("error"); diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index e16834e5707..f573ec5be56 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -11,6 +11,7 @@ * Copyright (C) 2018-2022 Frédéric France * Copyright (C) 2020 Andreu Bisquerra Gaya * Copyright (C) 2021 OpenDsi + * Copyright (C) 2023 Joachim Kueter * * 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 @@ -382,7 +383,19 @@ class Paiement extends CommonObject if (!in_array($invoice->type, $affected_types)) { dol_syslog("Invoice ".$facid." is not a standard, nor replacement invoice, nor credit note, nor deposit invoice, nor situation invoice. We do nothing more."); } elseif ($remaintopay) { - dol_syslog("Remain to pay for invoice ".$facid." not null. We do nothing more."); + // hook to have an option to automatically close a closable invoice with less payment than the total amount (e.g. agreed cash discount terms) + global $hookmanager; + $hookmanager->initHooks(array('paymentdao')); + $parameters = array('facid' => $facid, 'invoice' => $invoice, 'remaintopay' => $remaintopay); + $action = 'CLOSEPAIDINVOICE'; + $reshook = $hookmanager->executeHooks('createPayment', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) { + $this->errors[] = $hookmanager->error; + $this->error = $hookmanager->error; + $error++; + } elseif ($reshook == 0) { + dol_syslog("Remain to pay for invoice " . $facid . " not null. We do nothing more."); + } // } else if ($mustwait) dol_syslog("There is ".$mustwait." differed payment to process, we do nothing more."); } else { // If invoice is a down payment, we also convert down payment to discount diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 2c2e1788c8e..2bba488f51b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7577,7 +7577,7 @@ function dol_textishtml($msg, $option = 0) return true; } elseif (preg_match('/<\/textarea/i', $msg)) { return true; - } elseif (preg_match('/<(b|em|i|u)>/i', $msg)) { + } elseif (preg_match('/<(b|em|i|u)(\s+[^>]+)?>/i', $msg)) { return true; } elseif (preg_match('/
/i', $msg)) { + } elseif (preg_match('/<(b|em|i|u)(\s+[^>]+)?>/i', $msg)) { return true; } elseif (preg_match('//i', $msg)) { return true; diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index cd64c04e57d..4fdd85f3f24 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -270,9 +270,9 @@ function dol_verifyHash($chain, $hash, $type = '0') if ($type == '0' && !empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'password_hash' && function_exists('password_verify')) { if (! empty($hash[0]) && $hash[0] == '$') { return password_verify($chain, $hash); - } elseif (strlen($hash) == 32) { + } elseif (dol_strlen($hash) == 32) { return dol_verifyHash($chain, $hash, '3'); // md5 - } elseif (strlen($hash) == 40) { + } elseif (dol_strlen($hash) == 40) { return dol_verifyHash($chain, $hash, '2'); // sha1md5 } diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 6f3ac2cdf0f..52b9afab8a7 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -35,8 +35,10 @@ function dolStripPhpCode($str, $replacewith = '') $newstr = ''; - //split on each opening tag - $parts = explode(' * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2018 Frédéric France + * Copyright (C) 2023 Joachim Kueter * * 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 @@ -341,7 +342,18 @@ class PaiementFourn extends Paiement } } } else { - dol_syslog("Remain to pay for invoice ".$facid." not null. We do nothing."); + // hook to have an option to automatically close a closable invoice with less payment than the total amount (e.g. agreed cash discount terms) + global $hookmanager; + $hookmanager->initHooks(array('payment_supplierdao')); + $parameters = array('facid' => $facid, 'invoice' => $invoice, 'remaintopay' => $remaintopay); + $action = 'CLOSEPAIDSUPPLIERINVOICE'; + $reshook = $hookmanager->executeHooks('createPayment', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) { + $this->error = $hookmanager->error; + $error++; + } elseif ($reshook == 0) { + dol_syslog("Remain to pay for invoice " . $facid . " not null. We do nothing more."); + } } } diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 670e77ad4d7..c3464739589 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -43,6 +43,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; +require_once DOL_DOCUMENT_ROOT.'/workstation/class/workstation.class.php'; if (isModEnabled('categorie')) { require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcategory.class.php'; @@ -69,6 +70,7 @@ $search_ref = GETPOST("search_ref", 'alpha'); $search_ref_supplier = GETPOST("search_ref_supplier", 'alpha'); $search_barcode = GETPOST("search_barcode", 'alpha'); $search_label = GETPOST("search_label", 'alpha'); +$search_default_workstation = GETPOST("search_default_workstation", 'alpha'); $search_type = GETPOST("search_type", 'int'); $search_vatrate = GETPOST("search_vatrate", 'alpha'); $searchCategoryProductOperator = 0; @@ -233,6 +235,7 @@ $arrayfields = array( 'p.volume'=>array('label'=>'Volume', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>30), 'p.volume_units'=>array('label'=>'VolumeUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>31), 'cu.label'=>array('label'=>"DefaultUnitToShow", 'checked'=>0, 'enabled'=>(isModEnabled("product") && !empty($conf->global->PRODUCT_USE_UNITS)), 'position'=>32), + 'p.fk_default_workstation'=>array('label'=>'DefaultWorkstation', 'checked'=>0, 'enabled'=>isModEnabled('workstation') && $type == 1, 'position'=>33), 'p.sellprice'=>array('label'=>"SellingPrice", 'checked'=>1, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES), 'position'=>40), 'p.tva_tx'=>array('label'=>"VATRate", 'checked'=>0, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES), 'position'=>41), 'p.minbuyprice'=>array('label'=>"BuyingPriceMinShort", 'checked'=>1, 'enabled'=>(!empty($user->rights->fournisseur->lire)), 'position'=>42), @@ -334,6 +337,7 @@ if (empty($reshook)) { $search_ref = ""; $search_ref_supplier = ""; $search_label = ""; + $search_default_workstation = ""; $search_barcode = ""; $searchCategoryProductOperator = 0; $searchCategoryProductList = array(); @@ -413,7 +417,10 @@ if ($search_type != '' && $search_type != '-1') { $sql = 'SELECT p.rowid, p.ref, p.label, p.fk_product_type, p.barcode, p.price, p.tva_tx, p.price_ttc, p.price_base_type, p.entity,'; $sql .= ' p.fk_product_type, p.duration, p.finished, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,'; -$sql .= ' p.tobatch,'; +$sql .= ' p.tobatch, '; +if (isModEnabled('workstation')) { + $sql .= ' p.fk_default_workstation, ws.status as status_workstation, ws.ref as ref_workstation, '; +} if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { $sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export,"; } else { @@ -442,6 +449,9 @@ $sql .= $hookmanager->resPrint; $sqlfields = $sql; // $sql fields to remove for count total $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; +if (isModEnabled('workstation')) { + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "workstation_workstation ws ON (p.fk_default_workstation = ws.rowid)"; +} if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } @@ -497,6 +507,9 @@ if ($search_ref) { if ($search_label) { $sql .= natural_search('p.label', $search_label); } +if ($search_default_workstation) { + $sql .= natural_search('ws.ref', $search_default_workstation); +} if ($search_barcode) { $sql .= natural_search('p.barcode', $search_barcode); } @@ -594,6 +607,9 @@ $sql .= ' p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_u if (!empty($conf->global->PRODUCT_USE_UNITS)) { $sql .= ', p.fk_unit, cu.label'; } +if (isModEnabled('workstation')) { + $sql .= ', p.fk_default_workstation, ws.status, ws.ref '; +} if (isModEnabled('variants') && (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD) && !$show_childproducts)) { $sql .= ', pac.rowid'; @@ -709,6 +725,9 @@ if ($search_barcode) { if ($search_label) { $param .= "&search_label=".urlencode($search_label); } +if ($search_default_workstation) { + $param .= "&search_default_workstation=".urlencode($search_default_workstation); +} if ($search_tosell != '') { $param .= "&search_tosell=".urlencode($search_tosell); } @@ -1030,6 +1049,13 @@ if (!empty($arrayfields['cu.label']['checked'])) { print ''; } +// Default workstation +if (!empty($arrayfields['p.fk_default_workstation']['checked'])) { + print ''; + print ''; + print ''; +} + // Sell price if (!empty($arrayfields['p.sellprice']['checked'])) { print ''; @@ -1245,6 +1271,9 @@ if (!empty($arrayfields['p.volume_units']['checked'])) { if (!empty($arrayfields['cu.label']['checked'])) { print_liste_field_titre($arrayfields['cu.label']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'center '); } +if (!empty($arrayfields['p.fk_default_workstation']['checked'])) { + print_liste_field_titre($arrayfields['p.fk_default_workstation']['label'], $_SERVER['PHP_SELF'], 'ws.ref', '', $param, '', $sortfield, $sortorder); +} if (!empty($arrayfields['p.sellprice']['checked'])) { print_liste_field_titre($arrayfields['p.sellprice']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right '); } @@ -1338,6 +1367,7 @@ print "\n"; $product_static = new Product($db); +$static_ws = new Workstation($db); $product_fourn = new ProductFournisseur($db); $i = 0; @@ -1451,7 +1481,7 @@ while ($i < $imaxinloop) { $totalarray['nbfield']++; } } - // Ref + // Rowid if (!empty($arrayfields['p.rowid']['checked'])) { print ''; print $product_static->id; @@ -1696,6 +1726,22 @@ while ($i < $imaxinloop) { } } + // Default Workstation + if (!empty($arrayfields['p.fk_default_workstation']['checked'])) { + print ''; + if (!empty($obj->fk_default_workstation)) { + $static_ws->id = $obj->fk_default_workstation; + $static_ws->ref = $obj->ref_workstation; + $static_ws->status = $obj->status_workstation; + + print $static_ws->getNomUrl(1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Sell price if (!empty($arrayfields['p.sellprice']['checked'])) { print ''; diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index 1d5f6eccb37..5dcabf6cf6e 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -223,6 +223,7 @@ class AllTests require_once dirname(__FILE__).'/AccountingAccountTest.php'; $suite->addTestSuite('AccountingAccountTest'); + // Rest require_once dirname(__FILE__).'/RestAPIUserTest.php'; $suite->addTestSuite('RestAPIUserTest'); require_once dirname(__FILE__).'/RestAPIDocumentTest.php'; @@ -274,6 +275,10 @@ class AllTests require_once dirname(__FILE__).'/EmailCollectorTest.php'; $suite->addTestSuite('EmailCollectorTest'); + // Website + require_once dirname(__FILE__).'/WebsiteTest.php'; + $suite->addTestSuite('Website'); + return $suite; } } diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 57b640cd606..b7e3b4c7555 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -588,6 +588,9 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase $input='This is a text with accent é'; $after=dol_textishtml($input); $this->assertTrue($after, 'Test with a é'); + $input='xxx'; + $after=dol_textishtml($input); + $this->assertTrue($after, 'Test with i tag and class;'); // False $input='xxx < br>'; diff --git a/test/phpunit/Website.class.php b/test/phpunit/WebsiteTest.class.php similarity index 92% rename from test/phpunit/Website.class.php rename to test/phpunit/WebsiteTest.class.php index 364235bcc41..4fcf14f9eb1 100644 --- a/test/phpunit/Website.class.php +++ b/test/phpunit/WebsiteTest.class.php @@ -181,6 +181,23 @@ class WebsiteTest extends PHPUnit\Framework\TestCase $this->assertEquals($res['code'], 'KO'); } + /** + * testDolStripPhpCode + * + * @return void + */ + public function testDolStripPhpCode() + { + global $db; + + $s = "abc\nghi"; + $result = dolStripPhpCode($s); + $this->assertEquals("abc\nghi", $result); + + $s = "abc\nghi"; + $result = dolStripPhpCode($s); + $this->assertEquals("abc\nghi", $result); + } /** * testCheckPHPCode