31 require
'../../main.inc.php';
32 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
33 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formother.class.php';
34 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.form.class.php';
35 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.commande.class.php';
36 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
37 require_once
'./lib/replenishment.lib.php';
40 $langs->loadLangs(array(
'products',
'stocks',
'orders'));
44 $socid = $user->socid;
49 $hookmanager->initHooks(array(
'stockreplenishlist'));
53 $action =
GETPOST(
'action',
'aZ09');
54 $search_ref =
GETPOST(
'search_ref',
'alpha');
55 $search_label =
GETPOST(
'search_label',
'alpha');
56 $sall = trim((
GETPOST(
'search_all',
'alphanohtml') !=
'') ?
GETPOST(
'search_all',
'alphanohtml') :
GETPOST(
'sall',
'alphanohtml'));
58 $tobuy =
GETPOST(
'tobuy',
'int');
59 $salert =
GETPOST(
'salert',
'alpha');
60 $includeproductswithoutdesiredqty =
GETPOST(
'includeproductswithoutdesiredqty',
'alpha');
61 $mode =
GETPOST(
'mode',
'alpha');
62 $draftorder =
GETPOST(
'draftorder',
'alpha');
65 $fourn_id =
GETPOST(
'fourn_id',
'int');
66 $fk_supplier =
GETPOST(
'fk_supplier',
'int');
67 $fk_entrepot =
GETPOST(
'fk_entrepot',
'int');
70 $resWar = $db->query(
"SELECT rowid FROM " . MAIN_DB_PREFIX .
"entrepot WHERE entity IN (" . $db->sanitize(
getEntity(
'stock')) .
")");
71 $listofqualifiedwarehousesid =
"";
73 while ($tmpobj = $db->fetch_object($resWar)) {
74 if (!empty($listofqualifiedwarehousesid)) {
75 $listofqualifiedwarehousesid .=
",";
77 $listofqualifiedwarehousesid .= $tmpobj->rowid;
78 $lastWarehouseID = $tmpobj->rowid;
83 if ($count == 1 && (empty($fk_entrepot) || $fk_entrepot <= 0) && !empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED)) {
84 $fk_entrepot = $lastWarehouseID;
89 $sortfield =
GETPOST(
'sortfield',
'aZ09comma');
90 $sortorder =
GETPOST(
'sortorder',
'aZ09comma');
92 if (empty($page) || $page == -1) {
95 $limit =
GETPOST(
'limit',
'int') ?
GETPOST(
'limit',
'int') : $conf->liste_limit;
96 $offset = $limit * $page;
107 $virtualdiffersfromphysical = 0;
108 if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
109 || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)
110 || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)
111 || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION)
112 || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)
113 || !empty($conf->mrp->enabled)) {
114 $virtualdiffersfromphysical = 1;
117 if ($virtualdiffersfromphysical) {
118 $usevirtualstock = empty($conf->global->STOCK_USE_REAL_STOCK_BY_DEFAULT_FOR_REPLENISHMENT) ? 1 : 0;
120 $usevirtualstock = 0;
122 if ($mode ==
'physical') {
123 $usevirtualstock = 0;
125 if ($mode ==
'virtual') {
126 $usevirtualstock = 1;
129 $parameters = array();
130 $reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
140 if (
GETPOST(
'button_removefilter_x',
'alpha') ||
GETPOST(
'button_removefilter.x',
'alpha') ||
GETPOST(
'button_removefilter',
'alpha')) {
145 $includeproductswithoutdesiredqty =
'';
148 if ($draftorder ==
'on') {
149 $draftchecked =
"checked";
153 if ($action ==
'order' &&
GETPOST(
'valid')) {
154 $linecount =
GETPOST(
'linecount',
'int');
157 unset($_POST[
'linecount']);
158 if ($linecount > 0) {
161 $suppliers = array();
162 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
164 for ($i = 0; $i < $linecount; $i++) {
165 if (
GETPOST(
'choose'.$i,
'alpha') ===
'on' &&
GETPOST(
'fourn'.$i,
'int') > 0) {
168 $supplierpriceid =
GETPOST(
'fourn'.$i,
'int');
170 $qty =
GETPOST(
'tobuy'.$i,
'int');
171 $idprod = $productsupplier->get_buyprice($supplierpriceid, $qty);
172 $res = $productsupplier->fetch($idprod);
173 if ($res && $idprod > 0) {
178 $line->fk_product = $idprod;
182 if (!empty($conf->global->MAIN_MULTILANGS)) {
183 $productsupplier->getMultiLangs();
187 if (!empty($productsupplier->desc_supplier) && !empty($conf->global->PRODUIT_FOURN_TEXTS)) {
188 $desc = $productsupplier->desc_supplier;
190 $desc = $productsupplier->description;
193 if (!empty($conf->global->MAIN_MULTILANGS)) {
197 $line->tva_tx = $productsupplier->vatrate_supplier;
198 $line->subprice = $productsupplier->fourn_pu;
199 $line->total_ht = $productsupplier->fourn_pu * $qty;
200 $tva = $line->tva_tx / 100;
201 $line->total_tva = $line->total_ht * $tva;
202 $line->total_ttc = $line->total_ht + $line->total_tva;
203 $line->remise_percent = $productsupplier->remise_percent;
204 $line->ref_fourn = $productsupplier->ref_supplier;
205 $line->type = $productsupplier->type;
206 $line->fk_unit = $productsupplier->fk_unit;
207 $suppliers[$productsupplier->fourn_socid][
'lines'][] = $line;
209 } elseif ($idprod == -1) {
212 $error = $db->lasterror();
216 unset($_POST[
'fourn'.$i]);
225 $suppliersid = array_keys($suppliers);
226 foreach ($suppliers as $supplier) {
230 $sql =
"SELECT rowid FROM ".MAIN_DB_PREFIX.
"commande_fournisseur";
231 $sql .=
" WHERE fk_soc = ".((int) $suppliersid[$i]);
232 $sql .=
" AND source = ".((int) $order::SOURCE_ID_REPLENISHMENT).
" AND fk_statut = ".((int) $order::STATUS_DRAFT);
233 $sql .=
" AND entity IN (".getEntity(
'commande_fournisseur').
")";
234 $sql .=
" ORDER BY date_creation DESC";
235 $resql = $db->query($sql);
237 $obj = $db->fetch_object(
$resql);
239 $order->fetch($obj->rowid);
240 $order->fetch_thirdparty();
242 foreach ($supplier[
'lines'] as $line) {
243 if (empty($line->remise_percent)) {
244 $line->remise_percent = $order->thirdparty->remise_supplier_percent;
246 $result = $order->addline(
256 $line->remise_percent,
270 $msg = $langs->trans(
'OrderFail').
" : ";
271 $msg .= $order->error;
277 $order->socid = $suppliersid[$i];
278 $order->fetch_thirdparty();
281 $order->source = $order::SOURCE_ID_REPLENISHMENT;
283 foreach ($supplier[
'lines'] as $line) {
284 if (empty($line->remise_percent)) {
285 $line->remise_percent = $order->thirdparty->remise_supplier_percent;
287 $order->lines[] = $line;
289 $order->cond_reglement_id = $order->thirdparty->cond_reglement_supplier_id;
290 $order->mode_reglement_id = $order->thirdparty->mode_reglement_supplier_id;
292 $id = $order->create($user);
295 $msg = $langs->trans(
'OrderFail').
" : ";
296 $msg .= $order->error;
304 setEventMessages($langs->trans(
'ErrorOrdersNotCreatedQtyTooLow'),
null,
'warnings');
311 header(
'Location: replenishorders.php');
318 setEventMessages($langs->trans(
'SelectProductWithNotNullQty'),
null,
'warnings');
331 $title = $langs->trans(
'MissingStocks');
333 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
334 $sqldesiredtock = $db->ifsql(
"pse.desiredstock IS NULL",
"p.desiredstock",
"pse.desiredstock");
335 $sqlalertstock = $db->ifsql(
"pse.seuil_stock_alerte IS NULL",
"p.seuil_stock_alerte",
"pse.seuil_stock_alerte");
337 $sqldesiredtock =
'p.desiredstock';
338 $sqlalertstock =
'p.seuil_stock_alerte';
341 $sql =
'SELECT p.rowid, p.ref, p.label, p.description, p.price,';
342 $sql .=
' p.price_ttc, p.price_base_type, p.fk_product_type,';
343 $sql .=
' p.tms as datem, p.duration, p.tobuy,';
344 $sql .=
' p.desiredstock, p.seuil_stock_alerte,';
345 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
346 $sql .=
' pse.desiredstock as desiredstockpse, pse.seuil_stock_alerte as seuil_stock_alertepse,';
348 $sql .=
" ".$sqldesiredtock.
" as desiredstockcombined, ".$sqlalertstock.
" as seuil_stock_alertecombined,";
349 $sql .=
' s.fk_product,';
350 $sql .=
" SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
') as stock_physique';
351 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
352 $sql .=
", SUM(".$db->ifsql(
"s.reel IS NULL OR s.fk_entrepot <> ".$fk_entrepot,
"0",
"s.reel").
') as stock_real_warehouse';
356 $parameters = array();
357 $reshook = $hookmanager->executeHooks(
'printFieldListSelect', $parameters);
358 $sql .= $hookmanager->resPrint;
360 $sql .=
' FROM '.MAIN_DB_PREFIX.
'product as p';
361 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product_stock as s ON p.rowid = s.fk_product';
362 $list_warehouse = (empty($listofqualifiedwarehousesid) ?
'0' : $listofqualifiedwarehousesid);
363 $sql .=
' AND s.fk_entrepot IN ('.$db->sanitize($list_warehouse) .
')';
366 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
367 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product_warehouse_properties AS pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = '.((int) $fk_entrepot).
')';
370 $parameters = array();
371 $reshook = $hookmanager->executeHooks(
'printFieldListJoin', $parameters);
372 $sql .= $hookmanager->resPrint;
374 $sql .=
' WHERE p.entity IN ('.getEntity(
'product').
')';
376 $sql .=
natural_search(array(
'p.ref',
'p.label',
'p.description',
'p.note'), $sall);
381 $sql .=
' AND p.fk_product_type = 1';
383 $sql .=
' AND p.fk_product_type <> 1';
392 $sql .=
' AND p.tobuy = 1';
393 if (!empty($conf->variants->eabled) && empty($conf->global->VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT)) {
394 $sql .=
' AND p.rowid NOT IN (SELECT pac.fk_product_parent FROM '.MAIN_DB_PREFIX.
'product_attribute_combination as pac WHERE pac.entity IN ('.
getEntity(
'product').
'))';
396 if ($fk_supplier > 0) {
397 $sql .=
' AND EXISTS (SELECT pfp.rowid FROM '.MAIN_DB_PREFIX.
'product_fournisseur_price as pfp WHERE pfp.fk_product = p.rowid AND pfp.fk_soc = '.((int) $fk_supplier).
' AND pfp.entity IN ('.
getEntity(
'product_fournisseur_price').
'))';
400 $parameters = array();
401 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters);
402 $sql .= $hookmanager->resPrint;
404 $sql .=
' GROUP BY p.rowid, p.ref, p.label, p.description, p.price';
405 $sql .=
', p.price_ttc, p.price_base_type,p.fk_product_type, p.tms';
406 $sql .=
', p.duration, p.tobuy';
407 $sql .=
', p.desiredstock';
408 $sql .=
', p.seuil_stock_alerte';
409 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
410 $sql .=
', pse.desiredstock';
411 $sql .=
', pse.seuil_stock_alerte';
413 $sql .=
', s.fk_product';
415 if ($usevirtualstock) {
416 if (!empty($conf->commande->enabled)) {
417 $sqlCommandesCli =
"(SELECT ".$db->ifsql(
"SUM(cd1.qty) IS NULL",
"0",
"SUM(cd1.qty)").
" as qty";
418 $sqlCommandesCli .=
" FROM ".MAIN_DB_PREFIX.
"commandedet as cd1, ".MAIN_DB_PREFIX.
"commande as c1";
419 $sqlCommandesCli .=
" WHERE c1.rowid = cd1.fk_commande AND c1.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'commande').
")";
420 $sqlCommandesCli .=
" AND cd1.fk_product = p.rowid";
421 $sqlCommandesCli .=
" AND c1.fk_statut IN (1,2))";
423 $sqlCommandesCli =
'0';
426 if (!empty($conf->expedition->enabled)) {
427 $sqlExpeditionsCli =
"(SELECT ".$db->ifsql(
"SUM(ed2.qty) IS NULL",
"0",
"SUM(ed2.qty)").
" as qty";
428 $sqlExpeditionsCli .=
" FROM ".MAIN_DB_PREFIX.
"expedition as e2,";
429 $sqlExpeditionsCli .=
" ".MAIN_DB_PREFIX.
"expeditiondet as ed2,";
430 $sqlExpeditionsCli .=
" ".MAIN_DB_PREFIX.
"commande as c2,";
431 $sqlExpeditionsCli .=
" ".MAIN_DB_PREFIX.
"commandedet as cd2";
432 $sqlExpeditionsCli .=
" WHERE ed2.fk_expedition = e2.rowid AND cd2.rowid = ed2.fk_origin_line AND e2.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'expedition').
")";
433 $sqlExpeditionsCli .=
" AND cd2.fk_commande = c2.rowid";
434 $sqlExpeditionsCli .=
" AND c2.fk_statut IN (1,2)";
435 $sqlExpeditionsCli .=
" AND cd2.fk_product = p.rowid";
436 $sqlExpeditionsCli .=
" AND e2.fk_statut IN (1,2))";
438 $sqlExpeditionsCli =
'0';
441 if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) {
442 $sqlCommandesFourn =
"(SELECT ".$db->ifsql(
"SUM(cd3.qty) IS NULL",
"0",
"SUM(cd3.qty)").
" as qty";
443 $sqlCommandesFourn .=
" FROM ".MAIN_DB_PREFIX.
"commande_fournisseurdet as cd3,";
444 $sqlCommandesFourn .=
" ".MAIN_DB_PREFIX.
"commande_fournisseur as c3";
445 $sqlCommandesFourn .=
" WHERE c3.rowid = cd3.fk_commande";
446 $sqlCommandesFourn .=
" AND c3.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'supplier_order').
")";
447 $sqlCommandesFourn .=
" AND cd3.fk_product = p.rowid";
448 $sqlCommandesFourn .=
" AND c3.fk_statut IN (3,4))";
450 $sqlReceptionFourn =
"(SELECT ".$db->ifsql(
"SUM(fd4.qty) IS NULL",
"0",
"SUM(fd4.qty)").
" as qty";
451 $sqlReceptionFourn .=
" FROM ".MAIN_DB_PREFIX.
"commande_fournisseur as cf4,";
452 $sqlReceptionFourn .=
" ".MAIN_DB_PREFIX.
"commande_fournisseur_dispatch as fd4";
453 $sqlReceptionFourn .=
" WHERE fd4.fk_commande = cf4.rowid AND cf4.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'supplier_order').
")";
454 $sqlReceptionFourn .=
" AND fd4.fk_product = p.rowid";
455 $sqlReceptionFourn .=
" AND cf4.fk_statut IN (3,4))";
457 $sqlCommandesFourn =
'0';
458 $sqlReceptionFourn =
'0';
461 if (!empty($conf->mrp->enabled)) {
462 $sqlProductionToConsume =
"(SELECT GREATEST(0, ".$db->ifsql(
"SUM(".$db->ifsql(
"mp5.role = 'toconsume'",
'mp5.qty',
'- mp5.qty').
") IS NULL",
"0",
"SUM(".$db->ifsql(
"mp5.role = 'toconsume'",
'mp5.qty',
'- mp5.qty').
")").
") as qty";
463 $sqlProductionToConsume .=
" FROM ".MAIN_DB_PREFIX.
"mrp_mo as mm5,";
464 $sqlProductionToConsume .=
" ".MAIN_DB_PREFIX.
"mrp_production as mp5";
465 $sqlProductionToConsume .=
" WHERE mm5.rowid = mp5.fk_mo AND mm5.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'mo').
")";
466 $sqlProductionToConsume .=
" AND mp5.fk_product = p.rowid";
467 $sqlProductionToConsume .=
" AND mp5.role IN ('toconsume', 'consumed')";
468 $sqlProductionToConsume .=
" AND mm5.status IN (1,2))";
470 $sqlProductionToProduce =
"(SELECT GREATEST(0, ".$db->ifsql(
"SUM(".$db->ifsql(
"mp5.role = 'toproduce'",
'mp5.qty',
'- mp5.qty').
") IS NULL",
"0",
"SUM(".$db->ifsql(
"mp5.role = 'toconsume'",
'mp5.qty',
'- mp5.qty').
")").
") as qty";
471 $sqlProductionToProduce .=
" FROM ".MAIN_DB_PREFIX.
"mrp_mo as mm5,";
472 $sqlProductionToProduce .=
" ".MAIN_DB_PREFIX.
"mrp_production as mp5";
473 $sqlProductionToProduce .=
" WHERE mm5.rowid = mp5.fk_mo AND mm5.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ?
'stock' :
'mo').
")";
474 $sqlProductionToProduce .=
" AND mp5.fk_product = p.rowid";
475 $sqlProductionToProduce .=
" AND mp5.role IN ('toproduce', 'produced')";
476 $sqlProductionToProduce .=
" AND mm5.status IN (1,2))";
478 $sqlProductionToConsume =
'0';
479 $sqlProductionToProduce =
'0';
483 $sql .=
" (".$sqldesiredtock.
" >= 0 AND (".$sqldesiredtock.
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
')';
484 $sql .=
" - (".$sqlCommandesCli.
" - ".$sqlExpeditionsCli.
") + (".$sqlCommandesFourn.
" - ".$sqlReceptionFourn.
") + (".$sqlProductionToProduce.
" - ".$sqlProductionToConsume.
")))";
486 if ($includeproductswithoutdesiredqty ==
'on') {
487 $sql .=
" ((".$sqlalertstock.
" >= 0 OR ".$sqlalertstock.
" IS NULL) AND (".$db->ifsql($sqlalertstock.
" IS NULL",
"0", $sqlalertstock).
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
")";
489 $sql .=
" (".$sqlalertstock.
" >= 0 AND (".$sqlalertstock.
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
')';
491 $sql .=
" - (".$sqlCommandesCli.
" - ".$sqlExpeditionsCli.
") + (".$sqlCommandesFourn.
" - ".$sqlReceptionFourn.
") + (".$sqlProductionToProduce.
" - ".$sqlProductionToConsume.
")))";
494 if ($salert ==
'on') {
496 if ($includeproductswithoutdesiredqty ==
'on') {
497 $sql .=
"(".$sqlalertstock.
" >= 0 OR ".$sqlalertstock.
" IS NULL) AND (".$db->ifsql($sqlalertstock.
" IS NULL",
"0", $sqlalertstock).
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
")";
499 $sql .= $sqlalertstock.
" >= 0 AND (".$sqlalertstock.
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
")";
501 $sql .=
" - (".$sqlCommandesCli.
" - ".$sqlExpeditionsCli.
") + (".$sqlCommandesFourn.
" - ".$sqlReceptionFourn.
") + (".$sqlProductionToProduce.
" - ".$sqlProductionToConsume.
"))";
503 $alertchecked =
'checked';
507 $sql .=
"(".$sqldesiredtock.
" >= 0 AND (".$sqldesiredtock.
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
")))";
509 if ($includeproductswithoutdesiredqty ==
'on') {
510 $sql .=
" ((".$sqlalertstock.
" >= 0 OR ".$sqlalertstock.
" IS NULL) AND (".$db->ifsql($sqlalertstock.
" IS NULL",
"0", $sqlalertstock).
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
')))';
512 $sql .=
" (".$sqlalertstock.
" >= 0 AND (".$sqlalertstock.
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
')))';
516 if ($salert ==
'on') {
518 if ($includeproductswithoutdesiredqty ==
'on') {
519 $sql .=
" (".$sqlalertstock.
" >= 0 OR ".$sqlalertstock.
" IS NULL) AND (".$db->ifsql($sqlalertstock.
" IS NULL",
"0", $sqlalertstock).
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
"))";
521 $sql .=
" ".$sqlalertstock.
" >= 0 AND (".$sqlalertstock.
" > SUM(".$db->ifsql(
"s.reel IS NULL",
"0",
"s.reel").
'))';
524 $alertchecked =
'checked';
528 $includeproductswithoutdesiredqtychecked =
'';
529 if ($includeproductswithoutdesiredqty ==
'on') {
530 $includeproductswithoutdesiredqtychecked =
'checked';
533 $nbtotalofrecords =
'';
534 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
535 $result = $db->query($sql);
536 $nbtotalofrecords = $db->num_rows($result);
537 if (($page * $limit) > $nbtotalofrecords) {
543 $sql .= $db->order($sortfield, $sortorder);
544 $sql .= $db->plimit($limit + 1, $offset);
547 $resql = $db->query($sql);
553 $num = $db->num_rows(
$resql);
556 $helpurl =
'EN:Module_Stocks_En|FR:Module_Stock|';
557 $helpurl .=
'ES:Módulo_Stocks';
563 $head[0][0] = DOL_URL_ROOT.
'/product/stock/replenish.php';
564 $head[0][1] = $title;
565 $head[0][2] =
'replenish';
567 $head[1][0] = DOL_URL_ROOT.
'/product/stock/replenishorders.php';
568 $head[1][1] = $langs->trans(
"ReplenishmentOrders");
569 $head[1][2] =
'replenishorders';
576 print
'<span class="opacitymedium">'.$langs->trans(
"ReplenishmentStatusDesc").
'</span>'.
"\n";
580 if (empty($fk_entrepot) && !empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) {
581 print
'<span class="opacitymedium">'.$langs->trans(
"ReplenishmentStatusDescPerWarehouse").
'</span>'.
"\n";
584 if ($usevirtualstock == 1) {
585 print $langs->trans(
"CurentSelectionMode").
': ';
586 print
'<span class="a-mesure">'.$langs->trans(
"UseVirtualStock").
'</span>';
587 print
' <a class="a-mesure-disabled" href="'.$_SERVER[
"PHP_SELF"].
'?mode=physical'.($fk_supplier > 0 ?
'&fk_supplier='.$fk_supplier :
'').($fk_entrepot > 0 ?
'&fk_entrepot='.$fk_entrepot :
'').
'">'.$langs->trans(
"UsePhysicalStock").
'</a>';
590 if ($usevirtualstock == 0) {
591 print $langs->trans(
"CurentSelectionMode").
': ';
592 print
'<a class="a-mesure-disabled" href="'.$_SERVER[
"PHP_SELF"].
'?mode=virtual'.($fk_supplier > 0 ?
'&fk_supplier='.$fk_supplier :
'').($fk_entrepot > 0 ?
'&fk_entrepot='.$fk_entrepot :
'').
'">'.$langs->trans(
"UseVirtualStock").
'</a>';
593 print
' <span class="a-mesure">'.$langs->trans(
"UsePhysicalStock").
'</span>';
598 print
'<form name="formFilterWarehouse" method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
599 print
'<input type="hidden" name="token" value="'.newToken().
'">';
600 print
'<input type="hidden" name="action" value="filter">';
601 print
'<input type="hidden" name="search_ref" value="'.$search_ref.
'">';
602 print
'<input type="hidden" name="search_label" value="'.$search_label.
'">';
603 print
'<input type="hidden" name="salert" value="'.$salert.
'">';
604 print
'<input type="hidden" name="includeproductswithoutdesiredqty" value="'.$includeproductswithoutdesiredqty.
'">';
605 print
'<input type="hidden" name="draftorder" value="'.$draftorder.
'">';
606 print
'<input type="hidden" name="mode" value="'.$mode.
'">';
607 if ($limit > 0 && $limit != $conf->liste_limit) {
608 print
'<input type="hidden" name="limit" value="'.$limit.
'">';
610 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) {
611 print
'<div class="inline-block valignmiddle" style="padding-right: 20px;">';
612 print $langs->trans(
'Warehouse').
' '.$formproduct->selectWarehouses($fk_entrepot,
'fk_entrepot',
'', 1);
615 print
'<div class="inline-block valignmiddle" style="padding-right: 20px;">';
616 print $langs->trans(
'Supplier').
' '.
$form->select_company($fk_supplier,
'fk_supplier',
'fournisseur=1', 1);
619 $parameters = array();
620 $reshook = $hookmanager->executeHooks(
'printFieldPreListTitle', $parameters);
621 if (empty($reshook)) {
622 print $hookmanager->resPrint;
625 print
'<div class="inline-block valignmiddle">';
626 print
'<input type="submit" class="button smallpaddingimp" name="valid" value="'.$langs->trans(
'ToFilter').
'">';
631 print
'<form action="'.$_SERVER[
"PHP_SELF"].
'" method="POST" name="formulaire">';
632 print
'<input type="hidden" name="token" value="'.newToken().
'">';
633 print
'<input type="hidden" name="fk_supplier" value="'.$fk_supplier.
'">';
634 print
'<input type="hidden" name="fk_entrepot" value="'.$fk_entrepot.
'">';
635 print
'<input type="hidden" name="sortfield" value="'.$sortfield.
'">';
636 print
'<input type="hidden" name="sortorder" value="'.$sortorder.
'">';
637 print
'<input type="hidden" name="type" value="'.$type.
'">';
638 print
'<input type="hidden" name="linecount" value="'.$num.
'">';
639 print
'<input type="hidden" name="action" value="order">';
640 print
'<input type="hidden" name="mode" value="'.$mode.
'">';
643 if ($search_ref || $search_label || $sall || $salert || $draftorder ||
GETPOST(
'search',
'alpha')) {
644 $filters =
'&search_ref='.urlencode($search_ref).
'&search_label='.urlencode($search_label);
645 $filters .=
'&sall='.urlencode($sall);
646 $filters .=
'&salert='.urlencode($salert);
647 $filters .=
'&draftorder='.urlencode($draftorder);
648 $filters .=
'&mode='.urlencode($mode);
649 if ($fk_supplier > 0) {
650 $filters .=
'&fk_supplier='.urlencode($fk_supplier);
652 if ($fk_entrepot > 0) {
653 $filters .=
'&fk_entrepot='.urlencode($fk_entrepot);
656 $filters =
'&search_ref='.urlencode($search_ref).
'&search_label='.urlencode($search_label);
657 $filters .=
'&fourn_id='.urlencode($fourn_id);
658 $filters .= (isset($type) ?
'&type='.urlencode($type) :
'');
659 $filters .=
'&='.urlencode($salert);
660 $filters .=
'&draftorder='.urlencode($draftorder);
661 $filters .=
'&mode='.urlencode($mode);
662 if ($fk_supplier > 0) {
663 $filters .=
'&fk_supplier='.urlencode($fk_supplier);
665 if ($fk_entrepot > 0) {
666 $filters .=
'&fk_entrepot='.urlencode($fk_entrepot);
669 if ($limit > 0 && $limit != $conf->liste_limit) {
670 $filters .=
'&limit='.urlencode($limit);
672 if (!empty($includeproductswithoutdesiredqty)) $filters .=
'&includeproductswithoutdesiredqty='.urlencode($includeproductswithoutdesiredqty);
673 if (!empty($salert)) $filters .=
'&salert='.urlencode($salert);
675 $param = (isset($type) ?
'&type='.urlencode($type) :
'');
676 $param .=
'&fourn_id='.urlencode($fourn_id).
'&search_label='.urlencode($search_label).
'&includeproductswithoutdesiredqty='.urlencode($includeproductswithoutdesiredqty).
'&salert='.urlencode($salert).
'&draftorder='.urlencode($draftorder);
677 $param .=
'&search_ref='.urlencode($search_ref);
678 $param .=
'&mode='.urlencode($mode);
679 $param .=
'&fk_supplier='.urlencode($fk_supplier);
680 $param .=
'&fk_entrepot='.urlencode($fk_entrepot);
681 if (!empty($includeproductswithoutdesiredqty)) $param .=
'&includeproductswithoutdesiredqty='.urlencode($includeproductswithoutdesiredqty);
682 if (!empty($salert)) $param .=
'&salert='.urlencode($salert);
684 $stocklabel = $langs->trans(
'Stock');
685 $stocklabelbis = $langs->trans(
'Stock');
686 if ($usevirtualstock == 1) {
687 $stocklabel = $langs->trans(
'VirtualStock');
689 if ($usevirtualstock == 0) {
690 $stocklabel = $langs->trans(
'PhysicalStock');
692 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
693 $stocklabelbis = $stocklabel.
' (Selected warehouse)';
694 $stocklabel .=
' ('.$langs->trans(
"AllWarehouses").
')';
696 $texte = $langs->trans(
'Replenishment');
700 print
'<div class="div-table-responsive-no-min">';
702 if (!empty($conf->global->REPLENISH_ALLOW_VARIABLESIZELIST)) {
734 print
'<table class="liste centpercent">';
737 print
'<tr class="liste_titre_filter">';
738 print
'<td class="liste_titre"> </td>';
739 print
'<td class="liste_titre"><input class="flat" type="text" name="search_ref" size="8" value="'.dol_escape_htmltag($search_ref).
'"></td>';
740 print
'<td class="liste_titre"><input class="flat" type="text" name="search_label" size="8" value="'.dol_escape_htmltag($search_label).
'"></td>';
741 if (!empty($conf->service->enabled) && $type == 1) {
742 print
'<td class="liste_titre"> </td>';
744 print
'<td class="liste_titre right">'.$form->textwithpicto($langs->trans(
'IncludeEmptyDesiredStock'), $langs->trans(
'IncludeProductWithUndefinedAlerts')).
' <input type="checkbox" id="includeproductswithoutdesiredqty" name="includeproductswithoutdesiredqty" '.(!empty($includeproductswithoutdesiredqtychecked) ? $includeproductswithoutdesiredqtychecked :
'').
'></td>';
745 print
'<td class="liste_titre right"></td>';
746 print
'<td class="liste_titre right">'.$langs->trans(
'AlertOnly').
' <input type="checkbox" id="salert" name="salert" '.(!empty($alertchecked) ? $alertchecked :
'').
'></td>';
747 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
748 print
'<td class="liste_titre"> </td>';
750 print
'<td class="liste_titre right">';
751 if (!empty($conf->global->STOCK_REPLENISH_ADD_CHECKBOX_INCLUDE_DRAFT_ORDER)) {
752 print $langs->trans(
'IncludeAlsoDraftOrders').
' <input type="checkbox" id="draftorder" name="draftorder" '.(!empty($draftchecked) ? $draftchecked :
'').
'>';
755 print
'<td class="liste_titre"> </td>';
757 $parameters = array(
'param'=>$param,
'sortfield'=>$sortfield,
'sortorder'=>$sortorder);
758 $reshook = $hookmanager->executeHooks(
'printFieldListOption', $parameters);
759 print $hookmanager->resPrint;
761 print
'<td class="liste_titre maxwidthsearch right">';
762 $searchpicto =
$form->showFilterAndCheckAddButtons(0);
768 print
'<tr class="liste_titre">';
772 if (!empty($conf->service->enabled) && $type == 1) {
773 print_liste_field_titre(
'Duration', $_SERVER[
"PHP_SELF"],
'p.duration', $param,
'',
'', $sortfield, $sortorder,
'center ');
775 print_liste_field_titre(
'DesiredStock', $_SERVER[
"PHP_SELF"],
'p.desiredstock', $param,
'',
'', $sortfield, $sortorder,
'right ');
776 print_liste_field_titre(
'StockLimitShort', $_SERVER[
"PHP_SELF"],
'p.seuil_stock_alerte', $param,
'',
'', $sortfield, $sortorder,
'right ');
777 print_liste_field_titre($stocklabel, $_SERVER[
"PHP_SELF"],
'stock_physique', $param,
'',
'', $sortfield, $sortorder,
'right ');
778 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
779 print_liste_field_titre($stocklabelbis, $_SERVER[
"PHP_SELF"],
'stock_real_warehouse', $param,
'',
'', $sortfield, $sortorder,
'right ');
781 print_liste_field_titre(
'Ordered', $_SERVER[
"PHP_SELF"],
'', $param,
'',
'', $sortfield, $sortorder,
'right ');
782 print_liste_field_titre(
'StockToBuy', $_SERVER[
"PHP_SELF"],
'', $param,
'',
'', $sortfield, $sortorder,
'right ');
783 print_liste_field_titre(
'SupplierRef', $_SERVER[
"PHP_SELF"],
'', $param,
'',
'', $sortfield, $sortorder,
'right ');
786 $parameters = array(
'param'=>$param,
'sortfield'=>$sortfield,
'sortorder'=>$sortorder);
787 $reshook = $hookmanager->executeHooks(
'printFieldListTitle', $parameters);
788 print $hookmanager->resPrint;
792 while ($i < ($limit ? min($num, $limit) : $num)) {
793 $objp = $db->fetch_object(
$resql);
795 if (!empty($conf->global->STOCK_SUPPORTS_SERVICES) || $objp->fk_product_type == 0) {
796 $result = $prod->fetch($objp->rowid);
802 $prod->load_stock(
'warehouseopen, warehouseinternal'.(!$usevirtualstock?
', novirtual':
''), $draftchecked);
805 if (!empty($conf->global->MAIN_MULTILANGS)) {
806 $sql =
'SELECT label,description';
807 $sql .=
' FROM '.MAIN_DB_PREFIX.
'product_lang';
808 $sql .=
' WHERE fk_product = '.((int) $objp->rowid);
809 $sql .=
" AND lang = '".$db->escape($langs->getDefaultLang()).
"'";
812 $resqlm = $db->query($sql);
814 $objtp = $db->fetch_object($resqlm);
815 if (!empty($objtp->description)) {
816 $objp->description = $objtp->description;
818 if (!empty($objtp->label)) {
819 $objp->label = $objtp->label;
825 if ($usevirtualstock) {
827 $stock = $prod->stock_theorique;
830 $stock = $prod->stock_reel;
831 $stockwarehouse = $prod->stock_warehouse[$fk_entrepot]->real;
835 if (isset($draftchecked)) {
836 $result = $prod->load_stats_commande_fournisseur(0,
'0,1,2,3,4');
837 } elseif (!$usevirtualstock) {
838 $result = $prod->load_stats_commande_fournisseur(0,
'1,2,3,4');
841 if (!$usevirtualstock) {
842 $result = $prod->load_stats_reception(0,
'4');
847 $ordered = $prod->stats_commande_fournisseur[
'qty'] - $prod->stats_reception[
'qty'];
849 $desiredstock = $objp->desiredstock;
850 $alertstock = $objp->seuil_stock_alerte;
851 $desiredstockwarehouse = ($objp->desiredstockpse ? $objp->desiredstockpse : 0);
852 $alertstockwarehouse = ($objp->seuil_stock_alertepse ? $objp->seuil_stock_alertepse : 0);
855 if ($alertstock && ($stock < $alertstock)) {
856 $warning =
img_warning($langs->trans(
'StockTooLow')).
' ';
858 $warningwarehouse =
'';
859 if ($alertstockwarehouse && ($stockwarehouse < $alertstockwarehouse)) {
860 $warningwarehouse =
img_warning($langs->trans(
'StockTooLow')).
' ';
866 if (empty($usevirtualstock)) {
867 $stocktobuy = max(max($desiredstock, $alertstock) - $stock - $ordered, 0);
869 $stocktobuy = max(max($desiredstock, $alertstock) - $stock, 0);
871 if (empty($usevirtualstock)) {
872 $stocktobuywarehouse = max(max($desiredstockwarehouse, $alertstockwarehouse) - $stockwarehouse - $ordered, 0);
874 $stocktobuywarehouse = max(max($desiredstockwarehouse, $alertstockwarehouse) - $stockwarehouse, 0);
879 $stockforcompare = ($usevirtualstock ? $stock : $stock + $ordered);
887 $picto =
img_picto($langs->trans(
"NoPendingReceptionOnSupplierOrder"),
'help');
890 print
'<tr class="oddeven">';
893 print
'<td><input type="checkbox" class="check" name="choose'.$i.
'"></td>';
895 print
'<td class="nowrap">'.$prod->getNomUrl(1,
'stock').
'</td>';
897 print
'<td class="tdoverflowmax200" title="'.dol_escape_htmltag($objp->label).
'">';
899 print
'<input type="hidden" name="desc'.$i.
'" value="'.
dol_escape_htmltag($objp->description).
'">';
902 if (!empty($conf->service->enabled) && $type == 1) {
904 if (preg_match(
'/([0-9]+)y/i', $objp->duration, $regs)) {
905 $duration = $regs[1].
' '.$langs->trans(
'DurationYear');
906 } elseif (preg_match(
'/([0-9]+)m/i', $objp->duration, $regs)) {
907 $duration = $regs[1].
' '.$langs->trans(
'DurationMonth');
908 } elseif (preg_match(
'/([0-9]+)d/i', $objp->duration, $regs)) {
909 $duration = $regs[1].
' '.$langs->trans(
'DurationDay');
911 $duration = $objp->duration;
913 print
'<td class="center">'.$duration.
'</td>';
917 print
'<td class="right">'.((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $desiredstockwarehouse : $desiredstock).
'</td>';
920 print
'<td class="right">'.((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $alertstockwarehouse : $alertstock).
'</td>';
923 print
'<td class="right">'.$warning.$stock;
924 print
'<!-- stock returned by main sql is '.$objp->stock_physique.
' -->';
928 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
929 print
'<td class="right">'.$warningwarehouse.$stockwarehouse.
'</td>';
933 print
'<td class="right"><a href="replenishorders.php?search_product='.$prod->id.
'">'.$ordered.
'</a> '.$picto.
'</td>';
936 print
'<td class="right"><input type="text" size="4" name="tobuy'.$i.
'" value="'.((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $stocktobuywarehouse : $stocktobuy).
'"></td>';
939 print
'<td class="right">';
940 print
$form->select_product_fourn_price($prod->id,
'fourn'.$i, $fk_supplier);
944 $parameters = array(
'objp'=>$objp);
945 $reshook = $hookmanager->executeHooks(
'printFieldListValue', $parameters);
946 print $hookmanager->resPrint;
953 $parameters = array(
'sql'=>$sql);
954 $reshook = $hookmanager->executeHooks(
'printFieldListFooter', $parameters);
955 print $hookmanager->resPrint;
965 $value = $langs->trans(
"CreateOrders");
966 print
'<div class="center"><input type="submit" class="button" name="valid" value="'.$value.
'"></div>';
974 <script type="text/javascript">
975 function toggle(source)
977 checkboxes = document.getElementsByClassName("check");
978 for (var i=0; i < checkboxes.length;i++) {
979 if (!checkboxes[i].disabled) {
980 checkboxes[i].checked = source.checked;