dolibarr 25.0.0-alpha
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-2023 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-2026 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2019-2020 Christophe Battarel <christophe@altairis.fr>
12 * Copyright (C) 2024-2026 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';
36
45require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php';
46require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
48require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
49require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
50require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
51require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
52require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
53
54if (isModEnabled('project')) {
55 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
56}
57
58// Load translation files required by the page
59$langs->loadLangs(array("bills", "orders", "sendings", "companies", "products", "stocks", "receptions"));
60
61if (isModEnabled('productbatch')) {
62 $langs->load('productbatch');
63}
64
65// Security check
66$id = GETPOSTINT("id");
67$ref = GETPOST('ref');
68$lineid = GETPOSTINT('lineid');
69$action = GETPOST('action', 'aZ09');
70$fk_default_warehouse = GETPOSTINT('fk_default_warehouse');
71$cancel = GETPOST('cancel', 'alpha');
72$confirm = GETPOST('confirm', 'alpha');
73
74if ($user->isExternalUser()) {
75 $socid = $user->isExternalUser();
76}
77
78$hookmanager->initHooks(array('ordersupplierdispatch'));
79
80// Get id of project
81$projectid = 0;
82if (GETPOSTISSET("projectid")) {
83 $projectid = GETPOSTINT("projectid");
84}
85
87
88if ($id > 0 || !empty($ref)) {
89 $result = $object->fetch($id, $ref);
90 if ($result < 0) {
91 setEventMessages($object->error, $object->errors, 'errors');
92 }
93 $result = $object->fetch_thirdparty();
94 if ($result < 0) {
95 setEventMessages($object->error, $object->errors, 'errors');
96 }
97}
98
99if (empty($conf->reception->enabled)) {
100 $permissiontoreceive = $user->hasRight("fournisseur", "commande", "receptionner");
101 $permissiontocontrol = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight("fournisseur", "commande", "receptionner")) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight("fournisseur", "commande_advance", "check")));
102} else {
103 $permissiontoreceive = $user->hasRight("reception", "creer");
104 $permissiontocontrol = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight("reception", "creer")) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight("reception", "reception_advance", "validate")));
105}
106
107// $id is id of a purchase order.
108$result = restrictedArea($user, 'fournisseur', $object, 'commande_fournisseur', 'commande');
109
110if (!isModEnabled('stock')) {
112}
113
114$usercancreate = ($user->hasRight("fournisseur", "commande", "creer") || $user->hasRight("supplier_order", "creer"));
115$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php
116
117
118/*
119 * Actions
120 */
121
122$error = 0;
123$errors = [];
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
130if ($action == 'checkdispatchline' && $permissiontocontrol) {
131 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
132
133 $db->begin();
134
135 $result = $supplierorderdispatch->fetch($lineid);
136 if (!$result) {
137 $error++;
138 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
139 $action = '';
140 }
141
142 if (!$error) {
143 $result = $supplierorderdispatch->setStatut(1);
144 if ($result < 0) {
145 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
146 $error++;
147 $action = '';
148 }
149 }
150
151 if (!$error) {
152 $result = $object->calcAndSetStatusDispatch($user);
153 if ($result < 0) {
154 setEventMessages($object->error, $object->errors, 'errors');
155 $error++;
156 $action = '';
157 }
158 }
159 if (!$error) {
160 $db->commit();
161 } else {
162 $db->rollback();
163 }
164}
165
166if ($action == 'uncheckdispatchline' && $permissiontocontrol) {
167 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
168
169 $db->begin();
170
171 $result = $supplierorderdispatch->fetch($lineid);
172 if (!$result) {
173 $error++;
174 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
175 $action = '';
176 }
177
178 if (!$error) {
179 $result = $supplierorderdispatch->setStatut(0);
180 if ($result < 0) {
181 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
182 $error++;
183 $action = '';
184 }
185 }
186 if (!$error) {
187 $result = $object->calcAndSetStatusDispatch($user);
188 if ($result < 0) {
189 setEventMessages($object->error, $object->errors, 'errors');
190 $error++;
191 $action = '';
192 }
193 }
194 if (!$error) {
195 $db->commit();
196 } else {
197 $db->rollback();
198 }
199}
200
201if ($action == 'denydispatchline' && $permissiontocontrol) {
202 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
203
204 $db->begin();
205
206 $result = $supplierorderdispatch->fetch($lineid);
207 if (!$result) {
208 $error++;
209 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
210 $action = '';
211 }
212
213 if (!$error) {
214 $result = $supplierorderdispatch->setStatut(2);
215 if ($result < 0) {
216 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
217 $error++;
218 $action = '';
219 }
220 }
221 if (!$error) {
222 $result = $object->calcAndSetStatusDispatch($user);
223 if ($result < 0) {
224 setEventMessages($object->error, $object->errors, 'errors');
225 $error++;
226 $action = '';
227 }
228 }
229 if (!$error) {
230 $db->commit();
231 } else {
232 $db->rollback();
233 }
234}
235
236$saveprice = "savepriceIsNotSet";
237if ($action == 'dispatch' && $permissiontoreceive) {
238 $notrigger = 0;
239
240 $db->begin();
241
242 $pos = 0;
243 $comment = (string) GETPOST('comment', 'alpha');
244
245 foreach ($_POST as $key => $value) {
246 // without batch module enabled
247 $reg = array();
248 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
249 $pos++;
250
251 // $numline=$reg[2] + 1; // line of product
252 $numline = $pos;
253 $prod = "product_".$reg[1].'_'.$reg[2];
254 $qty = "qty_".$reg[1].'_'.$reg[2];
255 $ent = "entrepot_".$reg[1].'_'.$reg[2];
256 if (empty(GETPOST($ent))) {
257 $ent = $fk_default_warehouse;
258 }
259 $pu = "pu_".$reg[1].'_'.$reg[2]; // This is unit price including discount
260 $fk_commandefourndet = "fk_commandefourndet_".$reg[1].'_'.$reg[2];
261
262 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
263 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
264 $dto = GETPOSTINT("dto_".$reg[1].'_'.$reg[2]);
265 if (!empty($dto)) {
266 $unit_price = price2num((float) GETPOST("pu_".$reg[1]) * (100 - $dto) / 100, 'MU');
267 }
268 $saveprice = "saveprice_".$reg[1].'_'.$reg[2];
269 }
270 }
271
272 // We ask to move a qty
273 $qtytomove = GETPOSTFLOAT($qty);
274 $puformove = GETPOSTFLOAT($pu);
275 if ($qtytomove != 0) {
276 if (!(GETPOSTINT($ent) > 0)) {
277 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.');
278 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline);
279 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
280 $error++;
281 }
282
283 if (!$error) {
284 $result = $object->dispatchProduct($user, GETPOSTINT($prod), $qtytomove, GETPOSTINT($ent), $puformove, GETPOST('comment'), '', '', '', GETPOSTINT($fk_commandefourndet), $notrigger);
285 if ($result < 0) {
286 setEventMessages($object->error, $object->errors, 'errors');
287 $error++;
288 }
289
290 if (!$error && getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
291 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
292 $dto = price2num(GETPOST("dto_".$reg[1].'_'.$reg[2]), '');
293 if (empty($dto)) {
294 $dto = 0;
295 }
296
297 //update supplier price
298 if (GETPOSTISSET($saveprice)) {
299 // TODO Use class
300 $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price";
301 $sql .= " SET unitprice='".price2num(GETPOST($pu), 'MU')."'";
302 $sql .= ", price=".price2num(GETPOST($pu), 'MU')."*quantity";
303 $sql .= ", remise_percent = ".((float) $dto);
304 $sql .= " WHERE fk_soc=".((int) $object->socid);
305 $sql .= " AND fk_product=".(GETPOSTINT($prod));
306
307 $resql = $db->query($sql);
308 }
309 }
310 }
311 }
312 }
313 }
314 // with batch module enabled
315 if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
316 $pos++;
317
318 // eat-by date dispatch
319 // $numline=$reg[2] + 1; // line of product
320 $numline = $pos;
321 $prod = 'product_batch_'.$reg[1].'_'.$reg[2];
322 $qty = 'qty_'.$reg[1].'_'.$reg[2];
323 $ent = 'entrepot_'.$reg[1].'_'.$reg[2];
324 $pu = 'pu_'.$reg[1].'_'.$reg[2];
325 $fk_commandefourndet = 'fk_commandefourndet_'.$reg[1].'_'.$reg[2];
326 $lot = 'lot_number_'.$reg[1].'_'.$reg[2];
327 $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'));
328 $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'));
329
330 $fk_commandefourndet = 'fk_commandefourndet_'.$reg[1].'_'.$reg[2];
331
332 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
333 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
334 $dto = GETPOSTFLOAT("dto_".$reg[1].'_'.$reg[2]);
335 if (!empty($dto)) {
336 $unit_price = price2num((float) GETPOST("pu_".$reg[1]) * (100 - $dto) / 100, 'MU');
337 }
338 $saveprice = "saveprice_".$reg[1].'_'.$reg[2];
339 }
340 }
341
342 // We ask to move a qty
343 $qtytomove = GETPOSTFLOAT($qty);
344 $puformove = GETPOSTFLOAT($pu);
345 if ($qtytomove > 0) {
346 $productId = GETPOSTINT($prod);
347
348 if (!(GETPOSTINT($ent) > 0)) {
349 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.');
350 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline).'-'.((int) $reg[1] + 1);
351 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
352 $error++;
353 }
354
355 // check sell-by / eat-by date is mandatory
356 /* Not required. Mandatory is checked when we insert the lot. Once lot has been recorded and is known, user can just enter the lot/serial
357 $errorMsgArr = Productlot::checkSellOrEatByMandatoryFromProductIdAndDates($productId, $dDLC, $dDLUO);
358 if (!(GETPOST($lot, 'alpha')) || !empty($errorMsgArr)) {
359 dol_syslog('No dispatch for line '.$key.' as serial/eat-by/sellby date are not set');
360 $text = $langs->transnoentities('atleast1batchfield').', '.$langs->transnoentities('Line').' '.($numline).'-'.($reg[1] + 1);
361 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
362 $error++;
363 }*/
364 if (!GETPOST($lot, 'alpha') && !$dDLUO && !$dDLC) {
365 dol_syslog('No dispatch for line '.$key.' as serial/eat-by/sellby date are not set');
366 $text = $langs->transnoentities('atleast1batchfield').', '.$langs->transnoentities('Line').' '.($numline).'-'.((int) $reg[1] + 1);
367 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
368 $error++;
369 }
370
371 if (!$error) {
372 $result = $object->dispatchProduct($user, $productId, $qtytomove, GETPOSTINT($ent), $puformove, GETPOST('comment'), $dDLUO, $dDLC, GETPOST($lot, 'alpha'), GETPOSTINT($fk_commandefourndet), $notrigger);
373 if ($result < 0) {
374 setEventMessages($object->error, $object->errors, 'errors');
375 $error++;
376 }
377
378 if (!$error && getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
379 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
380 $dto = GETPOSTFLOAT("dto_".$reg[1].'_'.$reg[2]);
381 //update supplier price
382 if (GETPOSTISSET($saveprice)) {
383 // TODO Use class
384 $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price";
385 $sql .= " SET unitprice = ".price2num(GETPOST($pu), 'MU', 2);
386 $sql .= ", price = ".price2num(GETPOST($pu), 'MU', 2)." * quantity";
387 $sql .= ", remise_percent = ".price2num((empty($dto) ? 0 : $dto), 3, 2);
388 $sql .= " WHERE fk_soc = ".((int) $object->socid);
389 $sql .= " AND fk_product=".((int) $productId);
390
391 $resql = $db->query($sql);
392 }
393 }
394 }
395 }
396 }
397 }
398 }
399
400 if (!$error) {
401 $result = $object->calcAndSetStatusDispatch($user, GETPOST('closeopenorder') ? 1 : 0, GETPOST('comment'));
402 if ($result < 0) {
403 setEventMessages($object->error, $object->errors, 'errors');
404 $error++;
405 }
406 }
407
408 if ($result >= 0 && !$error) {
409 $db->commit();
410
411 setEventMessages($langs->trans("ReceptionsRecorded"), null, 'mesgs');
412
413 header("Location: dispatch.php?id=".$id);
414 exit();
415 } else {
416 $db->rollback();
417 }
418}
419
420$batch = '';
421$eatby = null;
422$sellby = 0;
423$qty = 0;
424$price = '0';
425$entrepot = 0;
426$product = 0;
427
428// Remove a dispatched line
429if ($action == 'confirm_deleteline' && $confirm == 'yes' && $permissiontoreceive) {
430 $db->begin();
431
432 $comment = '';
433
434 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
435 $result = $supplierorderdispatch->fetch($lineid);
436 if ($result > 0) {
437 $qty = $supplierorderdispatch->qty;
438 $entrepot = $supplierorderdispatch->fk_entrepot;
439 $product = $supplierorderdispatch->fk_product;
440 $price = price2num(GETPOST('price', 'alpha'), 'MU');
441 $comment = $supplierorderdispatch->comment;
442 $eatby = $supplierorderdispatch->eatby;
443 $sellby = $supplierorderdispatch->sellby;
444 $batch = $supplierorderdispatch->batch;
445
446 $result = $supplierorderdispatch->delete($user);
447 }
448 if ($result < 0) {
449 $errors = $object->errors;
450 $error++;
451 } else {
452 // If module stock is enabled and the stock increase is done on purchase order dispatching
453 if ($entrepot > 0 && isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') && empty($supplierorderdispatch->fk_reception)) {
454 $mouv = new MouvementStock($db);
455 if ($product > 0) {
456 $mouv->origin = &$object;
457 $mouv->setOrigin($object->element, $object->id);
458 $result = $mouv->livraison($user, $product, $entrepot, $qty, (float) $price, (string) $comment, '', (int) $eatby, (int) $sellby, $batch);
459 if ($result < 0) {
460 $errors = $mouv->errors;
461 $error++;
462 }
463 }
464 }
465 }
466 if ($error > 0) {
467 $db->rollback();
468 setEventMessages(null, $errors, 'errors');
469 } else {
470 $db->commit();
471 }
472}
473
474// Update a dispatched line
475if ($action == 'updateline' && $permissiontoreceive && empty($cancel)) {
476 $db->begin();
477
478 $comment = '';
479
480 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
481 $result = $supplierorderdispatch->fetch($lineid);
482 if ($result > 0) {
483 $qty = $supplierorderdispatch->qty;
484 $entrepot = $supplierorderdispatch->fk_entrepot;
485 $product = $supplierorderdispatch->fk_product;
486 $price = GETPOSTFLOAT('price');
487 $comment = $supplierorderdispatch->comment;
488 $eatby = $supplierorderdispatch->eatby;
489 $sellby = $supplierorderdispatch->sellby;
490 $batch = $supplierorderdispatch->batch;
491
492 $supplierorderdispatch->qty = GETPOSTFLOAT('qty', 'MS');
493 $supplierorderdispatch->fk_entrepot = GETPOSTINT('fk_entrepot');
494 $result = $supplierorderdispatch->update($user);
495 }
496 if ($result < 0) {
497 $error++;
498 $errors = $supplierorderdispatch->errors;
499 } else {
500 // If module stock is enabled and the stock increase is done on purchase order dispatching
501 if ($entrepot > 0 && isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER')) {
502 $mouv = new MouvementStock($db);
503 if ($product > 0) {
504 $mouv->origin = &$object;
505 $mouv->setOrigin($object->element, $object->id);
506 $result = $mouv->livraison($user, $product, $entrepot, $qty, $price, (string) $comment, '', (int) $eatby, (int) $sellby, $batch);
507 if ($result < 0) {
508 $errors = $mouv->errors;
509 $error++;
510 } else {
511 $mouv->origin = &$object;
512 $result = $mouv->reception($user, $product, $supplierorderdispatch->fk_entrepot, $supplierorderdispatch->qty, $price, (string) $comment, (int) $eatby, (int) $sellby, $batch);
513 if ($result < 0) {
514 $errors = $mouv->errors;
515 $error++;
516 }
517 }
518 }
519 }
520 }
521 if ($error > 0) {
522 $db->rollback();
523 setEventMessages($langs->trans("Error"), $errors, 'errors');
524 } else {
525 $db->commit();
526 }
527}
528
529
530/*
531 * View
532 */
533
534$now = dol_now();
535
536$form = new Form($db);
537$formproduct = new FormProduct($db);
538$warehouse_static = new Entrepot($db);
539$supplierorderdispatch = new CommandeFournisseurDispatch($db);
540
541$title = $object->ref." - ".$langs->trans('OrderDispatch');
542$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores';
543$morejs = array('/fourn/js/lib_dispatch.js.php');
544
545llxHeader('', $title, $help_url, '', 0, 0, $morejs, '', '', 'mod-supplier-order page-card_dispatch');
546
547if ($id > 0 || !empty($ref)) {
548 $soc = new Societe($db);
549 $soc->fetch($object->socid);
550
551 $author = new User($db);
552 $author->fetch($object->user_author_id);
553
554 $head = ordersupplier_prepare_head($object);
555
556 $title = $langs->trans("SupplierOrder");
557 print dol_get_fiche_head($head, 'dispatch', $title, -1, 'order');
558
559 $formconfirm = '';
560
561 // Confirmation to delete line
562 if ($action == 'ask_deleteline') {
563 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
564 }
565
566 // Call Hook formConfirm
567 $parameters = array('lineid' => $lineid);
568 // Note that $action and $object may be modified by hook
569 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
570 if (empty($reshook)) {
571 $formconfirm .= $hookmanager->resPrint;
572 } elseif ($reshook > 0) {
573 $formconfirm = $hookmanager->resPrint;
574 }
575
576 // Print form confirm
577 print $formconfirm;
578
579 // Supplier order card
580
581 $linkback = '<a href="'.DOL_URL_ROOT.'/fourn/commande/list.php'.(!empty($socid) ? '?socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
582
583 $morehtmlref = '<div class="refidno">';
584 // Ref supplier
585 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, 0, 'string', '', 0, 1);
586 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, 0, 'string', '', null, null, '', 1);
587 // Thirdparty
588 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
589 // Project
590 if (isModEnabled('project')) {
591 $langs->load("projects");
592 $morehtmlref .= '<br>';
593 if (0) { // @phpstan-ignore-line
594 $caneditproject = false; // For static analysis
595 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
596 if ($action != 'classify' && $caneditproject) {
597 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
598 }
599 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $object->socid : -1), (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
600 } else {
601 if (!empty($object->fk_project)) {
602 $proj = new Project($db);
603 $proj->fetch($object->fk_project);
604 $morehtmlref .= $proj->getNomUrl(1);
605 if ($proj->title) {
606 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
607 }
608 }
609 }
610 }
611 $morehtmlref .= '</div>';
612
613
614 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
615
616
617 print '<div class="fichecenter">';
618 print '<div class="underbanner clearboth"></div>';
619
620 print '<table class="border tableforfield" width="100%">';
621
622 // Date
623 if ($object->methode_commande_id > 0) {
624 print '<tr><td class="titlefield">'.$langs->trans("Date").'</td><td>';
625 if ($object->date_commande) {
626 print dol_print_date($object->date_commande, "dayhour")."\n";
627 }
628 print "</td></tr>";
629
630 if ($object->methode_commande) {
631 print '<tr><td>'.$langs->trans("Method").'</td><td>'.$object->getInputMethod().'</td></tr>';
632 }
633 }
634
635 // Author
636 print '<tr><td class="titlefield">'.$langs->trans("AuthorRequest").'</td>';
637 print '<td>'.$author->getNomUrl(-1, '', 0, 0, 0).'</td>';
638 print '</tr>';
639
640 $parameters = array();
641 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
642
643 print "</table>";
644
645 print '</div>';
646
647 // if ($mesg) print $mesg;
648 print '<br>';
649
650 $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.
651
652 // Line of orders
654 print '<br><span class="opacitymedium">'.$langs->trans("OrderStatusNotReadyToDispatch").'</span>';
655 }
656
657
658 print '<br>';
659
660 $listwarehouses = array();
661
665 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
666 $formproduct = new FormProduct($db);
667 $formproduct->loadWarehouses();
668 $entrepot = new Entrepot($db);
669 $listwarehouses = $entrepot->list_array(1);
670
671
672 if (empty($conf->reception->enabled)) {
673 print '<form method="POST" action="dispatch.php?id='.$object->id.'">';
674 } else {
675 print '<form method="post" action="'.dol_buildpath('/reception/card.php', 1).'?originid='.$object->id.'&origin=supplierorder">';
676 }
677
678 print '<input type="hidden" name="token" value="'.newToken().'">';
679 if (empty($conf->reception->enabled)) {
680 print '<input type="hidden" name="action" value="dispatch">';
681 } else {
682 print '<input type="hidden" name="action" value="create">';
683 }
684
685 print '<div class="div-table-responsive-no-min">';
686 print '<table class="noborder centpercent">';
687
688 // Set $products_dispatched with qty dispatched for each product id
689 $products_dispatched = array();
690 $sql = "SELECT l.rowid, cfd.fk_product, sum(cfd.qty) as qty";
691 $sql .= " FROM ".MAIN_DB_PREFIX."receptiondet_batch as cfd";
692 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseurdet as l on l.rowid = cfd.fk_elementdet";
693 $sql .= " WHERE cfd.fk_element = ".((int) $object->id);
694 $sql .= " GROUP BY l.rowid, cfd.fk_product";
695
696 $resql = $db->query($sql);
697 if ($resql) {
698 $num = $db->num_rows($resql);
699 $i = 0;
700
701 if ($num) {
702 while ($i < $num) {
703 $objd = $db->fetch_object($resql);
704 $products_dispatched[$objd->rowid] = price2num($objd->qty, 'MS');
705 $i++;
706 }
707 }
708 $db->free($resql);
709 }
710
711 //$sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, SUM(l.qty) as qty,";
712 $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, l.qty as qty,";
713 $sql .= " p.ref, p.label, p.tobatch, p.fk_default_warehouse";
714
715 // Enable hooks to alter the SQL query (SELECT)
716 $parameters = array();
717 $reshook = $hookmanager->executeHooks(
718 'printFieldListSelect',
719 $parameters,
720 $object,
721 $action
722 );
723 if ($reshook < 0) {
724 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
725 }
726 $sql .= $hookmanager->resPrint;
727
728 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as l";
729 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON l.fk_product=p.rowid";
730 $sql .= " WHERE l.fk_commande = ".((int) $object->id);
731 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
732 $sql .= " AND l.product_type = 0";
733 }
734
735 // Enable hooks to alter the SQL query (WHERE)
736 $parameters = array();
737 $reshook = $hookmanager->executeHooks(
738 'printFieldListWhere',
739 $parameters,
740 $object,
741 $action
742 );
743 if ($reshook < 0) {
744 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
745 }
746 $sql .= $hookmanager->resPrint;
747
748 //$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
749 $sql .= " ORDER BY l.rang, p.ref, p.label";
750
751 // Nb of predefined product lines to dispatch (already done or not) if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is off (default)
752 // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on.
753 $nbproduct = 0;
754
755 $resql = $db->query($sql);
756 if ($resql) {
757 $num = $db->num_rows($resql);
758 $i = 0;
759
760 if ($num) {
761 print '<tr class="liste_titre">';
762
763 print '<td>'.$langs->trans("Description").'</td>';
764 if (isModEnabled('productbatch')) {
765 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>';
766 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
767 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>';
768 }
769 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
770 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>';
771 }
772 } else {
773 print '<td></td>';
774 print '<td></td>';
775 print '<td></td>';
776 }
777 print '<td class="right">'.$langs->trans("SupplierRef").'</td>';
778 print '<td class="right">'.$langs->trans("QtyOrdered").'</td>';
779 print '<td class="right">'.$langs->trans("QtyDispatchedShort").'</td>';
780 print ' <td class="right">'.$langs->trans("QtyToDispatchShort");
781 print '<br><a href="#" id="autoreset">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').$langs->trans("Reset").'</a></td>';
782 print '<td width="32"></td>';
783
784 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
785 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
786 print '<td class="right">'.$langs->trans("Price").'</td>';
787 print '<td class="right">'.$langs->trans("ReductionShort").' (%)</td>';
788 print '<td class="right">'.$langs->trans("UpdatePrice").'</td>';
789 }
790 }
791
792 print '<td align="right">'.$langs->trans("Warehouse");
793
794 // Select warehouse to force it everywhere
795 if (count($listwarehouses) > 1) {
796 print '<br>'.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans("ForceTo"), 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1);
797 } elseif (count($listwarehouses) == 1) {
798 print '<br>'.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1);
799 }
800
801 print '</td>';
802
803 // Enable hooks to append additional columns
804 $parameters = array();
805 $reshook = $hookmanager->executeHooks(
806 'printFieldListTitle',
807 $parameters,
808 $object,
809 $action
810 );
811 if ($reshook < 0) {
812 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
813 }
814 print $hookmanager->resPrint;
815
816 print "</tr>\n";
817 }
818
819 $nbfreeproduct = 0; // Nb of lines of free products/services
820
821 $conf->cache['product'] = array();
822
823 // Loop on each source order line (may be more or less than current number of lines in llx_commande_fournisseurdet)
824 while ($i < $num) {
825 $objp = $db->fetch_object($resql);
826
827 // We don't display free products
828 if (!$objp->fk_product > 0) {
829 $nbfreeproduct++;
830 } else {
831 $alreadydispatched = isset($products_dispatched[$objp->rowid]) ? $products_dispatched[$objp->rowid] : 0;
832 $remaintodispatch = price2num($objp->qty - ((float) $alreadydispatched), 5); // Calculation of dispatched
833 if ($remaintodispatch < 0 && !getDolGlobalString('SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN')) {
834 $remaintodispatch = 0;
835 }
836
837 if ($remaintodispatch || !getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
838 $nbproduct++;
839
840 // To show detail cref and description value, we must make calculation by cref
841 // print ($objp->cref?' ('.$objp->cref.')':'');
842 // if ($objp->description) print '<br>'.nl2br($objp->description);
843 $suffix = '_0_'.$i;
844
845 print "\n";
846 print '<!-- Line to dispatch '.$suffix.' -->'."\n";
847 // hidden fields for js function
848 print '<input id="qty_ordered'.$suffix.'" type="hidden" value="'.$objp->qty.'">';
849 print '<input id="qty_dispatched'.$suffix.'" type="hidden" value="'.(float) $alreadydispatched.'">';
850 print '<tr class="oddeven">';
851
852 if (empty($conf->cache['product'][$objp->fk_product])) {
853 $tmpproduct = new Product($db);
854 $tmpproduct->fetch($objp->fk_product);
855 $conf->cache['product'][$objp->fk_product] = $tmpproduct;
856 } else {
857 $tmpproduct = $conf->cache['product'][$objp->fk_product];
858 }
859
860 $linktoprod = $tmpproduct->getNomUrl(1);
861 $linktoprod .= ' - '.$objp->label."\n";
862
863 if (isModEnabled('productbatch')) {
864 if ($objp->tobatch) {
865 // Product
866 print '<td>';
867 print $linktoprod;
868 print "</td>";
869 print '<td class="dispatch_batch_number"></td>';
870 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
871 print '<td class="dispatch_dlc"></td>';
872 }
873 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
874 print '<td class="dispatch_dluo"></td>';
875 }
876 } else {
877 // Product
878 print '<td>';
879 print $linktoprod;
880 print "</td>";
881 print '<td class="dispatch_batch_number">';
882 print '<span class="opacitymedium small">'.$langs->trans("ProductDoesNotUseBatchSerial").'</small>';
883 print '</td>';
884 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
885 print '<td class="dispatch_dlc"></td>';
886 }
887 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
888 print '<td class="dispatch_dluo"></td>';
889 }
890 }
891 } else {
892 print '<td colspan="4">';
893 print $linktoprod;
894 print "</td>";
895 }
896
897 // Define unit price for PMP calculation
898 $up_ht_disc = $objp->subprice;
899 if (!empty($objp->remise_percent) && !getDolGlobalString('STOCK_EXCLUDE_DISCOUNT_FOR_PMP')) {
900 $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU');
901 }
902
903 // Supplier ref
904 print '<td class="right">'.$objp->sref.'</td>';
905
906 // Qty ordered
907 print '<td class="right">'.$objp->qty.'</td>';
908
909 // Already dispatched
910 print '<td class="right">'.$alreadydispatched.'</td>';
911
912 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
913 $type = 'batch';
914 print '<td class="right">';
915 print '</td>'; // Qty to dispatch
916 print '<td>';
917 //print img_picto($langs->trans('AddDispatchBatchLine'), 'split', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"');
918 print '</td>'; // Dispatch column
919 print '<td></td>'; // Warehouse column
920
921 // Enable hooks to append additional columns
922 $parameters = array(
923 // allows hook to distinguish between the rows with information and the rows with dispatch form input
924 'is_information_row' => true,
925 'i' => $i,
926 'suffix' => $suffix,
927 'objp' => $objp,
928 );
929 $reshook = $hookmanager->executeHooks(
930 'printFieldListValue',
931 $parameters,
932 $object,
933 $action
934 );
935 if ($reshook < 0) {
936 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
937 }
938 print $hookmanager->resPrint;
939
940 print '</tr>';
941
942 print '<tr class="oddeven" name="'.$type.$suffix.'">';
943 print '<td>';
944 print '<input name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
945 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
946
947 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
948 if (getDolGlobalString('SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT')) { // Not tested !
949 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price($up_ht_disc).'">';
950 } else {
951 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price($up_ht_disc).'">';
952 }
953
954 print '</td>';
955
956 print '<td>';
957 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.GETPOST('lot_number'.$suffix).'">';
958 print '</td>';
959 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
960 print '<td class="nowraponall">';
961 $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOSTINT('dlc'.$suffix.'month'), GETPOSTINT('dlc'.$suffix.'day'), GETPOSTINT('dlc'.$suffix.'year'));
962 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, 0, 0, 1, '');
963 print '</td>';
964 }
965 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
966 print '<td class="nowraponall">';
967 $dluodatesuffix = dol_mktime(0, 0, 0, GETPOSTINT('dluo'.$suffix.'month'), GETPOSTINT('dluo'.$suffix.'day'), GETPOSTINT('dluo'.$suffix.'year'));
968 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, 0, 0, 1, '');
969 print '</td>';
970 }
971 print '<td colspan="3">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
972 } else {
973 $type = 'dispatch';
974 $colspan = 7;
975 $colspan = (getDolGlobalString('PRODUCT_DISABLE_SELLBY')) ? --$colspan : $colspan;
976 $colspan = (getDolGlobalString('PRODUCT_DISABLE_EATBY')) ? --$colspan : $colspan;
977 print '<td class="right">';
978 print '</td>'; // Qty to dispatch
979 print '<td>';
980 //print img_picto($langs->trans('AddStockLocationLine'), 'split', 'class="splitbutton" onClick="addDispatchLine(' . $i . ',\'' . $type . '\')"');
981 print '</td>'; // Dispatch column
982 print '<td></td>'; // Warehouse column
983
984 // Enable hooks to append additional columns
985 $parameters = array(
986 // allows hook to distinguish between the rows with information and the rows with dispatch form input
987 'is_information_row' => true,
988 'i' => $i,
989 'suffix' => $suffix,
990 'objp' => $objp,
991 );
992 $reshook = $hookmanager->executeHooks(
993 'printFieldListValue',
994 $parameters,
995 $object,
996 $action
997 );
998 if ($reshook < 0) {
999 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1000 }
1001 print $hookmanager->resPrint;
1002
1003 print '</tr>';
1004
1005 print '<tr class="oddeven" name="'.$type.$suffix.'">';
1006 print '<td colspan="'.$colspan.'">';
1007 print '<input name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
1008 print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
1009
1010 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
1011 if (getDolGlobalString('SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT')) { // Not tested !
1012 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">';
1013 } else {
1014 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
1015 }
1016
1017 print '</td>';
1018 }
1019
1020 // Qty to dispatch
1021 print '<td class="right nowrap">';
1022 if ($remaintodispatch > 0) {
1023 $btnLabel = $langs->trans("Fill").' : '.$remaintodispatch;
1024 print '<button class="auto-fill-qty btn-low-emphasis --btn-icon" data-rowname="qty'.$suffix.'" data-value="'.$remaintodispatch.'" title="'.dol_escape_htmltag($btnLabel).'" aria-label="'.dol_escape_htmltag($btnLabel).'" >'.img_picto($btnLabel, 'fa-arrow-right', 'aria-hidden="true"', 0, 0, 1).'</button>';
1025 }
1026 print '<input id="qty'.$suffix.'" name="qty'.$suffix.'" type="number" step="any" class="width75 right qtydispatchinput" value="'.(GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : (!getDolGlobalString('SUPPLIER_ORDER_DISPATCH_FORCE_QTY_INPUT_TO_ZERO') ? $remaintodispatch : 0)).'">';
1027 print '<button class="resetline btn-low-emphasis --btn-icon" id="reset'.$suffix.'" title="'.dol_escape_htmltag($langs->trans("Reset")).'" >'.img_picto($langs->trans("Reset"), 'eraser', 'aria-hidden="true"', 0, 0, 1).'</button>';
1028 print '</td>';
1029
1030 print '<td>';
1031 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
1032 $type = 'batch';
1033 print img_picto($langs->trans('AddStockLocationLine'), 'split', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1034 if ($objp->tobatch == 2) {
1035 // Product managed with unique serial numbers: allow to enter several serial numbers at once (one line per serial)
1036 print img_picto($langs->trans('EnterMultipleSerialNumbers'), 'barcode', 'class="splitbutton marginleftonly" onClick="addDispatchLinesFromSerialList('.$i.', \''.$type.'\')"');
1037 }
1038 } else {
1039 $type = 'dispatch';
1040 print img_picto($langs->trans('AddStockLocationLine'), 'split', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1041 }
1042 print '</td>';
1043
1044 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
1045 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
1046 // Price
1047 print '<td class="right">';
1048 print '<input id="pu'.$suffix.'" name="pu'.$suffix.'" type="text" size="8" value="'.price((GETPOST('pu'.$suffix) != '' ? price2num(GETPOST('pu'.$suffix)) : $up_ht_disc)).'">';
1049 print '</td>';
1050
1051 // Discount
1052 print '<td class="right">';
1053 print '<input id="dto'.$suffix.'" name="dto'.$suffix.'" type="text" size="8" value="'.(GETPOST('dto'.$suffix) != '' ? GETPOST('dto'.$suffix) : '').'">';
1054 print '</td>';
1055
1056 // Save price
1057 print '<td class="center">';
1058 print '<input class="flat checkformerge" type="checkbox" name="saveprice'.$suffix.'" value="'.(GETPOST('saveprice'.$suffix) != '' ? GETPOST('saveprice'.$suffix) : '').'">';
1059 print '</td>';
1060 }
1061 }
1062
1063 // Warehouse
1064 print '<td class="right">';
1065 if (count($listwarehouses) > 1) {
1066 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, array(), 'csswarehouse'.$suffix);
1067 } elseif (count($listwarehouses) == 1) {
1068 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, array(), 'csswarehouse'.$suffix);
1069 } else {
1070 $langs->load("errors");
1071 print $langs->trans("ErrorNoWarehouseDefined");
1072 }
1073 print "</td>\n";
1074
1075 // Enable hooks to append additional columns
1076 $parameters = array(
1077 'is_information_row' => false, // this is a dispatch form row
1078 'i' => $i,
1079 'suffix' => $suffix,
1080 'objp' => $objp,
1081 );
1082 $reshook = $hookmanager->executeHooks(
1083 'printFieldListValue',
1084 $parameters,
1085 $object,
1086 $action
1087 );
1088 if ($reshook < 0) {
1089 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1090 }
1091 print $hookmanager->resPrint;
1092
1093 print "</tr>\n";
1094 }
1095 }
1096 $i++;
1097 }
1098 $db->free($resql);
1099 } else {
1100 dol_print_error($db);
1101 }
1102
1103 print "</table>\n";
1104 print '</div>';
1105
1106 if ($nbproduct) {
1107 $checkboxlabel = $langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv('StatusOrderReceivedAll'));
1108
1109 print '<div class="center">';
1110 $parameters = array();
1111 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1112 // modified by hook
1113 if (empty($reshook)) {
1114 if (empty($conf->reception->enabled)) {
1115 print $langs->trans("Comment").' : ';
1116 print '<input type="text" class="minwidth400" maxlength="128" name="comment" value="';
1117 print GETPOSTISSET("comment") ? GETPOST("comment") : $langs->trans("DispatchSupplierOrder", $object->ref);
1118 // print ' / '.$object->ref_supplier; // Not yet available
1119 print '" class="flat"><br>';
1120
1121 print '<input type="checkbox" checked="checked" name="closeopenorder"> '.$checkboxlabel;
1122 }
1123
1124 $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception");
1125
1126 print '<br>';
1127 print '<input type="hidden" name="backtopageforcancel" value="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
1128 print '<input type="submit" class="button" name="dispatch" value="'.dol_escape_htmltag($dispatchBt).'"';
1129 $disabled = 0;
1130 if (!$permissiontoreceive) {
1131 $disabled = 1;
1132 }
1133 if (count($listwarehouses) <= 0) {
1134 $disabled = 1;
1135 }
1136 if ($disabled) {
1137 print ' disabled';
1138 }
1139
1140 print '>';
1141 }
1142 print '</div>';
1143 }
1144
1145 // Message if nothing to dispatch
1146 if (!$nbproduct) {
1147 print "<br>\n";
1148 if (!getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
1149 print '<div class="opacitymedium">'.$langs->trans("NoPredefinedProductToDispatch").'</div>'; // No predefined line at all
1150 } else {
1151 print '<div class="opacitymedium">'.$langs->trans("NoMorePredefinedProductToDispatch").'</div>'; // No predefined line that remain to be dispatched.
1152 }
1153 }
1154
1155 print '</form>';
1156 }
1157
1158 print dol_get_fiche_end();
1159
1160 // default warehouse processing
1161 print '<script type="text/javascript">
1162 $(document).ready(function () {
1163 $("select[name=fk_default_warehouse]").change(function() {
1164 var fk_default_warehouse = $("option:selected", this).val();
1165 $("select[name^=entrepot_]").val(fk_default_warehouse).change();
1166 });
1167
1168 $(".auto-fill-qty").on("click touchstart", function(e){
1169 e.preventDefault();
1170 $("input[name="+$(this).data("rowname")+"]").val($(this).data("value")).trigger("change");
1171 });
1172
1173 $("#autoreset").click(function() {
1174 $(".qtydispatchinput").each(function(){
1175 id = $(this).attr("id");
1176 idtab = id.split("_");
1177 if(idtab[1] == 0){
1178 console.log(idtab);
1179 $(this).val("");
1180 $("#qty_dispatched_0_"+idtab[2]).val("0");
1181 } else {
1182 obj = $(this).parent().parent();
1183 nameobj = obj.attr("name");
1184 nametab = nameobj.split("_");
1185 obj.remove();
1186 $("tr[name^=\'"+nametab[0]+"_\'][name$=\'_"+nametab[2]+"\']:last .splitbutton").show();
1187 }
1188 });
1189 });
1190
1191 $(".resetline").click(function(e){
1192 e.preventDefault();
1193 id = $(this).attr("id");
1194 id = id.split("reset_");
1195 console.log("Reset trigger for id = qty_"+id[1]);
1196 $("#qty_"+id[1]).val("");
1197 });
1198 });
1199 </script>';
1200
1201 // List of lines already dispatched
1202 $sql = "SELECT p.rowid as pid, p.ref, p.label,";
1203 $sql .= " e.rowid as warehouse_id, e.ref as entrepot,";
1204 $sql .= " cfd.rowid as dispatchlineid, cfd.fk_product, cfd.qty, cfd.eatby, cfd.sellby, cfd.batch, cfd.comment, cfd.status, cfd.datec";
1205 $sql .= " ,cd.rowid, cd.subprice";
1206 if (isModEnabled('reception')) {
1207 $sql .= ", cfd.fk_reception, r.date_delivery";
1208 }
1209 $sql .= " FROM ".MAIN_DB_PREFIX."product as p,";
1210 $sql .= " ".MAIN_DB_PREFIX."receptiondet_batch as cfd";
1211 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseurdet as cd ON cd.rowid = cfd.fk_elementdet";
1212 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e ON cfd.fk_entrepot = e.rowid";
1213 if (isModEnabled('reception')) {
1214 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."reception as r ON cfd.fk_reception = r.rowid";
1215 }
1216 $sql .= " WHERE cfd.fk_element = ".((int) $object->id);
1217 $sql .= " AND cfd.fk_product = p.rowid";
1218 $sql .= " ORDER BY cfd.rowid ASC";
1219
1220 $resql = $db->query($sql);
1221 if ($resql) {
1222 $num = $db->num_rows($resql);
1223 $i = 0;
1224
1225 if ($num > 0) {
1226 print "<br>\n";
1227
1228 print load_fiche_titre($langs->trans("ReceivingForSameOrder"));
1229
1230 print '<div class="div-table-responsive">';
1231 print '<table id="dispatch_received_products" class="noborder centpercent">';
1232
1233 print '<tr class="liste_titre">';
1234 // Reception ref
1235 if (isModEnabled("reception")) {
1236 print '<td>'.$langs->trans("Reception").'</td>';
1237 }
1238 // Product
1239 print '<td>'.$langs->trans("Product").'</td>';
1240 print '<td class="center">'.$langs->trans("DateCreation").'</td>';
1241 print '<td class="center">'.$langs->trans("DateDeliveryPlanned").'</td>';
1242 if (isModEnabled('productbatch')) {
1243 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>';
1244 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1245 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>';
1246 }
1247 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1248 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>';
1249 }
1250 }
1251 print '<td class="right">'.$langs->trans("QtyDispatched").'</td>';
1252 print '<td>'.$langs->trans("Warehouse").'</td>';
1253 print '<td>'.$langs->trans("Comment").'</td>';
1254
1255 // Status
1256 if (getDolGlobalString('SUPPLIER_ORDER_USE_DISPATCH_STATUS') && !isModEnabled("reception")) {
1257 print '<td class="center" colspan="2">'.$langs->trans("Status").'</td>';
1258 } elseif (isModEnabled("reception")) {
1259 print '<td class="center"></td>';
1260 }
1261
1262 print '<td class="center" colspan="2"></td>';
1263
1264 print "</tr>\n";
1265
1266
1267 while ($i < $num) {
1268 $objp = $db->fetch_object($resql);
1269
1270 if ($action == 'editline' && $lineid == $objp->dispatchlineid) {
1271 print '<form name="editdispatchedlines" id="editdispatchedlines" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'#line_'.GETPOSTINT('lineid').'" method="POST">
1272 <input type="hidden" name="token" value="'.newToken().'">
1273 <input type="hidden" name="action" value="updateline">
1274 <input type="hidden" name="mode" value="">
1275 <input type="hidden" name="lineid" value="'.$objp->dispatchlineid.'">';
1276 }
1277
1278 print '<tr class="oddeven" id="line_'.$objp->dispatchlineid.'" >';
1279
1280 // Reception ref
1281 $reception = null;
1282 if (isModEnabled("reception")) {
1283 print '<td class="nowraponall">';
1284 if (!empty($objp->fk_reception)) {
1285 $reception = new Reception($db);
1286 $reception->fetch($objp->fk_reception);
1287 print $reception->getNomUrl(1);
1288 }
1289
1290 print "</td>";
1291 }
1292
1293 // Product
1294 print '<td class="tdoverflowmax150">';
1295 if (empty($conf->cache['product'][$objp->fk_product])) {
1296 $tmpproduct = new Product($db);
1297 $tmpproduct->fetch($objp->fk_product);
1298 $conf->cache['product'][$objp->fk_product] = $tmpproduct;
1299 } else {
1300 $tmpproduct = $conf->cache['product'][$objp->fk_product];
1301 }
1302 print $tmpproduct->getNomUrl(1);
1303 print ' - '.$objp->label;
1304 print "</td>\n";
1305
1306 // Date creation
1307 print '<td class="center">'.dol_print_date($db->jdate($objp->datec), 'day').'</td>';
1308
1309 // Date delivery of reception
1310 if (isModEnabled('reception')) {
1311 print '<td class="center">';
1312 if (!empty($objp->date_delivery)) {
1313 print dol_print_date($db->jdate($objp->date_delivery), 'day');
1314 }
1315 print '</td>';
1316 } else {
1317 print '<td class="center"></td>';
1318 }
1319
1320 // Batch / Eat by / Sell by
1321 if (isModEnabled('productbatch')) {
1322 if ($objp->batch) {
1323 include_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
1324 $lot = new Productlot($db);
1325 $lot->fetch(0, $objp->pid, $objp->batch);
1326 print '<td class="dispatch_batch_number" data-col="batch" data-batch="' . dolPrintHTMLForAttribute($objp->batch) . '" data-productid="' . $objp->fk_product . '" >'.$lot->getNomUrl(1).'</td>';
1327 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1328 print '<td class="dispatch_dlc">'.dol_print_date($lot->sellby, 'day').'</td>';
1329 }
1330 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1331 print '<td class="dispatch_dluo">'.dol_print_date($lot->eatby, 'day').'</td>';
1332 }
1333 } else {
1334 print '<td class="dispatch_batch_number" data-col="batch" data-batch="" data-productid="' . $objp->fk_product . '" ></td>';
1335 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1336 print '<td class="dispatch_dlc"></td>';
1337 }
1338 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1339 print '<td class="dispatch_dluo"></td>';
1340 }
1341 }
1342 }
1343
1344 // Qty
1345 print '<td class="right">';
1346 if ($action == 'editline' && $lineid == $objp->dispatchlineid) {
1347 print '<input style="width: 50px;" type="text" min="1" name="qty" value="'.$objp->qty.'" />';
1348 } else {
1349 print $objp->qty;
1350 }
1351 print '<input type="hidden" name="price" value="'.$objp->subprice.'" />';
1352 print '</td>';
1353 // Warehouse
1354 print '<td class="tdoverflowmax150">';
1355 if ($action == 'editline' && $lineid == $objp->dispatchlineid) {
1356 $warehouse_id = GETPOSTINT("fk_entrepot") ? GETPOSTINT("fk_entrepot") : ($objp->warehouse_id ? $objp->warehouse_id : '');
1357 if (count($listwarehouses) > 1) {
1358 print $formproduct->selectWarehouses($warehouse_id, "fk_entrepot", '', 1, 0, $objp->fk_product, '', 1, 1, array(), 'csswarehouse');
1359 } elseif (count($listwarehouses) == 1) {
1360 print $formproduct->selectWarehouses($warehouse_id, "fk_entrepot", '', 0, 0, $objp->fk_product, '', 1, 1, array(), 'csswarehouse');
1361 } else {
1362 $langs->load("errors");
1363 print $langs->trans("ErrorNoWarehouseDefined");
1364 }
1365 } else {
1366 $warehouse_static->id = $objp->warehouse_id;
1367 $warehouse_static->label = $objp->entrepot;
1368 print $warehouse_static->getNomUrl(1);
1369 }
1370 print '</td>';
1371
1372 // Comment
1373 print '<td class="tdoverflowmax300" style="white-space: pre;">'.$objp->comment.'</td>';
1374
1375 // Status
1376 if (getDolGlobalString('SUPPLIER_ORDER_USE_DISPATCH_STATUS') && !isModEnabled("reception")) {
1377 print '<td class="right">';
1378 $supplierorderdispatch->status = (empty($objp->status) ? 0 : $objp->status);
1379 // print $supplierorderdispatch->status;
1380 print $supplierorderdispatch->getLibStatut(5);
1381 print '</td>';
1382
1383 // Add button to check/uncheck dispatching
1384 print '<td class="center">';
1385 if (!$permissiontocontrol) {
1386 if (empty($objp->status)) {
1387 print '<a class="button buttonRefused" href="#">'.$langs->trans("Approve").'</a>';
1388 print '<a class="button buttonRefused" href="#">'.$langs->trans("Deny").'</a>';
1389 } else {
1390 print '<a class="button buttonRefused" href="#">'.$langs->trans("Disapprove").'</a>';
1391 print '<a class="button buttonRefused" href="#">'.$langs->trans("Deny").'</a>';
1392 }
1393 } else {
1394 $disabled = '';
1395 if ($object->status == $object::STATUS_RECEIVED_COMPLETELY) {
1396 $disabled = 1;
1397 }
1398 if (empty($objp->status)) {
1399 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=checkdispatchline&token=".newToken()."&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Approve").'</a>';
1400 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=denydispatchline&token=".newToken()."&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Deny").'</a>';
1401 }
1402 if ($objp->status == 1) {
1403 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=uncheckdispatchline&token=".newToken()."&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Reinit").'</a>';
1404 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=denydispatchline&token=".newToken()."&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Deny").'</a>';
1405 }
1406 if ($objp->status == 2) {
1407 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=uncheckdispatchline&token=".newToken()."&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Reinit").'</a>';
1408 print '<a class="button'.($disabled ? ' buttonRefused' : '').'" href="'.$_SERVER["PHP_SELF"]."?id=".$id."&action=checkdispatchline&token=".newToken()."&lineid=".$objp->dispatchlineid.'">'.$langs->trans("Approve").'</a>';
1409 }
1410 }
1411 print '</td>';
1412 } elseif (isModEnabled("reception")) {
1413 print '<td class="right">';
1414 if ($reception !== null && !empty($reception->id)) {
1415 print $reception->getLibStatut(5);
1416 }
1417 print '</td>';
1418 }
1419
1420 // Action
1421 if ($action != 'editline' || $lineid != $objp->dispatchlineid) {
1422 if (($reception === null) || empty($reception->id) || ($reception->statut == Reception::STATUS_DRAFT)) { // only allow edit on draft reception
1423 print '<td class="linecoledit center">';
1424 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&token='.newToken().'&lineid='.$objp->dispatchlineid.'#line_'.$objp->dispatchlineid.'">';
1425 print img_edit();
1426 print '</a>';
1427 print '</td>';
1428
1429 print '<td class="linecoldelete center">';
1430 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=ask_deleteline&token='.newToken().'&lineid='.$objp->dispatchlineid.'#dispatch_received_products">';
1431 print img_delete();
1432 print '</a>';
1433 print '</td>';
1434 } else {
1435 print '<td></td><td></td>';
1436 }
1437 } else {
1438 print '<td class="center valignmiddle">';
1439 print '<input type="submit" class="button button-save" id="savelinebutton" name="save" value="'.$langs->trans("Save").'" />';
1440 print '</td>';
1441 print '<td class="center valignmiddle">';
1442 print '<input type="submit" class="button button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'" />';
1443 print '</td>';
1444 }
1445
1446
1447 print "</tr>\n";
1448 if ($action == 'editline' && $lineid == $objp->dispatchlineid) {
1449 print '</form>';
1450 }
1451
1452 $i++;
1453 }
1454 $db->free($resql);
1455
1456 print "</table>\n";
1457 print '</div>';
1458 }
1459 } else {
1461 }
1462}
1463
1464// End of page
1465llxFooter();
1466$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage table ReceptionLineBatch.
Class to manage predefined suppliers products.
const STATUS_RECEIVED_PARTIALLY
Received partially.
const STATUS_CANCELED
Order canceled.
const STATUS_RECEIVED_COMPLETELY
Received completely.
const STATUS_ORDERSENT
Order sent, shipment on process.
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 stock movements.
Class to manage products or services.
Class with list of lots and properties.
Class to manage projects.
Class to manage receptions.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
ordersupplier_prepare_head(CommandeFournisseur $object)
Prepare array with list of tabs.
dol_now($mode='gmt')
Return date for now.
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...
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.
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, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
treeview li table
No Email.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:519
dolPrintHTMLForAttribute($s, $escapeonlyhtmltags=0, $allowothertags=array())
Return a string ready to be output into an HTML attribute (alt, title, data-html, ....
Definition html.lib.php:99
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Definition html.lib.php:172
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133
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.