diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index d2130e24291..ad81f7d7a2b 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -1862,10 +1862,10 @@ class Form
* @param int $forcecombo Force to use combo box
* @param string $morecss Add more css on select
* @param int $hidepriceinlabel 1=Hide prices in label
- * @param string $warehouseStatus warehouse status filter, following comma separated filter options can be used
- * 'warehouseopen' = select products from open warehouses,
- * 'warehouseclosed' = select products from closed warehouses,
- * 'warehouseinternal' = select products from warehouses for internal correct/transfer only
+ * @param string $warehouseStatus Warehouse status filter to count the quantity in stock. Following comma separated filter options can be used
+ * 'warehouseopen' = count products from open warehouses,
+ * 'warehouseclosed' = count products from closed warehouses,
+ * 'warehouseinternal' = count products from warehouses for internal correct/transfer only
* @param array $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...])
* @return void
*/
@@ -1877,7 +1877,7 @@ class Form
// check parameters
$price_level = (! empty($price_level) ? $price_level : 0);
if (is_null($ajaxoptions)) $ajaxoptions=array();
-
+
if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
{
$placeholder='';
@@ -2007,10 +2007,10 @@ class Form
* @param int $forcecombo Force to use combo box
* @param string $morecss Add more css on select
* @param int $hidepriceinlabel 1=Hide prices in label
- * @param string $warehouseStatus warehouse status filter, following comma separated filter options can be used
- * 'warehouseopen' = select products from open warehouses,
- * 'warehouseclosed' = select products from closed warehouses,
- * 'warehouseinternal' = select products from warehouses for internal correct/transfer only
+ * @param string $warehouseStatus Warehouse status filter to group/count stock. Following comma separated filter options can be used.
+ * 'warehouseopen' = count products from open warehouses,
+ * 'warehouseclosed' = count products from closed warehouses,
+ * 'warehouseinternal' = count products from warehouses for internal correct/transfer only
* @return array Array of keys for json
*/
function select_produits_list($selected='',$htmlname='productid',$filtertype='',$limit=20,$price_level=0,$filterkey='',$status=1,$finished=2,$outputmode=0,$socid=0,$showempty='1',$forcecombo=0,$morecss='',$hidepriceinlabel=0, $warehouseStatus='')
@@ -2040,7 +2040,14 @@ class Form
}
$selectFields = " p.rowid, p.label, p.ref, p.description, p.barcode, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.duration, p.fk_price_expression";
- (count($warehouseStatusArray)) ? $selectFieldsGrouped = ", sum(ps.reel) as stock" : $selectFieldsGrouped = ", p.stock";
+ if (count($warehouseStatusArray))
+ {
+ $selectFieldsGrouped = ", sum(".$db->ifsql("e.statut IS NULL", "0", "ps.reel").") as stock"; // e.statut is null if there is no record in stock
+ }
+ else
+ {
+ $selectFieldsGrouped = ", p.stock";
+ }
$sql = "SELECT ";
$sql.= $selectFields . $selectFieldsGrouped;
@@ -2076,6 +2083,7 @@ class Form
{
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e on ps.fk_entrepot = e.rowid";
+ $sql.= ' AND e.statut IN ('.$this->db->escape(implode(',',$warehouseStatusArray)).')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0.
}
// include search in supplier ref
@@ -2099,10 +2107,6 @@ class Form
}
$sql.= ' WHERE p.entity IN ('.getEntity('product').')';
- if (count($warehouseStatusArray))
- {
- $sql.= ' AND (p.fk_product_type = 1 OR e.statut IN ('.$this->db->escape(implode(',',$warehouseStatusArray)).'))';
- }
if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
$sql .= " AND pac.rowid IS NULL";
@@ -2273,7 +2277,7 @@ class Form
/**
* constructProductListOption
*
- * @param resultset $objp Resultset of fetch
+ * @param resource $objp Resultset of fetch
* @param string $opt Option (var used for returned value in string option format)
* @param string $optJson Option (var used for returned value in json format)
* @param int $price_level Price level
diff --git a/test/phpunit/FormTest.php b/test/phpunit/FormTest.php
new file mode 100644
index 00000000000..b3025b4c345
--- /dev/null
+++ b/test/phpunit/FormTest.php
@@ -0,0 +1,149 @@
+
+ *
+ * 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 http://www.gnu.org/
+ */
+
+/**
+ * \file test/phpunit/FormTest.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';
+require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
+require_once dirname(__FILE__).'/../../htdocs/core/class/html.form.class.php';
+
+if (empty($user->id))
+{
+ print "Load permissions for admin user nb 1\n";
+ $user->fetch(1);
+ $user->getrights();
+}
+$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 FormTest extends PHPUnit\Framework\TestCase
+{
+ protected $savconf;
+ protected $savuser;
+ protected $savlangs;
+ protected $savdb;
+
+ /**
+ * Constructor
+ * We save global variables into local variables
+ *
+ * @return FactureTest
+ */
+ function __construct()
+ {
+ parent::__construct();
+
+ //$this->sharedFixture
+ global $conf,$user,$langs,$db;
+ $this->savconf=$conf;
+ $this->savuser=$user;
+ $this->savlangs=$langs;
+ $this->savdb=$db;
+
+ print __METHOD__." db->type=".$db->type." user->id=".$user->id;
+ //print " - db ".$db->db;
+ print "\n";
+ }
+
+ // Static methods
+ public static function setUpBeforeClass()
+ {
+ global $conf,$user,$langs,$db;
+ $db->begin(); // This is to have all actions inside a transaction even if test launched without suite.
+
+ print __METHOD__."\n";
+ }
+
+ // tear down after class
+ public static function tearDownAfterClass()
+ {
+ global $conf,$user,$langs,$db;
+ $db->rollback();
+
+ print __METHOD__."\n";
+ }
+
+ /**
+ * Init phpunit tests
+ *
+ * @return void
+ */
+ protected function setUp()
+ {
+ global $conf,$user,$langs,$db;
+ $conf=$this->savconf;
+ $user=$this->savuser;
+ $langs=$this->savlangs;
+ $db=$this->savdb;
+
+ print __METHOD__."\n";
+ }
+
+ /**
+ * End phpunit tests
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ print __METHOD__."\n";
+ }
+
+ /**
+ * testSelectProduitsList
+ *
+ * @return int
+ */
+ public function testSelectProduitsList()
+ {
+ global $conf,$user,$langs,$db;
+ $conf=$this->savconf;
+ $user=$this->savuser;
+ $langs=$this->savlangs;
+ $db=$this->savdb;
+
+ $localobject=new Form($this->savdb);
+ $result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1);
+
+ $this->assertEquals(count($result), 5);
+ print __METHOD__." result=".$result."\n";
+
+ $conf->global->ENTREPOT_EXTRA_STATUS = 1;
+
+ // Exclude stock in warehouseinternal
+ $result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1, 0, '1', 0, '', 0, 'warehouseclosed,warehouseopen');
+ $this->assertEquals(count($result), 5);
+ print __METHOD__." result=".$result."\n";
+
+ return $result;
+ }
+}