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&amp;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">&nbsp;</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.'&amp;action=editline&amp;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.'&amp;action=ask_deleteline&amp;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