dolibarr  7.0.0-beta
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@capnetworks.com>
6  * Copyright (C) 2010 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 Ferran Marcet <fmarcet@2byte.es>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/>.
23  * or see http://www.gnu.org/
24  */
25 
32 require '../../main.inc.php';
33 require_once DOL_DOCUMENT_ROOT . '/core/modules/supplier_order/modules_commandefournisseur.php';
34 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
35 require_once DOL_DOCUMENT_ROOT . '/core/lib/fourn.lib.php';
36 require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.commande.class.php';
37 require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.commande.dispatch.class.php';
38 require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
39 if (! empty($conf->projet->enabled))
40  require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
41 
42 $langs->load('orders');
43 $langs->load('sendings');
44 $langs->load('companies');
45 $langs->load('bills');
46 $langs->load('deliveries');
47 $langs->load('products');
48 $langs->load('stocks');
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 if ($user->societe_id)
58  $socid = $user->societe_id;
59 $result = restrictedArea($user, 'fournisseur', $id, '', 'commande');
60 
61 if (empty($conf->stock->enabled)) {
63 }
64 
65 // Recuperation de l'id de projet
66 $projectid = 0;
67 if ($_GET["projectid"])
68  $projectid = GETPOST("projectid", 'int');
69 
70 $object = new CommandeFournisseur($db);
71 
72 if ($id > 0 || ! empty($ref)) {
73  $result = $object->fetch($id, $ref);
74  if ($result < 0) {
75  setEventMessages($object->error, $object->errors, 'errors');
76  }
77  $result = $object->fetch_thirdparty();
78  if ($result < 0) {
79  setEventMessages($object->error, $object->errors, 'errors');
80  }
81 }
82 
83 
84 /*
85  * Actions
86  */
87 
88 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))))
89 {
90  $error=0;
91  $supplierorderdispatch = new CommandeFournisseurDispatch($db);
92 
93  $db->begin();
94 
95  $result = $supplierorderdispatch->fetch($lineid);
96  if (! $result)
97  {
98  $error++;
99  setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
100  $action = '';
101  }
102 
103  if (! $error)
104  {
105  $result = $supplierorderdispatch->setStatut(1);
106  if ($result < 0) {
107  setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
108  $error++;
109  $action = '';
110  }
111  }
112 
113  if (! $error)
114  {
115  $result = $object->calcAndSetStatusDispatch($user);
116  if ($result < 0) {
117  setEventMessages($object->error, $object->errors, 'errors');
118  $error ++;
119  $action = '';
120  }
121  }
122  if (! $error)
123  {
124  $db->commit();
125  }
126  else
127  {
128  $db->rollback();
129  }
130 }
131 
132 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))))
133 {
134  $error=0;
135  $supplierorderdispatch = new CommandeFournisseurDispatch($db);
136 
137  $db->begin();
138 
139  $result = $supplierorderdispatch->fetch($lineid);
140  if (! $result)
141  {
142  $error++;
143  setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
144  $action = '';
145  }
146 
147  if (! $error)
148  {
149  $result = $supplierorderdispatch->setStatut(0);
150  if ($result < 0) {
151  setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
152  $error ++;
153  $action = '';
154  }
155  }
156  if (! $error)
157  {
158  $result = $object->calcAndSetStatusDispatch($user);
159  if ($result < 0) {
160  setEventMessages($object->error, $object->errors, 'errors');
161  $error ++;
162  $action = '';
163  }
164  }
165  if (! $error)
166  {
167  $db->commit();
168  }
169  else
170  {
171  $db->rollback();
172  }
173 }
174 
175 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))))
176 {
177  $error=0;
178  $supplierorderdispatch = new CommandeFournisseurDispatch($db);
179 
180  $db->begin();
181 
182  $result = $supplierorderdispatch->fetch($lineid);
183  if (! $result)
184  {
185  $error++;
186  setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
187  $action = '';
188  }
189 
190  if (! $error)
191  {
192  $result = $supplierorderdispatch->setStatut(2);
193  if ($result < 0) {
194  setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
195  $error ++;
196  $action = '';
197  }
198  }
199  if (! $error)
200  {
201  $result = $object->calcAndSetStatusDispatch($user);
202  if ($result < 0) {
203  setEventMessages($object->error, $object->errors, 'errors');
204  $error ++;
205  $action = '';
206  }
207  }
208  if (! $error)
209  {
210  $db->commit();
211  }
212  else
213  {
214  $db->rollback();
215  }
216 }
217 
218 if ($action == 'dispatch' && $user->rights->fournisseur->commande->receptionner) {
219  $error = 0;
220 
221  $db->begin();
222 
223  $pos = 0;
224  foreach ($_POST as $key => $value)
225  {
226  // without batch module enabled
227  if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg))
228  {
229  $pos ++;
230 
231  // $numline=$reg[2] + 1; // line of product
232  $numline = $pos;
233  $prod = "product_" . $reg[1] . '_' . $reg[2];
234  $qty = "qty_" . $reg[1] . '_' . $reg[2];
235  $ent = "entrepot_" . $reg[1] . '_' . $reg[2];
236  $pu = "pu_" . $reg[1] . '_' . $reg[2]; // This is unit price including discount
237  $fk_commandefourndet = "fk_commandefourndet_" . $reg[1] . '_' . $reg[2];
238 
239  // We ask to move a qty
240  if (GETPOST($qty) > 0) {
241  if (! (GETPOST($ent, 'int') > 0)) {
242  dol_syslog('No dispatch for line ' . $key . ' as no warehouse choosed');
243  $text = $langs->transnoentities('Warehouse') . ', ' . $langs->transnoentities('Line') . ' ' . ($numline);
244  setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
245  $error ++;
246  }
247 
248  if (! $error) {
249  $result = $object->dispatchProduct($user, GETPOST($prod, 'int'), GETPOST($qty), GETPOST($ent, 'int'), GETPOST($pu), GETPOST('comment'), '', '', '', GETPOST($fk_commandefourndet, 'int'), $notrigger);
250  if ($result < 0) {
251  setEventMessages($object->error, $object->errors, 'errors');
252  $error ++;
253  }
254  }
255  }
256  }
257  // with batch module enabled
258  if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg))
259  {
260  $pos ++;
261 
262  // eat-by date dispatch
263  // $numline=$reg[2] + 1; // line of product
264  $numline = $pos;
265  $prod = 'product_batch_' . $reg[1] . '_' . $reg[2];
266  $qty = 'qty_' . $reg[1] . '_' . $reg[2];
267  $ent = 'entrepot_' . $reg[1] . '_' . $reg[2];
268  $pu = 'pu_' . $reg[1] . '_' . $reg[2];
269  $fk_commandefourndet = 'fk_commandefourndet_' . $reg[1] . '_' . $reg[2];
270  $lot = 'lot_number_' . $reg[1] . '_' . $reg[2];
271  $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']);
272  $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']);
273 
274  $fk_commandefourndet = 'fk_commandefourndet_' . $reg[1] . '_' . $reg[2];
275 
276  // We ask to move a qty
277  if (GETPOST($qty) > 0) {
278  if (! (GETPOST($ent, 'int') > 0)) {
279  dol_syslog('No dispatch for line ' . $key . ' as no warehouse choosed');
280  $text = $langs->transnoentities('Warehouse') . ', ' . $langs->transnoentities('Line') . ' ' . ($numline) . '-' . ($reg[1] + 1);
281  setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
282  $error ++;
283  }
284 
285  if (! (GETPOST($lot, 'alpha') || $dDLUO || $dDLC)) {
286  dol_syslog('No dispatch for line ' . $key . ' as serial/eat-by/sellby date are not set');
287  $text = $langs->transnoentities('atleast1batchfield') . ', ' . $langs->transnoentities('Line') . ' ' . ($numline) . '-' . ($reg[1] + 1);
288  setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
289  $error ++;
290  }
291 
292  if (! $error) {
293  $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);
294  if ($result < 0) {
295  setEventMessages($object->error, $object->errors, 'errors');
296  $error ++;
297  }
298  }
299  }
300  }
301  }
302 
303  if (! $error) {
304  $result = $object->calcAndSetStatusDispatch($user, GETPOST('closeopenorder')?1:0, GETPOST('comment'));
305  if ($result < 0) {
306  setEventMessages($object->error, $object->errors, 'errors');
307  $error ++;
308  }
309  }
310 
311  if (! $notrigger && ! $error) {
312  global $conf, $langs, $user;
313  // Call trigger
314 
315  $result = $object->call_trigger('ORDER_SUPPLIER_DISPATCH', $user);
316  // End call triggers
317 
318  if ($result < 0) {
319  setEventMessages($object->error, $object->errors, 'errors');
320  $error ++;
321  }
322  }
323 
324  if ($result >= 0 && ! $error) {
325  $db->commit();
326 
327  header("Location: dispatch.php?id=" . $id);
328  exit();
329  } else {
330  $db->rollback();
331  }
332 }
333 
334 
335 /*
336  * View
337  */
338 
339 $now = dol_now();
340 
341 $form = new Form($db);
342 $formproduct = new FormProduct($db);
343 $warehouse_static = new Entrepot($db);
344 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
345 
346 $help_url='EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores';
347 llxHeader('', $langs->trans("Order"), $help_url, '', 0, 0, array('/fourn/js/lib_dispatch.js'));
348 
349 if ($id > 0 || ! empty($ref)) {
350  $soc = new Societe($db);
351  $soc->fetch($object->socid);
352 
353  $author = new User($db);
354  $author->fetch($object->user_author_id);
355 
356  $head = ordersupplier_prepare_head($object);
357 
358  $title = $langs->trans("SupplierOrder");
359  dol_fiche_head($head, 'dispatch', $title, -1, 'order');
360 
361 
362  // Supplier order card
363 
364  $linkback = '<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php'.(! empty($socid)?'?socid='.$socid:'').'">'.$langs->trans("BackToList").'</a>';
365 
366  $morehtmlref='<div class="refidno">';
367  // Ref supplier
368  $morehtmlref.=$form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, 0, 'string', '', 0, 1);
369  $morehtmlref.=$form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, 0, 'string', '', null, null, '', 1);
370  // Thirdparty
371  $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
372  // Project
373  if (! empty($conf->projet->enabled))
374  {
375  $langs->load("projects");
376  $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
377  if ($user->rights->fournisseur->commande->creer)
378  {
379  if ($action != 'classify')
380  //$morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
381  $morehtmlref.=' : ';
382  if ($action == 'classify') {
383  //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
384  $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
385  $morehtmlref.='<input type="hidden" name="action" value="classin">';
386  $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
387  $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
388  $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
389  $morehtmlref.='</form>';
390  } else {
391  $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
392  }
393  } else {
394  if (! empty($object->fk_project)) {
395  $proj = new Project($db);
396  $proj->fetch($object->fk_project);
397  $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
398  $morehtmlref.=$proj->ref;
399  $morehtmlref.='</a>';
400  } else {
401  $morehtmlref.='';
402  }
403  }
404  }
405  $morehtmlref.='</div>';
406 
407 
408  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
409 
410 
411  print '<div class="fichecenter">';
412  print '<div class="underbanner clearboth"></div>';
413 
414  print '<table class="border" width="100%">';
415 
416  // Date
417  if ($object->methode_commande_id > 0) {
418  print '<tr><td class="titlefield">' . $langs->trans("Date") . '</td><td>';
419  if ($object->date_commande) {
420  print dol_print_date($object->date_commande, "dayhourtext") . "\n";
421  }
422  print "</td></tr>";
423 
424  if ($object->methode_commande) {
425  print '<tr><td>' . $langs->trans("Method") . '</td><td>' . $object->getInputMethod() . '</td></tr>';
426  }
427  }
428 
429  // Author
430  print '<tr><td class="titlefield">' . $langs->trans("AuthorRequest") . '</td>';
431  print '<td>' . $author->getNomUrl(1, '', 0, 0, 0) . '</td>';
432  print '</tr>';
433 
434  print "</table>";
435 
436  print '</div>';
437 
438  // if ($mesg) print $mesg;
439  print '<br>';
440 
441  $disabled = 1;
442  if (! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER))
443  $disabled = 0;
444 
445  // Line of orders
446  if ($object->statut <= CommandeFournisseur::STATUS_ACCEPTED || $object->statut >= CommandeFournisseur::STATUS_CANCELED) {
447  print '<span class="opacitymedium">'.$langs->trans("OrderStatusNotReadyToDispatch").'</span>';
448  }
449 
450  if ($object->statut == CommandeFournisseur::STATUS_ORDERSENT
452  || $object->statut == CommandeFournisseur::STATUS_RECEIVED_COMPLETELY) {
453  $entrepot = new Entrepot($db);
454  $listwarehouses = $entrepot->list_array(1);
455 
456  print '<form method="POST" action="dispatch.php?id=' . $object->id . '">';
457  print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
458  print '<input type="hidden" name="action" value="dispatch">';
459 
460  print '<div class="div-table-responsive">';
461  print '<table class="noborder" width="100%">';
462 
463  // Set $products_dispatched with qty dispatched for each product id
464  $products_dispatched = array();
465  $sql = "SELECT l.rowid, cfd.fk_product, sum(cfd.qty) as qty";
466  $sql .= " FROM " . MAIN_DB_PREFIX . "commande_fournisseur_dispatch as cfd";
467  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "commande_fournisseurdet as l on l.rowid = cfd.fk_commandefourndet";
468  $sql .= " WHERE cfd.fk_commande = " . $object->id;
469  $sql .= " GROUP BY l.rowid, cfd.fk_product";
470 
471  $resql = $db->query($sql);
472  if ($resql) {
473  $num = $db->num_rows($resql);
474  $i = 0;
475 
476  if ($num) {
477  while ( $i < $num ) {
478  $objd = $db->fetch_object($resql);
479  $products_dispatched[$objd->rowid] = price2num($objd->qty, 5);
480  $i++;
481  }
482  }
483  $db->free($resql);
484  }
485 
486  $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, SUM(l.qty) as qty,";
487  $sql .= " p.ref, p.label, p.tobatch";
488  $sql .= " FROM " . MAIN_DB_PREFIX . "commande_fournisseurdet as l";
489  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON l.fk_product=p.rowid";
490  $sql .= " WHERE l.fk_commande = " . $object->id;
491  if (empty($conf->global->STOCK_SUPPORTS_SERVICES))
492  $sql .= " AND l.product_type = 0";
493  $sql .= " GROUP BY p.ref, p.label, p.tobatch, l.rowid, l.fk_product, l.subprice, l.remise_percent"; // Calculation of amount dispatched is done per fk_product so we must group by fk_product
494  $sql .= " ORDER BY p.ref, p.label";
495 
496  $resql = $db->query($sql);
497  if ($resql) {
498  $num = $db->num_rows($resql);
499  $i = 0;
500 
501  if ($num) {
502  print '<tr class="liste_titre">';
503 
504  print '<td>' . $langs->trans("Description") . '</td>';
505  print '<td></td>';
506  print '<td></td>';
507  print '<td></td>';
508  print '<td align="right">' . $langs->trans("QtyOrdered") . '</td>';
509  print '<td align="right">' . $langs->trans("QtyDispatchedShort") . '</td>';
510  print '<td align="right">' . $langs->trans("QtyToDispatchShort") . '</td>';
511  print '<td width="32"></td>';
512  print '<td align="right">' . $langs->trans("Warehouse") . '</td>';
513  print "</tr>\n";
514 
515  if (! empty($conf->productbatch->enabled)) {
516  print '<tr class="liste_titre">';
517  print '<td></td>';
518  print '<td>' . $langs->trans("batch_number") . '</td>';
519  print '<td>' . $langs->trans("EatByDate") . '</td>';
520  print '<td>' . $langs->trans("SellByDate") . '</td>';
521  print '<td colspan="5">&nbsp;</td>';
522  print "</tr>\n";
523  }
524  }
525 
526  $nbfreeproduct = 0; // Nb of lins of free products/services
527  $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)
528  // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on.
529 
530  $var = false;
531  while ( $i < $num ) {
532  $objp = $db->fetch_object($resql);
533 
534  // On n'affiche pas les produits libres
535  if (! $objp->fk_product > 0) {
536  $nbfreeproduct++;
537  } else {
538  $remaintodispatch = price2num($objp->qty - (( float ) $products_dispatched[$objp->rowid]), 5); // Calculation of dispatched
539  if ($remaintodispatch < 0)
540  $remaintodispatch = 0;
541 
542  if ($remaintodispatch || empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) {
543  $nbproduct++;
544 
545  // To show detail cref and description value, we must make calculation by cref
546  // print ($objp->cref?' ('.$objp->cref.')':'');
547  // if ($objp->description) print '<br>'.nl2br($objp->description);
548  $suffix = '_0_' . $i;
549 
550  print "\n";
551  print '<!-- Line to dispatch ' . $suffix . ' -->' . "\n";
552  // hidden fields for js function
553  print '<input id="qty_ordered' . $suffix . '" type="hidden" value="' . $objp->qty . '">';
554  print '<input id="qty_dispatched' . $suffix . '" type="hidden" value="' . ( float ) $products_dispatched[$objp->rowid] . '">';
555  print '<tr class="oddeven">';
556 
557  $linktoprod = '<a href="' . DOL_URL_ROOT . '/product/fournisseurs.php?id=' . $objp->fk_product . '">' . img_object($langs->trans("ShowProduct"), 'product') . ' ' . $objp->ref . '</a>';
558  $linktoprod .= ' - ' . $objp->label . "\n";
559 
560  if (! empty($conf->productbatch->enabled)) {
561  if ($objp->tobatch) {
562  print '<td colspan="4">';
563  print $linktoprod;
564  print "</td>";
565  } else {
566  print '<td>';
567  print $linktoprod;
568  print "</td>";
569  print '<td colspan="3">';
570  print $langs->trans("ProductDoesNotUseBatchSerial");
571  print '</td>';
572  }
573  } else {
574  print '<td colspan="4">';
575  print $linktoprod;
576  print "</td>";
577  }
578 
579  // Define unit price for PMP calculation
580  $up_ht_disc = $objp->subprice;
581  if (! empty($objp->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP))
582  $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU');
583 
584  // Qty ordered
585  print '<td align="right">' . $objp->qty . '</td>';
586 
587  // Already dispatched
588  print '<td align="right">' . $products_dispatched[$objp->rowid] . '</td>';
589 
590  if (! empty($conf->productbatch->enabled) && $objp->tobatch == 1) {
591  $type = 'batch';
592  print '<td align="right">';
593  print '</td>'; // Qty to dispatch
594  print '<td>';
595  //print img_picto($langs->trans('AddDispatchBatchLine'), 'split.png', 'onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"');
596  print '</td>'; // Dispatch column
597  print '<td></td>'; // Warehouse column
598  print '</tr>';
599 
600  print '<tr class="oddeven" name="' . $type . $suffix . '">';
601  print '<td>';
602  print '<input name="fk_commandefourndet' . $suffix . '" type="hidden" value="' . $objp->rowid . '">';
603  print '<input name="product_batch' . $suffix . '" type="hidden" value="' . $objp->fk_product . '">';
604 
605  print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
606  if (! empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) // Not tested !
607  {
608  print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu' . $suffix . '" type="text" value="' . price2num($up_ht_disc, 'MU') . '">';
609  }
610  else
611  {
612  print '<input class="maxwidth75" name="pu' . $suffix . '" type="hidden" value="' . price2num($up_ht_disc, 'MU') . '">';
613  }
614 
615  print '</td>';
616 
617  print '<td>';
618  print '<input type="text" class="inputlotnumber" id="lot_number' . $suffix . '" name="lot_number' . $suffix . '" size="40" value="' . GETPOST('lot_number' . $suffix) . '">';
619  print '</td>';
620  print '<td>';
621  $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOST('dlc' . $suffix . 'month'), GETPOST('dlc' . $suffix . 'day'), GETPOST('dlc' . $suffix . 'year'));
622  $form->select_date($dlcdatesuffix, 'dlc' . $suffix, '', '', 1, "");
623  print '</td>';
624  print '<td>';
625  $dluodatesuffix = dol_mktime(0, 0, 0, GETPOST('dluo' . $suffix . 'month'), GETPOST('dluo' . $suffix . 'day'), GETPOST('dluo' . $suffix . 'year'));
626  $form->select_date($dluodatesuffix, 'dluo' . $suffix, '', '', 1, "");
627  print '</td>';
628  print '<td colspan="2">&nbsp</td>'; // Qty ordered + qty already dispatached
629  } else {
630  $type = 'dispatch';
631  print '<td align="right">';
632  print '</td>'; // Qty to dispatch
633  print '<td>';
634  //print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"');
635  print '</td>'; // Dispatch column
636  print '<td></td>'; // Warehouse column
637  print '</tr>';
638 
639  print '<tr class="oddeven" name="' . $type . $suffix . '">';
640  print '<td colspan="6">';
641  print '<input name="fk_commandefourndet' . $suffix . '" type="hidden" value="' . $objp->rowid . '">';
642  print '<input name="product' . $suffix . '" type="hidden" value="' . $objp->fk_product . '">';
643 
644  print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
645  if (! empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) // Not tested !
646  {
647  print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu' . $suffix . '" type="text" value="' . price2num($up_ht_disc, 'MU') . '">';
648  }
649  else
650  {
651  print '<input class="maxwidth75" name="pu' . $suffix . '" type="hidden" value="' . price2num($up_ht_disc, 'MU') . '">';
652  }
653 
654  print '</td>';
655  }
656 
657  // Qty to dispatch
658  print '<td align="right">';
659  print '<input id="qty' . $suffix . '" name="qty' . $suffix . '" type="text" size="8" value="' . (GETPOST('qty' . $suffix) != '' ? GETPOST('qty' . $suffix) : $remaintodispatch) . '">';
660  print '</td>';
661 
662  print '<td>';
663  if (! empty($conf->productbatch->enabled) && $objp->tobatch == 1) {
664  $type = 'batch';
665  //print img_picto($langs->trans('AddDispatchBatchLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"');
666  print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"');
667  }
668  else
669  {
670  $type = 'dispatch';
671  print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"');
672  }
673 
674  print '</td>';
675 
676  // Warehouse
677  print '<td align="right">';
678  if (count($listwarehouses) > 1) {
679  print $formproduct->selectWarehouses(GETPOST("entrepot" . $suffix), "entrepot" . $suffix, '', 1, 0, $objp->fk_product, '', 1);
680  } elseif (count($listwarehouses) == 1) {
681  print $formproduct->selectWarehouses(GETPOST("entrepot" . $suffix), "entrepot" . $suffix, '', 0, 0, $objp->fk_product, '', 1);
682  } else {
683  $langs->load("errors");
684  print $langs->trans("ErrorNoWarehouseDefined");
685  }
686  print "</td>\n";
687 
688  print "</tr>\n";
689  }
690  }
691  $i++;
692  }
693  $db->free($resql);
694  } else {
695  dol_print_error($db);
696  }
697 
698  print "</table>\n";
699  print '</div>';
700  print "<br>\n";
701 
702  if ($nbproduct)
703  {
704  $checkboxlabel=$langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv($object->statuts[5]));
705 
706  print '<br><div class="center">';
707  print $langs->trans("Comment") . ' : ';
708  print '<input type="text" class="minwidth400" maxlength="128" name="comment" value="';
709  print $_POST["comment"] ? GETPOST("comment") : $langs->trans("DispatchSupplierOrder", $object->ref);
710  // print ' / '.$object->ref_supplier; // Not yet available
711  print '" class="flat"><br>';
712 
713  print '<input type="checkbox" checked="checked" name="closeopenorder"> '.$checkboxlabel;
714 
715  print '<br><input type="submit" class="button" value="' . $langs->trans("DispatchVerb") . '"';
716  if (count($listwarehouses) <= 0)
717  print ' disabled';
718  print '>';
719  print '</div>';
720  }
721 
722  // Message if nothing to dispatch
723  if (! $nbproduct) {
724  if (empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED))
725  print '<div class="opacitymedium">'.$langs->trans("NoPredefinedProductToDispatch").'</div>'; // No predefined line at all
726  else
727  print '<div class="opacitymedium">'.$langs->trans("NoMorePredefinedProductToDispatch").'</div>'; // No predefined line that remain to be dispatched.
728  }
729 
730  print '</form>';
731  }
732 
733  dol_fiche_end();
734 
735 
736  // List of lines already dispatched
737  $sql = "SELECT p.ref, p.label,";
738  $sql .= " e.rowid as warehouse_id, e.ref as entrepot,";
739  $sql .= " cfd.rowid as dispatchlineid, cfd.fk_product, cfd.qty, cfd.eatby, cfd.sellby, cfd.batch, cfd.comment, cfd.status";
740  $sql .= " FROM " . MAIN_DB_PREFIX . "product as p,";
741  $sql .= " " . MAIN_DB_PREFIX . "commande_fournisseur_dispatch as cfd";
742  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "entrepot as e ON cfd.fk_entrepot = e.rowid";
743  $sql .= " WHERE cfd.fk_commande = " . $object->id;
744  $sql .= " AND cfd.fk_product = p.rowid";
745  $sql .= " ORDER BY cfd.rowid ASC";
746 
747  $resql = $db->query($sql);
748  if ($resql) {
749  $num = $db->num_rows($resql);
750  $i = 0;
751 
752  if ($num > 0) {
753  print "<br>\n";
754 
755  print load_fiche_titre($langs->trans("ReceivingForSameOrder"));
756 
757  print '<div class="div-table-responsive">';
758  print '<table class="noborder" width="100%">';
759 
760  print '<tr class="liste_titre">';
761  print '<td>' . $langs->trans("Product") . '</td>';
762  if (! empty($conf->productbatch->enabled)) {
763  print '<td>' . $langs->trans("batch_number") . '</td>';
764  print '<td>' . $langs->trans("EatByDate") . '</td>';
765  print '<td>' . $langs->trans("SellByDate") . '</td>';
766  }
767  print '<td align="right">' . $langs->trans("QtyDispatched") . '</td>';
768  print '<td></td>';
769  print '<td>' . $langs->trans("Warehouse") . '</td>';
770  print '<td>' . $langs->trans("Comment") . '</td>';
771  if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS))
772  print '<td align="center" colspan="2">' . $langs->trans("Status") . '</td>';
773  print "</tr>\n";
774 
775  $var = false;
776 
777  while ( $i < $num ) {
778  $objp = $db->fetch_object($resql);
779 
780  print "<tr " . $bc[$var] . ">";
781  print '<td>';
782  print '<a href="' . DOL_URL_ROOT . '/product/fournisseurs.php?id=' . $objp->fk_product . '">' . img_object($langs->trans("ShowProduct"), 'product') . ' ' . $objp->ref . '</a>';
783  print ' - ' . $objp->label;
784  print "</td>\n";
785 
786  if (! empty($conf->productbatch->enabled)) {
787  print '<td>' . $objp->batch . '</td>';
788  print '<td>' . dol_print_date($db->jdate($objp->eatby), 'day') . '</td>';
789  print '<td>' . dol_print_date($db->jdate($objp->sellby), 'day') . '</td>';
790  }
791 
792  // Qty
793  print '<td align="right">' . $objp->qty . '</td>';
794  print '<td>&nbsp;</td>';
795 
796  // Warehouse
797  print '<td>';
798  $warehouse_static->id = $objp->warehouse_id;
799  $warehouse_static->libelle = $objp->entrepot;
800  print $warehouse_static->getNomUrl(1);
801  print '</td>';
802 
803  // Comment
804  print '<td class="tdoverflowmax300">' . $objp->comment . '</td>';
805 
806  // Status
807  if (! empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) {
808  print '<td align="right">';
809  $supplierorderdispatch->status = (empty($objp->status) ? 0 : $objp->status);
810  // print $supplierorderdispatch->status;
811  print $supplierorderdispatch->getLibStatut(5);
812  print '</td>';
813 
814  // Add button to check/uncheck disaptching
815  print '<td align="center">';
816  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)))
817  {
818  if (empty($objp->status)) {
819  print '<a class="button buttonRefused" href="#">' . $langs->trans("Approve") . '</a>';
820  print '<a class="button buttonRefused" href="#">' . $langs->trans("Deny") . '</a>';
821  } else {
822  print '<a class="button buttonRefused" href="#">' . $langs->trans("Disapprove") . '</a>';
823  print '<a class="button buttonRefused" href="#">' . $langs->trans("Deny") . '</a>';
824  }
825  } else {
826  $disabled = '';
827  if ($object->statut == 5)
828  $disabled = 1;
829  if (empty($objp->status)) {
830  print '<a class="button' . ($disabled ? ' buttonRefused' : '') . '" href="' . $_SERVER["PHP_SELF"] . "?id=" . $id . "&action=checkdispatchline&lineid=" . $objp->dispatchlineid . '">' . $langs->trans("Approve") . '</a>';
831  print '<a class="button' . ($disabled ? ' buttonRefused' : '') . '" href="' . $_SERVER["PHP_SELF"] . "?id=" . $id . "&action=denydispatchline&lineid=" . $objp->dispatchlineid . '">' . $langs->trans("Deny") . '</a>';
832  }
833  if ($objp->status == 1) {
834  print '<a class="button' . ($disabled ? ' buttonRefused' : '') . '" href="' . $_SERVER["PHP_SELF"] . "?id=" . $id . "&action=uncheckdispatchline&lineid=" . $objp->dispatchlineid . '">' . $langs->trans("Reinit") . '</a>';
835  print '<a class="button' . ($disabled ? ' buttonRefused' : '') . '" href="' . $_SERVER["PHP_SELF"] . "?id=" . $id . "&action=denydispatchline&lineid=" . $objp->dispatchlineid . '">' . $langs->trans("Deny") . '</a>';
836  }
837  if ($objp->status == 2) {
838  print '<a class="button' . ($disabled ? ' buttonRefused' : '') . '" href="' . $_SERVER["PHP_SELF"] . "?id=" . $id . "&action=uncheckdispatchline&lineid=" . $objp->dispatchlineid . '">' . $langs->trans("Reinit") . '</a>';
839  print '<a class="button' . ($disabled ? ' buttonRefused' : '') . '" href="' . $_SERVER["PHP_SELF"] . "?id=" . $id . "&action=checkdispatchline&lineid=" . $objp->dispatchlineid . '">' . $langs->trans("Approve") . '</a>';
840  }
841  }
842  print '</td>';
843  }
844 
845  print "</tr>\n";
846 
847  $i ++;
848  $var = ! $var;
849  }
850  $db->free($resql);
851 
852  print "</table>\n";
853  print '</div>';
854  }
855  } else {
856  dol_print_error($db);
857  }
858 }
859 
860 llxFooter();
861 
862 $db->close();
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='')
Show picto whatever it's its name (generic function)
setEventMessages($mesg, $mesgs, $style='mesgs')
Set event messages in dol_events session object.
ordersupplier_prepare_head($object)
Prepare array with list of tabs.
Definition: fourn.lib.php:102
const STATUS_RECEIVED_COMPLETELY
Received completely.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm=false, $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_fiche_head($links=array(), $active='0', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='')
Show tab header of a card.
Class to manage table commandefournisseurdispatch.
if(GETPOST('cancel','alpha')) if(!GETPOST('confirmmassaction','alpha')&&$massaction!= 'presend'&&$massaction!= 'confirm_presend')
Draft customers invoices.
Definition: list.php:147
Class to manage products or services.
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.
Class to manage Dolibarr users.
Definition: user.class.php:39
if(empty($reshook)) $form
View.
Definition: perms.php:103
GETPOST($paramname, $check='none', $method=0, $filter=NULL, $options=NULL, $noreplace=0)
Return value of a param into GET or POST supervariable.
Class with static methods for building HTML components related to products Only components common to ...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Class to manage generation of HTML components Only common components must be here.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage projects.
if($_POST["cancel"]==$langs->trans("Cancel")&&!$id) if($action== 'setdatev'&&$user->rights->tax->charges->creer) if($action== 'add'&&$_POST["cancel"]<> $langs->trans("Cancel")) if($action== 'delete') $title
Actions.
Definition: card.php:183
const STATUS_RECEIVED_PARTIALLY
Received partially.
llxHeader()
Empty header.
Definition: wrapper.php:46
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_now($mode='gmt')
Return date for now.
Class to manage predefined suppliers products.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Class to manage comment.
print
Draft customers invoices.
Definition: index.php:91
const STATUS_ORDERSENT
Order sent, shipment on process.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->societe->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)&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1013
const STATUS_CANCELED
Order canceled.
price2num($amount, $rounding='', $alreadysqlnb=0)
Function that return a number with universal decimal format (decimal separator is '...
restrictedArea($user, $features, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null)
Check permissions of a user to show a page and an object.
div float
Buy price without taxes.
Definition: style.css.php:525
Class to manage warehouses.