dolibarr 18.0.6
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-2022 Ferran Marcet <fmarcet@2byte.es>
10 * Copyright (C) 2018-2022 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 3 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 */
26
33// Load Dolibarr environment
34require '../main.inc.php';
35require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php';
36require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
39require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
40require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
41require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
42require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
43require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
44
45// Load translation files required by the page
46$langs->loadLangs(array("bills", "orders", "sendings", "companies", "deliveries", "products", "stocks", "receptions"));
47
48if (isModEnabled('productbatch')) {
49 $langs->load('productbatch');
50}
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$error = 0;
62$errors = array();
63
64if ($user->socid) {
65 $socid = $user->socid;
66}
67
68$hookmanager->initHooks(array('ordersupplierdispatch'));
69
70// Recuperation de l'id de projet
71$projectid = 0;
72if (GETPOSTISSET("projectid")) {
73 $projectid = GETPOST("projectid", 'int');
74}
75
76$object = new Reception($db);
77
78if ($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 if (!empty($object->origin)) {
88 $origin = $object->origin;
89
90 $object->fetch_origin();
91 $typeobject = $object->origin;
92 }
93 if ($origin == 'order_supplier' && $object->$typeobject->id && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order"))) {
94 $origin_id = $object->$typeobject->id;
95 $objectsrc = new CommandeFournisseur($db);
96 $objectsrc->fetch($object->$typeobject->id);
97 }
98}
99
100if (empty($conf->reception->enabled)) {
101 $permissiontoreceive = $user->rights->fournisseur->commande->receptionner;
102 $permissiontocontrol = ((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)));
103} else {
104 $permissiontoreceive = $user->rights->reception->creer;
105 $permissiontocontrol = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate)));
106}
107
108// $id is id of a reception
109$result = restrictedArea($user, 'reception', $object->id);
110
111if (!isModEnabled('stock')) {
112 accessforbidden('Module stock disabled');
113}
114
115$usercancreate = $user->hasRight('reception', 'creer');
116$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php
117
118
119/*
120 * Actions
121 */
122
123$parameters = array();
124$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
125if ($reshook < 0) {
126 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
127}
128
129// Update a dispatched line
130if ($action == 'updatelines' && $permissiontoreceive) {
131 $db->begin();
132 $error = 0;
133
134 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
135 $pos = 0;
136
137 foreach ($_POST as $key => $value) {
138 // without batch module enabled
139 $reg = array();
140 if (preg_match('/^product_.*([0-9]+)_([0-9]+)$/i', $key, $reg)) {
141 $pos++;
142 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
143 $modebatch = "barcode";
144 } elseif (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) { // With batchmode enabled
145 $modebatch = "batch";
146 }
147
148 $numline = $pos;
149 if ($modebatch == "barcode") {
150 $prod = "product_".$reg[1].'_'.$reg[2];
151 } else {
152 $prod = 'product_batch_'.$reg[1].'_'.$reg[2];
153 }
154 $qty = "qty_".$reg[1].'_'.$reg[2];
155 $ent = "entrepot_".$reg[1].'_'.$reg[2];
156 $pu = "pu_".$reg[1].'_'.$reg[2]; // This is unit price including discount
157 $fk_commandefourndet = "fk_commandefourndet_".$reg[1].'_'.$reg[2];
158 $idline = GETPOST("idline_".$reg[1].'_'.$reg[2]);
159 $lot = '';
160 $dDLUO = '';
161 $dDLC = '';
162 if ($modebatch == "batch") {
163 $lot = GETPOST('lot_number_'.$reg[1].'_'.$reg[2]);
164 $dDLUO = dol_mktime(12, 0, 0, GETPOST('dluo_'.$reg[1].'_'.$reg[2].'month', 'int'), GETPOST('dluo_'.$reg[1].'_'.$reg[2].'day', 'int'), GETPOST('dluo_'.$reg[1].'_'.$reg[2].'year', 'int'));
165 $dDLC = dol_mktime(12, 0, 0, GETPOST('dlc_'.$reg[1].'_'.$reg[2].'month', 'int'), GETPOST('dlc_'.$reg[1].'_'.$reg[2].'day', 'int'), GETPOST('dlc_'.$reg[1].'_'.$reg[2].'year', 'int'));
166 }
167
168 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) {
169 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
170 $dto = GETPOST("dto_".$reg[1].'_'.$reg[2], 'int');
171 if (!empty($dto)) {
172 $unit_price = price2num(GETPOST("pu_".$reg[1]) * (100 - $dto) / 100, 'MU');
173 }
174 $saveprice = "saveprice_".$reg[1].'_'.$reg[2];
175 }
176 }
177
178 // We ask to move a qty
179 if (($modebatch == "batch" && GETPOST($qty) > 0) || ($modebatch == "barcode" && GETPOST($qty) != 0)) {
180 if (!(GETPOST($ent, 'int') > 0)) {
181 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.');
182 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline);
183 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
184 $error++;
185 }
186
187 if (!$error) {
188 if ($idline > 0) {
189 $result = $supplierorderdispatch->fetch($idline);
190 if ($result < 0) {
191 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
192 $error++;
193 } else {
194 $qtystart = $supplierorderdispatch->qty;
195 $supplierorderdispatch->qty = GETPOST($qty);
196 $supplierorderdispatch->fk_entrepot = GETPOST($ent, 'int');
197 if ($modebatch == "batch") {
198 $supplierorderdispatch->eatby = $dDLUO;
199 $supplierorderdispatch->sellby = $dDLC;
200 }
201
202 $result = $supplierorderdispatch->update($user);
203 if ($result < 0) {
204 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
205 $error++;
206 }
207
208 // If module stock is enabled and the stock decrease is done on edtion of this page
209 /*
210 if (!$error && GETPOST($ent, 'int') > 0 && isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) {
211 $mouv = new MouvementStock($db);
212 $product = GETPOST($prod, 'int');
213 $entrepot = GETPOST($ent, 'int');
214 $qtymouv = GETPOST($qty) - $qtystart;
215 $price = GETPOST($pu);
216 $comment = GETPOST('comment');
217 $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
218 $now = dol_now();
219 $eatby = '';
220 $sellby = '';
221 $batch = '';
222 if ($modebatch == "batch") {
223 $eatby = $dDLUO;
224 $sellby = $dDLC;
225 $batch = $supplierorderdispatch->batch;
226 }
227 if ($product > 0) {
228 // $price should take into account discount (except if option STOCK_EXCLUDE_DISCOUNT_FOR_PMP is on)
229 $mouv->origin = $objectsrc;
230 $mouv->setOrigin($objectsrc->element, $objectsrc->id);
231
232 // Method change if qty < 0
233 if (!empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN) && $qtymouv < 0) {
234 $result = $mouv->livraison($user, $product, $entrepot, $qtymouv*(-1), $price, $comment, $now, $eatby, $sellby, $batch, 0, $inventorycode);
235 } else {
236 $result = $mouv->reception($user, $product, $entrepot, $qtymouv, $price, $comment, $eatby, $sellby, $batch, '', 0, $inventorycode);
237 }
238
239 if ($result < 0) {
240 setEventMessages($mouv->error, $mouv->errors, 'errors');
241 $error++;
242 }
243 }
244 }
245 */
246 }
247 } else {
248 $result = $objectsrc->dispatchProduct($user, GETPOST($prod, 'int'), GETPOST($qty), GETPOST($ent, 'int'), GETPOST($pu), GETPOST('comment'), $dDLUO, $dDLC, $lot, GETPOST($fk_commandefourndet, 'int'), 0, $object->id);
249 if ($result < 0) {
250 setEventMessages($objectsrc->error, $objectsrc->errors, 'errors');
251 $error++;
252 }
253 }
254
255 if (!$error && !empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) {
256 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
257 $dto = price2num(GETPOST("dto_".$reg[1].'_'.$reg[2], 'int'), '');
258 if (empty($dto)) {
259 $dto = 0;
260 }
261
262 //update supplier price
263 if (GETPOSTISSET($saveprice)) {
264 // TODO Use class
265 $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price";
266 $sql .= " SET unitprice='".price2num(GETPOST($pu), 'MU')."'";
267 $sql .= ", price=".price2num(GETPOST($pu), 'MU')."*quantity";
268 $sql .= ", remise_percent = ".((float) $dto);
269 $sql .= " WHERE fk_soc=".((int) $object->socid);
270 $sql .= " AND fk_product=".((int) GETPOST($prod, 'int'));
271
272 $resql = $db->query($sql);
273 }
274 }
275 }
276 }
277 }
278 }
279 }
280 if ($error > 0) {
281 $db->rollback();
282 setEventMessages($error, $errors, 'errors');
283 } else {
284 $db->commit();
285 setEventMessages($langs->trans("ReceptionUpdated"), null);
286
287 header("Location: ".DOL_URL_ROOT.'/reception/dispatch.php?id='.$object->id);
288 exit;
289 }
290}
291
292
293/*
294 * View
295 */
296
297$now = dol_now();
298
299$form = new Form($db);
300$formproduct = new FormProduct($db);
301$warehouse_static = new Entrepot($db);
302$supplierorderdispatch = new CommandeFournisseurDispatch($db);
303
304$title = $object->ref." - ".$langs->trans('ReceptionDistribution');
305$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores';
306$morejs = array('/fourn/js/lib_dispatch.js.php');
307
308llxHeader('', $title, $help_url, '', 0, 0, $morejs);
309
310if ($id > 0 || !empty($ref)) {
311 if (!empty($object->origin) && $object->origin_id > 0) {
312 $object->origin = 'CommandeFournisseur';
313 $typeobject = $object->origin;
314 $origin = $object->origin;
315 $origin_id = $object->origin_id;
316 $object->fetch_origin(); // Load property $object->commande, $object->propal, ...
317 }
318 $soc = new Societe($db);
319 $soc->fetch($object->socid);
320
321 $author = new User($db);
322 $author->fetch($object->user_author_id);
323
324 $head = reception_prepare_head($object);
325
326 $title = $langs->trans("SupplierOrder");
327 print dol_get_fiche_head($head, 'dispatch', $langs->trans("Reception"), -1, 'dollyrevert');
328
329
330 $formconfirm = '';
331
332 // Confirmation to delete line
333 if ($action == 'ask_deleteline') {
334 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
335 }
336
337 // Call Hook formConfirm
338 $parameters = array('lineid' => $lineid);
339 // Note that $action and $object may be modified by hook
340 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
341 if (empty($reshook)) {
342 $formconfirm .= $hookmanager->resPrint;
343 } elseif ($reshook > 0) {
344 $formconfirm = $hookmanager->resPrint;
345 }
346
347 // Print form confirm
348 print $formconfirm;
349
350 // Reception card
351 $linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
352 $morehtmlref = '<div class="refidno">';
353 // Ref customer reception
354
355 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', 0, 1);
356 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', null, null, '', 1);
357
358 // Thirdparty
359 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
360 // Project
361 if (isModEnabled('project')) {
362 $langs->load("projects");
363 $morehtmlref .= '<br>';
364 if (0) { // Do not change on reception
365 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
366 if ($action != 'classify' && $permissiontoadd) {
367 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
368 }
369 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $object->socid : -1), $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
370 } else {
371 if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
372 $proj = new Project($db);
373 $proj->fetch($objectsrc->fk_project);
374 $morehtmlref .= $proj->getNomUrl(1);
375 if ($proj->title) {
376 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
377 }
378 }
379 }
380 }
381 $morehtmlref .= '</div>';
382
383 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
384
385
386 print '<div class="fichecenter">';
387 print '<div class="underbanner clearboth"></div>';
388
389 print '<table class="border tableforfield" width="100%">';
390
391 // Linked documents
392 if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) {
393 print '<tr><td>';
394 print $langs->trans("RefOrder").'</td>';
395 print '<td colspan="3">';
396 print $objectsrc->getNomUrl(1, 'commande');
397 print "</td>\n";
398 print '</tr>';
399 }
400 if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) {
401 print '<tr><td>';
402 print $langs->trans("RefProposal").'</td>';
403 print '<td colspan="3">';
404 print $objectsrc->getNomUrl(1, 'reception');
405 print "</td>\n";
406 print '</tr>';
407 }
408 if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("propal")) {
409 print '<tr><td>';
410 print $langs->trans("SupplierOrder").'</td>';
411 print '<td colspan="3">';
412 print $objectsrc->getNomUrl(1, 'reception');
413 print "</td>\n";
414 print '</tr>';
415 }
416
417 // Date creation
418 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
419 print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
420 print '</tr>';
421
422 // Delivery date planned
423 print '<tr><td height="10">';
424 print '<table class="nobordernopadding" width="100%"><tr><td>';
425 print $langs->trans('DateDeliveryPlanned');
426 print '</td>';
427 print '</tr></table>';
428 print '</td><td colspan="2">';
429 print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
430 print '</td>';
431 print '</tr>';
432 print '</table>';
433
434 print '<br><br><center>';
435 print '<a href="#" id="resetalltoexpected" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'autofill', 'class="pictofixedwidth"').$langs->trans("RestoreWithCurrentQtySaved").'</a></td>';
436 // Link to clear qty
437 print '<a href="#" id="autoreset" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'eraser', 'class="pictofixedwidth"').$langs->trans("ClearQtys").'</a></td>';
438 print '<center>';
439
440 print '<br>';
441 $disabled = 0; // This is used to disable or not the bulk selection of target warehouse. No reason to have it disabled so forced to 0.
442
443 if ($object->statut == Reception::STATUS_DRAFT || ($object->statut == Reception::STATUS_VALIDATED && empty($conf->global->STOCK_CALCULATE_ON_RECEPTION))) {
444 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
445 $formproduct = new FormProduct($db);
446 $formproduct->loadWarehouses();
447 $entrepot = new Entrepot($db);
448 $listwarehouses = $entrepot->list_array(1);
449
450 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'">';
451
452 print '<input type="hidden" name="token" value="'.newToken().'">';
453 print '<input type="hidden" name="action" value="updatelines">';
454 print '<input type="hidden" name="id" value="'.$object->id.'">';
455
456 print '<div class="div-table-responsive-no-min">';
457 print '<table class="noborder centpercent">';
458
459 // Get list of lines from the original Order into $products_dispatched with qty dispatched for each product id
460 $products_dispatched = array();
461 $sql = "SELECT l.rowid, cfd.fk_product, sum(cfd.qty) as qty";
462 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd";
463 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseurdet as l on l.rowid = cfd.fk_commandefourndet";
464 $sql .= " WHERE cfd.fk_reception = ".((int) $object->id);
465 $sql .= " GROUP BY l.rowid, cfd.fk_product";
466
467 $resql = $db->query($sql);
468 if ($resql) {
469 $num = $db->num_rows($resql);
470 $i = 0;
471
472 if ($num) {
473 while ($i < $num) {
474 $objd = $db->fetch_object($resql);
475 $products_dispatched[$objd->rowid] = price2num($objd->qty, 'MS');
476 $i++;
477 }
478 }
479 $db->free($resql);
480 }
481
482
483 //$sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, SUM(l.qty) as qty,";
484 $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, l.qty as qty,";
485 $sql .= " p.ref, p.label, p.tobatch, p.fk_default_warehouse";
486 // Enable hooks to alter the SQL query (SELECT)
487 $parameters = array();
488 $reshook = $hookmanager->executeHooks(
489 'printFieldListSelect',
490 $parameters,
491 $object,
492 $action
493 );
494 if ($reshook < 0) {
495 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
496 }
497 $sql .= $hookmanager->resPrint;
498 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as l";
499 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON l.fk_product=p.rowid";
500 $sql .= " WHERE l.fk_commande = ".((int) $objectsrc->id);
501 if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
502 $sql .= " AND l.product_type = 0";
503 }
504 // Enable hooks to alter the SQL query (WHERE)
505 $parameters = array();
506 $reshook = $hookmanager->executeHooks(
507 'printFieldListWhere',
508 $parameters,
509 $object,
510 $action
511 );
512 if ($reshook < 0) {
513 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
514 }
515 $sql .= $hookmanager->resPrint;
516
517 //$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
518 $sql .= " ORDER BY l.rang, p.ref, p.label";
519
520 $resql = $db->query($sql);
521 if ($resql) {
522 $num = $db->num_rows($resql);
523 $i = 0;
524
525 if ($num) {
526 print '<tr class="liste_titre">';
527
528 print '<td>'.$langs->trans("Description").'</td>';
529 if (isModEnabled('productbatch')) {
530 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>';
531 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
532 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>';
533 }
534 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
535 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>';
536 }
537 } else {
538 print '<td></td>';
539 print '<td></td>';
540 print '<td></td>';
541 }
542 print '<td class="right">'.$langs->trans("SupplierRef").'</td>';
543 print '<td class="right">'.$langs->trans("QtyOrdered").'</td>';
544 print '<td class="right">'.$langs->trans("QtyDispatchedShort").'</td>';
545 print ' <td class="right">'.$langs->trans("QtyToDispatchShort");
546 //print '<br><a href="#" id="autoreset">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').$langs->trans("Reset").'</a></td>';
547 print '<td width="32"></td>';
548
549 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) {
550 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
551 print '<td class="right">'.$langs->trans("Price").'</td>';
552 print '<td class="right">'.$langs->trans("ReductionShort").' (%)</td>';
553 print '<td class="right">'.$langs->trans("UpdatePrice").'</td>';
554 }
555 }
556
557 print '<td align="right">'.$langs->trans("Warehouse");
558
559 // Select warehouse to force it everywhere
560 if (count($listwarehouses) > 1) {
561 print '<br><span class="opacitymedium">'.$langs->trans("ForceTo").'</span> '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 1, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1);
562 } elseif (count($listwarehouses) == 1) {
563 print '<br><span class="opacitymedium">'.$langs->trans("ForceTo").'</span> '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1);
564 }
565
566 print '</td>';
567
568 // Enable hooks to append additional columns
569 $parameters = array();
570 $reshook = $hookmanager->executeHooks(
571 'printFieldListTitle',
572 $parameters,
573 $object,
574 $action
575 );
576 if ($reshook < 0) {
577 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
578 }
579 print $hookmanager->resPrint;
580
581 print "</tr>\n";
582 }
583
584 $nbfreeproduct = 0; // Nb of lins of free products/services
585 $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)
586 // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on.
587
588 $conf->cache['product'] = array();
589
590 // Loop on each source order line (may be more or less than current number of lines in llx_commande_fournisseurdet)
591 while ($i < $num) {
592 $objp = $db->fetch_object($resql);
593
594 // On n'affiche pas les produits libres
595 if (!$objp->fk_product > 0) {
596 $nbfreeproduct++;
597 } else {
598 $alreadydispatched = isset($products_dispatched[$objp->rowid])?$products_dispatched[$objp->rowid]:0;
599 $remaintodispatch = price2num($objp->qty, 5); // Calculation of dispatched
600 if ($remaintodispatch < 0 && empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN)) {
601 $remaintodispatch = 0;
602 }
603
604 if ($remaintodispatch || empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) {
605 $nbproduct++;
606
607 // To show detail cref and description value, we must make calculation by cref
608 // print ($objp->cref?' ('.$objp->cref.')':'');
609 // if ($objp->description) print '<br>'.nl2br($objp->description);
610 $suffix = '_0_'.$i;
611
612 print "\n";
613 print '<!-- Line to dispatch '.$suffix.' -->'."\n";
614 // hidden fields for js function
615 print '<input id="qty_ordered'.$suffix.'" type="hidden" value="'.$objp->qty.'">';
616 print '<input id="qty_dispatched'.$suffix.'" type="hidden" data-dispatched="'.((float) $alreadydispatched).'" value="'.(float) $alreadydispatched.'">';
617 print '<tr class="oddeven">';
618
619 if (empty($conf->cache['product'][$objp->fk_product])) {
620 $tmpproduct = new Product($db);
621 $tmpproduct->fetch($objp->fk_product);
622 $conf->cache['product'][$objp->fk_product] = $tmpproduct;
623 } else {
624 $tmpproduct = $conf->cache['product'][$objp->fk_product];
625 }
626
627 $linktoprod = $tmpproduct->getNomUrl(1);
628 $linktoprod .= ' - '.$objp->label."\n";
629
630 if (isModEnabled('productbatch')) {
631 if ($objp->tobatch) {
632 // Product
633 print '<td>';
634 print $linktoprod;
635 print "</td>";
636 print '<td class="dispatch_batch_number"></td>';
637 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
638 print '<td class="dispatch_dlc"></td>';
639 }
640 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
641 print '<td class="dispatch_dluo"></td>';
642 }
643 } else {
644 // Product
645 print '<td>';
646 print $linktoprod;
647 print "</td>";
648 print '<td class="dispatch_batch_number">';
649 print '<span class="opacitymedium small">'.$langs->trans("ProductDoesNotUseBatchSerial").'</small>';
650 print '</td>';
651 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
652 print '<td class="dispatch_dlc"></td>';
653 }
654 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
655 print '<td class="dispatch_dluo"></td>';
656 }
657 }
658 } else {
659 print '<td colspan="4">';
660 print $linktoprod;
661 print "</td>";
662 }
663
664 // Define unit price for PMP calculation
665 $up_ht_disc = $objp->subprice;
666 if (!empty($objp->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) {
667 $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU');
668 }
669
670 // Supplier ref
671 print '<td class="right">'.$objp->sref.'</td>';
672
673 // Qty ordered
674 print '<td class="right">'.$objp->qty.'</td>';
675
676 // Already dispatched
677 print '<td class="right">'.$alreadydispatched.'</td>';
678
679 print '<td class="right">';
680 print '</td>'; // Qty to dispatch
681 print '<td>';
682 print '</td>'; // Dispatch column
683 print '<td></td>'; // Warehouse column
684
685 $sql = "SELECT cfd.rowid, cfd.qty, cfd.fk_entrepot, cfd.batch, cfd.eatby, cfd.sellby, cfd.fk_product";
686 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd";
687 $sql .= " WHERE cfd.fk_reception = ".((int) $object->id);
688 $sql .= " AND cfd.fk_commande = ".((int) $objectsrc->id);
689 $sql .= " AND cfd.fk_commandefourndet = ".(int) $objp->rowid;
690
691 //print $sql;
692 $resultsql = $db->query($sql);
693 $j = 0;
694 if ($resultsql) {
695 $numd = $db->num_rows($resultsql);
696
697 while ($j < $numd) {
698 $suffix = "_".$j."_".$i;
699 $objd = $db->fetch_object($resultsql);
700
701 if (isModEnabled('productbatch') && !empty($objd->batch)) {
702 $type = 'batch';
703
704 // Enable hooks to append additional columns
705 $parameters = array(
706 // allows hook to distinguish between the rows with information and the rows with dispatch form input
707 'is_information_row' => true,
708 'j' => $j,
709 'suffix' => $suffix,
710 'objd' => $objd,
711 );
712 $reshook = $hookmanager->executeHooks(
713 'printFieldListValue',
714 $parameters,
715 $object,
716 $action
717 );
718 if ($reshook < 0) {
719 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
720 }
721 print $hookmanager->resPrint;
722
723 print '</tr>';
724
725 print '<!-- line for batch '.$numline.' -->';
726 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
727 print '<td>';
728 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
729 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
730 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
731
732 print '<!-- This is a U.P. (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
733 if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested !
734 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">';
735 } else {
736 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
737 }
738
739 print '</td>';
740
741 print '<td>';
742 print '<input disabled="" type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.$objd->batch.'">';
743 print '</td>';
744 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
745 print '<td class="nowraponall">';
746 $dlcdatesuffix = !empty($objd->sellby) ? dol_stringtotime($objd->sellby) : dol_mktime(0, 0, 0, GETPOST('dlc'.$suffix.'month'), GETPOST('dlc'.$suffix.'day'), GETPOST('dlc'.$suffix.'year'));
747 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, '', '', 1, '');
748 print '</td>';
749 }
750 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
751 print '<td class="nowraponall">';
752 $dluodatesuffix = !empty($objd->eatby) ? dol_stringtotime($objd->eatby) : dol_mktime(0, 0, 0, GETPOST('dluo'.$suffix.'month'), GETPOST('dluo'.$suffix.'day'), GETPOST('dluo'.$suffix.'year'));
753 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, '', '', 1, '');
754 print '</td>';
755 }
756 print '<td colspan="3">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
757 } else {
758 $type = 'dispatch';
759 $colspan = 7;
760 $colspan = (!empty($conf->global->PRODUCT_DISABLE_SELLBY)) ? --$colspan : $colspan;
761 $colspan = (!empty($conf->global->PRODUCT_DISABLE_EATBY)) ? --$colspan : $colspan;
762
763 // Enable hooks to append additional columns
764 $parameters = array(
765 // allows hook to distinguish between the rows with information and the rows with dispatch form input
766 'is_information_row' => true,
767 'j' => $j,
768 'suffix' => $suffix,
769 'objd' => $objd,
770 );
771 $reshook = $hookmanager->executeHooks(
772 'printFieldListValue',
773 $parameters,
774 $object,
775 $action
776 );
777 if ($reshook < 0) {
778 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
779 }
780 print $hookmanager->resPrint;
781
782 print '</tr>';
783
784 print '<!-- line no batch '.$numline.' -->';
785 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
786 print '<td colspan="'.$colspan.'">';
787 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
788 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
789 print '<input name="product'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
790
791 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
792 if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested !
793 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">';
794 } else {
795 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
796 }
797
798 print '</td>';
799 }
800 // Qty to dispatch
801 print '<td class="right">';
802 print '<a href="#" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
803 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-type="'.$type.'" data-index="'.$i.'" class="width50 right qtydispatchinput" value="'.(GETPOSTISSET('qty'.$suffix) ? GETPOST('qty'.$suffix, 'int') : $objd->qty).'" data-expected="'.$objd->qty.'">';
804 print '</td>';
805 print '<td>';
806 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
807 $type = 'batch';
808 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j+1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
809 } else {
810 $type = 'dispatch';
811 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j+1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
812 }
813
814 print '</td>';
815
816 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) {
817 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
818 // Price
819 print '<td class="right">';
820 print '<input id="pu'.$suffix.'" name="pu'.$suffix.'" type="text" size="8" value="'.price((GETPOST('pu'.$suffix) != '' ? price2num(GETPOST('pu'.$suffix)) : $up_ht_disc)).'">';
821 print '</td>';
822
823 // Discount
824 print '<td class="right">';
825 print '<input id="dto'.$suffix.'" name="dto'.$suffix.'" type="text" size="8" value="'.(GETPOST('dto'.$suffix) != '' ? GETPOST('dto'.$suffix) : '').'">';
826 print '</td>';
827
828 // Save price
829 print '<td class="center">';
830 print '<input class="flat checkformerge" type="checkbox" name="saveprice'.$suffix.'" value="'.(GETPOST('saveprice'.$suffix) != '' ? GETPOST('saveprice'.$suffix) : '').'">';
831 print '</td>';
832 }
833 }
834
835 // Warehouse
836 print '<td class="right">';
837 if (count($listwarehouses) > 1) {
838 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix);
839 } elseif (count($listwarehouses) == 1) {
840 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix);
841 } else {
842 $langs->load("errors");
843 print $langs->trans("ErrorNoWarehouseDefined");
844 }
845 print "</td>\n";
846
847 // Enable hooks to append additional columns
848 $parameters = array(
849 'is_information_row' => false, // this is a dispatch form row
850 'i' => $i,
851 'suffix' => $suffix,
852 'objp' => $objp,
853 );
854 $reshook = $hookmanager->executeHooks(
855 'printFieldListValue',
856 $parameters,
857 $object,
858 $action
859 );
860 if ($reshook < 0) {
861 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
862 }
863 print $hookmanager->resPrint;
864
865 print "</tr>\n";
866 $j++;
867
868 $numline++;
869 }
870 $suffix = "_".$j."_".$i;
871 }
872
873 if ($j == 0) {
874 if (isModEnabled('productbatch') && !empty($objp->tobatch)) {
875 $type = 'batch';
876
877 // Enable hooks to append additional columns
878 $parameters = array(
879 // allows hook to distinguish between the rows with information and the rows with dispatch form input
880 'is_information_row' => true,
881 'j' => $j,
882 'suffix' => $suffix,
883 'objp' => $objp,
884 );
885 $reshook = $hookmanager->executeHooks(
886 'printFieldListValue',
887 $parameters,
888 $object,
889 $action
890 );
891 if ($reshook < 0) {
892 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
893 }
894 print $hookmanager->resPrint;
895
896 print '</tr>';
897
898 print '<!-- line for batch '.$numline.' (not dispatched line yet for this order line) -->';
899 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'">';
900 print '<td>';
901 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
902 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
903 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
904
905 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
906 if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested !
907 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">';
908 } else {
909 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
910 }
911
912 print '</td>';
913
914 print '<td>';
915 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.GETPOST('lot_number'.$suffix).'">';
916 print '</td>';
917 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
918 print '<td class="nowraponall">';
919 $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOST('dlc'.$suffix.'month'), GETPOST('dlc'.$suffix.'day'), GETPOST('dlc'.$suffix.'year'));
920 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, '', '', 1, '');
921 print '</td>';
922 }
923 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
924 print '<td class="nowraponall">';
925 $dluodatesuffix = dol_mktime(0, 0, 0, GETPOST('dluo'.$suffix.'month'), GETPOST('dluo'.$suffix.'day'), GETPOST('dluo'.$suffix.'year'));
926 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, '', '', 1, '');
927 print '</td>';
928 }
929 print '<td colspan="3">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
930 } else {
931 $type = 'dispatch';
932 $colspan = 7;
933 $colspan = (!empty($conf->global->PRODUCT_DISABLE_SELLBY)) ? --$colspan : $colspan;
934 $colspan = (!empty($conf->global->PRODUCT_DISABLE_EATBY)) ? --$colspan : $colspan;
935
936 // Enable hooks to append additional columns
937 $parameters = array(
938 // allows hook to distinguish between the rows with information and the rows with dispatch form input
939 'is_information_row' => true,
940 'j' => $j,
941 'suffix' => $suffix,
942 'objp' => $objp,
943 );
944 $reshook = $hookmanager->executeHooks(
945 'printFieldListValue',
946 $parameters,
947 $object,
948 $action
949 );
950 if ($reshook < 0) {
951 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
952 }
953 print $hookmanager->resPrint;
954
955 print '</tr>';
956
957 print '<!-- line no batch '.$numline.' (not dispatched line yet for this order line) -->';
958 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
959 print '<td colspan="'.$colspan.'">';
960 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
961 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
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 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" data-type="text" value="'.price2num($up_ht_disc, 'MU').'">';
967 } else {
968 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
969 }
970
971 print '</td>';
972 }
973 // Qty to dispatch
974 print '<td class="right">';
975 print '<a href="#" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
976 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-index="'.$i.'" data-type="text" class="width50 right qtydispatchinput" value="'.(GETPOSTISSET('qty'.$suffix) ? GETPOST('qty'.$suffix, 'int') : (empty($conf->global->SUPPLIER_ORDER_DISPATCH_FORCE_QTY_INPUT_TO_ZERO) ? $remaintodispatch : 0)).'" data-expected="'.$remaintodispatch.'">';
977 print '</td>';
978 print '<td>';
979 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
980 $type = 'batch';
981 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
982 } else {
983 $type = 'dispatch';
984 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
985 }
986
987 print '</td>';
988
989 if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) {
990 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
991 // Price
992 print '<td class="right">';
993 print '<input id="pu'.$suffix.'" name="pu'.$suffix.'" type="text" size="8" value="'.price((GETPOST('pu'.$suffix) != '' ? price2num(GETPOST('pu'.$suffix)) : $up_ht_disc)).'">';
994 print '</td>';
995
996 // Discount
997 print '<td class="right">';
998 print '<input id="dto'.$suffix.'" name="dto'.$suffix.'" type="text" size="8" value="'.(GETPOST('dto'.$suffix) != '' ? GETPOST('dto'.$suffix) : '').'">';
999 print '</td>';
1000
1001 // Save price
1002 print '<td class="center">';
1003 print '<input class="flat checkformerge" type="checkbox" name="saveprice'.$suffix.'" value="'.(GETPOST('saveprice'.$suffix) != '' ? GETPOST('saveprice'.$suffix) : '').'">';
1004 print '</td>';
1005 }
1006 }
1007
1008 // Warehouse
1009 print '<td class="right">';
1010 if (count($listwarehouses) > 1) {
1011 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);
1012 } elseif (count($listwarehouses) == 1) {
1013 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);
1014 } else {
1015 $langs->load("errors");
1016 print $langs->trans("ErrorNoWarehouseDefined");
1017 }
1018 print "</td>\n";
1019
1020 // Enable hooks to append additional columns
1021 $parameters = array(
1022 'is_information_row' => false, // this is a dispatch form row
1023 'i' => $i,
1024 'suffix' => $suffix,
1025 'objp' => $objp,
1026 );
1027 $reshook = $hookmanager->executeHooks(
1028 'printFieldListValue',
1029 $parameters,
1030 $object,
1031 $action
1032 );
1033 if ($reshook < 0) {
1034 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1035 }
1036 print $hookmanager->resPrint;
1037 print "</tr>\n";
1038 }
1039 }
1040 }
1041 $i++;
1042 }
1043 $db->free($resql);
1044 } else {
1045 dol_print_error($db);
1046 }
1047
1048 print "</table>\n";
1049 print '</div>';
1050
1051 if ($nbproduct) {
1052 print '<div class="center">';
1053 $parameters = array();
1054 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1055 // modified by hook
1056 if (empty($reshook)) {
1057 /*$checkboxlabel = $langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv('StatusOrderReceivedAll'));
1058
1059 if (empty($conf->reception->enabled)) {
1060 print $langs->trans("Comment").' : ';
1061 print '<input type="text" class="minwidth400" maxlength="128" name="comment" value="';
1062 print GETPOSTISSET("comment") ? GETPOST("comment") : $langs->trans("DispatchSupplierOrder", $object->ref);
1063 // print ' / '.$object->ref_supplier; // Not yet available
1064 print '" class="flat"><br>';
1065
1066 print '<input type="checkbox" checked="checked" name="closeopenorder"> '.$checkboxlabel;
1067 }
1068
1069 $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception");
1070
1071 print '<br>';
1072 */
1073
1074 print '<input type="submit" id="submitform" class="button" name="dispatch" value="'.$langs->trans("Save").'"';
1075 $disabled = 0;
1076 if (!$permissiontoreceive) {
1077 $disabled = 1;
1078 }
1079 if (count($listwarehouses) <= 0) {
1080 $disabled = 1;
1081 }
1082 if ($disabled) {
1083 print ' disabled';
1084 }
1085
1086 print '>';
1087 }
1088 print '</div>';
1089 }
1090
1091 // Message if nothing to dispatch
1092 if (!$nbproduct) {
1093 print "<br>\n";
1094 if (empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) {
1095 print '<div class="opacitymedium">'.$langs->trans("NoPredefinedProductToDispatch").'</div>'; // No predefined line at all
1096 } else {
1097 print '<div class="opacitymedium">'.$langs->trans("NoMorePredefinedProductToDispatch").'</div>'; // No predefined line that remain to be dispatched.
1098 }
1099 }
1100
1101 print '</form>';
1102 }
1103
1104 print dol_get_fiche_end();
1105
1106 // traitement entrepot par défaut
1107 print '<script type="text/javascript">
1108 $(document).ready(function () {
1109 $("select[name=fk_default_warehouse]").change(function() {
1110 var fk_default_warehouse = $("option:selected", this).val();
1111 $("select[name^=entrepot_]").val(fk_default_warehouse).change();
1112 });
1113
1114 $("#autoreset").click(function() {
1115 $(".autoresettr").each(function(){
1116 id = $(this).attr("name");
1117 idtab = id.split("_");
1118 if ($(this).data("remove") == "clear"){
1119 console.log("We clear the object to expected value")
1120 $("#qty_"+idtab[1]+"_"+idtab[2]).val("");
1121 /*
1122 qtyexpected = $("#qty_"+idtab[1]+"_"+idtab[2]).data("expected")
1123 console.log(qtyexpected);
1124 $("#qty_"+idtab[1]+"_"+idtab[2]).val(qtyexpected);
1125 qtydispatched = $("#qty_dispatched_0_"+idtab[2]).data("dispatched")
1126 $("#qty_dispatched_0_"+idtab[2]).val(qtydispatched);
1127 */
1128 } else {
1129 console.log("We remove the object")
1130 $(this).remove();
1131 $("tr[name^=\'"+idtab[0]+"_\'][name$=\'_"+idtab[2]+"\']:last .splitbutton").show();
1132 }
1133 });
1134 return false;
1135 });
1136
1137 $("#resetalltoexpected").click(function(){
1138 $(".qtydispatchinput").each(function(){
1139 console.log("We reset to expected "+$(this).attr("id")+" qty to dispatch");
1140 $(this).val($(this).data("expected"));
1141 });
1142 return false;
1143 });
1144
1145 $(".resetline").click(function(e){
1146 e.preventDefault();
1147 id = $(this).attr("id");
1148 id = id.split("reset_");
1149 console.log("Reset trigger for id = qty_"+id[1]);
1150 $("#qty_"+id[1]).val("");
1151 return false;
1152 });
1153 });
1154 </script>';
1155}
1156
1157// End of page
1158llxFooter();
1159$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:56
llxFooter()
Empty footer.
Definition wrapper.php:70
Class to manage table commandefournisseurdispatch.
Class to manage predefined suppliers products.
Class to manage comment.
Class to manage warehouses.
Class to manage generation of HTML components Only common components must be here.
Class with static methods for building HTML components related to products Only components common to ...
Class to manage products or services.
Class to manage projects.
Class to manage receptions.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition date.lib.php:409
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.
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...
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
ui dialog ui datepicker calendar ui widget content ui state ui datepicker calendar ui widget header ui state ui datepicker calendar ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
reception_prepare_head(Reception $object)
Prepare array with list of tabs.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:123
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=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.