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