dolibarr 18.0.6
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2008 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Simon TOSSER <simon@kornog-computing.com>
5 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
6 * Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8 * Copyright (C) 2013 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
10 * Copyright (C) 2014-2017 Francis Appels <francis.appels@yahoo.com>
11 * Copyright (C) 2015 Claudio Aschieri <c.aschieri@19.coop>
12 * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
13 * Copyright (C) 2016 Yasser Carreón <yacasia@gmail.com>
14 * Copyright (C) 2018 Quentin Vial-Gouteyron <quentin.vial-gouteyron@atm-consulting.fr>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 */
29
36// Load Dolibarr environment
37require '../main.inc.php';
38require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
39require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php';
40require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
43require_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
44require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
45require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
46require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
47require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
48if (isModEnabled("product") || isModEnabled("service")) {
49 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
50}
51if (isModEnabled("propal")) {
52 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
53}
54require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
55require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
56if (isModEnabled('productbatch')) {
57 require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
58}
59if (isModEnabled('project')) {
60 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
61 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
62}
63
64$langs->loadLangs(array("receptions", "companies", "bills", 'deliveries', 'orders', 'stocks', 'other', 'propal', 'sendings'));
65
66if (isModEnabled('incoterm')) {
67 $langs->load('incoterm');
68}
69if (isModEnabled('productbatch')) {
70 $langs->load('productbatch');
71}
72
73$origin = GETPOST('origin', 'alpha') ?GETPOST('origin', 'alpha') : 'reception'; // Example: commande, propal
74$origin_id = GETPOST('id', 'int') ? GETPOST('id', 'int') : '';
75$id = $origin_id;
76if (empty($origin_id)) {
77 $origin_id = GETPOST('origin_id', 'int'); // Id of order or propal
78}
79if (empty($origin_id)) {
80 $origin_id = GETPOST('object_id', 'int'); // Id of order or propal
81}
82if (empty($origin_id)) {
83 $origin_id = GETPOST('originid', 'int'); // Id of order or propal
84}
85$ref = GETPOST('ref', 'alpha');
86$line_id = GETPOST('lineid', 'int') ?GETPOST('lineid', 'int') : '';
87$facid = GETPOST('facid', 'int');
88
89$action = GETPOST('action', 'alpha');
90//Select mail models is same action as presend
91if (GETPOST('modelselected')) {
92 $action = 'presend';
93}
94$confirm = GETPOST('confirm', 'alpha');
95$cancel = GETPOST('cancel', 'alpha');
96$backtopage = GETPOST('backtopage', 'alpha');
97$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
98
99//PDF
100$hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
101$hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
102$hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
103
104$object = new Reception($db);
105$objectorder = new CommandeFournisseur($db);
106$extrafields = new ExtraFields($db);
107
108// fetch optionals attributes and labels
109$extrafields->fetch_name_optionals_label($object->table_element);
110$extrafields->fetch_name_optionals_label($object->table_element_line);
111$extrafields->fetch_name_optionals_label($objectorder->table_element_line);
112
113// Load object. Make an object->fetch
114include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
115
116// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
117$hookmanager->initHooks(array('receptioncard', 'globalcard'));
118
119$date_delivery = dol_mktime(GETPOST('date_deliveryhour', 'int'), GETPOST('date_deliverymin', 'int'), 0, GETPOST('date_deliverymonth', 'int'), GETPOST('date_deliveryday', 'int'), GETPOST('date_deliveryyear', 'int'));
120
121if ($id > 0 || !empty($ref)) {
122 $object->fetch($id, $ref);
123 $object->fetch_thirdparty();
124
125 if (!empty($object->origin)) {
126 $origin = $object->origin;
127
128 $object->fetch_origin();
129 $typeobject = $object->origin;
130 }
131
132 // Linked documents
133 if ($origin == 'order_supplier' && $object->$typeobject->id && isModEnabled("supplier_order")) {
134 $origin_id = $object->$typeobject->id;
135 $objectsrc = new CommandeFournisseur($db);
136 $objectsrc->fetch($object->$typeobject->id);
137 }
138}
139
140// Security check
141$socid = '';
142if ($user->socid) {
143 $socid = $user->socid;
144}
145
146// TODO Test on reception module on only
147if (isModEnabled("reception") || $origin == 'reception' || empty($origin)) {
148 $result = restrictedArea($user, 'reception', $object->id);
149} else {
150 // We do not use the reception module, so we test permission on the supplier orders
151 if ($origin == 'supplierorder' || $origin == 'order_supplier') {
152 $result = restrictedArea($user, 'fournisseur', $origin_id, 'commande_fournisseur', 'commande');
153 } elseif (!$user->hasRight($origin, 'lire') && !$user->hasRight($origin, 'read')) {
155 }
156}
157
158if (isModEnabled("reception")) {
159 $permissiontoread = $user->rights->reception->lire;
160 $permissiontoadd = $user->rights->reception->creer;
161 $permissiondellink = $user->rights->reception->creer; // Used by the include of actions_dellink.inc.php
162 $permissiontovalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate)));
163 $permissiontodelete = $user->rights->reception->supprimer;
164} else {
165 $permissiontoread = $user->rights->fournisseur->commande->receptionner;
166 $permissiontoadd = $user->rights->fournisseur->commande->receptionner;
167 $permissiondellink = $user->rights->fournisseur->commande->receptionner; // Used by the include of actions_dellink.inc.php
168 $permissiontovalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->fournisseur->commande->receptionner)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->fournisseur->commande_advance->check)));
169 $permissiontodelete = $user->rights->fournisseur->commande->receptionner;
170}
171
172
173/*
174 * Actions
175 */
176
177$parameters = array();
178$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
179if ($reshook < 0) {
180 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
181}
182
183if (empty($reshook)) {
184 /*
185 $backurlforlist = DOL_URL_ROOT.'/reception/list.php';
186
187 if (empty($backtopage) || ($cancel && empty($id))) {
188 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
189 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
190 $backtopage = $backurlforlist;
191 } else {
192 $backtopage = dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
193 }
194 }
195 }
196 */
197
198 if ($cancel) {
199 if (!empty($backtopageforcancel)) {
200 header("Location: ".$backtopageforcancel);
201 exit;
202 } elseif (!empty($backtopage)) {
203 header("Location: ".$backtopage);
204 exit;
205 }
206
207 $action = '';
208 }
209
210 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
211
212 // Reopen
213 if ($action == 'reopen' && $permissiontoadd) {
214 $result = $object->reOpen();
215 }
216
217 // Confirm back to draft status
218 if ($action == 'modif' && $permissiontoadd) {
219 $result = $object->setDraft($user);
220 if ($result >= 0) {
221 // Define output language
222 if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
223 $outputlangs = $langs;
224 $newlang = '';
225 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
226 $newlang = GETPOST('lang_id', 'aZ09');
227 }
228 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
229 $newlang = $object->thirdparty->default_lang;
230 }
231 if (!empty($newlang)) {
232 $outputlangs = new Translate("", $conf);
233 $outputlangs->setDefaultLang($newlang);
234 }
235 $model = $object->model_pdf;
236 $ret = $object->fetch($id); // Reload to get new records
237 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
238 }
239 } else {
240 setEventMessages($object->error, $object->errors, 'errors');
241 }
242 }
243
244 // Set incoterm
245 if ($action == 'set_incoterms' && isModEnabled('incoterm') && $permissiontoadd) {
246 $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
247 }
248
249 if ($action == 'setref_supplier' && $permissiontoadd) {
250 if ($result < 0) {
251 setEventMessages($object->error, $object->errors, 'errors');
252 }
253
254 $result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'RECEPTION_MODIFY');
255 if ($result < 0) {
256 setEventMessages($object->error, $object->errors, 'errors');
257 $action = 'editref_supplier';
258 } else {
259 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
260 exit;
261 }
262 }
263
264 if ($action == 'update_extras' && $permissiontoadd) {
265 $object->oldcopy = dol_clone($object);
266
267 // Fill array 'array_options' with data from update form
268 $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
269 if ($ret < 0) {
270 $error++;
271 }
272
273 if (!$error) {
274 // Actions on extra fields
275 $result = $object->insertExtraFields('RECEPTION_MODIFY');
276 if ($result < 0) {
277 setEventMessages($object->error, $object->errors, 'errors');
278 $error++;
279 }
280 }
281
282 if ($error) {
283 $action = 'edit_extras';
284 }
285 }
286
287 // Create reception
288 if ($action == 'add' && $permissiontoadd) {
289 $error = 0;
290 $predef = '';
291
292 $db->begin();
293
294 $object->note = GETPOST('note', 'alpha');
295 $object->origin = $origin;
296 $object->origin_id = $origin_id;
297 $object->fk_project = GETPOST('projectid', 'int');
298 $object->weight = GETPOST('weight', 'int') == '' ? null : GETPOST('weight', 'int');
299 $object->trueHeight = GETPOST('trueHeight', 'int') == '' ? null : GETPOST('trueHeight', 'int');
300 $object->trueWidth = GETPOST('trueWidth', 'int') == '' ? null : GETPOST('trueWidth', 'int');
301 $object->trueDepth = GETPOST('trueDepth', 'int') == '' ? null : GETPOST('trueDepth', 'int');
302 $object->size_units = GETPOST('size_units', 'int');
303 $object->weight_units = GETPOST('weight_units', 'int');
304
305 // On va boucler sur chaque ligne du document d'origine pour completer objet reception
306 // avec info diverses + qte a livrer
307
308 if ($object->origin == "supplierorder") {
309 $classname = 'CommandeFournisseur';
310 } else {
311 $classname = ucfirst($object->origin);
312 }
313 $objectsrc = new $classname($db);
314 $objectsrc->fetch($object->origin_id);
315
316 $object->socid = $objectsrc->socid;
317 $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
318 $object->model_pdf = GETPOST('model');
319 $object->date_delivery = $date_delivery; // Date delivery planed
320 $object->fk_delivery_address = $objectsrc->fk_delivery_address;
321 $object->shipping_method_id = GETPOST('shipping_method_id', 'int');
322 $object->tracking_number = GETPOST('tracking_number', 'alpha');
323 $object->note_private = GETPOST('note_private', 'restricthtml');
324 $object->note_public = GETPOST('note_public', 'restricthtml');
325 $object->fk_incoterms = GETPOST('incoterm_id', 'int');
326 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
327
328 $batch_line = array();
329 $stockLine = array();
330 $array_options = array();
331
332 $totalqty = 0;
333
334 $num = 0;
335 foreach ($_POST as $key => $value) {
336 // without batch module enabled
337
338 if (strpos($key, 'qtyasked') !== false) {
339 $num++;
340 }
341 }
342
343 // Loop lines to calculate $totalqty
344 for ($i = 1; $i <= $num; $i++) {
345 $idl = "idl".$i; // id line source
346
347 //$sub_qty = array();
348 //$subtotalqty = 0;
349
350 //$j = 0;
351 //$batch = "batchl".$i."_0";
352 //$stockLocation = "ent1".$i."_0";
353 $qty = "qtyl".$i; // qty
354
355 //reception line for product with no batch management and no multiple stock location
356 if (GETPOST($qty, 'alpha') > 0) {
357 $totalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
358 }
359
360 // Extrafields
361 $array_options[$i] = $extrafields->getOptionalsFromPost($object->table_element_line, $i);
362 }
363
364
365 if ($totalqty > 0) { // There is at least one thing to ship
366 for ($i = 1; $i <= $num; $i++) {
367 $idl = "idl".$i; // id line source
368 $lineToTest = '';
369 $lineId = GETPOST($idl, 'int');
370 foreach ($objectsrc->lines as $linesrc) {
371 if ($linesrc->id == $lineId) {
372 $lineToTest = $linesrc;
373 break;
374 }
375 }
376 if (empty($lineToTest)) {
377 continue;
378 }
379 $qty = "qtyl".$i;
380 $comment = "comment".$i;
381 // EATBY <-> DLUO and SELLBY <-> DLC, see productbatch.class.php
382 $eatby = "dluo".$i;
383 $sellby = "dlc".$i;
384 $batch = "batch".$i;
385 $cost_price = "cost_price".$i;
386
387 //var_dump(GETPOST("productl".$i, 'int').' '.GETPOST('entl'.$i, 'int').' '.GETPOST($idl, 'int').' '.GETPOST($qty, 'int').' '.GETPOST($batch, 'alpha'));
388
389 //if (GETPOST($qty, 'int') > 0 || (GETPOST($qty, 'int') == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS')) || (GETPOST($qty, 'int') < 0 && getDolGlobalString('RECEPTION_ALLOW_NEGATIVE_QTY'))) {
390 if (GETPOST($qty, 'int') > 0 || (GETPOST($qty, 'int') == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS'))) {
391 $ent = "entl".$i;
392 $idl = "idl".$i;
393
394 $entrepot_id = is_numeric(GETPOST($ent, 'int')) ? GETPOST($ent, 'int') : GETPOST('entrepot_id', 'int');
395
396 /*
397 if (!empty($lineToTest)) {
398 $fk_product = $lineToTest->fk_product;
399 } else {
400 $fk_product = $linesrc->fk_product;
401 }*/
402 $fk_product = GETPOST("productl".$i, 'int');
403
404 if ($entrepot_id < 0) {
405 $entrepot_id = '';
406 }
407 if (!($fk_product > 0) && empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
408 $entrepot_id = 0;
409 }
410
411 $eatby = GETPOST($eatby, 'alpha');
412 $sellby = GETPOST($sellby, 'alpha');
413 $eatbydate = str_replace('/', '-', $eatby);
414 $sellbydate = str_replace('/', '-', $sellby);
415
416 if (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) {
417 $ret = $object->addline($entrepot_id, GETPOST($idl, 'int'), GETPOST($qty, 'int'), $array_options[$i], GETPOST($comment, 'alpha'), strtotime($eatbydate), strtotime($sellbydate), GETPOST($batch, 'alpha'), price2num(GETPOST($cost_price, 'double'), 'MU'));
418 } else {
419 $ret = $object->addline($entrepot_id, GETPOST($idl, 'int'), GETPOST($qty, 'int'), $array_options[$i], GETPOST($comment, 'alpha'), strtotime($eatbydate), strtotime($sellbydate), GETPOST($batch, 'alpha'));
420 }
421 if ($ret < 0) {
422 setEventMessages($object->error, $object->errors, 'errors');
423 $error++;
424 }
425 }
426 }
427
428 // Fill array 'array_options' with data from add form
429 $ret = $extrafields->setOptionalsFromPost(null, $object);
430 if ($ret < 0) {
431 $error++;
432 }
433 if (!$error) {
434 $ret = $object->create($user); // This create reception (like Odoo picking) and line of receptions. Stock movement will when validating reception.
435
436 if ($ret <= 0) {
437 setEventMessages($object->error, $object->errors, 'errors');
438 $error++;
439 }
440 }
441 } else {
442 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("QtyToReceive").'/'.$langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
443 $error++;
444 }
445
446 if (!$error) {
447 $db->commit();
448 header("Location: card.php?id=".$object->id);
449 exit;
450 } else {
451 $db->rollback();
452 $_GET["commande_id"] = GETPOST('commande_id', 'int');
453 $action = 'create';
454 }
455 } elseif ($action == 'confirm_valid' && $confirm == 'yes' && $permissiontovalidate) {
456 $object->fetch_thirdparty();
457
458 $result = $object->valid($user);
459
460 if ($result < 0) {
461 $langs->load("errors");
462 setEventMessages($langs->trans($object->error), null, 'errors');
463 } else {
464 // Define output language
465 if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
466 $outputlangs = $langs;
467 $newlang = '';
468 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
469 $newlang = GETPOST('lang_id', 'aZ09');
470 }
471 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
472 $newlang = $object->thirdparty->default_lang;
473 }
474 if (!empty($newlang)) {
475 $outputlangs = new Translate("", $conf);
476 $outputlangs->setDefaultLang($newlang);
477 }
478 $model = $object->model_pdf;
479 $ret = $object->fetch($id); // Reload to get new records
480
481 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
482 if ($result < 0) {
483 dol_print_error($db, $result);
484 }
485 }
486 }
487 } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
488 $result = $object->delete($user);
489 if ($result > 0) {
490 header("Location: ".DOL_URL_ROOT.'/reception/index.php');
491 exit;
492 } else {
493 setEventMessages($object->error, $object->errors, 'errors');
494 }
495
496 // TODO add alternative status
497 /*} elseif ($action == 'reopen' && (!empty($user->rights->reception->creer) || !empty($user->rights->reception->reception_advance->validate))) {
498 $result = $object->setStatut(0);
499 if ($result < 0) {
500 setEventMessages($object->error, $object->errors, 'errors');
501 }*/
502 } elseif ($action == 'setdate_livraison' && $permissiontoadd) {
503 $datedelivery = dol_mktime(GETPOST('liv_hour', 'int'), GETPOST('liv_min', 'int'), 0, GETPOST('liv_month', 'int'), GETPOST('liv_day', 'int'), GETPOST('liv_year', 'int'));
504
505 $object->fetch($id);
506 $result = $object->setDeliveryDate($user, $datedelivery);
507 if ($result < 0) {
508 setEventMessages($object->error, $object->errors, 'errors');
509 }
510 } elseif ($action == 'settracking_number' || $action == 'settracking_url'
511 || $action == 'settrueWeight'
512 || $action == 'settrueWidth'
513 || $action == 'settrueHeight'
514 || $action == 'settrueDepth'
515 || $action == 'setshipping_method_id') {
516 // Action update
517 $error = 0;
518
519 if ($action == 'settracking_number') {
520 $object->tracking_number = trim(GETPOST('tracking_number', 'alpha'));
521 }
522 if ($action == 'settracking_url') {
523 $object->tracking_url = trim(GETPOST('tracking_url', 'int'));
524 }
525 if ($action == 'settrueWeight') {
526 $object->trueWeight = trim(GETPOST('trueWeight', 'int'));
527 $object->weight_units = GETPOST('weight_units', 'int');
528 }
529 if ($action == 'settrueWidth') {
530 $object->trueWidth = trim(GETPOST('trueWidth', 'int'));
531 }
532 if ($action == 'settrueHeight') {
533 $object->trueHeight = trim(GETPOST('trueHeight', 'int'));
534 $object->size_units = GETPOST('size_units', 'int');
535 }
536 if ($action == 'settrueDepth') {
537 $object->trueDepth = trim(GETPOST('trueDepth', 'int'));
538 }
539 if ($action == 'setshipping_method_id') {
540 $object->shipping_method_id = trim(GETPOST('shipping_method_id', 'int'));
541 }
542
543 if (!$error) {
544 if ($object->update($user) >= 0) {
545 header("Location: card.php?id=".$object->id);
546 exit;
547 }
548 setEventMessages($object->error, $object->errors, 'errors');
549 }
550
551 $action = "";
552 } elseif ($action == 'builddoc' && $permissiontoread) {
553 // Build document
554 // En get ou en post
555 // Save last template used to generate document
556 if (GETPOST('model')) {
557 $object->setDocModel($user, GETPOST('model', 'alpha'));
558 }
559
560 // Define output language
561 $outputlangs = $langs;
562 $newlang = '';
563 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
564 $newlang = GETPOST('lang_id', 'aZ09');
565 }
566 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
567 $newlang = $reception->thirdparty->default_lang;
568 }
569 if (!empty($newlang)) {
570 $outputlangs = new Translate("", $conf);
571 $outputlangs->setDefaultLang($newlang);
572 }
573 $result = $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
574 if ($result <= 0) {
575 setEventMessages($object->error, $object->errors, 'errors');
576 $action = '';
577 }
578 } elseif ($action == 'remove_file' && $permissiontoadd) {
579 // Delete file in doc form
580 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
581
582 $upload_dir = $conf->reception->dir_output;
583 $file = $upload_dir.'/'.GETPOST('file');
584 $ret = dol_delete_file($file, 0, 0, 0, $object);
585 if ($ret) {
586 setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
587 } else {
588 setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors');
589 }
590 } elseif ($action == 'classifybilled') {
591 $result = $object->setBilled();
592 if ($result >= 0) {
593 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
594 exit();
595 } else {
596 setEventMessages($object->error, $object->errors, 'errors');
597 $action = '';
598 }
599 } elseif ($action == 'classifyclosed' && $permissiontoread) {
600 $result = $object->setClosed();
601 if ($result >= 0) {
602 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
603 exit();
604 } else {
605 setEventMessages($object->error, $object->errors, 'errors');
606 $action = '';
607 }
608 } elseif ($action == 'deleteline' && !empty($line_id) && $permissiontoread) {
609 // delete a line
610 $lines = $object->lines;
611 $line = new CommandeFournisseurDispatch($db);
612
613 $num_prod = count($lines);
614 for ($i = 0; $i < $num_prod; $i++) {
615 if ($lines[$i]->id == $line_id) {
616 // delete single warehouse line
617 $line->id = $line_id;
618 if (!$error && $line->delete($user) < 0) {
619 $error++;
620 }
621 }
622 unset($_POST["lineid"]);
623 }
624
625 if (!$error) {
626 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
627 exit();
628 } else {
629 setEventMessages($line->error, $line->errors, 'errors');
630 }
631 } elseif ($action == 'updateline' && GETPOST('save') && $permissiontoadd) {
632 // Update a line
633 // Clean parameters
634 $qty = 0;
635 $entrepot_id = 0;
636 $batch_id = 0;
637
638 $lines = $object->lines;
639 $num_prod = count($lines);
640 for ($i = 0; $i < $num_prod; $i++) {
641 if ($lines[$i]->id == $line_id) { // we have found line to update
642 $line = new CommandeFournisseurDispatch($db);
643 $line->fetch($line_id);
644 // Extrafields Lines
645 $extrafields->fetch_name_optionals_label($object->table_element_line);
646 $line->array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
647
648
649 $line->fk_product = $lines[$i]->fk_product;
650
651
652 if ($lines[$i]->fk_product > 0) {
653 // single warehouse reception line
654 $stockLocation = "entl".$line_id;
655 $qty = "qtyl".$line_id;
656 $comment = "comment".$line_id;
657
658
659 $line->id = $line_id;
660 $line->fk_entrepot = GETPOST($stockLocation, 'int');
661 $line->qty = GETPOST($qty, 'int');
662 $line->comment = GETPOST($comment, 'alpha');
663
664 if (isModEnabled('productbatch')) {
665 $batch = "batch".$line_id;
666 $dlc = "dlc".$line_id;
667 $dluo = "dluo".$line_id;
668 // EATBY <-> DLUO
669 $eatby = GETPOST($dluo, 'alpha');
670 $eatbydate = str_replace('/', '-', $eatby);
671 // SELLBY <-> DLC
672 $sellby = GETPOST($dlc, 'alpha');
673 $sellbydate = str_replace('/', '-', $sellby);
674 $line->batch = GETPOST($batch, 'alpha');
675 $line->eatby = strtotime($eatbydate);
676 $line->sellby = strtotime($sellbydate);
677 }
678
679 if ($line->update($user) < 0) {
680 setEventMessages($line->error, $line->errors, 'errors');
681 $error++;
682 }
683 } else { // Product no predefined
684 $qty = "qtyl".$line_id;
685 $line->id = $line_id;
686 $line->qty = GETPOST($qty, 'int');
687 $line->fk_entrepot = 0;
688 if ($line->update($user) < 0) {
689 setEventMessages($line->error, $line->errors, 'errors');
690 $error++;
691 }
692 unset($_POST[$qty]);
693 }
694 }
695 }
696
697 unset($_POST["lineid"]);
698
699 if (!$error) {
700 if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
701 // Define output language
702 $outputlangs = $langs;
703 $newlang = '';
704 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
705 $newlang = GETPOST('lang_id', 'aZ09');
706 }
707 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
708 $newlang = $object->thirdparty->default_lang;
709 }
710 if (!empty($newlang)) {
711 $outputlangs = new Translate("", $conf);
712 $outputlangs->setDefaultLang($newlang);
713 }
714
715 $ret = $object->fetch($object->id); // Reload to get new records
716 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
717 }
718 } else {
719 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
720 exit();
721 }
722 } elseif ($action == 'updateline' && $permissiontoadd && GETPOST('cancel', 'alpha') == $langs->trans("Cancel")) {
723 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
724 exit();
725 }
726
727 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
728
729 // Actions to send emails
730 if (empty($id)) {
731 $id = $facid;
732 }
733 $triggersendname = 'RECEPTION_SENTBYMAIL';
734 $paramname = 'id';
735 $mode = 'emailfromreception';
736 $trackid = 'rec'.$object->id;
737 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
738}
739
740
741/*
742 * View
743 */
744
745$title = $object->ref.' - '.$langs->trans('Reception');
746
747llxHeader('', $title, 'Reception');
748
749$form = new Form($db);
750$formfile = new FormFile($db);
751$formproduct = new FormProduct($db);
752if (isModEnabled('project')) {
753 $formproject = new FormProjets($db);
754}
755
756$product_static = new Product($db);
757$reception_static = new Reception($db);
758$warehousestatic = new Entrepot($db);
759
760if ($action == 'create2') {
761 print load_fiche_titre($langs->trans("CreateReception"), '', 'dollyrevert');
762
763 print '<br>'.$langs->trans("ReceptionCreationIsDoneFromOrder");
764 $action = ''; $id = ''; $ref = '';
765}
766
767// Mode creation.
768if ($action == 'create') {
769 $recept = new Reception($db);
770
771 print load_fiche_titre($langs->trans("CreateReception"));
772 if (!$origin) {
773 setEventMessages($langs->trans("ErrorBadParameters"), null, 'errors');
774 }
775
776 if ($origin) {
777 if ($origin == 'supplierorder') {
778 $classname = 'CommandeFournisseur';
779 } else {
780 $classname = ucfirst($origin);
781 }
782
783 $objectsrc = new $classname($db);
784 if ($objectsrc->fetch($origin_id)) { // This include the fetch_lines
785 $soc = new Societe($db);
786 $soc->fetch($objectsrc->socid);
787
788 $author = new User($db);
789 $author->fetch($objectsrc->user_author_id);
790
791 if (isModEnabled('stock')) {
792 $entrepot = new Entrepot($db);
793 }
794
795 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
796 print '<input type="hidden" name="token" value="'.newToken().'">';
797 print '<input type="hidden" name="action" value="add">';
798 print '<input type="hidden" name="origin" value="'.$origin.'">';
799 print '<input type="hidden" name="origin_id" value="'.$objectsrc->id.'">';
800 print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
801 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
802 if (GETPOST('entrepot_id', 'int')) {
803 print '<input type="hidden" name="entrepot_id" value="'.GETPOST('entrepot_id', 'int').'">';
804 }
805
806 print dol_get_fiche_head('');
807
808 print '<table class="border centpercent">';
809
810 // Ref
811 print '<tr><td class="titlefieldcreate fieldrequired">';
812 if ($origin == 'supplierorder' && isModEnabled("supplier_order")) {
813 print $langs->trans("RefOrder").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$objectsrc->id.'">'.img_object($langs->trans("ShowOrder"), 'order').' '.$objectsrc->ref;
814 }
815 if ($origin == 'propal' && isModEnabled("propal")) {
816 print $langs->trans("RefProposal").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/comm/card.php?id='.$objectsrc->id.'">'.img_object($langs->trans("ShowProposal"), 'propal').' '.$objectsrc->ref;
817 }
818 print '</a></td>';
819 print "</tr>\n";
820
821 // Ref client
822 print '<tr><td>';
823 if ($origin == 'supplier_order') {
824 print $langs->trans('SupplierOrder');
825 } else {
826 print $langs->trans('RefSupplier');
827 }
828 print '</td><td colspan="3">';
829 print '<input type="text" name="ref_supplier" value="'.$objectsrc->ref_supplier.'" />';
830 print '</td>';
831 print '</tr>';
832
833 // Tiers
834 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Company').'</td>';
835 print '<td colspan="3">'.$soc->getNomUrl(1).'</td>';
836 print '</tr>';
837
838 // Project
839 if (isModEnabled('project')) {
840 $projectid = GETPOST('projectid', 'int') ?GETPOST('projectid', 'int') : 0;
841 if (empty($projectid) && !empty($objectsrc->fk_project)) {
842 $projectid = $objectsrc->fk_project;
843 }
844 if ($origin == 'project') {
845 $projectid = ($originid ? $originid : 0);
846 }
847
848 $langs->load("projects");
849 print '<tr>';
850 print '<td>'.$langs->trans("Project").'</td><td colspan="2">';
851 print img_picto('', 'project', 'class="paddingright"');
852 print $formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $soc->id : -1), $projectid, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500');
853 print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$soc->id.'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
854 print '</td>';
855 print '</tr>';
856 }
857
858 // Date delivery planned
859 print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
860 print '<td colspan="3">';
861 $date_delivery = ($date_delivery ? $date_delivery : $objectsrc->delivery_date); // $date_delivery comes from GETPOST
862 print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1);
863 print "</td>\n";
864 print '</tr>';
865
866 // Note Public
867 print '<tr><td>'.$langs->trans("NotePublic").'</td>';
868 print '<td colspan="3">';
869 $doleditor = new DolEditor('note_public', $objectsrc->note_public, '', 60, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PUBLIC) ? 0 : 1, ROWS_3, '90%');
870 print $doleditor->Create(1);
871 print "</td></tr>";
872
873 // Note Private
874 if ($objectsrc->note_private && !$user->socid) {
875 print '<tr><td>'.$langs->trans("NotePrivate").'</td>';
876 print '<td colspan="3">';
877 $doleditor = new DolEditor('note_private', $objectsrc->note_private, '', 60, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PRIVATE) ? 0 : 1, ROWS_3, '90%');
878 print $doleditor->Create(1);
879 print "</td></tr>";
880 }
881
882 // Weight
883 print '<tr><td>';
884 print $langs->trans("Weight");
885 print '</td><td colspan="3"><input name="weight" size="4" value="'.GETPOST('weight', 'int').'"> ';
886 $text = $formproduct->selectMeasuringUnits("weight_units", "weight", GETPOST('weight_units', 'int'), 0, 2);
887 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
888 print $form->textwithpicto($text, $htmltext);
889 print '</td></tr>';
890 // Dim
891 print '<tr><td>';
892 print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
893 print ' </td><td colspan="3"><input name="trueWidth" size="4" value="'.GETPOST('trueWidth', 'int').'">';
894 print ' x <input name="trueHeight" size="4" value="'.GETPOST('trueHeight', 'int').'">';
895 print ' x <input name="trueDepth" size="4" value="'.GETPOST('trueDepth', 'int').'">';
896 print ' ';
897 $text = $formproduct->selectMeasuringUnits("size_units", "size", GETPOST('size_units', 'int'), 0, 2);
898 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
899 print $form->textwithpicto($text, $htmltext);
900 print '</td></tr>';
901
902 // Delivery method
903 print "<tr><td>".$langs->trans("ReceptionMethod")."</td>";
904 print '<td colspan="3">';
905 $recept->fetch_delivery_methods();
906 print $form->selectarray("shipping_method_id", $recept->meths, GETPOST('shipping_method_id', 'int'), 1, 0, 0, "", 1);
907 if ($user->admin) {
908 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
909 }
910 print "</td></tr>\n";
911
912 // Tracking number
913 print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
914 print '<td colspan="3">';
915 print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number', 'alpha').'">';
916 print "</td></tr>\n";
917
918 // Other attributes
919 $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'cols' => '3', 'socid'=>$socid);
920 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $recept, $action); // Note that $action and $objectsrc may have been modified by hook
921 print $hookmanager->resPrint;
922
923 // Here $object can be of an object Reception
924 $extrafields->fetch_name_optionals_label($object->table_element);
925 if (empty($reshook) && !empty($extrafields->attributes[$object->table_element]['label'])) {
926 // copy from order
927 if ($objectsrc->fetch_optionals() > 0) {
928 $recept->array_options = array_merge($recept->array_options, $objectsrc->array_options);
929 }
930 print $recept->showOptionals($extrafields, 'create', $parameters);
931 }
932
933 // Incoterms
934 if (isModEnabled('incoterm')) {
935 print '<tr>';
936 print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $objectsrc->label_incoterms, 1).'</label></td>';
937 print '<td colspan="3" class="maxwidthonsmartphone">';
938 print $form->select_incoterms((!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : ''), (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : ''));
939 print '</td></tr>';
940 }
941
942 // Document model
943 include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
945
946 if (count($list) > 1) {
947 print "<tr><td>".$langs->trans("DefaultModel")."</td>";
948 print '<td colspan="3">';
949 print $form->selectarray('model', $list, $conf->global->RECEPTION_ADDON_PDF);
950 print "</td></tr>\n";
951 }
952
953 print "</table>";
954
955 print dol_get_fiche_end();
956
957 // Number of lines show on the reception card
958 $numAsked = 0;
959
964 $suffix2numAsked = array();
965 $dispatchLines = array();
966
967 foreach ($_POST as $key => $value) {
968 // If create form is coming from the button "Create Reception" of previous page
969
970 // without batch module enabled or product with no lot/serial
971 $reg = array();
972 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
973 $numAsked++;
974 $paramSuffix = $reg[1] . '_' . $reg[2];
975 $suffix2numAsked[$paramSuffix] = $numAsked;
976
977 // $numline=$reg[2] + 1; // line of product
978 $numline = $numAsked;
979
980 $prod = "product_" . $paramSuffix;
981 $qty = "qty_" . $paramSuffix;
982 $ent = "entrepot_" . $paramSuffix;
983 $pu = "pu_" . $paramSuffix; // This is unit price including discount
984 $fk_commandefourndet = "fk_commandefourndet_" . $paramSuffix;
985 $dispatchLines[$numAsked] = array('paramSuffix'=>$paramSuffix, 'prod' => GETPOST($prod, 'int'), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOST($ent, 'int'), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST('comment'), 'fk_commandefourndet' => GETPOST($fk_commandefourndet, 'int'));
986 }
987
988 // with batch module enabled and product with lot/serial
989 if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
990 $numAsked++;
991 $paramSuffix = $reg[1] . '_' . $reg[2];
992 $suffix2numAsked[$paramSuffix] = $numAsked;
993
994 // eat-by date dispatch
995 // $numline=$reg[2] + 1; // line of product
996 $numline = $numAsked;
997
998 $prod = 'product_batch_' . $paramSuffix;
999 $qty = 'qty_' . $paramSuffix;
1000 $ent = 'entrepot_' . $paramSuffix;
1001 $pu = 'pu_' . $paramSuffix;
1002 $lot = 'lot_number_' . $paramSuffix;
1003 $dDLUO = dol_mktime(12, 0, 0, GETPOST('dluo_'.$paramSuffix.'month', 'int'), GETPOST('dluo_'.$paramSuffix.'day', 'int'), GETPOST('dluo_'.$paramSuffix.'year', 'int'));
1004 $dDLC = dol_mktime(12, 0, 0, GETPOST('dlc_'.$paramSuffix.'month', 'int'), GETPOST('dlc_'.$paramSuffix.'day', 'int'), GETPOST('dlc_'.$paramSuffix.'year', 'int'));
1005 $fk_commandefourndet = 'fk_commandefourndet_'.$paramSuffix;
1006 $dispatchLines[$numAsked] = array('paramSuffix'=>$paramSuffix, 'prod' => GETPOST($prod, 'int'), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOST($ent, 'int'), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST('comment'), 'fk_commandefourndet' => GETPOST($fk_commandefourndet, 'int'), 'DLC'=> $dDLC, 'DLUO'=> $dDLUO, 'lot'=> GETPOST($lot, 'alpha'));
1007 }
1008
1009 // If create form is coming from same page, it means that post was sent but an error occured
1010 if (preg_match('/^productl([0-9]+)$/i', $key, $reg)) {
1011 $numAsked++;
1012 $paramSuffix = $reg[1];
1013 $suffix2numAsked[$paramSuffix] = $numAsked;
1014
1015 // eat-by date dispatch
1016 // $numline=$reg[2] + 1; // line of product
1017 $numline = $numAsked;
1018
1019 $prod = 'productid'.$paramSuffix;
1020 $comment = 'comment'.$paramSuffix;
1021 $qty = 'qtyl'.$paramSuffix;
1022 $ent = 'entl'.$paramSuffix;
1023 $pu = 'pul'.$paramSuffix;
1024 $lot = 'batch'.$paramSuffix;
1025 $dDLUO = dol_mktime(12, 0, 0, GETPOST('dluo'.$paramSuffix.'month', 'int'), GETPOST('dluo'.$paramSuffix.'day', 'int'), GETPOST('dluo'.$paramSuffix.'year', 'int'));
1026 $dDLC = dol_mktime(12, 0, 0, GETPOST('dlc'.$paramSuffix.'month', 'int'), GETPOST('dlc'.$paramSuffix.'day', 'int'), GETPOST('dlc'.$paramSuffix.'year', 'int'));
1027 $fk_commandefourndet = 'fk_commandefournisseurdet'.$paramSuffix;
1028 $dispatchLines[$numAsked] = array('prod' => GETPOST($prod, 'int'), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' =>GETPOST($ent, 'int'), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' =>GETPOST($comment), 'fk_commandefourndet' => GETPOST($fk_commandefourndet, 'int'), 'DLC'=> $dDLC, 'DLUO'=> $dDLUO, 'lot'=> GETPOST($lot, 'alpha'));
1029 }
1030 }
1031
1032 // If extrafield values are passed in the HTTP query, assign them to the correct dispatch line
1033 // Note that if an extrafield with the same name exists in the origin supplier order line, the value
1034 // from the HTTP query will be ignored
1035 foreach ($suffix2numAsked as $suffix => $n) {
1036 $dispatchLines[$n]['array_options'] = $extrafields->getOptionalsFromPost('commande_fournisseur_dispatch', '_' . $suffix, '');
1037 }
1038
1039 print '<script type="text/javascript">
1040 jQuery(document).ready(function() {
1041 jQuery("#autofill").click(function(event) {
1042 event.preventDefault();';
1043 $i = 1;
1044 while ($i <= $numAsked) {
1045 print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
1046 $i++;
1047 }
1048 print '});
1049 jQuery("#autoreset").click(function(event) {
1050 event.preventDefault();';
1051 $i = 1;
1052 while ($i <= $numAsked) {
1053 print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
1054 $i++;
1055 }
1056 print '});
1057 });
1058 </script>';
1059
1060 print '<br>';
1061
1062 print '<table class="noborder centpercent">';
1063
1064 // Load receptions already done for same order
1065 $objectsrc->loadReceptions();
1066
1067 if ($numAsked) {
1068 print '<tr class="liste_titre">';
1069 print '<td>'.$langs->trans("Description").'</td>';
1070 print '<td>'.$langs->trans("Comment").'</td>';
1071 print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1072 print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1073 print '<td class="center">'.$langs->trans("QtyToReceive");
1074 if (getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1075 print '<td>'.$langs->trans("BuyingPrice").'</td>';
1076 }
1077 if (isModEnabled('productbatch')) {
1078 print ' <br><center><a href="#" id="autofill"><span class="fas fa-fill pictofixedwidth" style=""></span> '.$langs->trans("Fill").'</a>';
1079 print ' &nbsp; &nbsp; <a href="#" id="autoreset"><span class="fas fa-eraser pictofixedwidth" style=""></span>'.$langs->trans("Reset").'</a></center><br>';
1080 }
1081 print '</td>';
1082 if (isModEnabled('stock')) {
1083 print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1084 }
1085 if (isModEnabled('productbatch')) {
1086 print '<td class="left">'.$langs->trans("batch_number").'</td>';
1087 if (!getDolGlobalInt('PRODUCT_DISABLE_SELLBY')) {
1088 print '<td class="left">'.$langs->trans("SellByDate").'</td>';
1089 }
1090 if (!getDolGlobalInt('PRODUCT_DISABLE_EATBY')) {
1091 print '<td class="left">'.$langs->trans("EatByDate").'</td>';
1092 }
1093 }
1094 print "</tr>\n";
1095 }
1096
1097 // $objectsrc->lines contains the line of the purchase order
1098 // $dispatchLines is list of lines with dispatching detail (with product, qty and warehouse). One purchase order line may have n of this dispatch lines.
1099
1100 $arrayofpurchaselinealreadyoutput= array();
1101
1102 // $_POST contains fk_commandefourndet_X_Y where Y is num of product line and X is number of splitted line
1103 $indiceAsked = 1;
1104 while ($indiceAsked <= $numAsked) { // Loop on $dispatchLines. Warning: $dispatchLines must be sorted by fk_commandefourndet (it is a regroupment key on output)
1105 $product = new Product($db);
1106
1107 // We search the purchase order line that is linked to the dispatchLines
1108 foreach ($objectsrc->lines as $supplierLine) {
1109 if ($dispatchLines[$indiceAsked]['fk_commandefourndet'] == $supplierLine->id) {
1110 $line = $supplierLine;
1111 break;
1112 }
1113 }
1114
1115 // Show product and description
1116 $type = $line->product_type ? $line->product_type : $line->fk_product_type;
1117 // Try to enhance type detection using date_start and date_end for free lines where type
1118 // was not saved.
1119 if (!empty($line->date_start)) {
1120 $type = 1;
1121 }
1122 if (!empty($line->date_end)) {
1123 $type = 1;
1124 }
1125
1126 print '<!-- line fk_commandefourndet='.$line->id.' for product='.$line->fk_product.' -->'."\n";
1127 print '<tr class="oddeven">'."\n";
1128
1129 // Product label
1130 if ($line->fk_product > 0) { // If predefined product
1131 $product->fetch($line->fk_product);
1132 $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
1133 //var_dump($product->stock_warehouse[1]);
1134 //var_dump($dispatchLines[$indiceAsked]);
1135
1136 print '<td>';
1137 print '<a name="'.$line->id.'"></a>'; // ancre pour retourner sur la ligne
1138
1139 print '<input type="hidden" name="productl'.$indiceAsked.'" value="'.$line->fk_product.'">';
1140
1141 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1142 print '<input type="hidden" name="productid'.$indiceAsked.'" value="'.$line->fk_product.'">';
1143
1144 // Show product and description
1145 $product_static = $product;
1146
1147 $text = $product_static->getNomUrl(1);
1148 $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
1149 $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($line->desc));
1150 print $form->textwithtooltip($text, $description, 3, '', '', $i);
1151
1152 // Show range
1153 print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1154
1155 // Add description in form
1156 if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1157 print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
1158 }
1159 }
1160 print '</td>';
1161 } else {
1162 print "<td>";
1163 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1164 if ($type == 1) {
1165 $text = img_object($langs->trans('Service'), 'service');
1166 } else {
1167 $text = img_object($langs->trans('Product'), 'product');
1168 }
1169
1170 if (!empty($line->label)) {
1171 $text .= ' <strong>'.$line->label.'</strong>';
1172 print $form->textwithtooltip($text, $line->desc, 3, '', '', $i);
1173 } else {
1174 print $text.' '.nl2br($line->desc);
1175 }
1176
1177 // Show range
1178 print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1179 }
1180 print "</td>\n";
1181 }
1182
1183 // Comment
1184 //$defaultcomment = 'Line create from order line id '.$line->id;
1185 $defaultcomment = $dispatchLines[$indiceAsked]['comment'];
1186 print '<td>';
1187 print '<input type="text" class="maxwidth100" name="comment'.$indiceAsked.'" value="'.$defaultcomment.'">';
1188 print '</td>';
1189
1190 // Qty in source purchase order line
1191 print '<td class="center">';
1192 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1193 print $line->qty;
1194 }
1195 print '<input type="hidden" name="fk_commandefournisseurdet'.$indiceAsked.'" value="'.$line->id.'">';
1196 print '<input type="hidden" name="pul'.$indiceAsked.'" value="'.$line->pu_ht.'">';
1197 print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
1198 print '</td>';
1199 $qtyProdCom = $line->qty;
1200
1201 // Qty already received
1202 print '<td class="center">';
1203 $quantityDelivered = $objectsrc->receptions[$line->id];
1204 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1205 print $quantityDelivered;
1206 }
1207 print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
1208 print '</td>';
1209
1210
1211 if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1212 $quantityToBeDelivered = 0;
1213 } else {
1214 $quantityToBeDelivered = $dispatchLines[$indiceAsked]['qty'];
1215 }
1216 $warehouse_id = $dispatchLines[$indiceAsked]['ent'];
1217
1218
1219 $warehouseObject = null;
1220 if (isModEnabled('stock')) {
1221 // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
1222 print '<!-- Case warehouse already known or product not a predefined product -->';
1223 if (array_key_exists($dispatchLines[$indiceAsked]['ent'], $product->stock_warehouse)) {
1224 $stock = +$product->stock_warehouse[$dispatchLines[$indiceAsked]['ent']]->real; // Convert to number
1225 }
1226 $deliverableQty = $dispatchLines[$indiceAsked]['qty'];
1227 $cost_price = $dispatchLines[$indiceAsked]['pu'];
1228
1229 // Quantity to send
1230 print '<td class="center">';
1231 if ($line->product_type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1232 if (GETPOST('qtyl'.$indiceAsked, 'int')) {
1233 $defaultqty = GETPOST('qtyl'.$indiceAsked, 'int');
1234 }
1235 print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1236 print '<input class="right" name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1237 } else {
1238 print $langs->trans("NA");
1239 }
1240 print '</td>';
1241
1242 if (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) {
1243 print '<td>';
1244 print '<input class="width75 right" name="cost_price'.$indiceAsked.'" id="cost_price'.$indiceAsked.'" value="'.$cost_price.'">';
1245 print '</td>';
1246 }
1247
1248 // Stock
1249 if (isModEnabled('stock')) {
1250 print '<td class="left">';
1251 if ($line->product_type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { // Type of product need stock change ?
1252 // Show warehouse combo list
1253 $ent = "entl".$indiceAsked;
1254 $idl = "idl".$indiceAsked;
1255 $tmpentrepot_id = is_numeric(GETPOST($ent, 'int')) ?GETPOST($ent, 'int') : $warehouse_id;
1256 if ($line->fk_product > 0) {
1257 print '<!-- Show warehouse selection -->';
1258 print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 0, 0, $line->fk_product, '', 1);
1259 }
1260 } else {
1261 print $langs->trans("Service");
1262 }
1263 print '</td>';
1264 }
1265
1266 if (isModEnabled('productbatch')) {
1267 if (!empty($product->status_batch)) {
1268 print '<td><input name="batch'.$indiceAsked.'" value="'.$dispatchLines[$indiceAsked]['lot'].'"></td>';
1269 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1270 print '<td class="nowraponall">';
1271 print $form->selectDate($dispatchLines[$indiceAsked]['DLC'], 'dlc'.$indiceAsked, '', '', 1, "");
1272 print '</td>';
1273 }
1274 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1275 print '<td class="nowraponall">';
1276 print $form->selectDate($dispatchLines[$indiceAsked]['DLUO'], 'dluo'.$indiceAsked, '', '', 1, "");
1277 print '</td>';
1278 }
1279 } else {
1280 print '<td colspan="3"></td>';
1281 }
1282 }
1283 }
1284
1285 $arrayofpurchaselinealreadyoutput[$line->id] = $line->id;
1286
1287 print "</tr>\n";
1288
1289 // Display lines for extrafields of the Reception line
1290 // $line is a 'CommandeFournisseurLigne', $dispatchLines contains values of Reception lines so properties of CommandeFournisseurDispatch
1291 if (!empty($extrafields)) {
1292 $colspan = 5;
1293 if (isModEnabled('productbatch')) {
1294 $colspan += 2;
1295 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1296 $colspan += 1;
1297 }
1298 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1299 $colspan += 1;
1300 }
1301 }
1302 $recLine = new CommandeFournisseurDispatch($db);
1303
1304 $srcLine = new CommandeFournisseurLigne($db);
1305 $srcLine->id = $line->id;
1306 $srcLine->fetch_optionals(); // fetch extrafields also available in orderline
1307
1308 if (empty($recLine->array_options) && !empty($dispatchLines[$indiceAsked]['array_options'])) {
1309 $recLine->array_options = $dispatchLines[$indiceAsked]['array_options'];
1310 }
1311 $recLine->array_options = array_merge($recLine->array_options, $srcLine->array_options);
1312
1313 print $recLine->showOptionals($extrafields, 'edit', array('style'=>'class="oddeven"', 'colspan'=>$colspan), $indiceAsked, '', 1);
1314 }
1315
1316 $indiceAsked++;
1317 }
1318
1319 print "</table>";
1320
1321 print '<br>';
1322
1323 print $form->buttonsSaveCancel("Create");
1324
1325 print '</form>';
1326
1327 print '<br>';
1328 } else {
1329 dol_print_error($db);
1330 }
1331 }
1332} elseif ($id || $ref) {
1333 /* *************************************************************************** */
1334 /* */
1335 /* Edit and view mode */
1336 /* */
1337 /* *************************************************************************** */
1338 $lines = $object->lines;
1339
1340 $num_prod = count($lines);
1341 $indiceAsked = 0;
1342 if ($object->id > 0) {
1343 if (!empty($object->origin) && $object->origin_id > 0) {
1344 $object->origin = 'CommandeFournisseur';
1345 $typeobject = $object->origin;
1346 $origin = $object->origin;
1347 $origin_id = $object->origin_id;
1348 $object->fetch_origin(); // Load property $object->commande, $object->propal, ...
1349 }
1350
1351 $soc = new Societe($db);
1352 $soc->fetch($object->socid);
1353
1354 $res = $object->fetch_optionals();
1355
1356 $head = reception_prepare_head($object);
1357 print dol_get_fiche_head($head, 'reception', $langs->trans("Reception"), -1, 'dollyrevert');
1358
1359 $formconfirm = '';
1360
1361 // Confirm deleteion
1362 if ($action == 'delete') {
1363 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('DeleteReception'), $langs->trans("ConfirmDeleteReception", $object->ref), 'confirm_delete', '', 0, 1);
1364 }
1365
1366 // Confirmation validation
1367 if ($action == 'valid') {
1368 $objectref = substr($object->ref, 1, 4);
1369 if ($objectref == 'PROV') {
1370 $numref = $object->getNextNumRef($soc);
1371 } else {
1372 $numref = $object->ref;
1373 }
1374
1375 $text = $langs->trans("ConfirmValidateReception", $numref);
1376 if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')) {
1377 $text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementWillBeRecorded").'.';
1378 } elseif (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1379 $text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementNotYetRecorded").'.';
1380 }
1381
1382 if (isModEnabled('notification')) {
1383 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
1384 $notify = new Notify($db);
1385 $text .= '<br>';
1386 $text .= $notify->confirmMessage('RECEPTION_VALIDATE', $object->socid, $object);
1387 }
1388
1389 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateReception'), $text, 'confirm_valid', '', 0, 1, 250);
1390 }
1391
1392 // Confirm cancelation
1393 if ($action == 'annuler') {
1394 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelReception'), $langs->trans("ConfirmCancelReception", $object->ref), 'confirm_cancel', '', 0, 1);
1395 }
1396
1397 if (!$formconfirm) {
1398 $parameters = array('formConfirm' => $formconfirm);
1399 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1400 if (empty($reshook)) {
1401 $formconfirm .= $hookmanager->resPrint;
1402 } elseif ($reshook > 0) {
1403 $formconfirm = $hookmanager->resPrint;
1404 }
1405 }
1406
1407 // Print form confirm
1408 print $formconfirm;
1409
1410
1411 // Calculate totalWeight and totalVolume for all products
1412 // by adding weight and volume of each product line.
1413 $tmparray = $object->getTotalWeightVolume();
1414 $totalWeight = $tmparray['weight'];
1415 $totalVolume = $tmparray['volume'];
1416
1417
1418 if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) {
1419 $objectsrc = new Commande($db);
1420 $objectsrc->fetch($object->$typeobject->id);
1421 }
1422 if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) {
1423 $objectsrc = new Propal($db);
1424 $objectsrc->fetch($object->$typeobject->id);
1425 }
1426 if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("supplier_order")) {
1427 $objectsrc = new CommandeFournisseur($db);
1428 $objectsrc->fetch($object->$typeobject->id);
1429 }
1430 // Reception card
1431 $linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1432 $morehtmlref = '<div class="refidno">';
1433 // Ref customer reception
1434
1435 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', 0, 1);
1436 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', null, null, '', 1);
1437
1438 // Thirdparty
1439 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
1440 // Project
1441 if (isModEnabled('project')) {
1442 $langs->load("projects");
1443 $morehtmlref .= '<br>';
1444 if (0) { // Do not change on reception
1445 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1446 if ($action != 'classify' && $permissiontoadd) {
1447 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1448 }
1449 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $object->socid : -1), $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
1450 } else {
1451 if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
1452 $proj = new Project($db);
1453 $proj->fetch($objectsrc->fk_project);
1454 $morehtmlref .= $proj->getNomUrl(1);
1455 if ($proj->title) {
1456 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
1457 }
1458 }
1459 }
1460 }
1461 $morehtmlref .= '</div>';
1462
1463 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1464
1465
1466 print '<div class="fichecenter">';
1467 print '<div class="fichehalfleft">';
1468 print '<div class="underbanner clearboth"></div>';
1469
1470 print '<table class="border centpercent tableforfield">';
1471
1472 // Linked documents
1473 if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) {
1474 print '<tr><td>';
1475 print $langs->trans("RefOrder").'</td>';
1476 print '<td colspan="3">';
1477 print $objectsrc->getNomUrl(1, 'commande');
1478 print "</td>\n";
1479 print '</tr>';
1480 }
1481 if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) {
1482 print '<tr><td>';
1483 print $langs->trans("RefProposal").'</td>';
1484 print '<td colspan="3">';
1485 print $objectsrc->getNomUrl(1, 'reception');
1486 print "</td>\n";
1487 print '</tr>';
1488 }
1489 if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("propal")) {
1490 print '<tr><td>';
1491 print $langs->trans("SupplierOrder").'</td>';
1492 print '<td colspan="3">';
1493 print $objectsrc->getNomUrl(1, 'reception');
1494 print "</td>\n";
1495 print '</tr>';
1496 }
1497
1498 // Date creation
1499 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
1500 print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
1501 print '</tr>';
1502
1503 // Delivery date planned
1504 print '<tr><td height="10">';
1505 print '<table class="nobordernopadding" width="100%"><tr><td>';
1506 print $langs->trans('DateDeliveryPlanned');
1507 print '</td>';
1508
1509 if ($action != 'editdate_livraison') {
1510 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>';
1511 }
1512 print '</tr></table>';
1513 print '</td><td colspan="2">';
1514 if ($action == 'editdate_livraison') {
1515 print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1516 print '<input type="hidden" name="token" value="'.newToken().'">';
1517 print '<input type="hidden" name="action" value="setdate_livraison">';
1518 print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0);
1519 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1520 print '</form>';
1521 } else {
1522 print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
1523 }
1524 print '</td>';
1525 print '</tr>';
1526
1527 // Weight
1528 print '<tr><td>';
1529 print $form->editfieldkey("Weight", 'trueWeight', $object->trueWeight, $object, $user->rights->reception->creer);
1530 print '</td><td colspan="3">';
1531
1532 if ($action == 'edittrueWeight') {
1533 print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1534 print '<input name="action" value="settrueWeight" type="hidden">';
1535 print '<input name="id" value="'.$object->id.'" type="hidden">';
1536 print '<input type="hidden" name="token" value="'.newToken().'">';
1537 print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
1538 print $formproduct->selectMeasuringUnits("weight_units", "weight", $object->weight_units, 0, 2);
1539 print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1540 print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1541 print '</form>';
1542 } else {
1543 print $object->trueWeight;
1544 print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : '';
1545 }
1546
1547 // Calculated
1548 if ($totalWeight > 0) {
1549 if (!empty($object->trueWeight)) {
1550 print ' ('.$langs->trans("SumOfProductWeights").': ';
1551 }
1552 print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND) ? $conf->global->MAIN_WEIGHT_DEFAULT_ROUND : -1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? $conf->global->MAIN_WEIGHT_DEFAULT_UNIT : 'no');
1553 if (!empty($object->trueWeight)) {
1554 print ')';
1555 }
1556 }
1557 print '</td></tr>';
1558
1559 // Width
1560 print '<tr><td>'.$form->editfieldkey("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1561 print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->reception->creer);
1562 print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : '';
1563 print '</td></tr>';
1564
1565 // Height
1566 print '<tr><td>'.$form->editfieldkey("Height", 'trueHeight', $object->trueHeight, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1567 if ($action == 'edittrueHeight') {
1568 print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1569 print '<input name="action" value="settrueHeight" type="hidden">';
1570 print '<input name="id" value="'.$object->id.'" type="hidden">';
1571 print '<input type="hidden" name="token" value="'.newToken().'">';
1572 print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
1573 print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2);
1574 print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1575 print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1576 print '</form>';
1577 } else {
1578 print $object->trueHeight;
1579 print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : '';
1580 }
1581
1582 print '</td></tr>';
1583
1584 // Depth
1585 print '<tr><td>'.$form->editfieldkey("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1586 print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->reception->creer);
1587 print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : '';
1588 print '</td></tr>';
1589
1590 // Volume
1591 print '<tr><td>';
1592 print $langs->trans("Volume");
1593 print '</td>';
1594 print '<td colspan="3">';
1595 $calculatedVolume = 0;
1596 $volumeUnit = 0;
1597 if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
1598 $calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth);
1599 $volumeUnit = $object->size_units * 3;
1600 }
1601 // If reception volume not defined we use sum of products
1602 if ($calculatedVolume > 0) {
1603 if ($volumeUnit < 50) {
1604 print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no');
1605 } else {
1606 print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit);
1607 }
1608 }
1609 if ($totalVolume > 0) {
1610 if ($calculatedVolume) {
1611 print ' ('.$langs->trans("SumOfProductVolumes").': ';
1612 }
1613 print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no');
1614 //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
1615 if ($calculatedVolume) {
1616 print ')';
1617 }
1618 }
1619 print "</td>\n";
1620 print '</tr>';
1621
1622 // Other attributes
1623 $cols = 2;
1624
1625 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1626
1627 print '</table>';
1628
1629 print '</div>';
1630 print '<div class="fichehalfright">';
1631 print '<div class="underbanner clearboth"></div>';
1632
1633 print '<table class="border centpercent tableforfield">';
1634
1635 // Reception method
1636 print '<tr><td height="10">';
1637 print '<table class="nobordernopadding centpercent"><tr><td>';
1638 print $langs->trans('ReceptionMethod');
1639 print '</td>';
1640
1641 if ($action != 'editshipping_method_id') {
1642 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editshipping_method_id&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetReceptionMethod'), 1).'</a></td>';
1643 }
1644 print '</tr></table>';
1645 print '</td><td colspan="2">';
1646 if ($action == 'editshipping_method_id') {
1647 print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1648 print '<input type="hidden" name="token" value="'.newToken().'">';
1649 print '<input type="hidden" name="action" value="setshipping_method_id">';
1650 $object->fetch_delivery_methods();
1651 print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1);
1652 if ($user->admin) {
1653 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1654 }
1655 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1656 print '</form>';
1657 } else {
1658 if ($object->shipping_method_id > 0) {
1659 // Get code using getLabelFromKey
1660 $code = $langs->getLabelFromKey($db, $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
1661 print $langs->trans("SendingMethod".strtoupper($code));
1662 }
1663 }
1664 print '</td>';
1665 print '</tr>';
1666
1667 // Tracking Number
1668 print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1669 print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->rights->reception->creer, 'safehtmlstring', $object->tracking_number);
1670 print '</td></tr>';
1671
1672 // Incoterms
1673 if (isModEnabled('incoterm')) {
1674 print '<tr><td>';
1675 print '<table width="100%" class="nobordernopadding"><tr><td>';
1676 print $langs->trans('IncotermLabel');
1677 print '<td><td class="right">';
1678 if ($user->rights->reception->creer) {
1679 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/reception/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
1680 } else {
1681 print '&nbsp;';
1682 }
1683 print '</td></tr></table>';
1684 print '</td>';
1685 print '<td colspan="3">';
1686 if ($action != 'editincoterm') {
1687 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
1688 } else {
1689 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
1690 }
1691 print '</td></tr>';
1692 }
1693
1694 print "</table>";
1695
1696 print '</div>';
1697 print '</div>';
1698
1699 print '<div class="clearboth"></div>';
1700
1701
1702 // Lines of products
1703 if ($action == 'editline') {
1704 print '<form name="updateline" id="updateline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;lineid='.$line_id.'" method="POST">
1705 <input type="hidden" name="token" value="' . newToken().'">
1706 <input type="hidden" name="action" value="updateline">
1707 <input type="hidden" name="mode" value="">
1708 <input type="hidden" name="id" value="' . $object->id.'">';
1709 }
1710 print '<br><br>';
1711
1712 print '<div class="div-table-responsive-no-min">';
1713 print '<table id="tablelines" class="noborder centpercent">';
1714 print '<thead>';
1715 print '<tr class="liste_titre">';
1716 // #
1717 if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
1718 print '<td width="5" class="center">&nbsp;</td>';
1719 }
1720 // Product/Service
1721 print '<td>'.$langs->trans("Products").'</td>';
1722 // Comment
1723 print '<td>'.$langs->trans("Comment").'</td>';
1724 // Qty
1725 print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1726 if ($origin && $origin_id > 0) {
1727 print '<td class="center">'.$langs->trans("QtyInOtherReceptions").'</td>';
1728 }
1729 if ($action == 'editline') {
1730 $editColspan = 3;
1731 if (!isModEnabled('stock')) {
1732 $editColspan--;
1733 }
1734 if (empty($conf->productbatch->enabled)) {
1735 $editColspan--;
1736 }
1737 print '<td class="center" colspan="'.$editColspan.'">';
1738 if ($object->statut <= 1) {
1739 print $langs->trans("QtyToReceive").' - ';
1740 } else {
1741 print $langs->trans("QtyReceived").' - ';
1742 }
1743 if (isModEnabled('stock')) {
1744 print $langs->trans("WarehouseTarget").' - ';
1745 }
1746 if (isModEnabled('productbatch')) {
1747 print $langs->trans("Batch");
1748 }
1749 print '</td>';
1750 } else {
1751 $statusreceived = $object::STATUS_CLOSED;
1752 if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) {
1753 $statusreceived = $object::STATUS_VALIDATED;
1754 }
1755 if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) {
1756 $statusreceived = $object::STATUS_CLOSED;
1757 }
1758 if ($object->statut < $statusreceived) {
1759 print '<td class="center">'.$langs->trans("QtyToReceive").'</td>';
1760 } else {
1761 print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1762 }
1763 if (isModEnabled('stock')) {
1764 print '<td class="left">'.$langs->trans("WarehouseTarget").'</td>';
1765 }
1766
1767 if (isModEnabled('productbatch')) {
1768 print '<td class="left">'.$langs->trans("Batch").'</td>';
1769 }
1770 }
1771 print '<td class="center">'.$langs->trans("CalculatedWeight").'</td>';
1772 print '<td class="center">'.$langs->trans("CalculatedVolume").'</td>';
1773 //print '<td class="center">'.$langs->trans("Size").'</td>';
1774 if ($object->statut == 0) {
1775 print '<td class="linecoledit"></td>';
1776 print '<td class="linecoldelete" width="10"></td>';
1777 }
1778 print "</tr>\n";
1779 print '</thead>';
1780
1781 $var = false;
1782
1783 if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1784 $object->fetch_thirdparty();
1785 $outputlangs = $langs;
1786 $newlang = '';
1787 if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1788 $newlang = GETPOST('lang_id', 'aZ09');
1789 }
1790 if (empty($newlang)) {
1791 $newlang = $object->thirdparty->default_lang;
1792 }
1793 if (!empty($newlang)) {
1794 $outputlangs = new Translate("", $conf);
1795 $outputlangs->setDefaultLang($newlang);
1796 }
1797 }
1798
1799 // Get list of products already sent for same source object into $alreadysent
1800 $alreadysent = array();
1801
1802 $origin = 'commande_fournisseur';
1803
1804 if ($origin && $origin_id > 0) {
1805 $sql = "SELECT obj.rowid, obj.fk_product, obj.label, obj.description, obj.product_type as fk_product_type, obj.qty as qty_asked, obj.date_start, obj.date_end";
1806 $sql .= ", ed.rowid as receptionline_id, ed.qty, ed.fk_reception as reception_id, ed.fk_entrepot";
1807 $sql .= ", e.rowid as reception_id, e.ref as reception_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_reception";
1808 //if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
1809 $sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
1810 $sql .= ', p.description as product_desc';
1811 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
1812 $sql .= ", ".MAIN_DB_PREFIX."reception as e";
1813 $sql .= ", ".MAIN_DB_PREFIX.$origin."det as obj";
1814 //if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.fk_reception = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."deliverydet as ld ON ld.fk_delivery = l.rowid AND obj.rowid = ld.fk_origin_line";
1815 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
1816 $sql .= " WHERE e.entity IN (".getEntity('reception').")";
1817 $sql .= " AND obj.fk_commande = ".((int) $origin_id);
1818 $sql .= " AND obj.rowid = ed.fk_commandefourndet";
1819 $sql .= " AND ed.fk_reception = e.rowid";
1820 $sql .= " AND ed.fk_reception !=".((int) $object->id);
1821 //if ($filter) $sql.= $filter;
1822 $sql .= " ORDER BY obj.fk_product";
1823
1824 dol_syslog("get list of reception lines", LOG_DEBUG);
1825 $resql = $db->query($sql);
1826 if ($resql) {
1827 $num = $db->num_rows($resql);
1828 $i = 0;
1829
1830 while ($i < $num) {
1831 $obj = $db->fetch_object($resql);
1832 if ($obj) {
1833 // $obj->rowid is rowid in $origin."det" table
1834 $alreadysent[$obj->rowid][$obj->receptionline_id] = array('reception_ref'=>$obj->reception_ref, 'reception_id'=>$obj->reception_id, 'warehouse'=>$obj->fk_entrepot, 'qty'=>$obj->qty, 'date_valid'=>$obj->date_valid, 'date_delivery'=>$obj->date_delivery);
1835 }
1836 $i++;
1837 }
1838 }
1839 //var_dump($alreadysent);
1840 }
1841
1842 $arrayofpurchaselinealreadyoutput = array();
1843
1844 // Loop on each product to send/sent. Warning: $lines must be sorted by ->fk_commandefourndet (it is a regroupment key on output)
1845 print '<tbody>';
1846 for ($i = 0; $i < $num_prod; $i++) {
1847 print '<!-- origin line id = '.(!empty($lines[$i]->origin_line_id) ? $lines[$i]->origin_line_id : 0).' -->'; // id of order line
1848 print '<tr class="oddeven" id="row-'.$lines[$i]->id.'" data-id="'.$lines[$i]->id.'" data-element="'.$lines[$i]->element.'">';
1849
1850 // #
1851 if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
1852 print '<td class="center">'.($i + 1).'</td>';
1853 }
1854
1855 // Predefined product or service
1856 if ($lines[$i]->fk_product > 0) {
1857 // Define output language
1858 if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1859 $prod = new Product($db);
1860 $prod->fetch($lines[$i]->fk_product);
1861 $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product->label;
1862 } else {
1863 $label = (!empty($lines[$i]->product->label) ? $lines[$i]->product->label : $lines[$i]->product->product_label);
1864 }
1865
1866 print '<td class="linecoldescription">';
1867 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1868 $text = $lines[$i]->product->getNomUrl(1);
1869 $text .= ' - '.$label;
1870 $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->product->description));
1871 print $form->textwithtooltip($text, $description, 3, '', '', $i);
1872 print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : 0, !empty($lines[$i]->date_end) ? $lines[$i]->date_end : 0);
1873 if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1874 print (!empty($lines[$i]->product->description) && $lines[$i]->description != $lines[$i]->product->description) ? '<br>'.dol_htmlentitiesbr($lines[$i]->description) : '';
1875 }
1876 }
1877 print "</td>\n";
1878 } else {
1879 print '<td class="linecoldescription">';
1880 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1881 if ($lines[$i]->product_type == Product::TYPE_SERVICE) {
1882 $text = img_object($langs->trans('Service'), 'service');
1883 } else {
1884 $text = img_object($langs->trans('Product'), 'product');
1885 }
1886
1887 if (!empty($lines[$i]->label)) {
1888 $text .= ' <strong>'.$lines[$i]->label.'</strong>';
1889 print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i);
1890 } else {
1891 print $text.' '.nl2br($lines[$i]->description);
1892 }
1893
1894 print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
1895 }
1896 print "</td>\n";
1897 }
1898
1899 if ($action == 'editline' && $lines[$i]->id == $line_id) {
1900 print '<td><input name="comment'.$line_id.'" id="comment'.$line_id.'" value="'.dol_escape_htmltag($lines[$i]->comment).'"></td>';
1901 } else {
1902 print '<td style="white-space: pre-wrap; max-width: 200px;">'.dol_escape_htmltag($lines[$i]->comment).'</td>';
1903 }
1904
1905
1906 // Qty ordered
1907 print '<td class="center linecolqty">';
1908 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1909 print $lines[$i]->qty_asked;
1910 }
1911 print '</td>';
1912
1913 // Qty in other receptions (with reception and warehouse used)
1914 if ($origin && $origin_id > 0) {
1915 print '<td class="center nowrap linecolqtyinotherreceptions">';
1916 $htmltooltip = '';
1917 $qtyalreadyreceived = 0;
1918 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1919 foreach ($alreadysent as $key => $val) {
1920 if ($lines[$i]->fk_commandefourndet == $key) {
1921 $j = 0;
1922 foreach ($val as $receptionline_id => $receptionline_var) {
1923 if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) {
1924 continue; // We want to show only "other receptions"
1925 }
1926
1927 $j++;
1928 if ($j > 1) {
1929 $htmltooltip .= '<br>';
1930 }
1931 $reception_static->fetch($receptionline_var['reception_id']);
1932 $htmltooltip .= $reception_static->getNomUrl(1, 0, 0, 0, 1);
1933 $htmltooltip .= ' - '.$receptionline_var['qty'];
1934
1935 $htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour'));
1936 if (isModEnabled('stock') && $receptionline_var['warehouse'] > 0) {
1937 $warehousestatic->fetch($receptionline_var['warehouse']);
1938 $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
1939 }
1940 $htmltooltip .= ' '.$form->textwithpicto('', $htmltext, 1);
1941
1942 $qtyalreadyreceived += $receptionline_var['qty'];
1943 }
1944 if ($j) {
1945 $htmltooltip = $langs->trans("QtyInOtherReceptions").'...<br><br>'.$htmltooltip.'<br><input type="submit" name="dummyhiddenbuttontogetfocus" style="display:none" autofocus>';
1946 }
1947 }
1948 }
1949 }
1950 print $form->textwithpicto($qtyalreadyreceived, $htmltooltip, 1, 'info', '', 0, 3, 'tooltip'.$lines[$i]->id);
1951 print '</td>';
1952 }
1953
1954 if ($action == 'editline' && $lines[$i]->id == $line_id) {
1955 // edit mode
1956 print '<td colspan="'.$editColspan.'" class="center"><table class="nobordernopadding">';
1957 if (isModEnabled('stock')) {
1958 if ($lines[$i]->fk_product > 0) {
1959 print '<!-- case edit 1 -->';
1960 print '<tr>';
1961 // Qty to receive or received
1962 print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
1963 // Warehouse source
1964 print '<td>'.$formproduct->selectWarehouses($lines[$i]->fk_entrepot, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).'</td>';
1965 // Batch number managment
1966 if ($conf->productbatch->enabled && !empty($lines[$i]->product->status_batch)) {
1967 print '<td class="nowraponall left"><input name="batch'.$line_id.'" id="batch'.$line_id.'" type="text" value="'.$lines[$i]->batch.'"><br>';
1968 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1969 print $langs->trans('SellByDate').' : ';
1970 print $form->selectDate($lines[$i]->sellby, 'dlc'.$line_id, '', '', 1, "").'</br>';
1971 }
1972 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1973 print $langs->trans('EatByDate').' : ';
1974 print $form->selectDate($lines[$i]->eatby, 'dluo'.$line_id, '', '', 1, "");
1975 }
1976 print '</td>';
1977 }
1978 print '</tr>';
1979 } else {
1980 print '<!-- case edit 2 -->';
1981 print '<tr>';
1982 // Qty to receive or received
1983 print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
1984 // Warehouse source
1985 print '<td></td>';
1986 // Batch number managment
1987 print '<td></td>';
1988 print '</tr>';
1989 }
1990 }
1991 print '</table></td>';
1992 } else {
1993 // Qty to receive or received
1994 print '<td class="center linecolqtytoreceive">'.$lines[$i]->qty.'</td>';
1995
1996 // Warehouse source
1997 if (isModEnabled('stock')) {
1998 if ($lines[$i]->fk_entrepot > 0) {
1999 $entrepot = new Entrepot($db);
2000 $entrepot->fetch($lines[$i]->fk_entrepot);
2001
2002 print '<td class="left tdoverflowmax150" title="'.dol_escape_htmltag($entrepot->label).'">';
2003 print $entrepot->getNomUrl(1);
2004 print '</td>';
2005 } else {
2006 print '<td></td>';
2007 }
2008 }
2009
2010 // Batch number managment
2011 if (isModEnabled('productbatch')) {
2012 if (isset($lines[$i]->batch)) {
2013 print '<!-- Detail of lot -->';
2014 print '<td class="linecolbatch nowrap">';
2015 $detail = $langs->trans("NA");
2016 if ($lines[$i]->product->status_batch > 0 && $lines[$i]->fk_product > 0) {
2017 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
2018 $productlot = new Productlot($db);
2019 $reslot = $productlot->fetch(0, $lines[$i]->fk_product, $lines[$i]->batch);
2020 if ($reslot > 0) {
2021 $detail = $productlot->getNomUrl(1);
2022 } else {
2023 // lot is not created and info is only in reception lines
2024 $batchinfo = $langs->trans("Batch").': '.$lines[$i]->batch;
2025 if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
2026 $batchinfo .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($lines[$i]->sellby, "day");
2027 }
2028 if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
2029 $batchinfo .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($lines[$i]->eatby, "day");
2030 }
2031 $detail = $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $batchinfo);
2032 }
2033 }
2034 print $detail . '</td>';
2035 } else {
2036 print '<td></td>';
2037 }
2038 }
2039 }
2040
2041 // Weight
2042 print '<td class="center linecolweight">';
2043 if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2044 print $lines[$i]->product->weight * $lines[$i]->qty.' '.measuringUnitString(0, "weight", $lines[$i]->product->weight_units);
2045 } else {
2046 print '&nbsp;';
2047 }
2048 print '</td>';
2049
2050 // Volume
2051 print '<td class="center linecolvolume">';
2052 if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2053 print $lines[$i]->product->volume * $lines[$i]->qty.' '.measuringUnitString(0, "volume", $lines[$i]->product->volume_units);
2054 } else {
2055 print '&nbsp;';
2056 }
2057 print '</td>';
2058
2059
2060 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2061 print '<td class="center valignmiddle" colspan="2">';
2062 print '<input type="submit" class="button small button-save" id="savelinebutton marginbottomonly" name="save" value="'.$langs->trans("Save").'"><br>';
2063 print '<input type="submit" class="button small button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'"><br>';
2064 print '</td>';
2065 } elseif ($object->statut == Reception::STATUS_DRAFT) {
2066 // edit-delete buttons
2067 print '<td class="linecoledit center">';
2068 print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_edit().'</a>';
2069 print '</td>';
2070 print '<td class="linecoldelete" width="10">';
2071 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deleteline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_delete().'</a>';
2072 print '</td>';
2073
2074 // Display lines extrafields
2075 if (!empty($rowExtrafieldsStart)) {
2076 print $rowExtrafieldsStart;
2077 print $rowExtrafieldsView;
2078 print $rowEnd;
2079 }
2080 }
2081 print "</tr>";
2082
2083 $arrayofpurchaselinealreadyoutput[$lines[$i]->fk_commandefourndet] = $lines[$i]->fk_commandefourndet;
2084
2085 // Display lines extrafields
2086 $extralabelslines = $extrafields->attributes[$lines[$i]->table_element];
2087 if (!empty($extralabelslines) && is_array($extralabelslines) && count($extralabelslines) > 0) {
2088 $colspan = 8;
2089 if (isModEnabled('stock')) { $colspan++; }
2090 if (isModEnabled('productbatch')) { $colspan++; }
2091
2092 $line = new CommandeFournisseurDispatch($db);
2093 $line->id = $lines[$i]->id;
2094 $line->fetch_optionals();
2095
2096 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2097 print $line->showOptionals($extrafields, 'edit', array('colspan'=>$colspan), '');
2098 } else {
2099 print $line->showOptionals($extrafields, 'view', array('colspan'=>$colspan), '');
2100 }
2101 }
2102 }
2103 print '</tbody>';
2104
2105 // TODO Show also lines ordered but not delivered
2106
2107 print "</table>\n";
2108 print '</div>';
2109 }
2110
2111
2112 print dol_get_fiche_end();
2113
2114
2115 $object->fetchObjectLinked($object->id, $object->element);
2116
2117
2118 /*
2119 * Boutons actions
2120 */
2121
2122 if (($user->socid == 0) && ($action != 'presend')) {
2123 print '<div class="tabsAction">';
2124
2125 $parameters = array();
2126 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2127 if (empty($reshook)) {
2128 if ($object->statut == Reception::STATUS_DRAFT && $num_prod > 0) {
2129 if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer))
2130 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate))) {
2131 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken().'">'.$langs->trans("Validate").'</a>';
2132 } else {
2133 print '<a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
2134 }
2135 }
2136 // Back to draft
2137 if ($object->statut == Reception::STATUS_VALIDATED && $user->rights->reception->creer) {
2138 print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('SetToDraft').'</a></div>';
2139 }
2140
2141 // TODO add alternative status
2142 // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
2143 if ($object->statut == Reception::STATUS_CLOSED && $user->rights->reception->creer) {
2144 if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2145 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ClassifyUnbilled").'</a>';
2146 } else {
2147 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
2148 }
2149 }
2150
2151 // Send
2152 if (empty($user->socid)) {
2153 if ($object->statut > 0) {
2154 if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->reception->reception_advance->send) {
2155 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendByMail').'</a>';
2156 } else {
2157 print '<a class="butActionRefused" href="#">'.$langs->trans('SendByMail').'</a>';
2158 }
2159 }
2160 }
2161
2162 // Create bill
2163 if (isModEnabled("supplier_invoice") && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED)) {
2164 if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight('supplier_invoice', 'creer')) {
2165 // TODO show button only if (!empty($conf->global->WORKFLOW_BILL_ON_RECEPTION))
2166 // If we do that, we must also make this option official.
2167 print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
2168 }
2169 }
2170
2171
2172 // Close
2173 if ($object->statut == Reception::STATUS_VALIDATED) {
2174 if ($user->rights->reception->creer && $object->statut > 0 && !$object->billed) {
2175 $label = "Close"; $paramaction = 'classifyclosed'; // = Transferred/Received
2176 // Label here should be "Close" or "ClassifyBilled" if we decided to make bill on receptions instead of orders
2177 if (isModEnabled("supplier_order") && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2178 $label = "ClassifyBilled";
2179 $paramaction = 'classifybilled';
2180 }
2181 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action='.$paramaction.'&token='.newToken().'">'.$langs->trans($label).'</a>';
2182 }
2183 }
2184
2185 if ($user->rights->reception->supprimer) {
2186 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
2187 }
2188 }
2189
2190 print '</div>';
2191 }
2192
2193
2194 /*
2195 * Documents generated
2196 */
2197
2198 if ($action != 'presend' && $action != 'editline') {
2199 print '<div class="fichecenter"><div class="fichehalfleft">';
2200
2201 $objectref = dol_sanitizeFileName($object->ref);
2202 $filedir = $conf->reception->dir_output."/".$objectref;
2203
2204 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2205
2206 $genallowed = $user->rights->reception->lire;
2207 $delallowed = $user->rights->reception->creer;
2208
2209 print $formfile->showdocuments('reception', $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
2210
2211 // Show links to link elements
2212 //$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
2213 $somethingshown = $form->showLinkedObjectBlock($object, '');
2214
2215 print '</div><div class="fichehalfright">';
2216
2217 print '</div></div>';
2218 }
2219
2220 // Presend form
2221 $modelmail = 'shipping_send';
2222 $defaulttopic = 'SendReceptionRef';
2223 $diroutput = $conf->reception->dir_output;
2224 $trackid = 'rec'.$object->id;
2225
2226 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2227}
2228
2229
2230llxFooter();
2231
2232$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:56
llxFooter()
Empty footer.
Definition wrapper.php:70
Class to manage table commandefournisseurdispatch.
Class to manage predefined suppliers products.
Class to manage customers orders.
Class to manage a WYSIWYG editor.
Class to manage warehouses.
Class to manage standard extra fields.
Class to offer components to list and upload files.
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 building of HTML components.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
Class to manage notifications.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class with list of lots and properties.
Class to manage projects.
Class to manage proposals.
Class to manage receptions.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
print_date_range($date_start, $date_end, $format='', $outputlangs='')
Format output for start and end date.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
reception_prepare_head(Reception $object)
Prepare array with list of tabs.
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.