1<?php 2/* Copyright (C) 2004-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org> 3 * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net> 4 * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com> 5 * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com> 6 * Copyright (C) 2010-2021 Juanjo Menent <jmenent@2byte.es> 7 * Copyright (C) 2014 Cedric Gross <c.gross@kreiz-it.fr> 8 * Copyright (C) 2016 Florian Henry <florian.henry@atm-consulting.fr> 9 * Copyright (C) 2017-2020 Ferran Marcet <fmarcet@2byte.es> 10 * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr> 11 * Copyright (C) 2019-2020 Christophe Battarel <christophe@altairis.fr> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program. If not, see <https://www.gnu.org/licenses/>. 25 * or see https://www.gnu.org/ 26 */ 27 28/** 29 * \file htdocs/fourn/commande/dispatch.php 30 * \ingroup commande 31 * \brief Page to dispatch receiving 32 */ 33 34require '../../main.inc.php'; 35require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php'; 36require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; 37require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php'; 38require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; 39require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php'; 40require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; 41require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; 42 43if (!empty($conf->projet->enabled)) { 44 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; 45} 46 47// Load translation files required by the page 48$langs->loadLangs(array("bills", "orders", "sendings", "companies", "deliveries", "products", "stocks", "receptions")); 49 50if (!empty($conf->productbatch->enabled)) { 51 $langs->load('productbatch'); 52} 53 54 // Security check 55$id = GETPOST("id", 'int'); 56$ref = GETPOST('ref'); 57$lineid = GETPOST('lineid', 'int'); 58$action = GETPOST('action', 'aZ09'); 59$fk_default_warehouse = GETPOST('fk_default_warehouse', 'int'); 60$cancel = GETPOST('cancel', 'alpha'); 61$confirm = GETPOST('confirm', 'alpha'); 62 63if ($user->socid) { 64 $socid = $user->socid; 65} 66$result = restrictedArea($user, 'fournisseur', $id, 'commande_fournisseur', 'commande'); 67 68if (empty($conf->stock->enabled)) { 69 accessforbidden(); 70} 71 72$hookmanager->initHooks(array('ordersupplierdispatch')); 73 74// Recuperation de l'id de projet 75$projectid = 0; 76if ($_GET["projectid"]) { 77 $projectid = GETPOST("projectid", 'int'); 78} 79 80$object = new CommandeFournisseur($db); 81 82if ($id > 0 || !empty($ref)) { 83 $result = $object->fetch($id, $ref); 84 if ($result < 0) { 85 setEventMessages($object->error, $object->errors, 'errors'); 86 } 87 $result = $object->fetch_thirdparty(); 88 if ($result < 0) { 89 setEventMessages($object->error, $object->errors, 'errors'); 90 } 91} 92 93 94/* 95 * Actions 96 */ 97 98$parameters = array(); 99$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks 100if ($reshook < 0) { 101 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 102} 103 104if ($action == 'checkdispatchline' && !((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) { 105 $error = 0; 106 $supplierorderdispatch = new CommandeFournisseurDispatch($db); 107 108 $db->begin(); 109 110 $result = $supplierorderdispatch->fetch($lineid); 111 if (!$result) { 112 $error++; 113 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); 114 $action = ''; 115 } 116 117 if (!$error) { 118 $result = $supplierorderdispatch->setStatut(1); 119 if ($result < 0) { 120 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); 121 $error++; 122 $action = ''; 123 } 124 } 125 126 if (!$error) { 127 $result = $object->calcAndSetStatusDispatch($user); 128 if ($result < 0) { 129 setEventMessages($object->error, $object->errors, 'errors'); 130 $error++; 131 $action = ''; 132 } 133 } 134 if (!$error) { 135 $db->commit(); 136 } else { 137 $db->rollback(); 138 } 139} 140 141if ($action == 'uncheckdispatchline' && !((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) { 142 $error = 0; 143 $supplierorderdispatch = new CommandeFournisseurDispatch($db); 144 145 $db->begin(); 146 147 $result = $supplierorderdispatch->fetch($lineid); 148 if (!$result) { 149 $error++; 150 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); 151 $action = ''; 152 } 153 154 if (!$error) { 155 $result = $supplierorderdispatch->setStatut(0); 156 if ($result < 0) { 157 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); 158 $error++; 159 $action = ''; 160 } 161 } 162 if (!$error) { 163 $result = $object->calcAndSetStatusDispatch($user); 164 if ($result < 0) { 165 setEventMessages($object->error, $object->errors, 'errors'); 166 $error++; 167 $action = ''; 168 } 169 } 170 if (!$error) { 171 $db->commit(); 172 } else { 173 $db->rollback(); 174 } 175} 176 177if ($action == 'denydispatchline' && !((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check)))) { 178 $error = 0; 179 $supplierorderdispatch = new CommandeFournisseurDispatch($db); 180 181 $db->begin(); 182 183 $result = $supplierorderdispatch->fetch($lineid); 184 if (!$result) { 185 $error++; 186 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); 187 $action = ''; 188 } 189 190 if (!$error) { 191 $result = $supplierorderdispatch->setStatut(2); 192 if ($result < 0) { 193 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); 194 $error++; 195 $action = ''; 196 } 197 } 198 if (!$error) { 199 $result = $object->calcAndSetStatusDispatch($user); 200 if ($result < 0) { 201 setEventMessages($object->error, $object->errors, 'errors'); 202 $error++; 203 $action = ''; 204 } 205 } 206 if (!$error) { 207 $db->commit(); 208 } else { 209 $db->rollback(); 210 } 211} 212 213if ($action == 'dispatch' && $user->rights->fournisseur->commande->receptionner) { 214 $error = 0; 215 216 $db->begin(); 217 218 $pos = 0; 219 foreach ($_POST as $key => $value) { 220 // without batch module enabled 221 $reg = array(); 222 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) { 223 $pos++; 224 225 // $numline=$reg[2] + 1; // line of product 226 $numline = $pos; 227 $prod = "product_".$reg[1].'_'.$reg[2]; 228 $qty = "qty_".$reg[1].'_'.$reg[2]; 229 $ent = "entrepot_".$reg[1].'_'.$reg[2]; 230 if (empty(GETPOST($ent))) { 231 $ent = $fk_default_warehouse; 232 } 233 $pu = "pu_".$reg[1].'_'.$reg[2]; // This is unit price including discount 234 $fk_commandefourndet = "fk_commandefourndet_".$reg[1].'_'.$reg[2]; 235 236 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { 237 if (empty($conf->multicurrency->enabled) && empty($conf->dynamicprices->enabled)) { 238 $dto = GETPOST("dto_".$reg[1].'_'.$reg[2], 'int'); 239 if (!empty($dto)) { 240 $unit_price = price2num(GETPOST("pu_".$reg[1]) * (100 - $dto) / 100, 'MU'); 241 } 242 $saveprice = "saveprice_".$reg[1].'_'.$reg[2]; 243 } 244 } 245 246 // We ask to move a qty 247 if (GETPOST($qty) != 0) { 248 if (!(GETPOST($ent, 'int') > 0)) { 249 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.'); 250 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline); 251 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors'); 252 $error++; 253 } 254 255 if (!$error) { 256 $result = $object->dispatchProduct($user, GETPOST($prod, 'int'), GETPOST($qty), GETPOST($ent, 'int'), GETPOST($pu), GETPOST('comment'), '', '', '', GETPOST($fk_commandefourndet, 'int'), $notrigger); 257 if ($result < 0) { 258 setEventMessages($object->error, $object->errors, 'errors'); 259 $error++; 260 } 261 262 if (!$error && !empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { 263 if (empty($conf->multicurrency->enabled) && empty($conf->dynamicprices->enabled)) { 264 $dto = price2num(GETPOST("dto_".$reg[1].'_'.$reg[2], 'int'), ''); 265 if (empty($dto)) { 266 $dto = 0; 267 } 268 269 //update supplier price 270 if (GETPOSTISSET($saveprice)) { 271 // TODO Use class 272 $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price"; 273 $sql .= " SET unitprice='".price2num(GETPOST($pu), 'MU')."'"; 274 $sql .= ", price=".price2num(GETPOST($pu), 'MU')."*quantity"; 275 $sql .= ", remise_percent = ".((float) $dto); 276 $sql .= " WHERE fk_soc=".((int) $object->socid); 277 $sql .= " AND fk_product=".((int) GETPOST($prod, 'int')); 278 279 $resql = $db->query($sql); 280 } 281 } 282 } 283 } 284 } 285 } 286 // with batch module enabled 287 if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) { 288 $pos++; 289 290 // eat-by date dispatch 291 // $numline=$reg[2] + 1; // line of product 292 $numline = $pos; 293 $prod = 'product_batch_'.$reg[1].'_'.$reg[2]; 294 $qty = 'qty_'.$reg[1].'_'.$reg[2]; 295 $ent = 'entrepot_'.$reg[1].'_'.$reg[2]; 296 $pu = 'pu_'.$reg[1].'_'.$reg[2]; 297 $fk_commandefourndet = 'fk_commandefourndet_'.$reg[1].'_'.$reg[2]; 298 $lot = 'lot_number_'.$reg[1].'_'.$reg[2]; 299 $dDLUO = dol_mktime(12, 0, 0, $_POST['dluo_'.$reg[1].'_'.$reg[2].'month'], $_POST['dluo_'.$reg[1].'_'.$reg[2].'day'], $_POST['dluo_'.$reg[1].'_'.$reg[2].'year']); 300 $dDLC = dol_mktime(12, 0, 0, $_POST['dlc_'.$reg[1].'_'.$reg[2].'month'], $_POST['dlc_'.$reg[1].'_'.$reg[2].'day'], $_POST['dlc_'.$reg[1].'_'.$reg[2].'year']); 301 302 $fk_commandefourndet = 'fk_commandefourndet_'.$reg[1].'_'.$reg[2]; 303 304 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { 305 if (empty($conf->multicurrency->enabled) && empty($conf->dynamicprices->enabled)) { 306 $dto = GETPOST("dto_".$reg[1].'_'.$reg[2], 'int'); 307 if (!empty($dto)) { 308 $unit_price = price2num(GETPOST("pu_".$reg[1]) * (100 - $dto) / 100, 'MU'); 309 } 310 $saveprice = "saveprice_".$reg[1].'_'.$reg[2]; 311 } 312 } 313 314 // We ask to move a qty 315 if (GETPOST($qty) > 0) { 316 if (!(GETPOST($ent, 'int') > 0)) { 317 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.'); 318 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline).'-'.($reg[1] + 1); 319 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors'); 320 $error++; 321 } 322 323 if (!(GETPOST($lot, 'alpha') || $dDLUO || $dDLC)) { 324 dol_syslog('No dispatch for line '.$key.' as serial/eat-by/sellby date are not set'); 325 $text = $langs->transnoentities('atleast1batchfield').', '.$langs->transnoentities('Line').' '.($numline).'-'.($reg[1] + 1); 326 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors'); 327 $error++; 328 } 329 330 if (!$error) { 331 $result = $object->dispatchProduct($user, GETPOST($prod, 'int'), GETPOST($qty), GETPOST($ent, 'int'), GETPOST($pu), GETPOST('comment'), $dDLC, $dDLUO, GETPOST($lot, 'alpha'), GETPOST($fk_commandefourndet, 'int'), $notrigger); 332 if ($result < 0) { 333 setEventMessages($object->error, $object->errors, 'errors'); 334 $error++; 335 } 336 337 if (!$error && !empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { 338 if (empty($conf->multicurrency->enabled) && empty($conf->dynamicprices->enabled)) { 339 $dto = GETPOST("dto_".$reg[1].'_'.$reg[2], 'int'); 340 //update supplier price 341 if (GETPOSTISSET($saveprice)) { 342 // TODO Use class 343 $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price"; 344 $sql .= " SET unitprice='".GETPOST($pu)."'"; 345 $sql .= ", price=".GETPOST($pu)."*quantity"; 346 $sql .= ", remise_percent='".(!empty($dto) ? $dto : 0)."'"; 347 $sql .= " WHERE fk_soc=".$object->socid; 348 $sql .= " AND fk_product=".GETPOST($prod, 'int'); 349 350 $resql = $db->query($sql); 351 } 352 } 353 } 354 } 355 } 356 } 357 } 358 359 if (!$error) { 360 $result = $object->calcAndSetStatusDispatch($user, GETPOST('closeopenorder') ? 1 : 0, GETPOST('comment')); 361 if ($result < 0) { 362 setEventMessages($object->error, $object->errors, 'errors'); 363 $error++; 364 } 365 } 366 367 if (!$notrigger && !$error) { 368 global $conf, $langs, $user; 369 // Call trigger 370 371 $result = $object->call_trigger('ORDER_SUPPLIER_DISPATCH', $user); 372 // End call triggers 373 374 if ($result < 0) { 375 setEventMessages($object->error, $object->errors, 'errors'); 376 $error++; 377 } 378 } 379 380 if ($result >= 0 && !$error) { 381 $db->commit(); 382 383 header("Location: dispatch.php?id=".$id); 384 exit(); 385 } else { 386 $db->rollback(); 387 } 388} 389 390// Remove a dispatched line 391if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->fournisseur->commande->receptionner) { 392 $db->begin(); 393 394 $supplierorderdispatch = new CommandeFournisseurDispatch($db); 395 $result = $supplierorderdispatch->fetch($lineid); 396 if ($result > 0) { 397 $qty = $supplierorderdispatch->qty; 398 $entrepot = $supplierorderdispatch->fk_entrepot; 399 $product = $supplierorderdispatch->fk_product; 400 $price = price2num(GETPOST('price', 'alpha'), 'MU'); 401 $comment = $supplierorderdispatch->comment; 402 $eatby = $supplierorderdispatch->eatby; 403 $sellby = $supplierorderdispatch->sellby; 404 $batch = $supplierorderdispatch->batch; 405 406 $result = $supplierorderdispatch->delete($user); 407 } 408 if ($result < 0) { 409 $errors = $object->errors; 410 $error++; 411 } else { 412 // If module stock is enabled and the stock increase is done on purchase order dispatching 413 if ($entrepot > 0 && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) && empty($supplierorderdispatch->fk_reception)) { 414 $mouv = new MouvementStock($db); 415 if ($product > 0) { 416 $mouv->origin = &$object; 417 $result = $mouv->livraison($user, $product, $entrepot, $qty, $price, $comment, '', $eatby, $sellby, $batch); 418 if ($result < 0) { 419 $errors = $mouv->errors; 420 $error++; 421 } 422 } 423 } 424 } 425 if ($error > 0) { 426 $db->rollback(); 427 setEventMessages($error, $errors, 'errors'); 428 } else { 429 $db->commit(); 430 } 431} 432 433// Update a dispatched line 434if ($action == 'updateline' && $user->rights->fournisseur->commande->receptionner) { 435 $db->begin(); 436 $error = 0; 437 438 $supplierorderdispatch = new CommandeFournisseurDispatch($db); 439 $result = $supplierorderdispatch->fetch($lineid); 440 if ($result > 0) { 441 $qty = $supplierorderdispatch->qty; 442 $entrepot = $supplierorderdispatch->fk_entrepot; 443 $product = $supplierorderdispatch->fk_product; 444 $price = price2num(GETPOST('price'), '', 2); 445 $comment = $supplierorderdispatch->comment; 446 $eatby = $supplierorderdispatch->eatby; 447 $sellby = $supplierorderdispatch->sellby; 448 $batch = $supplierorderdispatch->batch; 449 450 $supplierorderdispatch->qty = price2num(GETPOST('qty', 'alpha'), 'MS', 2); 451 $supplierorderdispatch->fk_entrepot = GETPOST('fk_entrepot'); 452 $result = $supplierorderdispatch->update($user); 453 } 454 if ($result < 0) { 455 $error++; 456 $errors = $supplierorderdispatch->errors; 457 } else { 458 // If module stock is enabled and the stock increase is done on purchase order dispatching 459 if ($entrepot > 0 && !empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) { 460 $mouv = new MouvementStock($db); 461 if ($product > 0) { 462 $mouv->origin = &$object; 463 $result = $mouv->livraison($user, $product, $entrepot, $qty, $price, $comment, '', $eatby, $sellby, $batch); 464 if ($result < 0) { 465 $errors = $mouv->errors; 466 $error++; 467 } else { 468 $mouv->origin = &$object; 469 $result = $mouv->reception($user, $product, $supplierorderdispatch->fk_entrepot, $supplierorderdispatch->qty, $price, $comment, $eatby, $sellby, $batch); 470 if ($result < 0) { 471 $errors = $mouv->errors; 472 $error++; 473 } 474 } 475 } 476 } 477 } 478 if ($error > 0) { 479 $db->rollback(); 480 setEventMessages($error, $errors, 'errors'); 481 } else { 482 $db->commit(); 483 } 484} 485 486/* 487 * View 488 */ 489 490$now = dol_now(); 491 492$form = new Form($db); 493$formproduct = new FormProduct($db); 494$warehouse_static = new Entrepot($db); 495$supplierorderdispatch = new CommandeFournisseurDispatch($db); 496 497$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; 498$morejs = array('/fourn/js/lib_dispatch.js.php'); 499 500llxHeader('', $langs->trans("OrderDispatch"), $help_url, '', 0, 0, $morejs); 501 502if ($id > 0 || !empty($ref)) { 503 $soc = new Societe($db); 504 $soc->fetch($object->socid); 505 506 $author = new User($db); 507 $author->fetch($object->user_author_id); 508 509 $head = ordersupplier_prepare_head($object); 510 511 $title = $langs->trans("SupplierOrder"); 512 print dol_get_fiche_head($head, 'dispatch', $title, -1, 'order'); 513 514 $formconfirm = ''; 515 516 // Confirmation to delete line 517 if ($action == 'ask_deleteline') { 518 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); 519 } 520 521 // Call Hook formConfirm 522 $parameters = array('lineid' => $lineid); 523 // Note that $action and $object may be modified by hook 524 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); 525 if (empty($reshook)) { 526 $formconfirm .= $hookmanager->resPrint; 527 } elseif ($reshook > 0) { 528 $formconfirm = $hookmanager->resPrint; 529 } 530 531 // Print form confirm 532 print $formconfirm; 533 534 // Supplier order card 535 536 $linkback = '<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php'.(!empty($socid) ? '?socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>'; 537 538 $morehtmlref = '<div class="refidno">'; 539 // Ref supplier 540 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, 0, 'string', '', 0, 1); 541 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, 0, 'string', '', null, null, '', 1); 542 // Thirdparty 543 $morehtmlref .= '<br>'.$langs->trans('ThirdParty').' : '.$object->thirdparty->getNomUrl(1); 544 // Project 545 if (!empty($conf->projet->enabled)) { 546 $langs->load("projects"); 547 $morehtmlref .= '<br>'.$langs->trans('Project').' '; 548 if ($user->rights->fournisseur->commande->creer || $user->rights->supplier_order->creer) { 549 if ($action != 'classify') { 550 //$morehtmlref.='<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : '; 551 $morehtmlref .= ' : '; 552 } 553 if ($action == 'classify') { 554 //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); 555 $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">'; 556 $morehtmlref .= '<input type="hidden" name="action" value="classin">'; 557 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">'; 558 $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); 559 $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">'; 560 $morehtmlref .= '</form>'; 561 } else { 562 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); 563 } 564 } else { 565 if (!empty($object->fk_project)) { 566 $proj = new Project($db); 567 $proj->fetch($object->fk_project); 568 $morehtmlref .= '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$object->fk_project.'" title="'.$langs->trans('ShowProject').'">'; 569 $morehtmlref .= $proj->ref; 570 $morehtmlref .= '</a>'; 571 } else { 572 $morehtmlref .= ''; 573 } 574 } 575 } 576 $morehtmlref .= '</div>'; 577 578 579 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); 580 581 582 print '<div class="fichecenter">'; 583 print '<div class="underbanner clearboth"></div>'; 584 585 print '<table class="border tableforfield" width="100%">'; 586 587 // Date 588 if ($object->methode_commande_id > 0) { 589 print '<tr><td class="titlefield">'.$langs->trans("Date").'</td><td>'; 590 if ($object->date_commande) { 591 print dol_print_date($object->date_commande, "dayhour")."\n"; 592 } 593 print "</td></tr>"; 594 595 if ($object->methode_commande) { 596 print '<tr><td>'.$langs->trans("Method").'</td><td>'.$object->getInputMethod().'</td></tr>'; 597 } 598 } 599 600 // Author 601 print '<tr><td class="titlefield">'.$langs->trans("AuthorRequest").'</td>'; 602 print '<td>'.$author->getNomUrl(1, '', 0, 0, 0).'</td>'; 603 print '</tr>'; 604 605 $parameters = array(); 606 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook 607 608 print "</table>"; 609 610 print '</div>'; 611 612 // if ($mesg) print $mesg; 613 print '<br>'; 614 615 $disabled = 1; 616 if (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) { 617 $disabled = 0; 618 } 619 620 // Line of orders 621 if ($object->statut <= CommandeFournisseur::STATUS_ACCEPTED || $object->statut >= CommandeFournisseur::STATUS_CANCELED) { 622 print '<br><span class="opacitymedium">'.$langs->trans("OrderStatusNotReadyToDispatch").'</span>'; 623 } 624 625 if ($object->statut == CommandeFournisseur::STATUS_ORDERSENT 626 || $object->statut == CommandeFournisseur::STATUS_RECEIVED_PARTIALLY 627 || $object->statut == CommandeFournisseur::STATUS_RECEIVED_COMPLETELY) { 628 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; 629 $formproduct = new FormProduct($db); 630 $formproduct->loadWarehouses(); 631 $entrepot = new Entrepot($db); 632 $listwarehouses = $entrepot->list_array(1); 633 634 635 if (empty($conf->reception->enabled)) { 636 print '<form method="POST" action="dispatch.php?id='.$object->id.'">'; 637 } else { 638 print '<form method="post" action="'.dol_buildpath('/reception/card.php', 1).'?originid='.$object->id.'&origin=supplierorder">'; 639 } 640 641 print '<input type="hidden" name="token" value="'.newToken().'">'; 642 if (empty($conf->reception->enabled)) { 643 print '<input type="hidden" name="action" value="dispatch">'; 644 } else { 645 print '<input type="hidden" name="action" value="create">'; 646 } 647 648 print '<div class="div-table-responsive-no-min">'; 649 print '<table class="noborder centpercent">'; 650 651 // Set $products_dispatched with qty dispatched for each product id 652 $products_dispatched = array(); 653 $sql = "SELECT l.rowid, cfd.fk_product, sum(cfd.qty) as qty"; 654 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd"; 655 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseurdet as l on l.rowid = cfd.fk_commandefourndet"; 656 $sql .= " WHERE cfd.fk_commande = ".$object->id; 657 $sql .= " GROUP BY l.rowid, cfd.fk_product"; 658 659 $resql = $db->query($sql); 660 if ($resql) { 661 $num = $db->num_rows($resql); 662 $i = 0; 663 664 if ($num) { 665 while ($i < $num) { 666 $objd = $db->fetch_object($resql); 667 $products_dispatched[$objd->rowid] = price2num($objd->qty, 5); 668 $i++; 669 } 670 } 671 $db->free($resql); 672 } 673 674 $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, SUM(l.qty) as qty,"; 675 $sql .= " p.ref, p.label, p.tobatch, p.fk_default_warehouse"; 676 677 // Enable hooks to alter the SQL query (SELECT) 678 $parameters = array(); 679 $reshook = $hookmanager->executeHooks( 680 'printFieldListSelect', 681 $parameters, 682 $object, 683 $action 684 ); 685 if ($reshook < 0) { 686 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 687 } 688 $sql .= $hookmanager->resPrint; 689 690 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as l"; 691 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON l.fk_product=p.rowid"; 692 $sql .= " WHERE l.fk_commande = ".$object->id; 693 if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) { 694 $sql .= " AND l.product_type = 0"; 695 } 696 697 // Enable hooks to alter the SQL query (WHERE) 698 $parameters = array(); 699 $reshook = $hookmanager->executeHooks( 700 'printFieldListWhere', 701 $parameters, 702 $object, 703 $action 704 ); 705 if ($reshook < 0) { 706 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 707 } 708 $sql .= $hookmanager->resPrint; 709 710 $sql .= " GROUP BY p.ref, p.label, p.tobatch, p.fk_default_warehouse, l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref"; // Calculation of amount dispatched is done per fk_product so we must group by fk_product 711 $sql .= " ORDER BY p.ref, p.label"; 712 713 $resql = $db->query($sql); 714 if ($resql) { 715 $num = $db->num_rows($resql); 716 $i = 0; 717 718 if ($num) { 719 print '<tr class="liste_titre">'; 720 721 print '<td>'.$langs->trans("Description").'</td>'; 722 if (!empty($conf->productbatch->enabled)) { 723 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>'; 724 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { 725 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>'; 726 } 727 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { 728 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>'; 729 } 730 } else { 731 print '<td></td>'; 732 print '<td></td>'; 733 print '<td></td>'; 734 } 735 print '<td class="right">'.$langs->trans("SupplierRef").'</td>'; 736 print '<td class="right">'.$langs->trans("QtyOrdered").'</td>'; 737 print '<td class="right">'.$langs->trans("QtyDispatchedShort").'</td>'; 738 print ' <td class="right">'.$langs->trans("QtyToDispatchShort"); 739 print '<br><a href="#" id="autoreset">'.$langs->trans("Reset").'</a></td>'; 740 print '<td width="32"></td>'; 741 742 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { 743 if (empty($conf->multicurrency->enabled) && empty($conf->dynamicprices->enabled)) { 744 print '<td class="right">'.$langs->trans("Price").'</td>'; 745 print '<td class="right">'.$langs->trans("ReductionShort").' (%)</td>'; 746 print '<td class="right">'.$langs->trans("UpdatePrice").'</td>'; 747 } 748 } 749 750 print '<td align="right">'.$langs->trans("Warehouse"); 751 752 // Select warehouse to force it everywhere 753 if (count($listwarehouses) > 1) { 754 print '<br>'.$langs->trans("ForceTo").' '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 1, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); 755 } elseif (count($listwarehouses) == 1) { 756 print '<br>'.$langs->trans("ForceTo").' '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); 757 } 758 759 print '</td>'; 760 761 // Enable hooks to append additional columns 762 $parameters = array(); 763 $reshook = $hookmanager->executeHooks( 764 'printFieldListTitle', 765 $parameters, 766 $object, 767 $action 768 ); 769 if ($reshook < 0) { 770 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 771 } 772 print $hookmanager->resPrint; 773 774 print "</tr>\n"; 775 } 776 777 $nbfreeproduct = 0; // Nb of lins of free products/services 778 $nbproduct = 0; // Nb of predefined product lines to dispatch (already done or not) if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is off (default) 779 // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on. 780 781 while ($i < $num) { 782 $objp = $db->fetch_object($resql); 783 784 // On n'affiche pas les produits libres 785 if (!$objp->fk_product > 0) { 786 $nbfreeproduct++; 787 } else { 788 $remaintodispatch = price2num($objp->qty - ((float) $products_dispatched[$objp->rowid]), 5); // Calculation of dispatched 789 if ($remaintodispatch < 0) { 790 $remaintodispatch = 0; 791 } 792 793 if ($remaintodispatch || empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) { 794 $nbproduct++; 795 796 // To show detail cref and description value, we must make calculation by cref 797 // print ($objp->cref?' ('.$objp->cref.')':''); 798 // if ($objp->description) print '<br>'.nl2br($objp->description); 799 $suffix = '_0_'.$i; 800 801 print "\n"; 802 print '<!-- Line to dispatch '.$suffix.' -->'."\n"; 803 // hidden fields for js function 804 print '<input id="qty_ordered'.$suffix.'" type="hidden" value="'.$objp->qty.'">'; 805 print '<input id="qty_dispatched'.$suffix.'" type="hidden" value="'.(float) $products_dispatched[$objp->rowid].'">'; 806 print '<tr class="oddeven">'; 807 808 $linktoprod = '<a href="'.DOL_URL_ROOT.'/product/fournisseurs.php?id='.$objp->fk_product.'">'.img_object($langs->trans("ShowProduct"), 'product').' '.$objp->ref.'</a>'; 809 $linktoprod .= ' - '.$objp->label."\n"; 810 811 if (!empty($conf->productbatch->enabled)) { 812 if ($objp->tobatch) { 813 print '<td>'; 814 print $linktoprod; 815 print "</td>"; 816 print '<td class="dispatch_batch_number"></td>'; 817 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { 818 print '<td class="dispatch_dlc"></td>'; 819 } 820 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { 821 print '<td class="dispatch_dluo"></td>'; 822 } 823 } else { 824 print '<td>'; 825 print $linktoprod; 826 print "</td>"; 827 print '<td class="dispatch_batch_number">'; 828 print $langs->trans("ProductDoesNotUseBatchSerial"); 829 print '</td>'; 830 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { 831 print '<td class="dispatch_dlc"></td>'; 832 } 833 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { 834 print '<td class="dispatch_dluo"></td>'; 835 } 836 } 837 } else { 838 print '<td colspan="4">'; 839 print $linktoprod; 840 print "</td>"; 841 } 842 843 // Define unit price for PMP calculation 844 $up_ht_disc = $objp->subprice; 845 if (!empty($objp->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) { 846 $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU'); 847 } 848 849 // Supplier ref 850 print '<td class="right">'.$objp->sref.'</td>'; 851 852 // Qty ordered 853 print '<td class="right">'.$objp->qty.'</td>'; 854 855 // Already dispatched 856 print '<td class="right">'.$products_dispatched[$objp->rowid].'</td>'; 857 858 if (!empty($conf->productbatch->enabled) && $objp->tobatch > 0) { 859 $type = 'batch'; 860 print '<td class="right">'; 861 print '</td>'; // Qty to dispatch 862 print '<td>'; 863 //print img_picto($langs->trans('AddDispatchBatchLine'), 'split.png', 'onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"'); 864 print '</td>'; // Dispatch column 865 print '<td></td>'; // Warehouse column 866 867 // Enable hooks to append additional columns 868 $parameters = array( 869 'is_information_row' => true, // allows hook to distinguish between the 870 // rows with information and the rows with 871 // dispatch form input 872 'objp' => $objp 873 ); 874 $reshook = $hookmanager->executeHooks( 875 'printFieldListValue', 876 $parameters, 877 $object, 878 $action 879 ); 880 if ($reshook < 0) { 881 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 882 } 883 print $hookmanager->resPrint; 884 885 print '</tr>'; 886 887 print '<tr class="oddeven" name="'.$type.$suffix.'">'; 888 print '<td>'; 889 print '<input name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">'; 890 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">'; 891 892 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->'; 893 if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested ! 894 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">'; 895 } else { 896 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">'; 897 } 898 899 print '</td>'; 900 901 print '<td>'; 902 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.GETPOST('lot_number'.$suffix).'">'; 903 print '</td>'; 904 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { 905 print '<td class="nowraponall">'; 906 $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOST('dlc'.$suffix.'month'), GETPOST('dlc'.$suffix.'day'), GETPOST('dlc'.$suffix.'year')); 907 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, '', '', 1, ''); 908 print '</td>'; 909 } 910 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { 911 print '<td class="nowraponall">'; 912 $dluodatesuffix = dol_mktime(0, 0, 0, GETPOST('dluo'.$suffix.'month'), GETPOST('dluo'.$suffix.'day'), GETPOST('dluo'.$suffix.'year')); 913 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, '', '', 1, ''); 914 print '</td>'; 915 } 916 print '<td colspan="3"> </td>'; // Supplier ref + Qty ordered + qty already dispatched 917 } else { 918 $type = 'dispatch'; 919 $colspan = 7; 920 $colspan = (!empty($conf->global->PRODUCT_DISABLE_SELLBY)) ? --$colspan : $colspan; 921 $colspan = (!empty($conf->global->PRODUCT_DISABLE_EATBY)) ? --$colspan : $colspan; 922 print '<td class="right">'; 923 print '</td>'; // Qty to dispatch 924 print '<td>'; 925 //print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"'); 926 print '</td>'; // Dispatch column 927 print '<td></td>'; // Warehouse column 928 929 // Enable hooks to append additional columns 930 $parameters = array( 931 'is_information_row' => true, // allows hook to distinguish between the 932 // rows with information and the rows with 933 // dispatch form input 934 'objp' => $objp 935 ); 936 $reshook = $hookmanager->executeHooks( 937 'printFieldListValue', 938 $parameters, 939 $object, 940 $action 941 ); 942 if ($reshook < 0) { 943 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 944 } 945 print $hookmanager->resPrint; 946 947 print '</tr>'; 948 949 print '<tr class="oddeven" name="'.$type.$suffix.'">'; 950 print '<td colspan="'.$colspan.'">'; 951 print '<input name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">'; 952 print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">'; 953 954 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->'; 955 if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested ! 956 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">'; 957 } else { 958 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">'; 959 } 960 961 print '</td>'; 962 } 963 964 // Qty to dispatch 965 print '<td class="right">'; 966 print '<input id="qty'.$suffix.'" name="qty'.$suffix.'" type="text" class="width50 right" value="'.(GETPOSTISSET('qty'.$suffix) ? GETPOST('qty'.$suffix, 'int') : (empty($conf->global->SUPPLIER_ORDER_DISPATCH_FORCE_QTY_INPUT_TO_ZERO) ? $remaintodispatch : 0)).'">'; 967 print '</td>'; 968 969 print '<td>'; 970 if (!empty($conf->productbatch->enabled) && $objp->tobatch > 0) { 971 $type = 'batch'; 972 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"'); 973 } else { 974 $type = 'dispatch'; 975 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"'); 976 } 977 print '</td>'; 978 979 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { 980 if (empty($conf->multicurrency->enabled) && empty($conf->dynamicprices->enabled)) { 981 // Price 982 print '<td class="right">'; 983 print '<input id="pu'.$suffix.'" name="pu'.$suffix.'" type="text" size="8" value="'.price((GETPOST('pu'.$suffix) != '' ? GETPOST('pu'.$suffix) : $up_ht_disc)).'">'; 984 print '</td>'; 985 986 // Discount 987 print '<td class="right">'; 988 print '<input id="dto'.$suffix.'" name="dto'.$suffix.'" type="text" size="8" value="'.(GETPOST('dto'.$suffix) != '' ? GETPOST('dto'.$suffix) : '').'">'; 989 print '</td>'; 990 991 // Save price 992 print '<td class="center">'; 993 print '<input class="flat checkformerge" type="checkbox" name="saveprice'.$suffix.'" value="'.(GETPOST('saveprice'.$suffix) != '' ? GETPOST('saveprice'.$suffix) : '').'">'; 994 print '</td>'; 995 } 996 } 997 998 // Warehouse 999 print '<td class="right">'; 1000 if (count($listwarehouses) > 1) { 1001 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : ($objp->fk_default_warehouse ? $objp->fk_default_warehouse : ''), "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix); 1002 } elseif (count($listwarehouses) == 1) { 1003 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : ($objp->fk_default_warehouse ? $objp->fk_default_warehouse : ''), "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix); 1004 } else { 1005 $langs->load("errors"); 1006 print $langs->trans("ErrorNoWarehouseDefined"); 1007 } 1008 print "</td>\n"; 1009 1010 // Enable hooks to append additional columns 1011 $parameters = array( 1012 'is_information_row' => false // this is a dispatch form row 1013 ); 1014 $reshook = $hookmanager->executeHooks( 1015 'printFieldListValue', 1016 $parameters, 1017 $object, 1018 $action 1019 ); 1020 if ($reshook < 0) { 1021 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 1022 } 1023 print $hookmanager->resPrint; 1024 1025 print "</tr>\n"; 1026 } 1027 } 1028 $i++; 1029 } 1030 $db->free($resql); 1031 } else { 1032 dol_print_error($db); 1033 } 1034 1035 print "</table>\n"; 1036 print '</div>'; 1037 1038 if ($nbproduct) { 1039 $checkboxlabel = $langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv('StatusOrderReceivedAll')); 1040 1041 print '<div class="center">'; 1042 $parameters = array(); 1043 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been 1044 // modified by hook 1045 if (empty($reshook)) { 1046 if (empty($conf->reception->enabled)) { 1047 print $langs->trans("Comment").' : '; 1048 print '<input type="text" class="minwidth400" maxlength="128" name="comment" value="'; 1049 print GETPOSTISSET("comment") ? GETPOST("comment") : $langs->trans("DispatchSupplierOrder", $object->ref); 1050 // print ' / '.$object->ref_supplier; // Not yet available 1051 print '" class="flat"><br>'; 1052 1053 print '<input type="checkbox" checked="checked" name="closeopenorder"> '.$checkboxlabel; 1054 } 1055 1056 $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception"); 1057 1058 print '<br><input type="submit" class="button" name="dispatch" value="'.dol_escape_htmltag($dispatchBt).'"'; 1059 if (count($listwarehouses) <= 0) { 1060 print ' disabled'; 1061 } 1062 print '>'; 1063 } 1064 print '</div>'; 1065 } 1066 1067 // Message if nothing to dispatch 1068 if (!$nbproduct) { 1069 print "<br>\n"; 1070 if (empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) { 1071 print '<div class="opacitymedium">'.$langs->trans("NoPredefinedProductToDispatch").'</div>'; // No predefined line at all 1072 } else { 1073 print '<div class="opacitymedium">'.$langs->trans("NoMorePredefinedProductToDispatch").'</div>'; // No predefined line that remain to be dispatched. 1074 } 1075 } 1076 1077 print '</form>'; 1078 } 1079 1080 print dol_get_fiche_end(); 1081 1082 // traitement entrepot par défaut 1083 print '<script type="text/javascript"> 1084 $(document).ready(function () { 1085 $("select[name=fk_default_warehouse]").change(function() { 1086 var fk_default_warehouse = $("option:selected", this).val(); 1087 $("select[name^=entrepot_]").val(fk_default_warehouse).change(); 1088 }); 1089 1090 jQuery("#autoreset").click(function() {'; 1091 $i = 0; 1092 while ($i < $nbproduct) { 1093 print ' jQuery("#qty_0_'.$i.'").val("");'; 1094 $i++; 1095 } 1096 print ' 1097 }); 1098 }); 1099 </script>'; 1100 1101 // List of lines already dispatched 1102 $sql = "SELECT p.rowid as pid, p.ref, p.label,"; 1103 $sql .= " e.rowid as warehouse_id, e.ref as entrepot,"; 1104 $sql .= " cfd.rowid as dispatchlineid, cfd.fk_product, cfd.qty, cfd.eatby, cfd.sellby, cfd.batch, cfd.comment, cfd.status, cfd.datec"; 1105 $sql .= " ,cd.rowid, cd.subprice"; 1106 if ($conf->reception->enabled) { 1107 $sql .= " ,cfd.fk_reception, r.date_delivery"; 1108 } 1109 $sql .= " FROM ".MAIN_DB_PREFIX."product as p,"; 1110 $sql .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd"; 1111 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseurdet as cd ON cd.rowid = cfd.fk_commandefourndet"; 1112 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e ON cfd.fk_entrepot = e.rowid"; 1113 if ($conf->reception->enabled) { 1114 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."reception as r ON cfd.fk_reception = r.rowid"; 1115 } 1116 $sql .= " WHERE cfd.fk_commande = ".$object->id; 1117 $sql .= " AND cfd.fk_product = p.rowid"; 1118 $sql .= " ORDER BY cfd.rowid ASC"; 1119 1120 $resql = $db->query($sql); 1121 if ($resql) { 1122 $num = $db->num_rows($resql); 1123 $i = 0; 1124 1125 if ($num > 0) { 1126 print "<br>\n"; 1127 1128 print load_fiche_titre($langs->trans("ReceivingForSameOrder")); 1129 1130 print '<div class="div-table-responsive">'; 1131 print '<table id="dispatch_received_products" class="noborder centpercent">'; 1132 1133 print '<tr class="liste_titre">'; 1134 if ($conf->reception->enabled) { 1135 print '<td>'.$langs->trans("Reception").'</td>'; 1136 } 1137 1138 print '<td>'.$langs->trans("Product").'</td>'; 1139 print '<td>'.$langs->trans("DateCreation").'</td>'; 1140 print '<td>'.$langs->trans("DateDeliveryPlanned").'</td>'; 1141 if (!empty($conf->productbatch->enabled)) { 1142 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>'; 1143 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { 1144 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>'; 1145 } 1146 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { 1147 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>'; 1148 } 1149 } 1150 print '<td class="right">'.$langs->trans("QtyDispatched").'</td>'; 1151 print '<td>'.$langs->trans("Warehouse").'</td>'; 1152 print '<td>'.$langs->trans("Comment").'</td>'; 1153 1154 // Status 1155 if (!empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS) && empty($reception->rowid)) { 1156 print '<td class="center" colspan="2">'.$langs->trans("Status").'</td>'; 1157 } elseif (!empty($conf->reception->enabled)) { 1158 print '<td class="center"></td>'; 1159 } 1160 1161 print '<td class="center" colspan="2"></td>'; 1162 1163 print "</tr>\n"; 1164 1165 while ($i < $num) { 1166 $objp = $db->fetch_object($resql); 1167 1168 if ($action == 'editline' && $lineid == $objp->dispatchlineid) { 1169 print '<form name="editdispatchedlines" id="editdispatchedlines" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'#line_'.GETPOST('lineid', 'int').'" method="POST"> 1170 <input type="hidden" name="token" value="'.newToken().'"> 1171 <input type="hidden" name="action" value="updateline"> 1172 <input type="hidden" name="mode" value=""> 1173 <input type="hidden" name="lineid" value="'.$objp->dispatchlineid.'">'; 1174 } 1175 1176 print '<tr class="oddeven" id="line_'.$objp->dispatchlineid.'" >'; 1177 1178 if (!empty($conf->reception->enabled)) { 1179 print '<td>'; 1180 if (!empty($objp->fk_reception)) { 1181 $reception = new Reception($db); 1182 $reception->fetch($objp->fk_reception); 1183 print $reception->getNomUrl(1); 1184 } 1185 1186 print "</td>"; 1187 } 1188 1189 print '<td>'; 1190 print '<a href="'.DOL_URL_ROOT.'/product/fournisseurs.php?id='.$objp->fk_product.'">'.img_object($langs->trans("ShowProduct"), 'product').' '.$objp->ref.'</a>'; 1191 print ' - '.$objp->label; 1192 print "</td>\n"; 1193 print '<td>'.dol_print_date($db->jdate($objp->datec), 'day').'</td>'; 1194 print '<td>'.dol_print_date($db->jdate($objp->date_delivery), 'day').'</td>'; 1195 1196 if (!empty($conf->productbatch->enabled)) { 1197 if ($objp->batch) { 1198 include_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; 1199 $lot = new Productlot($db); 1200 $lot->fetch(0, $objp->pid, $objp->batch); 1201 print '<td class="dispatch_batch_number">'.$lot->getNomUrl(1).'</td>'; 1202 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { 1203 print '<td class="dispatch_dlc">'.dol_print_date($lot->sellby, 'day').'</td>'; 1204 } 1205 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { 1206 print '<td class="dispatch_dluo">'.dol_print_date($lot->eatby, 'day').'</td>'; 1207 } 1208 } else { 1209 print '<td class="dispatch_batch_number"></td>'; 1210 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { 1211 print '<td class="dispatch_dlc"></td>'; 1212 } 1213 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { 1214 print '<td class="dispatch_dluo"></td>'; 1215 } 1216 } 1217 } 1218 1219 // Qty 1220 print '<td class="right">'; 1221 if ($action == 'editline' && $lineid == $objp->dispatchlineid) { 1222 print '<input style="width: 50px;" type="number" min="1" name="qty" value="'.$objp->qty.'" />'; 1223 } else { 1224 print $objp->qty; 1225 } 1226 print '<input type="hidden" name="price" value="'.$objp->subprice.'" />'; 1227 print '</td>'; 1228 1229 // Warehouse 1230 print '<td>'; 1231 if ($action == 'editline' && $lineid == $objp->dispatchlineid) { 1232 if (count($listwarehouses) > 1) { 1233 print $formproduct->selectWarehouses(GETPOST("fk_entrepot") ?GETPOST("fk_entrepot") : ($objp->warehouse_id ? $objp->warehouse_id : ''), "fk_entrepot", '', 1, 0, $objp->fk_product, '', 1, 1, null, 'csswarehouse'); 1234 } elseif (count($listwarehouses) == 1) { 1235 print $formproduct->selectWarehouses(GETPOST("fk_entrepot") ?GETPOST("fk_entrepot") : ($objp->warehouse_id ? $objp->warehouse_id : ''), "fk_entrepot", '', 0, 0, $objp->fk_product, '', 1, 1, null, 'csswarehouse'); 1236 } else { 1237 $langs->load("errors"); 1238 print $langs->trans("ErrorNoWarehouseDefined"); 1239 } 1240 } else { 1241 $warehouse_static->id = $objp->warehouse_id; 1242 $warehouse_static->label = $objp->entrepot; 1243 print $warehouse_static->getNomUrl(1); 1244 } 1245 print '</td>'; 1246 1247 // Comment 1248 print '<td class="tdoverflowmax300" style="white-space: pre;">'.$objp->comment.'</td>'; 1249 1250 // Status 1251 if (!empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS) && empty($reception->rowid)) { 1252 print '<td class="right">'; 1253 $supplierorderdispatch->status = (empty($objp->status) ? 0 : $objp->status); 1254 // print $supplierorderdispatch->status; 1255 print $supplierorderdispatch->getLibStatut(5); 1256 print '</td>'; 1257 1258 // Add button to check/uncheck disaptching 1259 print '<td class="center">'; 1260 if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande->receptionner)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->fournisseur->commande_advance->check))) { 1261 if (empty($objp->status)) { 1262 print '<a class="button buttonRefused" href="#">'.$langs->trans("Approve").'</a>'; 1263 print '<a class="button buttonRefused" href="#">'.$langs->trans("Deny").'</a>'; 1264 } else { 1265 print '<a class="button buttonRefused" href="#">'.$langs->trans("Disapprove").'</a>'; 1266 print '<a class="button buttonRefused" href="#">'.$langs->trans("Deny").'</a>'; 1267 } 1268 } else { 1269 $disabled = ''; 1270 if ($object->statut == 5) { 1271 $disabled = 1; 1272 } 1273 if (empty($objp->status)) { 1274 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=checkdispatchline&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Approve").'</a>'; 1275 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=denydispatchline&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Deny").'</a>'; 1276 } 1277 if ($objp->status == 1) { 1278 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=uncheckdispatchline&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Reinit").'</a>'; 1279 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=denydispatchline&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Deny").'</a>'; 1280 } 1281 if ($objp->status == 2) { 1282 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=uncheckdispatchline&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Reinit").'</a>'; 1283 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=checkdispatchline&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Approve").'</a>'; 1284 } 1285 } 1286 print '</td>'; 1287 } elseif (!empty($conf->reception->enabled)) { 1288 print '<td class="right">'; 1289 if (!empty($reception->id)) { 1290 print $reception->getLibStatut(5); 1291 } 1292 print '</td>'; 1293 } 1294 if ($action != 'editline' || $lineid != $objp->dispatchlineid) { 1295 if (empty($reception->id) || ($reception->statut == Reception::STATUS_DRAFT)) { // only allow edit on draft reception 1296 print '<td class="linecoledit center">'; 1297 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&lineid='.$objp->dispatchlineid.'#line_'.$objp->dispatchlineid.'">'; 1298 print img_edit(); 1299 print '</a>'; 1300 print '</td>'; 1301 1302 print '<td class="linecoldelete center">'; 1303 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=ask_deleteline&lineid='.$objp->dispatchlineid.'#dispatch_received_products">'; 1304 print img_delete(); 1305 print '</a>'; 1306 print '</td>'; 1307 } else { 1308 print '<td></td><td></td>'; 1309 } 1310 } else { 1311 print '<td class="center valignmiddle">'; 1312 print '<input type="submit" class="button button-save" id="savelinebutton" name="save" value="'.$langs->trans("Save").'" />'; 1313 print '</td>'; 1314 print '<td class="center valignmiddle">'; 1315 print '<input type="submit" class="button button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'" />'; 1316 print '</td>'; 1317 } 1318 1319 1320 print "</tr>\n"; 1321 if ($action == 'editline' && $lineid == $objp->dispatchlineid) { 1322 print '</form>'; 1323 } 1324 1325 $i++; 1326 } 1327 $db->free($resql); 1328 1329 print "</table>\n"; 1330 print '</div>'; 1331 } 1332 } else { 1333 dol_print_error($db); 1334 } 1335} 1336 1337// End of page 1338llxFooter(); 1339$db->close(); 1340