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