From 49442c0b7f624daa8fdd5eca12248e7f43427ad8 Mon Sep 17 00:00:00 2001 From: fappels Date: Wed, 30 Nov 2016 13:03:17 +0100 Subject: [PATCH 01/10] Add filter on warehouse status to object line product list --- htdocs/core/class/html.form.class.php | 23 ++++++++++++++++------- htdocs/core/tpl/objectline_create.tpl.php | 9 ++++++++- htdocs/product/ajax/products.php | 3 ++- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 3e704816d5c..60ce8428d7f 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1630,7 +1630,7 @@ class Form * @param int $hidepriceinlabel 1=Hide prices in label * @return void */ - function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0) + function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0, $warehouseStatus=0) { global $langs,$conf; @@ -1649,7 +1649,7 @@ class Form unset($producttmpselect); } // mode=1 means customers products - $urloption='htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished; + $urloption='htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished.'&warehousestatus='.$warehouseStatus; //Price by customer if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $urloption.='&socid='.$socid; @@ -1670,7 +1670,7 @@ class Form } else { - print $this->select_produits_list($selected,$htmlname,$filtertype,$limit,$price_level,'',$status,$finished,0,$socid,$showempty,$forcecombo,$morecss,$hidepriceinlabel); + print $this->select_produits_list($selected,$htmlname,$filtertype,$limit,$price_level,'',$status,$finished,0,$socid,$showempty,$forcecombo,$morecss,$hidepriceinlabel, $warehouseStatus); } } @@ -1691,28 +1691,33 @@ 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 int $warehouseStatus Additional warehousestatus to filter (stock from status 1 is always shown) * @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) + 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=0) { global $langs,$conf,$user,$db; $out=''; $outarray=array(); - $sql = "SELECT "; - $sql.= " 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.stock, p.fk_price_expression"; + $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"; + $selectFieldsGrouped = ", sum(ps.reel) as stock"; + $sql = "SELECT "; + $sql.= $selectFields . $selectFieldsGrouped; //Price by customer if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql.=' ,pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,'; $sql.=' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx'; + $selectFields.= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx"; } // Multilang : we add translation if (! empty($conf->global->MAIN_MULTILANGS)) { $sql.= ", pl.label as label_translated"; + $selectFields.= ", pl.label as label_translated"; } // Price by quantity if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) @@ -1725,8 +1730,11 @@ class Form if ($price_level >= 1 && !empty($conf->global->PRODUIT_MULTIPRICES)) $sql.= " AND price_level=".$price_level; $sql.= " ORDER BY date_price"; $sql.= " DESC LIMIT 1) as price_by_qty"; + $selectFields.= ", price_rowid, price_by_qty"; } - $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; + $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid"; + $sql.= " JOIN ".MAIN_DB_PREFIX."entrepot as e on (ps.fk_entrepot = e.rowid AND e.statut IN (1, ".$warehouseStatus."))"; //Price by customer if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql.=" LEFT JOIN ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".$socid." AND pcp.fk_product=p.rowid"; @@ -1772,6 +1780,7 @@ class Form if (! empty($conf->barcode->enabled)) $sql.= " OR p.barcode LIKE '".$db->escape($prefix.$filterkey)."%'"; $sql.=')'; } + $sql.= ' GROUP BY'.$selectFields; $sql.= $db->order("p.ref"); $sql.= $db->plimit($limit); diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 62866e31ea1..3cd0bd78993 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -184,7 +184,14 @@ else { if (empty($senderissupplier)) { - $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, 1, 2, '', 1, array(),$buyer->id); + if ($conf->global->ENTREPOT_EXTRA_STATUS) + { + $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, 1, 2, '', 1, array(),$buyer->id, '1', 0, '', 0, 3); + } + else + { + $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, 1, 2, '', 1, array(),$buyer->id); + } } else { diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index c399d222177..e8d75c4ba19 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -50,6 +50,7 @@ $id = GETPOST('id', 'int'); $price_by_qty_rowid = GETPOST('pbq', 'int'); $finished = GETPOST('finished', 'int'); $alsoproductwithnosupplierprice = GETPOST('alsoproductwithnosupplierprice', 'int'); +$warehouseStatus = GETPOST('warehousestatus', 'int'); /* @@ -185,7 +186,7 @@ else $form = new Form($db); if (empty($mode) || $mode == 1) { // mode=1: customer - $arrayresult = $form->select_produits_list("", $htmlname, $type, 0, $price_level, $searchkey, $status, $finished, $outjson, $socid); + $arrayresult = $form->select_produits_list("", $htmlname, $type, 0, $price_level, $searchkey, $status, $finished, $outjson, $socid, '1', 0, '', 0, $warehouseStatus); } elseif ($mode == 2) { // mode=2: supplier $arrayresult = $form->select_produits_fournisseurs_list($socid, "", $htmlname, $type, "", $searchkey, $status, $outjson, 0, $alsoproductwithnosupplierprice); } From a7a20f45a11319ea309f1c05ba34712bdc32113d Mon Sep 17 00:00:00 2001 From: fappels Date: Fri, 2 Dec 2016 11:03:21 +0100 Subject: [PATCH 02/10] Remove Only shipping and dispatch status Remove Only shipping and dispatch status, better to create new future option 'Routing' for this. --- htdocs/langs/en_US/stocks.lang | 4 +--- htdocs/product/stock/class/entrepot.class.php | 15 +-------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 90ec9a6fb2c..c3f9c359dac 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -133,9 +133,7 @@ InventoryCodeShort=Inv./Mov. code NoPendingReceptionOnSupplierOrder=No pending reception due to open supplier order ThisSerialAlreadyExistWithDifferentDate=This lot/serial number (%s) already exists but with different eatby or sellby date (found %s but you enter %s). OpenAll=Open for all actions -OpenInternal=Open for internal actions -OpenShipping=Open for shippings -OpenDispatch=Open for dispatch +OpenInternal=Open only for internal actions UseDispatchStatus=Use a dispatch status (approve/refuse) for product lines on supplier order reception OptionMULTIPRICESIsOn=Option "several prices per segment" is on. It means a product has several selling price so value for sell can't be calculated ProductStockWarehouseCreated=Stock limit for alert and desired optimal stock correctly created diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index 36599833c2d..aed4a866efa 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -50,18 +50,7 @@ class Entrepot extends CommonObject /** * Warehouse open and operations for stock transfers/corrections allowed (not for customer shipping and supplier dispatch). */ - const STATUS_OPEN_INTERNAL = 2; - - /** - * Warehouse open and operations for customer shipping and internal stock transfers/corrections allowed (not for supplier dispatch). - */ - const STATUS_OPEN_SHIPPING = 3; - - /** - * Warehouse open and operations for supplier dispatch internal stock transfers/corrections allowed (not for customer shipping). - */ - const STATUS_OPEN_DISPATCH = 4; - + const STATUS_OPEN_INTERNAL = 2; var $libelle; var $description; @@ -91,8 +80,6 @@ class Entrepot extends CommonObject { $this->statuts[self::STATUS_OPEN_ALL] = 'OpenAll'; $this->statuts[self::STATUS_OPEN_INTERNAL] = 'OpenInternal'; - $this->statuts[self::STATUS_OPEN_SHIPPING] = 'OpenShipping'; - $this->statuts[self::STATUS_OPEN_DISPATCH] = 'OpenDispatch'; } else { From b21fd14a114448f94e6fbabeae35cbc7ebe7e35c Mon Sep 17 00:00:00 2001 From: fappels Date: Fri, 2 Dec 2016 12:17:33 +0100 Subject: [PATCH 03/10] Ignore Service, only filter warehouse if parameter set --- htdocs/core/class/html.form.class.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index fba20648623..0998579f250 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1698,7 +1698,7 @@ 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 int $warehouseStatus Additional warehousestatus to filter (stock from status 1 is always shown) + * @param int $warehouseStatus Additional warehousestatus to filter (products with stock from status 1 are always shown) * @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=0) @@ -1709,7 +1709,7 @@ class Form $outarray=array(); $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"; - $selectFieldsGrouped = ", sum(ps.reel) as stock"; + $warehouseStatus ? $selectFieldsGrouped = ", sum(ps.reel) as stock" : $selectFieldsGrouped = ", p.stock"; $sql = "SELECT "; $sql.= $selectFields . $selectFieldsGrouped; @@ -1724,7 +1724,7 @@ class Form if (! empty($conf->global->MAIN_MULTILANGS)) { $sql.= ", pl.label as label_translated"; - $selectFields.= ", pl.label as label_translated"; + $selectFields.= ", label_translated"; } // Price by quantity if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) @@ -1739,9 +1739,11 @@ class Form $sql.= " DESC LIMIT 1) as price_by_qty"; $selectFields.= ", price_rowid, price_by_qty"; } - $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; - $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid"; - $sql.= " JOIN ".MAIN_DB_PREFIX."entrepot as e on (ps.fk_entrepot = e.rowid AND e.statut IN (1, ".$warehouseStatus."))"; + $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; + if ($warehouseStatus) + { + } + //Price by customer if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql.=" LEFT JOIN ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".$socid." AND pcp.fk_product=p.rowid"; @@ -1752,6 +1754,9 @@ class Form $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang='". $langs->getDefaultLang() ."'"; } $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; + if ($warehouseStatus) + { + } if ($finished == 0) { $sql.= " AND p.finished = ".$finished; @@ -1787,7 +1792,10 @@ class Form if (! empty($conf->barcode->enabled)) $sql.= " OR p.barcode LIKE '".$db->escape($prefix.$filterkey)."%'"; $sql.=')'; } - $sql.= ' GROUP BY'.$selectFields; + if ($warehouseStatus) + { + $sql.= ' GROUP BY'.$selectFields; + } $sql.= $db->order("p.ref"); $sql.= $db->plimit($limit); From af5eb00933edf13cf6d500d03a9690814c9ce31e Mon Sep 17 00:00:00 2001 From: fappels Date: Fri, 2 Dec 2016 12:18:36 +0100 Subject: [PATCH 04/10] Ignore filtering if service --- htdocs/core/class/html.form.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 0998579f250..7a8bbf5288d 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1742,6 +1742,8 @@ class Form $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; if ($warehouseStatus) { + $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"; } //Price by customer @@ -1756,6 +1758,7 @@ class Form $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; if ($warehouseStatus) { + $sql.= ' AND (p.fk_product_type = 1 OR e.statut IN (1, '.$warehouseStatus.'))'; } if ($finished == 0) { From c697141851892fd735187043cded2d482630a9d3 Mon Sep 17 00:00:00 2001 From: fappels Date: Fri, 2 Dec 2016 12:22:09 +0100 Subject: [PATCH 05/10] hide products in closed warehouse, but show products for internal transfer Products only for internal transfer should be sellable (for example, they can have virtual stock) --- htdocs/core/tpl/objectline_create.tpl.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 3cd0bd78993..27be5ebf75d 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -186,7 +186,9 @@ else { { if ($conf->global->ENTREPOT_EXTRA_STATUS) { - $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, 1, 2, '', 1, array(),$buyer->id, '1', 0, '', 0, 3); + // hide products in closed warehouse, but show products for internal transfer + require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; + $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, 1, 2, '', 1, array(),$buyer->id, '1', 0, '', 0, Entrepot::STATUS_OPEN_INTERNAL); } else { From fbdc0c25e368427e0e740ad8b9feb38955f224ce Mon Sep 17 00:00:00 2001 From: fappels Date: Mon, 5 Dec 2016 11:42:03 +0100 Subject: [PATCH 06/10] Add STATUS_OPEN_INTERNAL to stock change/move pages --- htdocs/product/class/html.formproduct.class.php | 11 ++++++----- htdocs/product/stock/massstockmove.php | 4 ++-- htdocs/product/stock/mouvement.php | 2 +- htdocs/product/stock/tpl/stockcorrection.tpl.php | 2 +- htdocs/product/stock/tpl/stocktransfer.tpl.php | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php index 55e104990fc..c077859dde1 100644 --- a/htdocs/product/class/html.formproduct.class.php +++ b/htdocs/product/class/html.formproduct.class.php @@ -21,6 +21,7 @@ * \brief Fichier de la classe des fonctions predefinie de composants html */ +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; /** * Class with static methods for building HTML components related to products @@ -168,7 +169,7 @@ class FormProduct * * @param int $selected Id of preselected warehouse ('' for no value, 'ifone'=select value if one value otherwise no value) * @param string $htmlname Name of html select html - * @param string $filtertype For filter, additional filter on status other then 1 + * @param string $filterstatus For filter, additional filter on status other then 1 (open_all). No filter when empty * @param int $empty 1=Can be empty, 0 if not * @param int $disabled 1=Select is disabled * @param int $fk_product Add quantity of stock in label for product with id fk_product. Nothing if 0. @@ -181,15 +182,15 @@ class FormProduct * @param int $showfullpath 1=Show full path of name (parent ref into label), 0=Show only ref of current warehouse * @return string HTML select */ - function selectWarehouses($selected='',$htmlname='idwarehouse',$filtertype='',$empty=0,$disabled=0,$fk_product=0,$empty_label='', $showstock=0, $forcecombo=0, $events=array(), $morecss='minwidth200', $exclude='', $showfullpath=1) + function selectWarehouses($selected='',$htmlname='idwarehouse',$filterstatus='',$empty=0,$disabled=0,$fk_product=0,$empty_label='', $showstock=0, $forcecombo=0, $events=array(), $morecss='minwidth200', $exclude='', $showfullpath=1) { global $conf,$langs,$user; - dol_syslog(get_class($this)."::selectWarehouses $selected, $htmlname, $filtertype, $empty, $disabled, $fk_product, $empty_label, $showstock, $forcecombo, $morecss",LOG_DEBUG); + dol_syslog(get_class($this)."::selectWarehouses $selected, $htmlname, $filterstatus, $empty, $disabled, $fk_product, $empty_label, $showstock, $forcecombo, $morecss",LOG_DEBUG); $out=''; - - $this->loadWarehouses($fk_product, '', + $filtertype, true, $exclude); // filter on numeric status + if (empty($conf->global->ENTREPOT_EXTRA_STATUS)) $filterstatus = ''; + $this->loadWarehouses($fk_product, '', + $filterstatus, true, $exclude); // filter on numeric status $nbofwarehouses=count($this->cache_warehouses); if ($conf->use_javascript_ajax && ! $forcecombo) diff --git a/htdocs/product/stock/massstockmove.php b/htdocs/product/stock/massstockmove.php index 0c96d1f7a04..7a1ef75e9fd 100644 --- a/htdocs/product/stock/massstockmove.php +++ b/htdocs/product/stock/massstockmove.php @@ -383,11 +383,11 @@ if ($conf->productbatch->enabled) } // In warehouse print ''; -print $formproduct->selectWarehouses($id_sw, 'id_sw', '', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); +print $formproduct->selectWarehouses($id_sw, 'id_sw', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); print ''; // Out warehouse print ''; -print $formproduct->selectWarehouses($id_tw, 'id_tw', '', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); +print $formproduct->selectWarehouses($id_tw, 'id_tw', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); print ''; // Qty print ''; diff --git a/htdocs/product/stock/mouvement.php b/htdocs/product/stock/mouvement.php index e2cb108f87d..63fc770d40e 100644 --- a/htdocs/product/stock/mouvement.php +++ b/htdocs/product/stock/mouvement.php @@ -791,7 +791,7 @@ if ($resql) { print ''; //print ''; - print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', '', 1, 0, 0, '', 0, 0, null, 'maxwidth200'); + print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, null, 'maxwidth200'); print ''; } if (! empty($arrayfields['m.fk_user_author']['checked'])) diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index 0b48be2b0d5..7a64056bdfb 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -56,7 +56,7 @@ { print ''.$langs->trans("Warehouse").''; print ''; - print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')), 'id_entrepot', '', 1, 0, 0, '', 0, 0, null, 'minwidth100'); + print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')), 'id_entrepot', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, null, 'minwidth100'); print ''; } if ($object->element == 'stock') diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index dfddd1e19f1..8945575d258 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -63,7 +63,7 @@ { print ''.$langs->trans("WarehouseSource").''; print ''; - print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')),'id_entrepot','',1); + print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')), 'id_entrepot', Entrepot::STATUS_OPEN_INTERNAL, 1); print ''; } if ($object->element == 'stock') @@ -75,7 +75,7 @@ } print ''.$langs->trans("WarehouseTarget").''; - print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'),'id_entrepot_destination','',1); + print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'), 'id_entrepot_destination', Entrepot::STATUS_OPEN_INTERNAL, 1); print ''; print ''.$langs->trans("NumberOfUnit").''; print ''; From 18478eaa31ad739e7bdf6b8202da4800672901fa Mon Sep 17 00:00:00 2001 From: fappels Date: Mon, 5 Dec 2016 18:08:09 +0100 Subject: [PATCH 07/10] Add warehouse status filter to load_stock function --- htdocs/product/class/product.class.php | 28 ++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index bb122dc70e8..e0650415a22 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -35,7 +35,7 @@ */ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php'; - +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; /** * Class to manage products or services @@ -3471,16 +3471,39 @@ class Product extends CommonObject /** * Load information about stock of a product into stock_reel, stock_warehouse[] (including stock_warehouse[idwarehouse]->detail_batch for batch products) * This function need a lot of load. If you use it on list, use a cache to execute it one for each product id. + * If ENTREPOT_EXTRA_STATUS set, filtering on warehouse status possible. * - * @param string $option '', 'nobatch' = Do not load batch information, 'novirtual' = Do not load virtual stock + * @param string $option '' = Load all stock info, also from closed and internal warehouses, + * 'nobatch' = Do not load batch information, + * 'novirtual' = Do not load virtual stock, + * 'warehouseopen' = Load stock from open warehouses, + * 'warehouseclosed' = Load stock from closed warehouses, + * 'warehouseinternal' = Load stock from warehouses for internal correct/transfer only * @return int < 0 if KO, > 0 if OK * @see load_virtual_stock, getBatchInfo */ function load_stock($option='') { + global $conf; + $this->stock_reel = 0; $this->stock_warehouse = array(); $this->stock_theorique = 0; + + $warehouseStatus = array(); + + if (preg_match('/warehouseclosed/', $option)) + { + $warehouseStatus[] = Entrepot::STATUS_CLOSED; + } + if (preg_match('/warehouseopen/', $option)) + { + $warehouseStatus[] = Entrepot::STATUS_OPEN_ALL; + } + if (preg_match('/warehouseinternal/', $option)) + { + $warehouseStatus[] = Entrepot::STATUS_OPEN_INTERNAL; + } $sql = "SELECT ps.rowid, ps.reel, ps.fk_entrepot"; $sql.= " FROM ".MAIN_DB_PREFIX."product_stock as ps"; @@ -3488,6 +3511,7 @@ class Product extends CommonObject $sql.= " WHERE w.entity IN (".getEntity('stock', 1).")"; $sql.= " AND w.rowid = ps.fk_entrepot"; $sql.= " AND ps.fk_product = ".$this->id; + if ($conf->global->ENTREPOT_EXTRA_STATUS && count($warehouseStatus)) $sql.= " AND w.statut IN (".implode(',',$warehouseStatus).")"; dol_syslog(get_class($this)."::load_stock", LOG_DEBUG); $result = $this->db->query($sql); From 0aacb7ce1792c72c457d80de2ba93e1a1f06cf04 Mon Sep 17 00:00:00 2001 From: fappels Date: Mon, 5 Dec 2016 18:14:03 +0100 Subject: [PATCH 08/10] Filter stock on warehouse status for shipping Do not show stock of closed and internal warehouse. --- htdocs/expedition/card.php | 2 +- htdocs/expedition/class/expedition.class.php | 2 +- htdocs/expedition/shipment.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 5187d2e979a..edb0d42321c 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -862,7 +862,7 @@ if ($action == 'create') if ($line->fk_product > 0) // If predefined product { $product->fetch($line->fk_product); - $product->load_stock(); + $product->load_stock('warehouseopen'); print ''; print ''; // ancre pour retourner sur la ligne diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 1ae5556a898..971a2189854 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -892,7 +892,7 @@ class Expedition extends CommonObject $result=$product->fetch($fk_product); if ($entrepot_id > 0) { - $product->load_stock(); + $product->load_stock('warehouseopen'); $product_stock = $product->stock_warehouse[$entrepot_id]->real; } else diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index 887b5805533..3044a1beb10 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -766,7 +766,7 @@ if ($id > 0 || ! empty($ref)) { $product = new Product($db); $product->fetch($objp->fk_product); - $product->load_stock(); + $product->load_stock('warehouseopen'); } if ($objp->fk_product > 0 && $type == 0 && ! empty($conf->stock->enabled)) From 3ca966459510abd7e05299ec3bc38e37dfbd72cd Mon Sep 17 00:00:00 2001 From: fappels Date: Mon, 5 Dec 2016 18:14:42 +0100 Subject: [PATCH 09/10] Filter stock on warehouse status for replenishment Do not show stock of closed warehouse --- htdocs/product/stock/replenish.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 5281d913d95..25232c3bf52 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -552,7 +552,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) if (! empty($conf->global->STOCK_SUPPORTS_SERVICES) || $objp->fk_product_type == 0) { $prod->fetch($objp->rowid); - $prod->load_stock(); + $prod->load_stock('warehouseopen, warehouseinternal'); // Multilangs if (! empty($conf->global->MAIN_MULTILANGS)) From bbbc768fa7087c70c4cf6fb07257d17322fef1ec Mon Sep 17 00:00:00 2001 From: fappels Date: Tue, 6 Dec 2016 20:07:19 +0100 Subject: [PATCH 10/10] Change filter parameter to string with comma seperated values Change warehousefilter from int to string with comma seperated values for selectWarehouses and select_produits form functions. --- htdocs/core/class/html.form.class.php | 41 +++++++++++++++---- htdocs/core/tpl/objectline_create.tpl.php | 3 +- htdocs/product/ajax/products.php | 2 +- .../product/class/html.formproduct.class.php | 33 ++++++++++++--- htdocs/product/stock/massstockmove.php | 4 +- htdocs/product/stock/mouvement.php | 2 +- .../product/stock/tpl/stockcorrection.tpl.php | 2 +- .../product/stock/tpl/stocktransfer.tpl.php | 4 +- 8 files changed, 68 insertions(+), 23 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index aefec319d65..d5b0d898a9c 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1636,9 +1636,13 @@ 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 * @return void */ - function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0, $warehouseStatus=0) + function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0, $warehouseStatus='') { global $langs,$conf; @@ -1699,18 +1703,39 @@ 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 int $warehouseStatus Additional warehousestatus to filter (products with stock from status 1 are always shown) + * @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 * @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=0) + 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='') { global $langs,$conf,$user,$db; $out=''; $outarray=array(); + $warehouseStatusArray = array(); + if (! empty($warehouseStatus)) + { + require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; + if (preg_match('/warehouseclosed/', $warehouseStatus)) + { + $warehouseStatusArray[] = Entrepot::STATUS_CLOSED; + } + if (preg_match('/warehouseopen/', $warehouseStatus)) + { + $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL; + } + if (preg_match('/warehouseinternal/', $warehouseStatus)) + { + $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL; + } + } + $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"; - $warehouseStatus ? $selectFieldsGrouped = ", sum(ps.reel) as stock" : $selectFieldsGrouped = ", p.stock"; + (count($warehouseStatusArray)) ? $selectFieldsGrouped = ", sum(ps.reel) as stock" : $selectFieldsGrouped = ", p.stock"; $sql = "SELECT "; $sql.= $selectFields . $selectFieldsGrouped; @@ -1741,7 +1766,7 @@ class Form $selectFields.= ", price_rowid, price_by_qty"; } $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; - if ($warehouseStatus) + if (count($warehouseStatusArray)) { $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"; @@ -1757,9 +1782,9 @@ class Form $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang='". $langs->getDefaultLang() ."'"; } $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; - if ($warehouseStatus) + if (count($warehouseStatusArray)) { - $sql.= ' AND (p.fk_product_type = 1 OR e.statut IN (1, '.$warehouseStatus.'))'; + $sql.= ' AND (p.fk_product_type = 1 OR e.statut IN ('.implode(',',$warehouseStatusArray).'))'; } if ($finished == 0) { @@ -1796,7 +1821,7 @@ class Form if (! empty($conf->barcode->enabled)) $sql.= " OR p.barcode LIKE '".$db->escape($prefix.$filterkey)."%'"; $sql.=')'; } - if ($warehouseStatus) + if (count($warehouseStatusArray)) { $sql.= ' GROUP BY'.$selectFields; } diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index fa0553af1a3..beeecf9f511 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -187,8 +187,7 @@ else { if ($conf->global->ENTREPOT_EXTRA_STATUS) { // hide products in closed warehouse, but show products for internal transfer - require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; - $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, 1, 2, '', 1, array(),$buyer->id, '1', 0, '', 0, Entrepot::STATUS_OPEN_INTERNAL); + $form->select_produits(GETPOST('idprod'), 'idprod', $filtertype, $conf->product->limit_size, $buyer->price_level, 1, 2, '', 1, array(),$buyer->id, '1', 0, '', 0, 'warehouseopen,warehouseinternal'); } else { diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index bffc5f15531..0510299fbd7 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -50,7 +50,7 @@ $id = GETPOST('id', 'int'); $price_by_qty_rowid = GETPOST('pbq', 'int'); $finished = GETPOST('finished', 'int'); $alsoproductwithnosupplierprice = GETPOST('alsoproductwithnosupplierprice', 'int'); -$warehouseStatus = GETPOST('warehousestatus', 'int'); +$warehouseStatus = GETPOST('warehousestatus', 'alpha'); /* diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php index c077859dde1..dda92ea0c0f 100644 --- a/htdocs/product/class/html.formproduct.class.php +++ b/htdocs/product/class/html.formproduct.class.php @@ -55,18 +55,36 @@ class FormProduct * * @param int $fk_product Add quantity of stock in label for product with id fk_product. Nothing if 0. * @param string $batch Add quantity of batch stock in label for product with batch name batch, batch name precedes batch_id. Nothing if ''. - * @param int $status additional filter on status other then 1 + * @param string $status 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 boolean $sumStock sum total stock of a warehouse, default true * @param array $exclude warehouses ids to exclude * @return int Nb of loaded lines, 0 if already loaded, <0 if KO */ - function loadWarehouses($fk_product=0, $batch = '', $status=null, $sumStock = true, $exclude='') + function loadWarehouses($fk_product=0, $batch = '', $status='', $sumStock = true, $exclude='') { global $conf, $langs; if (empty($fk_product) && count($this->cache_warehouses)) return 0; // Cache already loaded and we do not want a list with information specific to a product if (is_array($exclude)) $excludeGroups = implode("','",$exclude); + + $warehouseStatus = array(); + + if (preg_match('/warehouseclosed/', $status)) + { + $warehouseStatus[] = Entrepot::STATUS_CLOSED; + } + if (preg_match('/warehouseopen/', $status)) + { + $warehouseStatus[] = Entrepot::STATUS_OPEN_ALL; + } + if (preg_match('/warehouseinternal/', $status)) + { + $warehouseStatus[] = Entrepot::STATUS_OPEN_INTERNAL; + } $sql = "SELECT e.rowid, e.label, e.description, e.fk_parent"; if (!empty($fk_product)) @@ -95,9 +113,9 @@ class FormProduct } } $sql.= " WHERE e.entity IN (".getEntity('stock', 1).")"; - if (!empty($status)) + if (count($warehouseStatus)) { - $sql.= " AND e.statut IN (1, ".$status.")"; + $sql.= " AND e.statut IN (".implode(',',$warehouseStatus).")"; } else { @@ -169,7 +187,10 @@ class FormProduct * * @param int $selected Id of preselected warehouse ('' for no value, 'ifone'=select value if one value otherwise no value) * @param string $htmlname Name of html select html - * @param string $filterstatus For filter, additional filter on status other then 1 (open_all). No filter when empty + * @param string $filterstatus 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 int $empty 1=Can be empty, 0 if not * @param int $disabled 1=Select is disabled * @param int $fk_product Add quantity of stock in label for product with id fk_product. Nothing if 0. @@ -190,7 +211,7 @@ class FormProduct $out=''; if (empty($conf->global->ENTREPOT_EXTRA_STATUS)) $filterstatus = ''; - $this->loadWarehouses($fk_product, '', + $filterstatus, true, $exclude); // filter on numeric status + $this->loadWarehouses($fk_product, '', $filterstatus, true, $exclude); $nbofwarehouses=count($this->cache_warehouses); if ($conf->use_javascript_ajax && ! $forcecombo) diff --git a/htdocs/product/stock/massstockmove.php b/htdocs/product/stock/massstockmove.php index 7a1ef75e9fd..ce585fb7587 100644 --- a/htdocs/product/stock/massstockmove.php +++ b/htdocs/product/stock/massstockmove.php @@ -383,11 +383,11 @@ if ($conf->productbatch->enabled) } // In warehouse print ''; -print $formproduct->selectWarehouses($id_sw, 'id_sw', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); +print $formproduct->selectWarehouses($id_sw, 'id_sw', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); print ''; // Out warehouse print ''; -print $formproduct->selectWarehouses($id_tw, 'id_tw', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); +print $formproduct->selectWarehouses($id_tw, 'id_tw', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp'); print ''; // Qty print ''; diff --git a/htdocs/product/stock/mouvement.php b/htdocs/product/stock/mouvement.php index 63fc770d40e..3505247862b 100644 --- a/htdocs/product/stock/mouvement.php +++ b/htdocs/product/stock/mouvement.php @@ -791,7 +791,7 @@ if ($resql) { print ''; //print ''; - print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, null, 'maxwidth200'); + print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'maxwidth200'); print ''; } if (! empty($arrayfields['m.fk_user_author']['checked'])) diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index 7a64056bdfb..ac37566457f 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -56,7 +56,7 @@ { print ''.$langs->trans("Warehouse").''; print ''; - print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')), 'id_entrepot', Entrepot::STATUS_OPEN_INTERNAL, 1, 0, 0, '', 0, 0, null, 'minwidth100'); + print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')), 'id_entrepot', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'minwidth100'); print ''; } if ($object->element == 'stock') diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index 8945575d258..b38804c05b1 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -63,7 +63,7 @@ { print ''.$langs->trans("WarehouseSource").''; print ''; - print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')), 'id_entrepot', Entrepot::STATUS_OPEN_INTERNAL, 1); + print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')), 'id_entrepot', 'warehouseopen,warehouseinternal', 1); print ''; } if ($object->element == 'stock') @@ -75,7 +75,7 @@ } print ''.$langs->trans("WarehouseTarget").''; - print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'), 'id_entrepot_destination', Entrepot::STATUS_OPEN_INTERNAL, 1); + print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'), 'id_entrepot_destination', 'warehouseopen,warehouseinternal', 1); print ''; print ''.$langs->trans("NumberOfUnit").''; print '';