diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index 5f1b081c46d..6762770d564 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -845,10 +845,12 @@ class Categorie extends CommonObject * @param int $offset Offset * @param string $sortfield Sort fields * @param string $sortorder Sort order ('ASC' or 'DESC'); + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customsql'=>...) + * @param string $filtermode Filter mode (AND or OR) * @return array|int -1 if KO, array of instance of object if OK * @see containsObject() */ - public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC') + public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC', $filter = array(), $filtermode = 'AND') { global $user; @@ -867,10 +869,24 @@ class Categorie extends CommonObject if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) { $sql .= " AND o.rowid = ".((int) $user->socid); } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 'o.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + $sql .= $this->db->order($sortfield, $sortorder); if ($limit > 0 || $offset > 0) { $sql .= $this->db->plimit($limit + 1, $offset); } - $sql .= $this->db->order($sortfield, $sortorder); dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ee8806f267c..c85f66ca2c6 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -12,7 +12,7 @@ * Copyright (C) 2017 ATM Consulting * Copyright (C) 2017-2019 Nicolas ZABOURI * Copyright (C) 2017 Rui Strecht - * Copyright (C) 2018-2021 Frédéric France + * Copyright (C) 2018-2023 Frédéric France * Copyright (C) 2018 Josep Lluís Amador * Copyright (C) 2023 Gauthier VERDOL * Copyright (C) 2021 Grégory Blémand @@ -183,6 +183,7 @@ abstract class CommonObject public $fk_project; /** + * @var Project The related project object * @deprecated * @see project */ diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index bfe12d7efe2..02d8e6e2002 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -151,6 +151,10 @@ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as s ON p.rowid = s.fk_produ if (!empty($conf->global->PRODUCT_USE_UNITS)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_units as u on p.fk_unit = u.rowid'; } +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= " WHERE p.entity IN (".getEntity('product').")"; if (!empty($search_categ) && $search_categ != '-1') { $sql .= " AND "; @@ -207,10 +211,12 @@ $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $objec $sql .= $hookmanager->resPrint; $sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,"; $sql .= " p.fk_product_type, p.tms, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock"; -// Add fields from hooks + +// Add GROUP BY from hooks $parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; + $sql_having = ''; if ($search_toolowstock) { $sql_having .= " HAVING SUM(".$db->ifsql('s.reel IS NULL', '0', 's.reel').") < p.seuil_stock_alerte"; @@ -226,6 +232,19 @@ if ($search_stock_physique != '') { } $sql_having .= $natural_search_physique; } + +// Add HAVING from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook +if (!empty($hookmanager->resPrint)) { + if (!empty($sql_having)) { + $sql_having .= " AND"; + } else { + $sql_having .= " HAVING"; + } + $sql_having .= $hookmanager->resPrint; +} + if (!empty($sql_having)) { $sql .= $sql_having; } diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index c823379ce31..d24b5282d11 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -126,6 +126,9 @@ if (!empty($canvas)) { $objcanvas->getCanvas('product', 'list', $canvas); } +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('productreassortlotlist')); + // Security check if ($user->socid) { $socid = $user->socid; @@ -222,11 +225,19 @@ $sql .= ' e.ref as warehouse_ref, e.lieu as warehouse_lieu, e.fk_parent as wareh $sql .= ' pb.batch, pb.eatby as oldeatby, pb.sellby as oldsellby,'; $sql .= ' pl.rowid as lotid, pl.eatby, pl.sellby,'; $sql .= ' SUM(pb.qty) as stock_physique, COUNT(pb.rowid) as nbinbatchtable'; +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps on p.rowid = ps.fk_product'; // Detail for each warehouse $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot as e on ps.fk_entrepot = e.rowid'; // Link on unique key $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_batch as pb on pb.fk_product_stock = ps.rowid'; // Detail for each lot on each warehouse $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_lot as pl on pl.fk_product = p.rowid AND pl.batch = pb.batch'; // Link on unique key +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= " WHERE p.entity IN (".getEntity('product').") AND e.entity IN (".getEntity('stock').")"; if (!empty($search_categ) && $search_categ != '-1') { $sql .= " AND "; @@ -315,6 +326,10 @@ foreach ($search as $key => $val) { } } } +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,"; $sql .= " p.fk_product_type, p.tms,"; @@ -323,6 +338,10 @@ $sql .= " ps.fk_entrepot, ps.reel,"; $sql .= " e.ref, e.lieu, e.fk_parent,"; $sql .= " pb.batch, pb.eatby, pb.sellby,"; $sql .= " pl.rowid, pl.eatby, pl.sellby"; +// Add GROUP BY 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_having = ''; if ($search_toolowstock) { $sql_having .= " HAVING SUM(".$db->ifsql('ps.reel IS NULL', '0', 'ps.reel').") < p.seuil_stock_alerte"; // Not used yet @@ -337,6 +356,17 @@ if ($search_stock_physique != '') { } $sql_having .= $natural_search_physique; } +// Add HAVING from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook +if (!empty($hookmanager->resPrint)) { + if (!empty($sql_having)) { + $sql_having .= " AND"; + } else { + $sql_having .= " HAVING"; + } + $sql_having .= $hookmanager->resPrint; +} if (!empty($sql_having)) { $sql .= $sql_having; } @@ -563,6 +593,9 @@ print ''; print ' '; print ' '; print ' '; +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; // Action column if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print ''; @@ -602,6 +635,10 @@ print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", print_liste_field_titre(''); print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", "", $param, '', $sortfield, $sortorder, 'right '); print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'right '); +// Hook fields +$parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print_liste_field_titre(''); } @@ -741,6 +778,11 @@ while ($i < $imaxinloop) { print ''.$product_static->LibStatut($objp->tobuy, 5, 1).''; + // Fields values from hook + $parameters = array('obj'=>$objp); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Action column if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print ''; diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index 87357d10091..5b75ef04275 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -62,6 +62,10 @@ $hookmanager->initHooks(array('takeposproductsearch')); // new context for produ */ if ($action == 'getProducts') { + $tosell = GETPOSTISSET('tosell') ? GETPOST('tosell', 'int') : ''; + $limit = GETPOSTISSET('limit') ? GETPOST('limit', 'int') : 0; + $offset = GETPOSTISSET('offset') ? GETPOST('offset', 'int') : 0; + top_httphead('application/json'); $object = new Categorie($db); @@ -70,7 +74,11 @@ if ($action == 'getProducts') { } $result = $object->fetch($category); if ($result > 0) { - $prods = $object->getObjectsInCateg("product", 0, 0, 0, getDolGlobalString('TAKEPOS_SORTPRODUCTFIELD'), 'ASC'); + $filter = array(); + if ($tosell != '') { + $filter = array('customsql' => 'o.tosell = '.((int) $tosell)); + } + $prods = $object->getObjectsInCateg("product", 0, $limit, $offset, getDolGlobalString('TAKEPOS_SORTPRODUCTFIELD'), 'ASC', $filter); // Removed properties we don't need $res = array(); if (is_array($prods) && count($prods) > 0) { diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index bbbf9e0cd33..84ec7439ca3 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -322,7 +322,12 @@ function LoadProducts(position, issubcat) { }); idata=0; //product data counter - $.getJSON('/takepos/ajax/ajax.php?action=getProducts&token=&category='+currentcat, function(data) { + var limit = 0; + if (maxproduct >= 1) { + limit = maxproduct-1; + } + // Only show products for sale (tosell=1) + $.getJSON('/takepos/ajax/ajax.php?action=getProducts&token=&category='+currentcat+'&tosell=1&limit='+limit+'&offset=0', function(data) { console.log("Call ajax.php (in LoadProducts) to get Products of category "+currentcat+" then loop on result to fill image thumbs"); console.log(data); while (ishow < maxproduct) { @@ -342,10 +347,7 @@ function LoadProducts(position, issubcat) { $("#proprice"+ishow).html(""); $("#prodiv"+ishow).data("rowid",""); $("#prodiv"+ishow).attr("class","wrapper2 divempty"); - $("#prowatermark"+ishow).hide(); - ishow++; //Next product to show after print data product - } - else if ((data[idata]['status']) == "1") { // Only show products with status=1 (for sell) + } else { transnoentities('Ref').': ')."' + data[idata]['ref']"; $titlestring .= " + ' - ".dol_escape_js($langs->trans("Barcode").': ')."' + data[idata]['barcode']"; @@ -376,8 +378,7 @@ function LoadProducts(position, issubcat) { console.log($('#prodiv4').data('rowid')); $("#prodiv"+ishow).data("iscat", 0); $("#prodiv"+ishow).attr("class","wrapper2"); - $("#prowatermark"+ishow).hide(); - ishow++; //Next product to show after print data product + resPrint; ?> } - //console.log("Hide the prowatermark for ishow="+ishow); + $("#prowatermark"+ishow).hide(); + ishow++; //Next product to show after print data product idata++; //Next data everytime } }); @@ -414,15 +416,22 @@ function MoreProducts(moreorless) { if (pageproducts==0) return; //Return if no less pages pageproducts=pageproducts-1; } - $.getJSON('/takepos/ajax/ajax.php?action=getProducts&token=&category='+currentcat, function(data) { + + ishow=0; //product to show counter + idata=0; //product data counter + var limit = 0; + if (maxproduct >= 1) { + limit = maxproduct-1; + } + var offset = * pageproducts; + // Only show products for sale (tosell=1) + $.getJSON('/takepos/ajax/ajax.php?action=getProducts&token=&category='+currentcat+'&tosell=1&limit='+limit+'&offset='+offset, function(data) { console.log("Call ajax.php (in MoreProducts) to get Products of category "+currentcat); - if (typeof (data[(maxproduct * pageproducts)]) == "undefined" && moreorless=="more"){ // Return if no more pages + if (typeof (data[0]) == "undefined" && moreorless=="more"){ // Return if no more pages pageproducts=pageproducts-1; return; } - idata= * pageproducts; //product data counter - ishow=0; //product to show counter while (ishow < maxproduct) { if (typeof (data[idata]) == "undefined") { @@ -434,10 +443,7 @@ function MoreProducts(moreorless) { $("#proprice"+ishow).html(""); $("#proimg"+ishow).attr("src","genimg/empty.png"); $("#prodiv"+ishow).data("rowid",""); - ishow++; //Next product to show after print data product - } - else if ((data[idata]['status']) == "1") { - //Only show products with status=1 (for sell) + } else { $("#prodivdesc"+ishow).show(); @@ -454,9 +460,9 @@ function MoreProducts(moreorless) { $("#proimg"+ishow).attr("src","genimg/index.php?query=pro&id="+data[idata]['id']); $("#prodiv"+ishow).data("rowid",data[idata]['id']); $("#prodiv"+ishow).data("iscat",0); - ishow++; //Next product to show after print data product } $("#prowatermark"+ishow).hide(); + ishow++; //Next product to show after print data product idata++; //Next data everytime } });