diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index f59aa43a6af43cadce9c79110b392407d6b6ce7c..140fc3480ea07f4369eab76b7fdb692f19e26b59 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -102,6 +102,8 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3102__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/liste.php', 'List', 1, 'stocks', '$user->rights->stock->lire', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3103__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/valo.php', 'EnhancedValue', 1, 'stocks', '$user->rights->stock->lire', '', 2, 2, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled', __HANDLER__, 'left', 3104__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/mouvement.php', 'Movements', 1, 'stocks', '$user->rights->stock->mouvement->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->stock->enabled && $conf->fournisseur->enabled', __HANDLER__, 'left', 3105__+MAX_llx_menu__, 'products', '', 3100__+MAX_llx_menu__, '/product/stock/replenish.php', 'Replenishments', 1, 'stocks', '$user->rights->stock->mouvement->lire && $user->rights->fournisseur->lire', '', 2, 4, __ENTITY__); + -- Product - Categories insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->categorie->enabled', __HANDLER__, 'left', 3200__+MAX_llx_menu__, 'products', 'cat', 3__+MAX_llx_menu__, '/categories/index.php?leftmenu=cat&type=0', 'Categories', 0, 'categories', '$user->rights->categorie->lire', '', 2, 4, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->categorie->enabled', __HANDLER__, 'left', 3201__+MAX_llx_menu__, 'products', '', 3200__+MAX_llx_menu__, '/categories/fiche.php?action=create&type=0', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index f6604ff0253441ec6ca280b4720f815ee84e8ddc..98021186e345393cf9fc5f9e70f7a205f4df54c0 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1007,7 +1007,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu if (empty($leftmenu) || $leftmenu=="stock") $newmenu->add("/product/stock/liste.php", $langs->trans("List"), 1, $user->rights->stock->lire); if (empty($leftmenu) || $leftmenu=="stock") $newmenu->add("/product/stock/valo.php", $langs->trans("EnhancedValue"), 1, $user->rights->stock->lire); if (empty($leftmenu) || $leftmenu=="stock") $newmenu->add("/product/stock/mouvement.php", $langs->trans("Movements"), 1, $user->rights->stock->mouvement->lire); - if (empty($leftmenu) || $leftmenu=="stock") $newmenu->add("/product/stock/replenish.php", $langs->trans("Replenishment"), 1, $user->rights->stock->mouvement->lire); + if ($conf->fournisseur->enabled) if (empty($leftmenu) || $leftmenu=="stock") $newmenu->add("/product/stock/replenish.php", $langs->trans("Replenishment"), 1, $user->rights->stock->mouvement->lire && $user->rights->fournisseur->lire); } // Expeditions diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index fde34aa52a0b105a4064bdea6111dd9172c11c8c..27108adef185292b30af4f4b1ab794f3f283f3b0 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -143,11 +143,11 @@ NoStockForThisProduct=No stock for this product NoStock=No Stock Restock=Restock ProductSpecial=Special -QtyMin=Min. Order Qty. +QtyMin=Minimum Qty PriceQty=Price for this quantity -PriceQtyMin=MOQ Price (w/o discount) +PriceQtyMin=Price for this min. qty (w/o discount) VATRateForSupplierProduct=VAT Rate (for this supplier/product) -DiscountQtyMin=MOQ Discount (by default) +DiscountQtyMin=Default discount for qty NoPriceDefinedForThisSupplier=No price/qty defined for this supplier/product NoSupplierPriceDefinedForThisProduct=No supplier price/qty defined for this product RecordedProducts=Products recorded diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 80b8fb352ac1d82784a0fc4715ec2783ae58f03f..b26970e110d8556e4ef818a00156a8ce05c1b554 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -95,8 +95,10 @@ Replenishment=Replenishment ReplenishmentOrders=Replenishment orders UseVirtualStock=Use virtual stock instead of physical stock RuleForStockReplenishment=Rule for stocks replenishment -SelectProduct=Select at least one product +SelectProductWithNotNullQty=Select at least one product with a qty not null and a supplier AlertOnly= Alerts only WarehouseForStockDecrease=The warehouse <b>%s</b> will be used for stock decrease WarehouseForStockIncrease=The warehouse <b>%s</b> will be used for stock increase -ForThisWarehouse=For this warehouse \ No newline at end of file +ForThisWarehouse=For this warehouse +ReplenishmentStatusDesc=This is list of all product with a physical stock lower than desired stock and suggest you to create supplier orders to fill the difference. +ReplenishmentOrdersDesc=This is list of all opened supplier orders \ No newline at end of file diff --git a/htdocs/langs/fr_FR/stocks.lang b/htdocs/langs/fr_FR/stocks.lang index 934e0b59b9969faef212fdb18d739375f0726a2f..d1ce8931a1ad595d8389d8e7f81c3825cf8fa132 100644 --- a/htdocs/langs/fr_FR/stocks.lang +++ b/htdocs/langs/fr_FR/stocks.lang @@ -95,8 +95,10 @@ Replenishment=Réapprovisionnement ReplenishmentOrders=Commandes de réapprovisionnement UseVirtualStock=Utiliser le stock théorique à la place du stock physique RuleForStockReplenishment=Règle de gestion du réapprovisionnement des stocks -SelectProduct=Sélectionnez au moins un produit +SelectProductWithNotNullQty=Sélectionnez au moins un produit avec une quantité non nulle et un fournisseur AlertOnly = Alertes seulement WarehouseForStockDecrease=L'entrepôt <b>%s</b> sera utilisé pour la décrémentation du stock WarehouseForStockIncrease=L'entrepôt <b>%s</b> sera utilisé pour l'incrémentation du stock -ForThisWarehouse=Pour cet entrepôt \ No newline at end of file +ForThisWarehouse=Pour cet entrepôt +ReplenishmentStatusDesc=Cet écran permet de voir les produits avec un stock physique inférieure à la quantité minimale désirée et propose de créer des commandes fournisseurs pour compléter la différence +ReplenishmentOrdersDesc=Voici la liste des commandes fournisseurs en cours \ No newline at end of file diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 30941ec0cc2f02fa625183a7432e72b9e129b6aa..650891bb6bdf10d10c7e0a89ecfc49d688be3735 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -67,7 +67,8 @@ $offset = $limit * $page ; * Actions */ -if (isset($_POST['button_removefilter']) || isset($_POST['valid'])) { +if (isset($_POST['button_removefilter']) || isset($_POST['valid'])) +{ $sref = ''; $snom = ''; $sal = ''; @@ -75,16 +76,19 @@ if (isset($_POST['button_removefilter']) || isset($_POST['valid'])) { } //orders creation -//FIXME: could go in the lib -if ($action == 'order' && isset($_POST['valid'])) { +//TODO: could go in the lib +if ($action == 'order' && isset($_POST['valid'])) +{ $linecount = GETPOST('linecount', 'int'); $box = 0; unset($_POST['linecount']); if ($linecount > 0) { $suppliers = array(); - for ($i = 0; $i < $linecount; $i++) { - if(GETPOST($i, 'alpha') === 'on' - && GETPOST('fourn' . $i, 'int') > 0) { //one line + for ($i = 0; $i < $linecount; $i++) + { + if (GETPOST($i, 'alpha') === 'on' && GETPOST('fourn' . $i, 'int') > 0) + { + //one line $box = $i; $supplierpriceid = GETPOST('fourn'.$i, 'int'); //get all the parameters needed to create a line @@ -95,22 +99,28 @@ if ($action == 'order' && isset($_POST['valid'])) { $sql .= MAIN_DB_PREFIX . 'product_fournisseur_price'; $sql .= ' WHERE rowid = ' . $supplierpriceid; $resql = $db->query($sql); - if ($resql && $db->num_rows($resql) > 0) { - //might need some value checks - $obj = $db->fetch_object($resql); - $line = new CommandeFournisseurLigne($db); - $line->qty = $qty; - $line->desc = $desc; - $line->fk_product = $obj->fk_product; - $line->tva_tx = $obj->tva_tx; - $line->subprice = $obj->unitprice; - $line->total_ht = $obj->unitprice * $qty; - $tva = $line->tva_tx / 100; - $line->total_tva = $line->total_ht * $tva; - $line->total_ttc = $line->total_ht + $line->total_tva; - $line->ref_fourn = $obj->ref_fourn; - $suppliers[$obj->fk_soc]['lines'][] = $line; - } else { + if ($resql && $db->num_rows($resql) > 0) + { + if ($qty) + { + //might need some value checks + $obj = $db->fetch_object($resql); + $line = new CommandeFournisseurLigne($db); + $line->qty = $qty; + $line->desc = $desc; + $line->fk_product = $obj->fk_product; + $line->tva_tx = $obj->tva_tx; + $line->subprice = $obj->unitprice; + $line->total_ht = $obj->unitprice * $qty; + $tva = $line->tva_tx / 100; + $line->total_tva = $line->total_ht * $tva; + $line->total_ttc = $line->total_ht + $line->total_tva; + $line->ref_fourn = $obj->ref_fourn; + $suppliers[$obj->fk_soc]['lines'][] = $line; + } + } + else + { $error=$db->lasterror(); dol_print_error($db); dol_syslog('replenish.php: '.$error, LOG_ERR); @@ -120,11 +130,13 @@ if ($action == 'order' && isset($_POST['valid'])) { } unset($_POST[$i]); } + //we now know how many orders we need and what lines they have $i = 0; $orders = array(); $suppliersid = array_keys($suppliers); - foreach ($suppliers as $supplier) { + foreach ($suppliers as $supplier) + { $order = new CommandeFournisseur($db); $order->socid = $suppliersid[$i]; //trick to know which orders have been generated this way @@ -150,13 +162,15 @@ if ($action == 'order' && isset($_POST['valid'])) { } } if ($box == 0) { - setEventMessage($langs->trans('SelectProduct'), 'warnings'); + setEventMessage($langs->trans('SelectProductWithNotNullQty'), 'warnings'); } } + /* * View */ + $title = $langs->trans('Status'); $sql = 'SELECT p.rowid, p.ref, p.label, p.price'; @@ -196,385 +210,399 @@ if ($snom) { $sql .= ' AND p.label LIKE "%' . $db->escape($crit) . '%"'; } } - $sql .= ' AND p.tobuy = 1'; - -if (!empty($canvas)) { - $sql .= ' AND p.canvas = "' . $db->escape($canvas) . '"'; -} +if (!empty($canvas)) $sql .= ' AND p.canvas = "' . $db->escape($canvas) . '"'; $sql .= ' GROUP BY p.rowid, p.ref, p.label, p.price'; $sql .= ', p.price_ttc, p.price_base_type,p.fk_product_type, p.tms'; $sql .= ', p.duration, p.tobuy, p.seuil_stock_alerte'; $sql .= ', p.desiredstock, s.fk_product'; $sql .= ' HAVING p.desiredstock > SUM(COALESCE(s.reel, 0))'; $sql .= ' AND p.desiredstock > 0'; -if ($salert == 'on') { +if ($salert == 'on') +{ $sql .= ' AND SUM(COALESCE(s.reel, 0)) < p.seuil_stock_alerte AND p.seuil_stock_alerte is not NULL'; $alertchecked = 'checked="checked"'; } $sql .= $db->order($sortfield,$sortorder); $sql .= $db->plimit($limit + 1, $offset); $resql = $db->query($sql); +if (empty($resql)) +{ + dol_print_error($db); + exit; +} -if ($resql) { - $num = $db->num_rows($resql); - $i = 0; - - $helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|'; - $helpurl .= 'ES:Módulo_Stocks'; - llxHeader('', $title, $helpurl, $title); - $head = array(); - $head[0][0] = DOL_URL_ROOT.'/product/stock/replenish.php'; - $head[0][1] = $title; - $head[0][2] = 'replenish'; - $head[1][0] = DOL_URL_ROOT.'/product/stock/replenishorders.php'; - $head[1][1] = $langs->trans("ReplenishmentOrders"); - $head[1][2] = 'replenishorders'; - dol_fiche_head($head, 'replenish', $langs->trans('Replenishment'), 0, 'stock'); - if ($sref || $snom || $sall || $salert || GETPOST('search', 'alpha')) { - $filters = '&sref=' . $sref . '&snom=' . $snom; - $filters .= '&sall=' . $sall; - $filters .= '&salert=' . $salert; - print_barre_liste( - $texte, - $page, - 'replenish.php', - $filters, - $sortfield, - $sortorder, - '', - $num - ); - } else { - $filters = '&sref=' . $sref . '&snom=' . $snom; - $filters .= '&fourn_id=' . $fourn_id; - $filters .= (isset($type)?'&type=' . $type:''); - $filters .= '&salert=' . $salert; - print_barre_liste( - $texte, - $page, - 'replenish.php', - $filters, - $sortfield, - $sortorder, - '', - $num - ); - } - - print '<form action="replenish.php" method="post" name="formulaire">'. - '<input type="hidden" name="token" value="' .$_SESSION['newtoken'] . '">'. - '<input type="hidden" name="sortfield" value="' . $sortfield . '">'. - '<input type="hidden" name="sortorder" value="' . $sortorder . '">'. - '<input type="hidden" name="type" value="' . $type . '">'. - '<input type="hidden" name="linecount" value="' . $num . '">'. - '<input type="hidden" name="action" value="order">'. - - '<table class="liste" width="100%">'; - - $param = (isset($type)? '&type=' . $type : ''); - $param .= '&fourn_id=' . $fourn_id . '&snom='. $snom . '&salert=' . $salert; - $param .= '&sref=' . $sref; - - // Lignes des titres - print '<tr class="liste_titre">'. - '<td><input type="checkbox" onClick="toggle(this)" /></td>'; - print_liste_field_titre( - $langs->trans('Ref'), - 'replenish.php', - 'p.ref', - $param, - '', - '', - $sortfield, - $sortorder - ); - print_liste_field_titre( - $langs->trans('Label'), - 'replenish.php', - 'p.label', - $param, - '', - '', - $sortfield, - $sortorder - ); - if (!empty($conf->service->enabled) && $type == 1) - { - print_liste_field_titre( - $langs->trans('Duration'), - 'replenish.php', - 'p.duration', - $param, - '', - 'align="center"', - $sortfield, - $sortorder - ); - } - print_liste_field_titre( - $langs->trans('DesiredStock'), - 'replenish.php', - 'p.desiredstock', - $param, - '', - 'align="right"', - $sortfield, - $sortorder - ); - if ($conf->global->USE_VIRTUAL_STOCK) - { - $stocklabel = $langs->trans('VirtualStock'); - } - else - { - $stocklabel = $langs->trans('PhysicalStock'); - } - print_liste_field_titre( - $stocklabel, - 'replenish.php', - 'stock_physique', - $param, - '', - 'align="right"', - $sortfield, - $sortorder - ); - print_liste_field_titre( - $langs->trans('Ordered'), - 'replenish.php', - '', - $param, - '', - 'align="right"', - $sortfield, - $sortorder - ); - print_liste_field_titre( - $langs->trans('StockToBuy'), - 'replenish.php', - '', - $param, - '', - 'align="right"', - $sortfield, - $sortorder - ); - print_liste_field_titre( - $langs->trans('Supplier'), - 'replenish.php', - '', - $param, - '', - 'align="right"', - $sortfield, - $sortorder - ); - print '<td> </td>'. - '</tr>'. - - // Lignes des champs de filtre - '<tr class="liste_titre">'. - '<td class="liste_titre"> </td>'. - '<td class="liste_titre">'. - '<input class="flat" type="text" name="sref" value="' . $sref . '">'. - '</td>'. - '<td class="liste_titre">'. - '<input class="flat" type="text" name="snom" value="' . $snom . '">'. - '</td>'; - if (!empty($conf->service->enabled) && $type == 1) - { - print '<td class="liste_titre">'. - ' '. - '</td>'; - } - print '<td class="liste_titre"> </td>'. - '<td class="liste_titre" align="right">' . $langs->trans('AlertOnly') . ' <input type="checkbox" name="salert" ' . $alertchecked . '></td>'. - '<td class="liste_titre" align="right"> </td>'. - '<td class="liste_titre"> </td>'. - '<td class="liste_titre"> </td>'. - '<td class="liste_titre" align="right">'. - '<input type="image" class="liste_titre" name="button_search"'. - 'src="' . DOL_URL_ROOT . '/theme/' . $conf->theme . '/img/search.png" alt="' . $langs->trans("Search") . '">'. - '<input type="image" class="liste_titre" name="button_removefilter" - src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/searchclear.png" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">'. - '</td>'. - '</tr>'; - - $prod = new Product($db); - - $var = True; - while ($i < min($num, $limit)) { - $objp = $db->fetch_object($resql); - if ($conf->global->STOCK_SUPPORTS_SERVICES - || $objp->fk_product_type == 0) { - // Multilangs - if (! empty($conf->global->MAIN_MULTILANGS)) { - $sql = 'SELECT label'; - $sql .= ' FROM ' . MAIN_DB_PREFIX . 'product_lang'; - $sql .= ' WHERE fk_product = ' . $objp->rowid; - $sql .= ' AND lang = "' . $langs->getDefaultLang() . '"'; - $sql .= ' LIMIT 1'; - - $result = $db->query($sql); - if ($result) { - $objtp = $db->fetch_object($result); - if (!empty($objtp->label)) { - $objp->label = $objtp->label; - } - } - } - $form = new Form($db); - $var =! $var; - $prod->ref = $objp->ref; - $prod->id = $objp->rowid; - $prod->type = $objp->fk_product_type; - $ordered = ordered($prod->id); - - if ($conf->global->USE_VIRTUAL_STOCK) { - //compute virtual stock - $prod->fetch($prod->id); - $result=$prod->load_stats_commande(0, '1,2'); - if ($result < 0) { - dol_print_error($db, $prod->error); - } - $stock_commande_client = $prod->stats_commande['qty']; - $result=$prod->load_stats_commande_fournisseur(0, '3'); - if ($result < 0) { - dol_print_error($db,$prod->error); - } - $stock_commande_fournisseur = $prod->stats_commande_fournisseur['qty']; - $stock = $objp->stock_physique - $stock_commande_client + $stock_commande_fournisseur; - } else { - $stock = $objp->stock_physique; - } - $warning=''; - if ($objp->seuil_stock_alerte - && ($stock < $objp->seuil_stock_alerte)) { - $warning = img_warning($langs->trans('StockTooLow')) . ' '; - } - //depending on conf, use either physical stock or - //virtual stock to compute the stock to buy value - $stocktobuy = max($objp->desiredstock - $stock - $ordered, 0); - $disabled = ''; - if($ordered > 0) { - if($ordered + $stock >= $objp->desiredstock) { - $picto = img_picto('', './img/yes', '', 1); - $disabled = 'disabled="disabled"'; - } - else { - $picto = img_picto('', './img/no', '', 1); - } - } else { - $picto = img_picto('', './img/no', '', 1); - } - print '<tr ' . $bc[$var] . '>'. - '<td><input type="checkbox" class="check" name="' . $i . '"' . $disabled . '></td>'. - '<td class="nowrap">'. - $prod->getNomUrl(1, '', 16). - '</td>'. - '<td>' . $objp->label . '</td>'. - '<input type="hidden" name="desc' . $i . '" value="' . $objp->label . '" >'; - - if (!empty($conf->service->enabled) && $type == 1) { - if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) { - $duration = $regs[1] . ' ' . $langs->trans('DurationYear'); - } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) { - $duration = $regs[1] . ' ' . $langs->trans('DurationMonth'); - } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) { - $duration = $regs[1] . ' ' . $langs->trans('DurationDay'); - } else { - $duration = $objp->duration; - } - print '<td align="center">'. - $duration. - '</td>'; - } +$num = $db->num_rows($resql); +$i = 0; + +$helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|'; +$helpurl .= 'ES:Módulo_Stocks'; + +llxHeader('', $title, $helpurl, $title); + +$head = array(); +$head[0][0] = DOL_URL_ROOT.'/product/stock/replenish.php'; +$head[0][1] = $title; +$head[0][2] = 'replenish'; +$head[1][0] = DOL_URL_ROOT.'/product/stock/replenishorders.php'; +$head[1][1] = $langs->trans("ReplenishmentOrders"); +$head[1][2] = 'replenishorders'; + +dol_fiche_head($head, 'replenish', $langs->trans('Replenishment'), 0, 'stock'); + +print $langs->trans("ReplenishmentStatusDesc").'<br><br>'; + +if ($sref || $snom || $sall || $salert || GETPOST('search', 'alpha')) { + $filters = '&sref=' . $sref . '&snom=' . $snom; + $filters .= '&sall=' . $sall; + $filters .= '&salert=' . $salert; + print_barre_liste( + $texte, + $page, + 'replenish.php', + $filters, + $sortfield, + $sortorder, + '', + $num + ); +} else { + $filters = '&sref=' . $sref . '&snom=' . $snom; + $filters .= '&fourn_id=' . $fourn_id; + $filters .= (isset($type)?'&type=' . $type:''); + $filters .= '&salert=' . $salert; + print_barre_liste( + $texte, + $page, + 'replenish.php', + $filters, + $sortfield, + $sortorder, + '', + $num + ); +} - print '<td align="right">' . $objp->desiredstock . '</td>'. - '<td align="right">'. - $warning . $stock. - '</td>'. - '<td align="right">'. - '<a href="replenishorders.php?sproduct=' . $prod->id . '">'. - $ordered . '</a> ' . $picto. - '</td>'. - '<td align="right">'. - '<input type="text" name="tobuy' . $i . - '" value="' . $stocktobuy . '" ' . $disabled . '>'. - '</td>'. - '<td align="right">'. - $form->select_product_fourn_price($prod->id, 'fourn'.$i, 1). - '</td>'. - '<td> </td>'. - '</tr>'; - } - $i++; - } - $value = $langs->trans("CreateOrders"); - print '</table>'. - '</div>'. - '<table width="100%">'. - '<tr><td align="right">'. - '<input class="butAction" type="submit" name="valid" value="' . $value . '">'. - '</td></tr></table>'. - '</form>'; - - if ($num > $conf->liste_limit) - { - if ($sref || $snom || $sall || $salert || GETPOST('search', 'alpha')) - { - $filters = '&sref=' . $sref . '&snom=' . $snom; - $filters .= '&sall=' . $sall; - $filters .= '&salert=' . $salert; - print_barre_liste( - '', - $page, - 'replenish.php', - $filters, - $sortfield, - $sortorder, - '', - $num, - 0, - '' - ); - } else { - $filters = '&sref=' . $sref . '&snom=' . $snom; - $filters .= '&fourn_id=' . $fourn_id; - $filters .= (isset($type)? '&type=' . $type : ''); - $filters .= '&salert=' . $salert; - print_barre_liste( - '', - $page, - 'replenish.php', - $filters, - $sortfield, - $sortorder, - '', - $num, - 0, - '' - ); - } - } +print '<form action="replenish.php" method="post" name="formulaire">'. + '<input type="hidden" name="token" value="' .$_SESSION['newtoken'] . '">'. + '<input type="hidden" name="sortfield" value="' . $sortfield . '">'. + '<input type="hidden" name="sortorder" value="' . $sortorder . '">'. + '<input type="hidden" name="type" value="' . $type . '">'. + '<input type="hidden" name="linecount" value="' . $num . '">'. + '<input type="hidden" name="action" value="order">'. + + '<table class="liste" width="100%">'; + +$param = (isset($type)? '&type=' . $type : ''); +$param .= '&fourn_id=' . $fourn_id . '&snom='. $snom . '&salert=' . $salert; +$param .= '&sref=' . $sref; + +// Lignes des titres +print '<tr class="liste_titre">'. + '<td><input type="checkbox" onClick="toggle(this)" /></td>'; +print_liste_field_titre( + $langs->trans('Ref'), + 'replenish.php', + 'p.ref', + $param, + '', + '', + $sortfield, + $sortorder +); +print_liste_field_titre( + $langs->trans('Label'), + 'replenish.php', + 'p.label', + $param, + '', + '', + $sortfield, + $sortorder +); +if (!empty($conf->service->enabled) && $type == 1) +{ + print_liste_field_titre( + $langs->trans('Duration'), + 'replenish.php', + 'p.duration', + $param, + '', + 'align="center"', + $sortfield, + $sortorder + ); +} +print_liste_field_titre( + $langs->trans('DesiredStock'), + 'replenish.php', + 'p.desiredstock', + $param, + '', + 'align="right"', + $sortfield, + $sortorder +); +if ($conf->global->USE_VIRTUAL_STOCK) +{ + $stocklabel = $langs->trans('VirtualStock'); +} +else +{ + $stocklabel = $langs->trans('PhysicalStock'); +} +print_liste_field_titre( + $stocklabel, + 'replenish.php', + 'stock_physique', + $param, + '', + 'align="right"', + $sortfield, + $sortorder +); +print_liste_field_titre( + $langs->trans('Ordered'), + 'replenish.php', + '', + $param, + '', + 'align="right"', + $sortfield, + $sortorder +); +print_liste_field_titre( + $langs->trans('StockToBuy'), + 'replenish.php', + '', + $param, + '', + 'align="right"', + $sortfield, + $sortorder +); +print_liste_field_titre( + $langs->trans('Supplier'), + 'replenish.php', + '', + $param, + '', + 'align="right"', + $sortfield, + $sortorder +); +print '</tr>'; + +// Lignes des champs de filtre +print '<tr class="liste_titre">'. +'<td class="liste_titre"> </td>'. +'<td class="liste_titre">'. +'<input class="flat" type="text" name="sref" value="' . $sref . '">'. +'</td>'. +'<td class="liste_titre">'. +'<input class="flat" type="text" name="snom" value="' . $snom . '">'. +'</td>'; +if (!empty($conf->service->enabled) && $type == 1) +{ + print '<td class="liste_titre"> </td>'; +} +print '<td class="liste_titre"> </td>'. + '<td class="liste_titre" align="right">' . $langs->trans('AlertOnly') . ' <input type="checkbox" name="salert" ' . $alertchecked . '></td>'. + '<td class="liste_titre" align="right"> </td>'. + '<td class="liste_titre"> </td>'. + '<td class="liste_titre" align="right">'. + '<input type="image" class="liste_titre" name="button_search"'. + 'src="' . DOL_URL_ROOT . '/theme/' . $conf->theme . '/img/search.png" alt="' . $langs->trans("Search") . '">'. + '<input type="image" class="liste_titre" name="button_removefilter" + src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/searchclear.png" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">'. + '</td>'. + '</tr>'; + +$prod = new Product($db); + +$var = True; +while ($i < min($num, $limit)) +{ + $objp = $db->fetch_object($resql); + + if ($conf->global->STOCK_SUPPORTS_SERVICES || $objp->fk_product_type == 0) + { + // Multilangs + if (! empty($conf->global->MAIN_MULTILANGS)) + { + $sql = 'SELECT label'; + $sql .= ' FROM ' . MAIN_DB_PREFIX . 'product_lang'; + $sql .= ' WHERE fk_product = ' . $objp->rowid; + $sql .= ' AND lang = "' . $langs->getDefaultLang() . '"'; + $sql .= ' LIMIT 1'; + + $resqlm = $db->query($sql); + if ($resqlm) + { + $objtp = $db->fetch_object($resqlm); + if (!empty($objtp->label)) $objp->label = $objtp->label; + } + } + $form = new Form($db); + $var =! $var; + $prod->ref = $objp->ref; + $prod->id = $objp->rowid; + $prod->type = $objp->fk_product_type; + $ordered = ordered($prod->id); + + if ($conf->global->USE_VIRTUAL_STOCK) + { + //compute virtual stock + $prod->fetch($prod->id); + $result=$prod->load_stats_commande(0, '1,2'); + if ($result < 0) { + dol_print_error($db, $prod->error); + } + $stock_commande_client = $prod->stats_commande['qty']; + $result=$prod->load_stats_commande_fournisseur(0, '3'); + if ($result < 0) { + dol_print_error($db,$prod->error); + } + $stock_commande_fournisseur = $prod->stats_commande_fournisseur['qty']; + $stock = $objp->stock_physique - $stock_commande_client + $stock_commande_fournisseur; + } + else + { + $stock = $objp->stock_physique; + } + $warning=''; + + if ($objp->seuil_stock_alerte && ($stock < $objp->seuil_stock_alerte)) + { + $warning = img_warning($langs->trans('StockTooLow')) . ' '; + } + //depending on conf, use either physical stock or + //virtual stock to compute the stock to buy value + $stocktobuy = max($objp->desiredstock - $stock - $ordered, 0); + $disabled = ''; + if($ordered > 0) { + if($ordered + $stock >= $objp->desiredstock) { + $picto = img_picto('', './img/yes', '', 1); + $disabled = 'disabled="disabled"'; + } + else { + $picto = img_picto('', './img/no', '', 1); + } + } else { + $picto = img_picto('', './img/no', '', 1); + } + print '<tr ' . $bc[$var] . '>'; + + // Select field + //print '<td><input type="checkbox" class="check" name="' . $i . '"' . $disabled . '></td>'; + print '<td><input type="checkbox" class="check" name="' . $i . '"></td>'; + + print '<td class="nowrap">'. + $prod->getNomUrl(1, '', 16). + '</td>'. + '<td>' . $objp->label . '</td>'. + '<input type="hidden" name="desc' . $i . '" value="' . $objp->label . '" >'; + + if (!empty($conf->service->enabled) && $type == 1) { + if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) { + $duration = $regs[1] . ' ' . $langs->trans('DurationYear'); + } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) { + $duration = $regs[1] . ' ' . $langs->trans('DurationMonth'); + } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) { + $duration = $regs[1] . ' ' . $langs->trans('DurationDay'); + } else { + $duration = $objp->duration; + } + print '<td align="center">'. + $duration. + '</td>'; + } + + print '<td align="right">' . $objp->desiredstock . '</td>'. + '<td align="right">'. + $warning . $stock. + '</td>'. + '<td align="right">'. + '<a href="replenishorders.php?sproduct=' . $prod->id . '">'. + $ordered . '</a> ' . $picto. + '</td>'; + + // To order + //print '<td align="right"><input type="text" name="tobuy'.$i.'" value="'.$stocktobuy.'" '.$disabled.'></td>'; + print '<td align="right"><input type="text" name="tobuy'.$i.'" value="'.$stocktobuy.'"></td>'; + + // Supplier + print '<td align="right">'. $form->select_product_fourn_price($prod->id, 'fourn'.$i, 1).'</td>'; + + print '</tr>'; + } + $i++; +} +$value = $langs->trans("CreateOrders"); +print '</table>'. + '</div>'. + '<table width="100%">'. + '<tr><td align="center">'. + '<input class="button" type="submit" name="valid" value="' . $value . '">'. + '</td></tr></table>'. + '</form>'; + +if ($num > $conf->liste_limit) +{ + if ($sref || $snom || $sall || $salert || GETPOST('search', 'alpha')) + { + $filters = '&sref=' . $sref . '&snom=' . $snom; + $filters .= '&sall=' . $sall; + $filters .= '&salert=' . $salert; + print_barre_liste( + '', + $page, + 'replenish.php', + $filters, + $sortfield, + $sortorder, + '', + $num, + 0, + '' + ); + } else { + $filters = '&sref=' . $sref . '&snom=' . $snom; + $filters .= '&fourn_id=' . $fourn_id; + $filters .= (isset($type)? '&type=' . $type : ''); + $filters .= '&salert=' . $salert; + print_barre_liste( + '', + $page, + 'replenish.php', + $filters, + $sortfield, + $sortorder, + '', + $num, + 0, + '' + ); + } +} - $db->free($resql); -print ' <script type="text/javascript"> - function toggle(source) - { - checkboxes = document.getElementsByClassName("check"); - for (var i=0; i < checkboxes.length;i++) { - if (!checkboxes[i].disabled) { - checkboxes[i].checked = source.checked; - } - } - } </script>'; -} else { - dol_print_error($db); +$db->free($resql); + +print ' +<script type="text/javascript"> +function toggle(source) +{ + checkboxes = document.getElementsByClassName("check"); + for (var i=0; i < checkboxes.length;i++) { + if (!checkboxes[i].disabled) { + checkboxes[i].checked = source.checked; + } + } } +</script>'; + llxFooter(); $db->close(); -?> +?> \ No newline at end of file diff --git a/htdocs/product/stock/replenishorders.php b/htdocs/product/stock/replenishorders.php index e5e4379baa8ec47bd9e8f29cd8920de5bad50b3d..be7a0ed0821a40a841e8d052de07351d7f0c4d48 100644 --- a/htdocs/product/stock/replenishorders.php +++ b/htdocs/product/stock/replenishorders.php @@ -48,7 +48,9 @@ $head[0][2] = 'replenish'; $head[1][0] = DOL_URL_ROOT.'/product/stock/replenishorders.php'; $head[1][1] = $texte; $head[1][2] = 'replenishorders'; + dol_fiche_head($head, 'replenishorders', $langs->trans('Replenishment'), 0, 'stock'); + $commandestatic = new CommandeFournisseur($db); $sref = GETPOST('search_ref', 'alpha'); $snom = GETPOST('search_nom', 'alpha'); @@ -72,21 +74,15 @@ if (!$sortfield) { $offset = $conf->liste_limit * $page ; $sql = 'SELECT s.rowid as socid, s.nom, cf.date_creation as dc,'; -$sql .= ' cf.rowid, cf.ref, cf.fk_statut, cf.total_ttc'; -$sql .= ", cf.fk_user_author, u.login"; -$sql .= ' FROM (' . MAIN_DB_PREFIX . 'societe as s,'; -$sql .= ' ' . MAIN_DB_PREFIX . 'commande_fournisseur as cf'; - +$sql.= ' cf.rowid, cf.ref, cf.fk_statut, cf.total_ttc, cf.fk_user_author,'; +$sql.= ' u.login'; +$sql.= ' FROM '.MAIN_DB_PREFIX.'societe as s, '.MAIN_DB_PREFIX.'commande_fournisseur as cf'; +$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'user as u ON cf.fk_user_author = u.rowid'; if (!$user->rights->societe->client->voir && !$socid) { $sql.= ', ' . MAIN_DB_PREFIX . 'societe_commerciaux as sc'; - } - -$sql .= ') LEFT JOIN ' . MAIN_DB_PREFIX . 'user as u '; -$sql .= 'ON cf.fk_user_author = u.rowid'; -$sql .= ' WHERE cf.fk_soc = s.rowid '; -$sql .= ' AND cf.entity = ' . $conf->entity; - +$sql.= ' WHERE cf.fk_soc = s.rowid '; +$sql.= ' AND cf.entity = ' . $conf->entity; if ($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) { $sql .= ' AND cf.fk_statut < 3'; } elseif ($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) { @@ -94,7 +90,6 @@ if ($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) { } else { $sql .= ' AND cf.fk_statut < 5'; } - if (!$user->rights->societe->client->voir && !$socid) { $sql .= ' AND s.rowid = sc.fk_soc AND sc.fk_user = ' . $user->id; } @@ -117,13 +112,13 @@ if ($suser) { if ($sttc) { $sql .= ' AND cf.total_ttc = ' . price2num($sttc); } -if ($sdate) +if ($sdate) { - if (GETPOST('search_datemonth', 'int') && GETPOST('search_dateday', 'int') && GETPOST('search_dateyear', 'int')) + if (GETPOST('search_datemonth', 'int') && GETPOST('search_dateday', 'int') && GETPOST('search_dateyear', 'int')) { $date = dol_mktime(0, 0, 0, GETPOST('search_datemonth', 'int'), GETPOST('search_dateday', 'int'), GETPOST('search_dateyear', 'int')); } - else + else { $date = dol_stringtotime($sdate); } @@ -145,20 +140,24 @@ $sql .= ', cf.total_ttc, cf.fk_user_author, u.login, s.rowid, s.nom'; $sql .= ' ORDER BY ' . $sortfield . ' ' . $sortorder . ' '; $sql .= $db->plimit($conf->liste_limit+1, $offset); $resql = $db->query($sql); -if ($resql) +if ($resql) { $num = $db->num_rows($resql); $i = 0; + print $langs->trans("ReplenishmentOrdersDesc").'<br><br>'; + print_barre_liste( - $langs->trans('ReplenishmentOrders'), + '', $page, 'replenishorders.php', '', $sortfield, $sortorder, '', - $num + $num, + 0, + '' ); print '<form action="replenishorders.php" method="GET">'. '<table class="noborder" width="100%">'. @@ -255,8 +254,7 @@ if ($resql) { $obj = $db->fetch_object($resql); $var = !$var; - if (!dispatched($obj->rowid) && - (!$sproduct || in_array($sproduct, getProducts($obj->rowid)))) + if (!dispatched($obj->rowid) && (!$sproduct || in_array($sproduct, getProducts($obj->rowid)))) { $href = DOL_URL_ROOT . '/fourn/commande/fiche.php?id=' . $obj->rowid; print '<tr ' . $bc[$var] . '>'. @@ -288,9 +286,10 @@ if ($resql) '<td>'. price($obj->total_ttc). '</td>'; + // Date if ($obj->dc) { - $date = dol_print_date($db->jdate($obj->dc), 'day'); + $date = dol_print_date($db->jdate($obj->dc), 'dayhour'); } else { $date = '-'; } @@ -310,6 +309,10 @@ if ($resql) $db->free($resql); } +else +{ + dol_print_error($db); +} llxFooter(); $db->close();