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