* Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2004 Eric Seigne * Copyright (C) 2005 Simon TOSSER * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2013 Juanjo Menent * * 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 . */ /** * \file htdocs/product/stock/product.php * \ingroup product stock * \brief Page to list detailed stock of a product */ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; $langs->load("products"); $langs->load("orders"); $langs->load("bills"); $langs->load("stocks"); $action=GETPOST("action"); $cancel=GETPOST('cancel'); // Security check $id=GETPOST('id', 'int'); $ref=GETPOST('ref', 'alpha'); $stocklimit = GETPOST('stocklimit'); $desiredstock = GETPOST('desiredstock'); $cancel = GETPOST('cancel'); $fieldid = isset($_GET["ref"])?'ref':'rowid'; if ($user->societe_id) $socid=$user->societe_id; $result=restrictedArea($user,'produit&stock',$id,'product&product','','',$fieldid); /* * Actions */ if ($cancel) $action=''; // Set stock limit if ($action == 'setstocklimit') { $product = new Product($db); $result=$product->fetch($id); $product->seuil_stock_alerte=$stocklimit; $result=$product->update($product->id,$user,1,0,1); if ($result < 0) setEventMessage($product->error, 'errors'); $action=''; } // Set desired stock if ($action == 'setdesiredstock') { $product = new Product($db); $result=$product->fetch($id); $product->desiredstock=$desiredstock; $result=$product->update($product->id,$user,1,0,1); if ($result < 0) setEventMessage($product->error, 'errors'); $action=''; } // Correct stock if ($action == "correct_stock" && ! $cancel) { if (! (GETPOST("id_entrepot") > 0)) { setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Warehouse")), 'errors'); $error++; $action='correction'; } if (! GETPOST("nbpiece")) { setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("NumberOfUnit")), 'errors'); $error++; $action='correction'; } if (! $error) { $priceunit=price2num(GETPOST("price")); if (is_numeric(GETPOST("nbpiece")) && $id) { $product = new Product($db); $result=$product->fetch($id); $result=$product->correct_stock( $user, GETPOST("id_entrepot"), GETPOST("nbpiece"), GETPOST("mouvement"), GETPOST("label"), $priceunit ); // We do not change value of stock for a correction if ($result > 0) { header("Location: ".$_SERVER["PHP_SELF"]."?id=".$product->id); exit; } } } } // Transfer stock from a warehouse to another warehouse if ($action == "transfert_stock" && ! $cancel) { if (! (GETPOST("id_entrepot_source") > 0) || ! (GETPOST("id_entrepot_destination") > 0)) { setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Warehouse")), 'errors'); $error++; $action='transfert'; } if (! GETPOST("nbpiece")) { setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("NumberOfUnit")), 'errors'); $error++; $action='transfert'; } if (! $error) { if (GETPOST("id_entrepot_source") <> GETPOST("id_entrepot_destination")) { if (is_numeric(GETPOST("nbpiece")) && $id) { $product = new Product($db); $result=$product->fetch($id); $db->begin(); $product->load_stock(); // Load array product->stock_warehouse // Define value of products moved $pricesrc=0; if (isset($product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp)) $pricesrc=$product->stock_warehouse[GETPOST("id_entrepot_source")]->pmp; $pricedest=$pricesrc; //print 'price src='.$pricesrc.', price dest='.$pricedest;exit; // Remove stock $result1=$product->correct_stock( $user, GETPOST("id_entrepot_source"), GETPOST("nbpiece"), 1, GETPOST("label"), $pricesrc ); // Add stock $result2=$product->correct_stock( $user, GETPOST("id_entrepot_destination"), GETPOST("nbpiece"), 0, GETPOST("label"), $pricedest ); if ($result1 >= 0 && $result2 >= 0) { $db->commit(); header("Location: product.php?id=".$product->id); exit; } else { setEventMessage($product->error, 'errors'); $db->rollback(); } } } } } /* * View */ $formproduct=new FormProduct($db); if ($id > 0 || $ref) { $product = new Product($db); $result = $product->fetch($id,$ref); $product->load_stock(); $help_url='EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; llxHeader("",$langs->trans("CardProduct".$product->type),$help_url); if ($result > 0) { $head=product_prepare_head($product, $user); $titre=$langs->trans("CardProduct".$product->type); $picto=($product->type==1?'service':'product'); dol_fiche_head($head, 'stock', $titre, 0, $picto); $form = new Form($db); print ''; // Ref print ''; print ''; print ''; // Label print ''; print ''; // Status (to sell) print ''; // Status (to buy) print ''; // PMP print ''; print ''; print ''; // Sell price print ''; print ''; print ''; // Stock print ''; // Desired stock print ''; // Real stock $product->load_stock(); print ''; print ''; print ''; // Calculating a theorical value of stock if stock increment is done on real sending if (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) { $stock_commande_client=$stock_commande_fournisseur=0; if (! empty($conf->commande->enabled)) { $result=$product->load_stats_commande(0,'1,2'); if ($result < 0) dol_print_error($db,$product->error); $stock_commande_client=$product->stats_commande['qty']; } if (! empty($conf->fournisseur->enabled)) { $result=$product->load_stats_commande_fournisseur(0,'3'); if ($result < 0) dol_print_error($db,$product->error); $stock_commande_fournisseur=$product->stats_commande_fournisseur['qty']; } $product->stock_theorique=$product->stock_reel-($stock_commande_client+$stock_sending_client)+$stock_commande_fournisseur; // Stock theorique print ''; print "'; print ''; print ''; print ''; } // Last movement $sql = "SELECT max(m.datem) as datem"; $sql.= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m"; $sql.= " WHERE m.fk_product = '".$product->id."'"; $resqlbis = $db->query($sql); if ($resqlbis) { $obj = $db->fetch_object($resqlbis); $lastmovementdate=$db->jdate($obj->datem); } else { dol_print_error($db); } print '"; print "
'.$langs->trans("Ref").''; print $form->showrefnav($product,'ref','',1,'ref'); print '
'.$langs->trans("Label").''.$product->libelle.'
'.$langs->trans("Status").' ('.$langs->trans("Sell").')'; print $product->getLibStatut(2,0); print '
'.$langs->trans("Status").' ('.$langs->trans("Buy").')'; print $product->getLibStatut(2,1); print '
'.$langs->trans("AverageUnitPricePMP").''.price($product->pmp).' '.$langs->trans("HT").'
'.$langs->trans("SellPriceMin").''; if (empty($conf->global->PRODUIT_MULTIPRICES)) print price($product->price).' '.$langs->trans("HT"); else print $langs->trans("Variable"); print '
'.$form->editfieldkey("StockLimit",'stocklimit',$product->seuil_stock_alerte,$product,$user->rights->produit->creer).''; print $form->editfieldval("StockLimit",'stocklimit',$product->seuil_stock_alerte,$product,$user->rights->produit->creer); print '
'.$form->editfieldkey("DesiredStock",'desiredstock',$product->desiredstock,$product,$user->rights->produit->creer).''; print $form->editfieldval("DesiredStock",'desiredstock',$product->desiredstock,$product,$user->rights->produit->creer); print '
'.$langs->trans("PhysicalStock").''.$product->stock_reel; if ($product->seuil_stock_alerte && ($product->stock_reel < $product->seuil_stock_alerte)) print ' '.img_warning($langs->trans("StockLowerThanLimit")); print '
'.$langs->trans("VirtualStock").'".$product->stock_theorique; if ($product->stock_theorique < $product->seuil_stock_alerte) { print ' '.img_warning($langs->trans("StockLowerThanLimit")); } print '
'; if ($product->stock_theorique != $product->stock_reel) print $langs->trans("StockDiffPhysicTeoric"); else print $langs->trans("RunningOrders"); print ''; $found=0; // Nbre de commande clients en cours if (! empty($conf->commande->enabled)) { if ($found) print '
'; else $found=1; print $langs->trans("CustomersOrdersRunning").': '.($stock_commande_client+$stock_sending_client); $result=$product->load_stats_commande(0,'0'); if ($result < 0) dol_print_error($db,$product->error); print ' ('.$langs->trans("Draft").': '.$product->stats_commande['qty'].')'; //print '
'; //print $langs->trans("CustomersSendingRunning").': '.$stock_sending_client; } // Nbre de commande fournisseurs en cours if (! empty($conf->fournisseur->enabled)) { if ($found) print '
'; else $found=1; print $langs->trans("SuppliersOrdersRunning").': '.$stock_commande_fournisseur; $result=$product->load_stats_commande_fournisseur(0,'0,1,2'); if ($result < 0) dol_print_error($db,$product->error); print ' ('.$langs->trans("DraftOrWaitingApproved").': '.$product->stats_commande_fournisseur['qty'].')'; } print '
'.$langs->trans("LastMovement").''; if ($lastmovementdate) { print dol_print_date($lastmovementdate,'dayhour').' '; print '('.$langs->trans("FullList").')'; } else { print ''.$langs->trans("None").''; } print "
"; } print ''; /* * Correct stock */ if ($action == "correction") { print ''; print_titre($langs->trans("StockCorrection")); print '
'."\n"; print ''; print ''; print ''; // Warehouse print ''; print ''; print ''; print ''; print ''; print ''; // Label print ''; print ''; print ''; print ''; print ''; print '
'.$langs->trans("Warehouse").''; print $formproduct->selectWarehouses(($_GET["dwid"]?$_GET["dwid"]:GETPOST('id_entrepot')),'id_entrepot','',1); print ''; print ''.$langs->trans("NumberOfUnit").'
'.$langs->trans("Label").''; print ''; print ''.$langs->trans("UnitPurchaseValue").'
'; print '
 '; print '
'; print '
'; } /* * Transfer of units */ if ($action == "transfert") { print_titre($langs->trans("StockTransfer")); print '
'."\n"; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; // Label print ''; print ''; print ''; print ''; print '
'.$langs->trans("WarehouseSource").''; print $formproduct->selectWarehouses(($_GET["dwid"]?$_GET["dwid"]:GETPOST('id_entrepot_source')),'id_entrepot_source','',1); print ''.$langs->trans("WarehouseTarget").''; print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'),'id_entrepot_destination','',1); print ''.$langs->trans("NumberOfUnit").'
'.$langs->trans("LabelMovement").''; print ''; print '
'; print '
 '; print '
'; print '
'; } /* * Set initial stock */ /* if ($_GET["action"] == "definir") { print_titre($langs->trans("SetStock")); print "
id\" method=\"post\">\n"; print ''; print ''; print ''; print ''; print ''; print '
'.$langs->trans("Warehouse").''; print $formproduct->selectWarehouses('','id_entrepot','',1); print ''.$langs->trans("NumberOfUnit").'
 '; print '
'; print '
'; } */ } else { dol_print_error(); } /* ************************************************************************** */ /* */ /* Barre d'action */ /* */ /* ************************************************************************** */ if (empty($action) && $product->id) { print "
\n"; if ($user->rights->stock->creer) { print ''.$langs->trans("StockCorrection").''; } if ($user->rights->stock->mouvement->creer) { print ''.$langs->trans("StockMovement").''; } print '
'; } /* * Contenu des stocks */ print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; $sql = "SELECT e.rowid, e.label, ps.reel, ps.pmp"; $sql.= " FROM ".MAIN_DB_PREFIX."entrepot as e,"; $sql.= " ".MAIN_DB_PREFIX."product_stock as ps"; $sql.= " WHERE ps.reel != 0"; $sql.= " AND ps.fk_entrepot = e.rowid"; $sql.= " AND e.entity = ".$conf->entity; $sql.= " AND ps.fk_product = ".$product->id; $sql.= " ORDER BY e.label"; $entrepotstatic=new Entrepot($db); $total=0; $totalvalue=$totalvaluesell=0; $resql=$db->query($sql); if ($resql) { $num = $db->num_rows($resql); $total=$totalwithpmp; $i=0; $var=false; while ($i < $num) { $obj = $db->fetch_object($resql); $entrepotstatic->id=$obj->rowid; $entrepotstatic->libelle=$obj->label; print ''; print ''; print ''; // PMP print ''; // Ditto : Show PMP from movement or from product print ''; // Ditto : Show PMP from movement or from product // Sell price print ''; // Ditto : Show PMP from movement or from product print ''; // Ditto : Show PMP from movement or from product else print $langs->trans("Variable"); print ''; ; $total += $obj->reel; if (price2num($obj->pmp)) $totalwithpmp += $obj->reel; $totalvalue = $totalvalue + price2num($obj->pmp*$obj->reel,'MU'); // Ditto : Show PMP from movement or from product $totalvaluesell = $totalvaluesell + price2num($product->price*$obj->reel,'MU'); // Ditto : Show PMP from movement or from product $i++; $var=!$var; } } else dol_print_error($db); print ''; print ''; print ''; print ''; print ''; print ''; print ""; print "
'.$langs->trans("Warehouse").''.$langs->trans("NumberOfUnit").''.$langs->trans("AverageUnitPricePMPShort").''.$langs->trans("EstimatedStockValueShort").''.$langs->trans("SellPriceMin").''.$langs->trans("EstimatedStockValueSellShort").'
'.$entrepotstatic->getNomUrl(1).''.$obj->reel.($obj->reel<0?' '.img_warning():'').''.(price2num($obj->pmp)?price2num($obj->pmp,'MU'):'').''.(price2num($obj->pmp)?price(price2num($obj->pmp*$obj->reel,'MT')):'').''; if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price,'MU')); else print $langs->trans("Variable"); print ''; if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($product->price*$obj->reel,'MT')).'
'.$langs->trans("Total").':'.$total.''; print ($totalwithpmp?price($totalvalue/$totalwithpmp):' '); print ''; print price(price2num($totalvalue,'MT')); print ''; if (empty($conf->global->PRODUIT_MULTI_PRICES)) print ($total?price($totalvaluesell/$total):' '); else print $langs->trans("Variable"); print ''; if (empty($conf->global->PRODUIT_MULTI_PRICES)) print price(price2num($totalvaluesell,'MT')); else print $langs->trans("Variable"); print '
"; llxFooter(); $db->close(); ?>