dolibarr 21.0.0-beta
dispatch.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
5 * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@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-2024 Frédéric France <frederic.france@free.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/sendings.lib.php';
44if (isModEnabled('project')) {
45 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
46}
47
56// Load translation files required by the page
57$langs->loadLangs(array("sendings", "companies", "bills", 'deliveries', 'orders', 'stocks', 'other', 'propal', 'receptions'));
58
59if (isModEnabled('productbatch')) {
60 $langs->load('productbatch');
61}
62
63// Security check
64$id = GETPOSTINT("id");
65$ref = GETPOST('ref');
66$lineid = GETPOSTINT('lineid');
67$action = GETPOST('action', 'aZ09');
68$fk_default_warehouse = GETPOSTINT('fk_default_warehouse');
69$cancel = GETPOST('cancel', 'alpha');
70$confirm = GETPOST('confirm', 'alpha');
71
72$error = 0;
73$errors = array();
74
75if ($user->socid) {
76 $socid = $user->socid;
77}
78
79$hookmanager->initHooks(array('expeditiondispatch'));
80
81// Recuperation de l'id de projet
82$projectid = 0;
83if (GETPOSTISSET("projectid")) {
84 $projectid = GETPOSTINT("projectid");
85}
86
87$object = new Expedition($db);
88$objectorder = new Commande($db);
89
90
91if ($id > 0 || !empty($ref)) {
92 $result = $object->fetch($id, $ref);
93 if ($result <= 0) {
94 setEventMessages($object->error, $object->errors, 'errors');
95 }
96 $result = $object->fetch_thirdparty();
97 if ($result < 0) {
98 setEventMessages($object->error, $object->errors, 'errors');
99 }
100 if (!empty($object->origin)) {
101 $origin = $object->origin;
102 $typeobject = $object->origin;
103
104 $object->fetch_origin();
105 }
106}
107
108// $id is id of a purchase order.
109$result = restrictedArea($user, 'expedition', $object, '');
110
111if (!isModEnabled('stock')) {
112 accessforbidden('Module stock disabled');
113}
114
115$usercancreate = $user->hasRight('expedition', 'creer');
116$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php
117
118
119/*
120 * Actions
121 */
122
123$parameters = array();
124$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
125if ($reshook < 0) {
126 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
127}
128
129// Update a dispatched line
130if ($action == 'updatelines' && $usercancreate) {
131 $db->begin();
132 $error = 0;
133
134 $expeditiondispatch = new ExpeditionLigne($db);
135 $expeditionlinebatch = new ExpeditionLineBatch($db);
136
137 $pos = 0;
138
139 foreach ($_POST as $key => $value) {
140 // without batch module enabled
141 $reg = array();
142 if (preg_match('/^product_.*([0-9]+)_([0-9]+)$/i', $key, $reg)) {
143 $pos++;
144 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
145 $modebatch = "barcode";
146 } elseif (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) { // With batchmode enabled
147 $modebatch = "batch";
148 }
149
150 $numline = $pos;
151 if ($modebatch == "barcode") {
152 $prod = "product_".$reg[1].'_'.$reg[2];
153 } else {
154 $prod = 'product_batch_'.$reg[1].'_'.$reg[2];
155 }
156 $qty = "qty_".$reg[1].'_'.$reg[2];
157 $ent = "entrepot_".$reg[1].'_'.$reg[2];
158 $fk_commandedet = "fk_commandedet_".$reg[1].'_'.$reg[2];
159 $idline = GETPOST("idline_".$reg[1].'_'.$reg[2]);
160 $warehouse_id = GETPOSTINT($ent);
161 $prod_id = GETPOSTINT($prod);
162 //$pu = "pu_".$reg[1].'_'.$reg[2]; // This is unit price including discount
163 $lot = '';
164 $dDLUO = '';
165 $dDLC = '';
166 if ($modebatch == "batch") { //TODO: Make impossible to input non existing batch code
167 $lot = GETPOST('lot_number_'.$reg[1].'_'.$reg[2]);
168 $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'));
169 $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'));
170 }
171
172 $newqty = GETPOSTFLOAT($qty, 'MS');
173 //var_dump("modebatch=".$modebatch." newqty=".$newqty." ent=".$ent." idline=".$idline);
174
175 // We ask to move a qty
176 if (($modebatch == "batch" && $newqty >= 0) || ($modebatch == "barcode" && $newqty != 0)) {
177 if ($newqty > 0) { // If we want a qty, we make test on input data
178 if (!($warehouse_id > 0)) {
179 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.');
180 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline);
181 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
182 $error++;
183 }
184 if (!$error && $modebatch == "batch") {
185 $sql = "SELECT pb.rowid ";
186 $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb";
187 $sql .= " JOIN ".MAIN_DB_PREFIX."product_stock as ps";
188 $sql .= " ON ps.rowid = pb.fk_product_stock";
189 $sql .= " WHERE pb.batch = '".$db->escape($lot)."'";
190 $sql .= " AND ps.fk_product = ".((int) $prod_id) ;
191 $sql .= " AND ps.fk_entrepot = ".((int) $warehouse_id) ;
192
193 $resql = $db->query($sql);
194 if ($resql) {
195 $num = $db->num_rows($resql);
196 if ($num > 1) {
197 dol_syslog('No dispatch for line '.$key.' as too many combination warehouse, product, batch code was found ('.$num.').');
198 setEventMessages($langs->trans('ErrorTooManyCombinationBatchcode', $numline, $num), null, 'errors');
199 $error++;
200 } elseif ($num < 1) {
201 $tmpwarehouse = new Entrepot($db);
202 $tmpwarehouse->fetch($warehouse_id);
203 $tmpprod = new Product($db);
204 $tmpprod->fetch($prod_id);
205 dol_syslog('No dispatch for line '.$key.' as no combination warehouse, product, batch code was found.');
206 setEventMessages($langs->trans('ErrorNoCombinationBatchcode', $numline, $tmpwarehouse->ref, $tmpprod->ref, $lot), null, 'errors');
207 $error++;
208 }
209 $db->free($resql);
210 }
211 }
212 }
213
214 if (!$error) {
215 $qtystart = 0;
216
217 if ($idline > 0) {
218 $result = $expeditiondispatch->fetch($idline); // get line from llx_expeditiondet
219 if ($result < 0) {
220 setEventMessages($expeditiondispatch->error, $expeditiondispatch->errors, 'errors');
221 $error++;
222 } else {
223 $qtystart = $expeditiondispatch->qty;
224 $expeditiondispatch->qty = $newqty;
225 $expeditiondispatch->entrepot_id = GETPOSTINT($ent);
226
227 if ($newqty > 0) {
228 $result = $expeditiondispatch->update($user);
229 } else {
230 $result = $expeditiondispatch->delete($user);
231 }
232 if ($result < 0) {
233 setEventMessages($expeditiondispatch->error, $expeditiondispatch->errors, 'errors');
234 $error++;
235 }
236
237 if (!$error && $modebatch == "batch") {
238 if ($newqty > 0) {
239 $suffixkeyfordate = preg_replace('/^product_batch/', '', $key);
240 $sellby = dol_mktime(0, 0, 0, GETPOSTINT('dlc'.$suffixkeyfordate.'month'), GETPOSTINT('dlc'.$suffixkeyfordate.'day'), GETPOSTINT('dlc'.$suffixkeyfordate.'year'), '');
241 $eatby = dol_mktime(0, 0, 0, GETPOSTINT('dluo'.$suffixkeyfordate.'month'), GETPOSTINT('dluo'.$suffixkeyfordate.'day'), GETPOSTINT('dluo'.$suffixkeyfordate.'year'));
242
243 $sqlsearchdet = "SELECT rowid FROM ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element;
244 $sqlsearchdet .= " WHERE fk_expeditiondet = ".((int) $idline);
245 $sqlsearchdet .= " AND batch = '".$db->escape($lot)."'";
246 $resqlsearchdet = $db->query($sqlsearchdet);
247
248 if ($resqlsearchdet) {
249 $objsearchdet = $db->fetch_object($resqlsearchdet);
250 } else {
251 dol_print_error($db);
252 }
253
254 if ($objsearchdet) {
255 $sql = "UPDATE ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element." SET";
256 $sql .= " eatby = ".($eatby ? "'".$db->idate($eatby)."'" : "null");
257 $sql .= " , sellby = ".($sellby ? "'".$db->idate($sellby)."'" : "null");
258 $sql .= " , qty = ".((float) $newqty);
259 $sql .= " , fk_warehouse = ".((int) $warehouse_id);
260 $sql .= " WHERE rowid = ".((int) $objsearchdet->rowid);
261 } else {
262 $sql = "INSERT INTO ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element." (";
263 $sql .= "fk_expeditiondet, eatby, sellby, batch, qty, fk_origin_stock, fk_warehouse)";
264 $sql .= " VALUES (".((int) $idline).", ".($eatby ? "'".$db->idate($eatby)."'" : "null").", ".($sellby ? "'".$db->idate($sellby)."'" : "null").", ";
265 $sql .= " '".$db->escape($lot)."', ".((float) $newqty).", 0, ".((int) $warehouse_id).")";
266 }
267 } else {
268 $sql = " DELETE FROM ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element;
269 $sql .= " WHERE fk_expeditiondet = ".((int) $idline);
270 $sql .= " AND batch = '".$db->escape($lot)."'";
271 }
272
273 $resql = $db->query($sql);
274 if (!$resql) {
275 dol_print_error($db);
276 $error++;
277 }
278 }
279 }
280 } else {
281 $expeditiondispatch->fk_expedition = $object->id;
282 $expeditiondispatch->entrepot_id = GETPOSTINT($ent);
283 $expeditiondispatch->fk_elementdet = GETPOSTINT($fk_commandedet);
284 $expeditiondispatch->qty = $newqty;
285
286 if ($newqty > 0) {
287 $idline = $expeditiondispatch->insert($user);
288 if ($idline < 0) {
289 setEventMessages($expeditiondispatch->error, $expeditiondispatch->errors, 'errors');
290 $error++;
291 }
292
293 if ($modebatch == "batch" && !$error) {
294 $expeditionlinebatch->sellby = $dDLUO;
295 $expeditionlinebatch->eatby = $dDLC;
296 $expeditionlinebatch->batch = $lot;
297 $expeditionlinebatch->qty = $newqty;
298 $expeditionlinebatch->fk_origin_stock = 0;
299 $expeditionlinebatch->fk_warehouse = GETPOSTINT($ent);
300
301 $result = $expeditionlinebatch->create($idline);
302 if ($result < 0) {
303 setEventMessages($expeditionlinebatch->error, $expeditionlinebatch->errors, 'errors');
304 $error++;
305 }
306 }
307 }
308 }
309
310 // If module stock is enabled and the stock decrease is done on edition of this page
311 /*
312 if (!$error && GETPOST($ent, 'int') > 0 && isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_DISPATCH_ORDER)) {
313 $mouv = new MouvementStock($db);
314 $product = GETPOST($prod, 'int');
315 $entrepot = GETPOST($ent, 'int');
316 $qtymouv = price2num(GETPOST($qty, 'alpha'), 'MS') - $qtystart;
317 $price = price2num(GETPOST($pu), 'MU');
318 $comment = GETPOST('comment');
319 $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
320 $now = dol_now();
321 $eatby = '';
322 $sellby = '';
323 $batch = '';
324 if ($modebatch == "batch") {
325 $eatby = $dDLUO;
326 $sellby = $dDLC;
327 $batch = $lot ;
328 }
329 if ($product > 0 && $qtymouv != 0) {
330 // $price should take into account discount (except if option STOCK_EXCLUDE_DISCOUNT_FOR_PMP is on)
331 $mouv->origin = $objectorder;
332 $mouv->setOrigin($objectorder->element, $objectorder->id);
333
334 // Method change if qty < 0
335 if (!empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN) && $qtymouv < 0) {
336 $result = $mouv->reception($user, $product, $entrepot, $qtymouv*(-1), $price, $comment, $eatby, $sellby, $batch, '', 0, $inventorycode);
337 } else {
338 $result = $mouv->livraison($user, $product, $entrepot, $qtymouv, $price, $comment, $now, $eatby, $sellby, $batch, 0, $inventorycode);
339 }
340
341 if ($result < 0) {
342 setEventMessages($mouv->error, $mouv->errors, 'errors');
343 $error++;
344 }
345 }
346 }
347 */
348 }
349 }
350 }
351 }
352
353 if ($error > 0) {
354 $db->rollback();
355 setEventMessages($langs->trans("Error"), $errors, 'errors');
356 } else {
357 $db->commit();
358 setEventMessages($langs->trans("ReceptionUpdated"), null);
359
360 header("Location: ".DOL_URL_ROOT.'/expedition/dispatch.php?id='.$object->id);
361 exit;
362 }
363} elseif ($action == 'setdate_livraison' && $usercancreate) {
364 $datedelivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
365
366 $object->fetch($id);
367 $result = $object->setDeliveryDate($user, $datedelivery);
368 if ($result < 0) {
369 setEventMessages($object->error, $object->errors, 'errors');
370 }
371}
372
373
374/*
375 * View
376 */
377
378$now = dol_now();
379
380$form = new Form($db);
381$formproduct = new FormProduct($db);
382$warehouse_static = new Entrepot($db);
383
384$title = $object->ref." - ".$langs->trans('ShipmentDistribution');
385$help_url = 'EN:Module_Shipments|FR:Module_Expéditions|ES:M&oacute;dulo_Expediciones|DE:Modul_Lieferungen';
386$morejs = array('/expedition/js/lib_dispatch.js.php');
387
388llxHeader('', $title, $help_url, '', 0, 0, $morejs, '', '', 'mod-expedition page-card_dispatch');
389
390if ($object->id > 0 || !empty($object->ref)) {
391 $lines = $object->lines; // This is an array of detail of line, on line per source order line found intolines[]->fk_elementdet, then each line may have sub data
392 //var_dump($lines[0]->fk_elementdet); exit;
393
394 $num_prod = count($lines);
395
396 if (!empty($object->origin) && $object->origin_id > 0) {
397 $object->origin = 'commande';
398 $typeobject = $object->origin;
399 $origin = $object->origin;
400
401 $object->fetch_origin(); // Load property $object->origin_object, $object->commande, $object->propal, ...
402 }
403 $soc = new Societe($db);
404 $soc->fetch($object->socid);
405
406 $author = new User($db);
407 $author->fetch($object->user_author_id);
408
409 $head = shipping_prepare_head($object);
410
411 print dol_get_fiche_head($head, 'dispatch', $langs->trans("Shipment"), -1, $object->picto);
412
413
414 $formconfirm = '';
415
416 // Confirmation to delete line
417 if ($action == 'ask_deleteline') {
418 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
419 }
420
421 // Call Hook formConfirm
422 $parameters = array('lineid' => $lineid);
423 // Note that $action and $object may be modified by hook
424 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
425 if (empty($reshook)) {
426 $formconfirm .= $hookmanager->resPrint;
427 } elseif ($reshook > 0) {
428 $formconfirm = $hookmanager->resPrint;
429 }
430
431 // Print form confirm
432 print $formconfirm;
433
434 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
435 $objectsrc = new Commande($db);
436 $objectsrc->fetch($object->origin_object->id);
437 }
438 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
439 $objectsrc = new Propal($db);
440 $objectsrc->fetch($object->origin_object->id);
441 }
442
443 // Shipment card
444 $linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
445 $morehtmlref = '<div class="refidno">';
446
447 // Ref customer shipment
448 $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->hasRight('expedition', 'creer'), 'string', '', 0, 1);
449 $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->hasRight('expedition', 'creer'), 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1);
450
451 // Thirdparty
452 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
453 // Project
454 if (isModEnabled('project')) {
455 $langs->load("projects");
456 $morehtmlref .= '<br>';
457 if (0) { // Do not change on reception
458 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
459 if ($action != 'classify' && $permissiontoadd) {
460 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
461 }
462 $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');
463 } else {
464 if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
465 $proj = new Project($db);
466 $proj->fetch($objectsrc->fk_project);
467 $morehtmlref .= $proj->getNomUrl(1);
468 if ($proj->title) {
469 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
470 }
471 }
472 }
473 }
474 $morehtmlref .= '</div>';
475
476 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
477
478
479 print '<div class="fichecenter">';
480 print '<div class="underbanner clearboth"></div>';
481
482 print '<table class="border tableforfield centpercent">';
483
484 // Linked documents
485 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
486 print '<tr><td>';
487 print $langs->trans("RefOrder").'</td>';
488 print '<td colspan="3">';
489 print $objectsrc->getNomUrl(1, 'commande');
490 print "</td>\n";
491 print '</tr>';
492 }
493 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
494 print '<tr><td>';
495 print $langs->trans("RefProposal").'</td>';
496 print '<td colspan="3">';
497 print $objectsrc->getNomUrl(1, 'expedition');
498 print "</td>\n";
499 print '</tr>';
500 }
501
502 // Date creation
503 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
504 print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
505 print '</tr>';
506
507 // Delivery date planned
508 print '<tr><td height="10">';
509 print '<table class="nobordernopadding" width="100%"><tr><td>';
510 print $langs->trans('DateDeliveryPlanned');
511 print '</td>';
512 if ($action != 'editdate_livraison') {
513 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'), 1).'</a></td>';
514 }
515 print '</tr></table>';
516 print '</td><td colspan="2">';
517 if ($action == 'editdate_livraison') {
518 print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
519 print '<input type="hidden" name="token" value="'.newToken().'">';
520 print '<input type="hidden" name="action" value="setdate_livraison">';
521 print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, 0, "setdate_livraison", 1, 0);
522 print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Modify').'">';
523 print '</form>';
524 } else {
525 print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
526 }
527 print '</td>';
528 print '</tr></table>';
529
530 print '<br><center>';
531 if (isModEnabled('barcode') || isModEnabled('productbatch')) {
532 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=updatebyscaning&token='.currentToken().'" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto('', 'barcode', 'class="paddingrightonly"').$langs->trans("UpdateByScaning").'</a>';
533 }
534 print '<a href="#" id="resetalltoexpected" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'autofill', 'class="pictofixedwidth"').$langs->trans("RestoreWithCurrentQtySaved").'</a></td>';
535 // Link to clear qty
536 print '<a href="#" id="autoreset" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'eraser', 'class="pictofixedwidth"').$langs->trans("ClearQtys").'</a></td>';
537 print '<center>';
538
539 print '<br>';
540 $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.
541
542 if ($object->statut == Expedition::STATUS_DRAFT) {
543 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
544 $formproduct = new FormProduct($db);
545 $formproduct->loadWarehouses();
546 $entrepot = new Entrepot($db);
547 $listwarehouses = $entrepot->list_array(1);
548
549
550 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'">';
551
552 print '<input type="hidden" name="token" value="'.newToken().'">';
553 print '<input type="hidden" name="action" value="updatelines">';
554 print '<input type="hidden" name="id" value="'.$object->id.'">';
555
556 print '<div class="div-table-responsive-no-min">';
557 print '<table class="noborder centpercent">';
558
559 // Get list of lines of the shipment $products_dispatched, with qty dispatched for each product id
560 $products_dispatched = array();
561 $sql = "SELECT ed.fk_elementdet as rowid, sum(ed.qty) as qty";
562 $sql .= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed";
563 $sql .= " WHERE ed.fk_expedition = ".((int) $object->id);
564 $sql .= " GROUP BY ed.fk_elementdet";
565
566 $resql = $db->query($sql);
567 if ($resql) {
568 $num = $db->num_rows($resql);
569 $i = 0;
570
571 if ($num) {
572 while ($i < $num) {
573 $objd = $db->fetch_object($resql);
574 $products_dispatched[$objd->rowid] = price2num($objd->qty, 'MS');
575 $i++;
576 }
577 }
578 $db->free($resql);
579 }
580
581 //$sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, SUM(l.qty) as qty,";
582 $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, '' AS sref, l.qty as qty,";
583 $sql .= " p.ref, p.label, p.tobatch, p.fk_default_warehouse, p.barcode";
584 // Enable hooks to alter the SQL query (SELECT)
585 $parameters = array();
586 $reshook = $hookmanager->executeHooks(
587 'printFieldListSelect',
588 $parameters,
589 $object,
590 $action
591 );
592 if ($reshook < 0) {
593 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
594 }
595 $sql .= $hookmanager->resPrint;
596
597 $sql .= " FROM ".MAIN_DB_PREFIX."commandedet as l";
598 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON l.fk_product=p.rowid";
599 $sql .= " WHERE l.fk_commande = ".((int) $objectsrc->id);
600 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
601 $sql .= " AND l.product_type = 0";
602 }
603 // Enable hooks to alter the SQL query (WHERE)
604 $parameters = array();
605 $reshook = $hookmanager->executeHooks(
606 'printFieldListWhere',
607 $parameters,
608 $object,
609 $action
610 );
611 if ($reshook < 0) {
612 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
613 }
614 $sql .= $hookmanager->resPrint;
615
616 //$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
617 $sql .= " ORDER BY l.rang, p.ref, p.label";
618
619 $resql = $db->query($sql);
620 if ($resql) {
621 $num = $db->num_rows($resql);
622 $i = 0;
623 $numline = 1;
624
625 if ($num) {
626 print '<tr class="liste_titre">';
627
628 print '<td>'.$langs->trans("Description").'</td>';
629 if (isModEnabled('productbatch')) {
630 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>';
631 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
632 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>';
633 }
634 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
635 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>';
636 }
637 } else {
638 print '<td></td>';
639 print '<td></td>';
640 print '<td></td>';
641 }
642 print '<td class="right">'.$langs->trans("QtyOrdered").'</td>';
643 if ($object->status == Expedition::STATUS_DRAFT) {
644 print '<td class="right">'.$langs->trans("QtyToShip"); // Qty to dispatch (sum for all lines of batch detail if there is)
645 } else {
646 print '<td class="right">'.$langs->trans("QtyDispatchedShort").'</td>';
647 }
648 print '<td class="right">'.$langs->trans("Details");
649 print '<td width="32"></td>';
650
651 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
652 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
653 print '<td class="right">'.$langs->trans("Price").'</td>';
654 print '<td class="right">'.$langs->trans("ReductionShort").' (%)</td>';
655 print '<td class="right">'.$langs->trans("UpdatePrice").'</td>';
656 }
657 }
658
659 print '<td align="right">'.$langs->trans("Warehouse");
660
661 // Select warehouse to force it everywhere
662 if (count($listwarehouses) > 1) {
663 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);
664 } elseif (count($listwarehouses) == 1) {
665 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);
666 }
667
668 print '</td>';
669
670 // Enable hooks to append additional columns
671 $parameters = array();
672 $reshook = $hookmanager->executeHooks(
673 'printFieldListTitle',
674 $parameters,
675 $object,
676 $action
677 );
678 if ($reshook < 0) {
679 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
680 }
681 print $hookmanager->resPrint;
682
683 print "</tr>\n";
684 }
685
686 $nbfreeproduct = 0; // Nb of lines of free products/services
687 $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)
688 // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on.
689
690 $conf->cache['product'] = array();
691
692 // Loop on each line of origin order
693 while ($i < $num) {
694 $objp = $db->fetch_object($resql);
695
696 // On n'affiche pas les produits libres
697 if (!$objp->fk_product > 0) {
698 $nbfreeproduct++;
699 } else {
700 $alreadydispatched = isset($products_dispatched[$objp->rowid]) ? $products_dispatched[$objp->rowid] : 0;
701 $remaintodispatch = price2num($objp->qty, 5); // Calculation of dispatched
702 if ($remaintodispatch < 0 && !getDolGlobalString('SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN')) {
703 $remaintodispatch = 0;
704 }
705
706 if ($remaintodispatch || !getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
707 $nbproduct++;
708
709 // To show detail cref and description value, we must make calculation by cref
710 // print ($objp->cref?' ('.$objp->cref.')':'');
711 // if ($objp->description) print '<br>'.nl2br($objp->description);
712 $suffix = '_0_'.$i;
713
714 print "\n";
715 print '<!-- Line to dispatch '.$suffix.' -->'."\n";
716 // hidden fields for js function
717 print '<input id="qty_ordered'.$suffix.'" type="hidden" value="'.$objp->qty.'">';
718 print '<input id="qty_dispatched'.$suffix.'" type="hidden" data-dispatched="'.((float) $alreadydispatched).'" value="'.(float) $alreadydispatched.'">';
719 print '<tr class="oddeven">';
720
721 if (empty($conf->cache['product'][$objp->fk_product])) {
722 $tmpproduct = new Product($db);
723 $tmpproduct->fetch($objp->fk_product);
724 $conf->cache['product'][$objp->fk_product] = $tmpproduct;
725 } else {
726 $tmpproduct = $conf->cache['product'][$objp->fk_product];
727 }
728
729 $linktoprod = $tmpproduct->getNomUrl(1);
730 $linktoprod .= ' - '.$objp->label."\n";
731
732 if (isModEnabled('productbatch')) {
733 if ($objp->tobatch) {
734 // Product
735 print '<td id="product_'.$i.'" data-idproduct="'.$objp->fk_product.'" data-barcode="'.$objp->barcode.'">';
736 print $linktoprod;
737 print "</td>";
738 print '<td class="dispatch_batch_number"></td>';
739 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
740 print '<td class="dispatch_dlc"></td>';
741 }
742 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
743 print '<td class="dispatch_dluo"></td>';
744 }
745 } else {
746 // Product
747 print '<td id="product_'.$i.'" data-idproduct="'.$objp->fk_product.'" data-barcode="'.$objp->barcode.'">';
748 print $linktoprod;
749 print "</td>";
750 print '<td class="dispatch_batch_number">';
751 print '<span class="opacitymedium small">'.$langs->trans("ProductDoesNotUseBatchSerial").'</span>';
752 print '</td>';
753 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
754 print '<td class="dispatch_dlc"></td>';
755 }
756 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
757 print '<td class="dispatch_dluo"></td>';
758 }
759 }
760 } else {
761 print '<td colspan="4">';
762 print $linktoprod;
763 print "</td>";
764 }
765
766 // Define unit price for PMP calculation
767 $up_ht_disc = $objp->subprice;
768 if (!empty($objp->remise_percent) && !getDolGlobalString('STOCK_EXCLUDE_DISCOUNT_FOR_PMP')) {
769 $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU');
770 }
771
772 // Qty ordered
773 print '<td class="right">'.$objp->qty.'</td>';
774
775 // Already dispatched
776 print '<td class="right">'.$alreadydispatched.'</td>';
777
778 print '<td class="right">';
779 print '</td>'; // Qty to dispatch
780 print '<td>';
781 print '</td>'; // Dispatch column
782 print '<td></td>'; // Warehouse column
783
784 $sql = "SELECT ed.rowid, ed.qty, ed.fk_entrepot,";
785 $sql .= " eb.batch, eb.eatby, eb.sellby, cd.fk_product";
786 $sql .= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed";
787 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as eb on ed.rowid = eb.fk_expeditiondet";
788 $sql .= " JOIN ".MAIN_DB_PREFIX."commandedet as cd on ed.fk_elementdet = cd.rowid";
789 $sql .= " WHERE ed.fk_elementdet =".(int) $objp->rowid;
790 $sql .= " AND ed.fk_expedition =".(int) $object->id;
791 $sql .= " ORDER BY ed.rowid, ed.fk_elementdet";
792
793 $resultsql = $db->query($sql);
794 $j = 0;
795 if ($resultsql) {
796 $numd = $db->num_rows($resultsql);
797
798 while ($j < $numd) {
799 $suffix = "_".$j."_".$i;
800 $objd = $db->fetch_object($resultsql);
801
802 if (isModEnabled('productbatch') && (!empty($objd->batch) || (is_null($objd->batch) && $tmpproduct->status_batch > 0))) {
803 $type = 'batch';
804
805 // Enable hooks to append additional columns
806 $parameters = array(
807 // allows hook to distinguish between the rows with information and the rows with dispatch form input
808 'is_information_row' => true,
809 'j' => $j,
810 'suffix' => $suffix,
811 'objd' => $objd,
812 );
813 $reshook = $hookmanager->executeHooks(
814 'printFieldListValue',
815 $parameters,
816 $object,
817 $action
818 );
819 if ($reshook < 0) {
820 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
821 }
822 print $hookmanager->resPrint;
823
824 print '</tr>';
825
826 print '<!-- line for batch '.$numline.' -->';
827 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
828 print '<td>';
829 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
830 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
831 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
832
833 print '<!-- This is a U.P. (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
834 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
835
836 print '</td>';
837
838 print '<td>';
839 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.(GETPOSTISSET('lot_number'.$suffix) ? GETPOST('lot_number'.$suffix) : $objd->batch).'">';
840 //print '<input type="hidden" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.$objd->batch.'">';
841 print '</td>';
842 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
843 print '<td class="nowraponall">';
844 $dlcdatesuffix = !empty($objd->sellby) ? dol_stringtotime($objd->sellby) : dol_mktime(0, 0, 0, GETPOSTINT('dlc'.$suffix.'month'), GETPOSTINT('dlc'.$suffix.'day'), GETPOSTINT('dlc'.$suffix.'year'));
845 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, 0, 0, 1, '');
846 print '</td>';
847 }
848 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
849 print '<td class="nowraponall">';
850 $dluodatesuffix = !empty($objd->eatby) ? dol_stringtotime($objd->eatby) : dol_mktime(0, 0, 0, GETPOSTINT('dluo'.$suffix.'month'), GETPOSTINT('dluo'.$suffix.'day'), GETPOSTINT('dluo'.$suffix.'year'));
851 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, 0, 0, 1, '');
852 print '</td>';
853 }
854 print '<td colspan="2">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
855 } else {
856 $type = 'dispatch';
857 $colspan = 6;
858 $colspan = (getDolGlobalString('PRODUCT_DISABLE_SELLBY')) ? --$colspan : $colspan;
859 $colspan = (getDolGlobalString('PRODUCT_DISABLE_EATBY')) ? --$colspan : $colspan;
860
861 // Enable hooks to append additional columns
862 $parameters = array(
863 // allows hook to distinguish between the rows with information and the rows with dispatch form input
864 'is_information_row' => true,
865 'j' => $j,
866 'suffix' => $suffix,
867 'objd' => $objd,
868 );
869 $reshook = $hookmanager->executeHooks(
870 'printFieldListValue',
871 $parameters,
872 $object,
873 $action
874 );
875 if ($reshook < 0) {
876 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
877 }
878 print $hookmanager->resPrint;
879
880 print '</tr>';
881
882 print '<!-- line no batch '.$numline.' -->';
883 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
884 print '<td colspan="'.$colspan.'">';
885 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
886 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
887 print '<input name="product'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
888 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
889 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
890 print '</td>';
891 }
892 // Qty to dispatch
893 print '<td class="right nowraponall">';
894 print '<a href="" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
895 $suggestedvalue = (GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : $objd->qty);
896 //var_dump($suggestedvalue);exit;
897 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-type="'.$type.'" data-index="'.$i.'" class="width50 right qtydispatchinput" value="'.$suggestedvalue.'" data-expected="'.$objd->qty.'">';
898 print '</td>';
899 print '<td>';
900 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
901 $type = 'batch';
902 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j + 1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
903 } else {
904 $type = 'dispatch';
905 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j + 1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
906 }
907
908 print '</td>';
909
910 // Warehouse
911 print '<td class="right">';
912 if (count($listwarehouses) > 1) {
913 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, array(), 'csswarehouse'.$suffix);
914 } elseif (count($listwarehouses) == 1) {
915 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, array(), 'csswarehouse'.$suffix);
916 } else {
917 $langs->load("errors");
918 print $langs->trans("ErrorNoWarehouseDefined");
919 }
920 print "</td>\n";
921
922 // Enable hooks to append additional columns
923 $parameters = array(
924 'is_information_row' => false, // this is a dispatch form row
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>\n";
941 $j++;
942
943 $numline++;
944 }
945 $suffix = "_".$j."_".$i;
946 }
947
948 if ($j == 0) {
949 if (isModEnabled('productbatch') && !empty($objp->tobatch)) {
950 $type = 'batch';
951
952 // Enable hooks to append additional columns
953 $parameters = array(
954 // allows hook to distinguish between the rows with information and the rows with dispatch form input
955 'is_information_row' => true,
956 'j' => $j,
957 'suffix' => $suffix,
958 'objp' => $objp,
959 );
960 $reshook = $hookmanager->executeHooks(
961 'printFieldListValue',
962 $parameters,
963 $object,
964 $action
965 );
966 if ($reshook < 0) {
967 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
968 }
969 print $hookmanager->resPrint;
970
971 print '</tr>';
972
973 print '<!-- line for batch '.$numline.' (not dispatched line yet for this order line) -->';
974 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
975 print '<td>';
976 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
977 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
978 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
979
980 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
981 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
982 print '</td>';
983
984 print '<td>';
985 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.GETPOST('lot_number'.$suffix).'">';
986 print '</td>';
987 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
988 print '<td class="nowraponall">';
989 $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOSTINT('dlc'.$suffix.'month'), GETPOSTINT('dlc'.$suffix.'day'), GETPOSTINT('dlc'.$suffix.'year'));
990 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, 0, 0, 1, '');
991 print '</td>';
992 }
993 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
994 print '<td class="nowraponall">';
995 $dluodatesuffix = dol_mktime(0, 0, 0, GETPOSTINT('dluo'.$suffix.'month'), GETPOSTINT('dluo'.$suffix.'day'), GETPOSTINT('dluo'.$suffix.'year'));
996 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, 0, 0, 1, '');
997 print '</td>';
998 }
999 print '<td colspan="2">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
1000 } else {
1001 $type = 'dispatch';
1002 $colspan = 6;
1003 $colspan = (getDolGlobalString('PRODUCT_DISABLE_SELLBY')) ? --$colspan : $colspan;
1004 $colspan = (getDolGlobalString('PRODUCT_DISABLE_EATBY')) ? --$colspan : $colspan;
1005
1006 // Enable hooks to append additional columns
1007 $parameters = array(
1008 // allows hook to distinguish between the rows with information and the rows with dispatch form input
1009 'is_information_row' => true,
1010 'j' => $j,
1011 'suffix' => $suffix,
1012 'objp' => $objp,
1013 );
1014 $reshook = $hookmanager->executeHooks(
1015 'printFieldListValue',
1016 $parameters,
1017 $object,
1018 $action
1019 );
1020 if ($reshook < 0) {
1021 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1022 }
1023 print $hookmanager->resPrint;
1024
1025 print '</tr>';
1026
1027 print '<!-- line no batch '.$numline.' (not dispatched line yet for this order line) -->';
1028 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
1029 print '<td colspan="'.$colspan.'">';
1030 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
1031 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
1032 print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
1033
1034 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
1035 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
1036 print '</td>';
1037 }
1038 // Qty to dispatch
1039 print '<td class="right">';
1040 print '<a href="" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
1041 $amounttosuggest = (GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : (!getDolGlobalString('SUPPLIER_ORDER_DISPATCH_FORCE_QTY_INPUT_TO_ZERO') ? $remaintodispatch : 0));
1042 if (count($products_dispatched)) {
1043 // There is already existing lines into llx_expeditiondet, this means a plan for the shipment has already been started.
1044 // In such a case, we do not suggest new values, we suggest the value known.
1045 $amounttosuggest = (GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : (isset($products_dispatched[$objp->rowid]) ? $products_dispatched[$objp->rowid] : ''));
1046 }
1047 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-index="'.$i.'" data-type="text" class="width50 right qtydispatchinput" value="'.$amounttosuggest.'" data-expected="'.$amounttosuggest.'">';
1048 print '</td>';
1049 print '<td>';
1050 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
1051 $type = 'batch';
1052 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1053 } else {
1054 $type = 'dispatch';
1055 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1056 }
1057
1058 print '</td>';
1059
1060 // Warehouse
1061 print '<td class="right">';
1062 if (count($listwarehouses) > 1) {
1063 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);
1064 } elseif (count($listwarehouses) == 1) {
1065 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);
1066 } else {
1067 $langs->load("errors");
1068 print $langs->trans("ErrorNoWarehouseDefined");
1069 }
1070 print "</td>\n";
1071
1072 // Enable hooks to append additional columns
1073 $parameters = array(
1074 'is_information_row' => false, // this is a dispatch form row
1075 'i' => $i,
1076 'suffix' => $suffix,
1077 'objp' => $objp,
1078 );
1079 $reshook = $hookmanager->executeHooks(
1080 'printFieldListValue',
1081 $parameters,
1082 $object,
1083 $action
1084 );
1085 if ($reshook < 0) {
1086 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1087 }
1088 print $hookmanager->resPrint;
1089 print "</tr>\n";
1090 }
1091 }
1092 }
1093 $i++;
1094 }
1095 $db->free($resql);
1096 } else {
1097 dol_print_error($db);
1098 }
1099
1100 print "</table>\n";
1101 print '</div>';
1102
1103 if ($nbproduct) {
1104 //$checkboxlabel = $langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv('StatusOrderReceivedAll'));
1105
1106 print '<div class="center">';
1107 $parameters = array();
1108 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1109 // modified by hook
1110 if (empty($reshook)) {
1111 /*if (empty($conf->reception->enabled)) {
1112 print $langs->trans("Comment").' : ';
1113 print '<input type="text" class="minwidth400" maxlength="128" name="comment" value="';
1114 print GETPOSTISSET("comment") ? GETPOST("comment") : $langs->trans("DispatchSupplierOrder", $object->ref);
1115 // print ' / '.$object->ref_supplier; // Not yet available
1116 print '" class="flat"><br>';
1117
1118 print '<input type="checkbox" checked="checked" name="closeopenorder"> '.$checkboxlabel;
1119 }
1120
1121 $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception");
1122
1123 print '<br>';
1124 */
1125
1126 print '<input type="submit" id="submitform" class="button" name="dispatch" value="'.$langs->trans("Save").'"';
1127 $disabled = 0;
1128 if (!$usercancreate) {
1129 $disabled = 1;
1130 }
1131 if (count($listwarehouses) <= 0) {
1132 $disabled = 1;
1133 }
1134 if ($disabled) {
1135 print ' disabled';
1136 }
1137
1138 print '>';
1139 }
1140 print '</div>';
1141 }
1142
1143 // Message if nothing to dispatch
1144 if (!$nbproduct) {
1145 print "<br>\n";
1146 if (!getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
1147 print '<div class="opacitymedium">'.$langs->trans("NoPredefinedProductToDispatch").'</div>'; // No predefined line at all
1148 } else {
1149 print '<div class="opacitymedium">'.$langs->trans("NoMorePredefinedProductToDispatch").'</div>'; // No predefined line that remain to be dispatched.
1150 }
1151 }
1152
1153 print '</form>';
1154 }
1155
1156 print dol_get_fiche_end();
1157
1158 // Popup for mass barcode scanning
1159 if ($action == 'updatebyscaning') {
1160 if ($permissiontoadd) {
1161 // Output the javascript to manage the scanner tool.
1162 print '<script>';
1163
1164 print '
1165 var duplicatedbatchcode = [];
1166 var errortab1 = [];
1167 var errortab2 = [];
1168 var errortab3 = [];
1169 var errortab4 = [];
1170
1171 function barcodescannerjs(){
1172 console.log("We catch inputs in scanner box");
1173 jQuery("#scantoolmessage").text();
1174
1175 var selectaddorreplace = $("select[name=selectaddorreplace]").val();
1176 var barcodemode = $("input[name=barcodemode]:checked").val();
1177 var barcodeproductqty = $("input[name=barcodeproductqty]").val();
1178 var warehousetouse = $("select[name=warehousenew]").val();
1179 var textarea = $("textarea[name=barcodelist]").val();
1180 var textarray = textarea.split(/[\s,;]+/);
1181 var tabproduct = [];
1182 duplicatedbatchcode = [];
1183 errortab1 = [];
1184 errortab2 = [];
1185 errortab3 = [];
1186 errortab4 = [];
1187
1188 textarray = textarray.filter(function(value){
1189 return value != "";
1190 });
1191 if(textarray.some((element) => element != "")){
1192 $(".qtydispatchinput").each(function(){
1193 id = $(this).attr(\'id\');
1194 idarray = id.split(\'_\');
1195 idproduct = idarray[2];
1196 id = idarray[1] + \'_\' + idarray[2];
1197 console.log("Analyze the line "+id+" in inventory, barcodemode="+barcodemode);
1198 warehouse = $("#entrepot_"+id).val();
1199 console.log(warehouse);
1200 productbarcode = $("#product_"+idproduct).attr(\'data-barcode\');
1201 console.log(productbarcode);
1202 productbatchcode = $("#lot_number_"+id).val();
1203 if(productbatchcode == undefined){
1204 productbatchcode = "";
1205 }
1206 console.log(productbatchcode);
1207
1208 if (barcodemode != "barcodeforproduct") {
1209 tabproduct.forEach(product=>{
1210 console.log("product.Batch="+product.Batch+" productbatchcode="+productbatchcode);
1211 if(product.Batch != "" && product.Batch == productbatchcode){
1212 console.log("duplicate batch code found for batch code "+productbatchcode);
1213 duplicatedbatchcode.push(productbatchcode);
1214 }
1215 })
1216 }
1217 productinput = $("#qty_"+id).val();
1218 if(productinput == ""){
1219 productinput = 0
1220 }
1221 tabproduct.push({\'Id\':id,\'Warehouse\':warehouse,\'Barcode\':productbarcode,\'Batch\':productbatchcode,\'Qty\':productinput,\'fetched\':false});
1222 });
1223 console.log("Loop on each record entered in the textarea");
1224
1225 textarray.forEach(function(element,index){
1226 console.log("Process record element="+element+" id="+id);
1227 var verify_batch = false;
1228 var verify_barcode = false;
1229 switch(barcodemode){
1230 case "barcodeforautodetect":
1231 verify_barcode = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"barcode",true);
1232 verify_batch = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"lotserial",true);
1233 break;
1234 case "barcodeforproduct":
1235 verify_barcode = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"barcode");
1236 break;
1237 case "barcodeforlotserial":
1238 verify_batch = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"lotserial");
1239 break;
1240 default:
1241 alert(\''.dol_escape_js($langs->trans("ErrorWrongBarcodemode")).' "\'+barcodemode+\'"\');
1242 throw \''.dol_escape_js($langs->trans('ErrorWrongBarcodemode')).' "\'+barcodemode+\'"\';
1243 }
1244
1245 if (verify_batch == false && verify_barcode == false) { /* If the 2 flags are false, not found error */
1246 errortab2.push(element);
1247 } else if (verify_batch == true && verify_barcode == true) { /* If the 2 flags are true, error: we don t know which one to take */
1248 errortab3.push(element);
1249 } else if (verify_batch == true) {
1250 console.log("element="+element);
1251 console.log(duplicatedbatchcode);
1252 if (duplicatedbatchcode.includes(element)) {
1253 errortab1.push(element);
1254 }
1255 }
1256 });
1257
1258 if (Object.keys(errortab1).length < 1 && Object.keys(errortab2).length < 1 && Object.keys(errortab3).length < 1) {
1259 tabproduct.forEach(product => {
1260 if(product.Qty!=0){
1261 if(product.hasOwnProperty("reelqty")){
1262 idprod = $("td[data-idproduct=\'"+product.fk_product+"\']").attr("id");
1263 idproduct = idprod.split("_")[1];
1264 console.log("We create a new line for product_"+idproduct);
1265 if(product.Barcode != null){
1266 modedispatch = "dispatch";
1267 } else {
1268 modedispatch = "batch";
1269 }
1270 addDispatchLine(idproduct,modedispatch);
1271 console.log($("tr[name^=\'"+modedispatch+"_\'][name$=\'_"+idproduct+"\']"));
1272 nbrTrs = $("tr[name^=\'"+modedispatch+"_\'][name$=\'_"+idproduct+"\']").length;
1273
1274 $("#qty_"+(nbrTrs-1)+"_"+idproduct).val(product.Qty);
1275 $("#entrepot_"+(nbrTrs-1)+"_"+idproduct).val(product.Warehouse);
1276
1277 if(modedispatch == "batch"){
1278 $("#lot_number_"+(nbrTrs-1)+"_"+idproduct).val(product.Batch);
1279 }
1280
1281 } else {
1282 console.log("We change #qty_"+product.Id +" to match input in scanner box");
1283 $("#qty_"+product.Id).val(product.Qty);
1284 }
1285 }
1286 });
1287 jQuery("#scantoolmessage").text("'.dol_escape_js($langs->transnoentities("QtyWasAddedToTheScannedBarcode")).'\n");
1288 /* document.forms["formrecord"].submit(); */
1289 } else {
1290 let stringerror = "";
1291 if (Object.keys(errortab1).length > 0) {
1292 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorSameBatchNumber')).': ";
1293 errortab1.forEach(element => {
1294 stringerror += (element + ", ")
1295 });
1296 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1297 }
1298 if (Object.keys(errortab2).length > 0) {
1299 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorCantFindCodeInInventory')).': ";
1300 errortab2.forEach(element => {
1301 stringerror += (element + ", ")
1302 });
1303 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1304 }
1305 if (Object.keys(errortab3).length > 0) {
1306 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorCodeScannedIsBothProductAndSerial')).': ";
1307 errortab3.forEach(element => {
1308 stringerror += (element + ", ")
1309 });
1310 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1311 }
1312 if (Object.keys(errortab4).length > 0) {
1313 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorBarcodeNotFoundForProductWarehouse')).': ";
1314 errortab4.forEach(element => {
1315 stringerror += (element + ", ")
1316 });
1317 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1318 }
1319
1320 jQuery("#scantoolmessage").html(\''.dol_escape_js($langs->transnoentities("ErrorOnElementsInventory")).'\' + stringerror);
1321 //alert("'.dol_escape_js($langs->trans("ErrorOnElementsInventory")).' :\n" + stringerror);
1322 }
1323 }
1324
1325 }
1326
1327 /* This methode is called by parent barcodescannerjs() */
1328 function barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,mode,autodetect=false){
1329 BarcodeIsInProduct=0;
1330 newproductrow=0
1331 result=false;
1332 tabproduct.forEach(product => {
1333 $.ajax({ url: \''.DOL_URL_ROOT.'/expedition/ajax/searchfrombarcode.php\',
1334 data: { "token":"'.newToken().'", "action":"existbarcode","fk_entrepot": warehousetouse, "barcode":element, "mode":mode},
1335 type: \'POST\',
1336 async: false,
1337 success: function(response) {
1338 if (response.status == "success"){
1339 console.log(response.message);
1340 if(!newproductrow){
1341 newproductrow = response.object;
1342 }
1343 }else{
1344 if (mode!="lotserial" && autodetect==false && !errortab4.includes(element)){
1345 errortab4.push(element);
1346 console.error(response.message);
1347 }
1348 }
1349 },
1350 error : function(output) {
1351 console.error("Error on barcodeserialforproduct function");
1352 },
1353 });
1354 console.log("Product "+(index+=1)+": "+element);
1355 if(mode == "barcode"){
1356 testonproduct = product.Barcode
1357 }else if (mode == "lotserial"){
1358 testonproduct = product.Batch
1359 }
1360 testonwarehouse = product.Warehouse;
1361 if(testonproduct == element && testonwarehouse == warehousetouse){
1362 if(selectaddorreplace == "add"){
1363 productqty = parseInt(product.Qty,10);
1364 product.Qty = productqty + parseInt(barcodeproductqty,10);
1365 }else if(selectaddorreplace == "replace"){
1366 if(product.fetched == false){
1367 product.Qty = barcodeproductqty
1368 product.fetched=true
1369 }else{
1370 productqty = parseInt(product.Qty,10);
1371 product.Qty = productqty + parseInt(barcodeproductqty,10);
1372 }
1373 }
1374 BarcodeIsInProduct+=1;
1375 }
1376 })
1377 if(BarcodeIsInProduct==0 && newproductrow!=0){
1378 tabproduct.push({\'Id\':tabproduct.length-1,\'Warehouse\':newproductrow.fk_warehouse,\'Barcode\':mode=="barcode"?element:null,\'Batch\':mode=="lotserial"?element:null,\'Qty\':barcodeproductqty,\'fetched\':true,\'reelqty\':newproductrow.reelqty,\'fk_product\':newproductrow.fk_product,\'mode\':mode});
1379 result = true;
1380 }
1381 if(BarcodeIsInProduct > 0){
1382 result = true;
1383 }
1384 return result;
1385 }
1386 ';
1387 print '</script>';
1388 }
1389 include DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
1390 $formother = new FormOther($db);
1391 print $formother->getHTMLScannerForm("barcodescannerjs", 'all', 1);
1392 }
1393
1394 // traitement entrepot par défaut
1395 print '<script type="text/javascript">
1396 $(document).ready(function () {
1397 $("select[name=fk_default_warehouse]").change(function() {
1398 console.log("warehouse is modified");
1399 var fk_default_warehouse = $("option:selected", this).val();
1400 $("select[name^=entrepot_]").val(fk_default_warehouse).change();
1401 });
1402
1403 $("#autoreset").click(function() {
1404 console.log("we click on autoreset");
1405 $(".autoresettr").each(function(){
1406 id = $(this).attr("name");
1407 idtab = id.split("_");
1408 console.log("we process line "+id+" "+idtab);
1409 if ($(this).data("remove") == "clear") { /* data-remove=clear means that line qty must be cleared but line must not be removed */
1410 console.log("We clear the object to expected value")
1411 $("#qty_"+idtab[1]+"_"+idtab[2]).val("");
1412 /*
1413 qtyexpected = $("#qty_"+idtab[1]+"_"+idtab[2]).data("expected")
1414 console.log(qtyexpected);
1415 $("#qty_"+idtab[1]+"_"+idtab[2]).val(qtyexpected);
1416 qtydispatched = $("#qty_dispatched_0_"+idtab[2]).data("dispatched")
1417 $("#qty_dispatched_0_"+idtab[2]).val(qtydispatched);
1418 */
1419 } else { /* data-remove=remove means that line must be removed */
1420 console.log("We remove the object")
1421 $(this).remove();
1422 $("tr[name^=\'"+idtab[0]+"_\'][name$=\'_"+idtab[2]+"\']:last .splitbutton").show();
1423 }
1424 });
1425 return false;
1426 });
1427
1428 $("#resetalltoexpected").click(function(){
1429 $(".qtydispatchinput").each(function(){
1430 console.log("We reset to expected "+$(this).attr("id")+" qty to dispatch");
1431 $(this).val($(this).data("expected"));
1432 });
1433 return false;
1434 });
1435
1436 $(".resetline").on("click", function(event) {
1437 event.preventDefault();
1438 id = $(this).attr("id");
1439 id = id.split("reset_");
1440 console.log("Reset trigger for id = qty_"+id[1]);
1441 $("#qty_"+id[1]).val("");
1442 });
1443 });
1444 </script>';
1445}
1446
1447// End of page
1448llxFooter();
1449$db->close();
$id
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
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:71
Class to manage customers orders.
Class to manage comment.
Class to manage warehouses.
const STATUS_DRAFT
Draft status.
Class to manage lines of shipment.
CRUD class for batch number management within shipment.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation de composants html autre Only common components are 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 proposals.
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:431
llxFooter()
Footer empty.
Definition document.php:107
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...
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)
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 '.
currentToken()
Return the value of token currently saved into session with name 'token'.
dol_now($mode='auto')
Return date for now.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
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.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a 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
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:152
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.
shipping_prepare_head($object)
Prepare array with list of tabs.