dolibarr 24.0.0-beta
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
5 * Copyright (C) 2005-2015 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
7 * Copyright (C) 2010-2013 Juanjo Menent <jmenent@2byte.es>
8 * Copyright (C) 2011-2023 Philippe Grand <philippe.grand@atoo-net.com>
9 * Copyright (C) 2012-2023 Christophe Battarel <christophe.battarel@altairis.fr>
10 * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
11 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
12 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
13 * Copyright (C) 2014 Ferran Marcet <fmarcet@2byte.es>
14 * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
15 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
16 * Copyright (C) 2022 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
17 * Copyright (C) 2023-2024 Benjamin Falière <benjamin.faliere@altairis.fr>
18 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
19 * Copyright (C) 2025 Lenin Rivas <lenin.rivas777@gmail.com>
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 3 of the License, or
24 * (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program. If not, see <https://www.gnu.org/licenses/>.
33 */
34
41// Load Dolibarr environment
42require '../main.inc.php';
53require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
54require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
55require_once DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php';
56require_once DOL_DOCUMENT_ROOT . '/core/class/html.formorder.class.php';
57require_once DOL_DOCUMENT_ROOT . '/core/class/html.formmargin.class.php';
58require_once DOL_DOCUMENT_ROOT . '/core/modules/commande/modules_commande.php';
59require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
60require_once DOL_DOCUMENT_ROOT . '/core/lib/order.lib.php';
61
62require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php';
63require_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
64require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
65
66if (isModEnabled("propal")) {
67 require_once DOL_DOCUMENT_ROOT . '/comm/propal/class/propal.class.php';
68}
69
70if (isModEnabled('project')) {
71 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
72 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
73}
74
75if (isModEnabled('variants')) {
76 require_once DOL_DOCUMENT_ROOT . '/variants/class/ProductCombination.class.php';
77}
78
79
80// Load translation files required by the page
81$langs->loadLangs(array('orders', 'sendings', 'companies', 'bills', 'propal', 'products', 'other'));
82
83if (isModEnabled('incoterm')) {
84 $langs->load('incoterm');
85}
86if (isModEnabled('margin')) {
87 $langs->load('margins');
88}
89if (isModEnabled('productbatch')) {
90 $langs->load('productbatch');
91}
92
93
94$id = (GETPOSTINT('id') ? GETPOSTINT('id') : GETPOSTINT('orderid'));
95$ref = GETPOST('ref', 'alpha');
96$socid = GETPOSTINT('socid');
97$action = GETPOST('action', 'aZ09');
98$cancel = GETPOST('cancel', 'alpha');
99$confirm = GETPOST('confirm', 'alpha');
100$backtopage = GETPOST('backtopage', 'alpha');
101
102$lineid = GETPOSTINT('lineid');
103$contactid = GETPOSTINT('contactid');
104$projectid = GETPOSTINT('projectid');
105$origin = GETPOST('origin', 'alpha');
106$originid = (GETPOSTINT('originid') ? GETPOSTINT('originid') : GETPOSTINT('origin_id')); // For backward compatibility
107$rank = (GETPOSTINT('rank') > 0) ? GETPOSTINT('rank') : -1;
108
109// Type Contact default
110$type_contact_code = (getDolGlobalString('ORDER_TYPE_CONTACT_DEFAULT') ? getDolGlobalString('ORDER_TYPE_CONTACT_DEFAULT') : 'CUSTOMER');
111
112// PDF
113$hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
114$hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
115$hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
116
117// Security check
118if (!empty($user->socid)) {
119 $socid = $user->socid;
120}
121
122$array_options = 0;
123$object_id = 0;
124$price_base_type = null;
125$lineClassName = null;
126$remise_percent = null;
127$ref_client = null;
128$availability_id = null;
129$shipping_method_id = null;
130$warehouse_id = null;
131$demand_reason_id = null;
132$formproject = null;
133$objectsrc = null;
134$note_public = null;
135$note_private = null;
136$classname = null;
137
138
139// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
140$hookmanager->initHooks(array('ordercard', 'globalcard'));
141
142$result = restrictedArea($user, 'commande', $id);
143
144$object = new Commande($db);
145
146// fetch optionals attributes and labels
147$extrafields->fetch_name_optionals_label($object->table_element);
148
149// Load object
150include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
151
152// Permissions / Rights
153$usercanread = $user->hasRight("commande", "lire");
154$usercancreate = $user->hasRight("commande", "creer");
155$usercandelete = $user->hasRight("commande", "supprimer");
156
157// Advanced permissions
158$usercanclose = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !empty($usercancreate)) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('commande', 'order_advance', 'close')));
159$usercanvalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $usercancreate) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('commande', 'order_advance', 'validate')));
160$usercancancel = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $usercancreate) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('commande', 'order_advance', 'annuler')));
161$usercansend = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('commande', 'order_advance', 'send'));
162$usercangeneratedoc = (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('commande', 'order_advance', 'generetedoc'));
163
164$usermustrespectpricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
165$usercancreatepurchaseorder = ($user->hasRight('fournisseur', 'commande', 'creer') || $user->hasRight('supplier_order', 'creer'));
166
167$permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php
168$permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php
169$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
170$permissiontoeditextra = $usercancreate;
171if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
172 // For action 'update_extras', is there a specific permission set for the attribute to update
173 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
174}
175
176$error = 0;
177
178$date_delivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
179
180$selectedLines = array();
181
182
183/*
184 * Actions
185 */
186
187$parameters = array('socid' => $socid);
188// Note that $action and $object may be modified by some hooks
189$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
190if ($reshook < 0) {
191 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
192}
193
194if (empty($reshook)) {
195 $backurlforlist = DOL_URL_ROOT . '/commande/list.php';
196
197 if (empty($backtopage) || ($cancel && empty($id))) {
198 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
199 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
200 $backtopage = $backurlforlist;
201 } else {
202 $backtopage = DOL_URL_ROOT . '/commande/card.php?id=' . ((!empty($id) && $id > 0) ? $id : '__ID__');
203 }
204 }
205 }
206
207 $selectedLines = GETPOST('toselect', 'array:int');
208
209 if ($cancel) {
210 if (!empty($backtopageforcancel)) {
211 header("Location: " . $backtopageforcancel);
212 exit;
213 } elseif (!empty($backtopage)) {
214 header("Location: " . $backtopage);
215 exit;
216 }
217 $action = '';
218 }
219
220 include DOL_DOCUMENT_ROOT . '/core/actions_setnotes.inc.php'; // Must be 'include', not 'include_once'
221
222 include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
223
224 include DOL_DOCUMENT_ROOT . '/core/actions_lineupdown.inc.php'; // Must be 'include', not 'include_once'
225
226 // Action clone object
227 if ($action == 'confirm_clone' && $confirm == 'yes' && $usercancreate) {
228 if (!($socid > 0)) {
229 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('IdThirdParty')), null, 'errors');
230 } else {
231 if ($object->id > 0) {
232 // We clone object to avoid to denaturate loaded object when setting some properties for clone or if createFromClone modifies the object.
233 $objectutil = dol_clone($object, 1);
234
235 $result = $objectutil->createFromClone($user, $socid);
236 if ($result > 0) {
237 $warningMsgLineList = array();
238 // check all product lines are to sell otherwise add a warning message for each product line is not to sell
239 foreach ($object->lines as $line) {
240 if (!is_object($line->product)) {
241 $line->fetch_product();
242 }
243 if (is_object($line->product) && $line->product->id > 0) {
244 if (empty($line->product->status)) {
245 $warningMsgLineList[$line->id] = $langs->trans('WarningLineProductNotToSell', $line->product->ref);
246 }
247 }
248 }
249 if (!empty($warningMsgLineList)) {
250 setEventMessages('', $warningMsgLineList, 'warnings');
251 }
252
253 header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $result);
254 exit;
255 } else {
256 setEventMessages($object->error, $object->errors, 'errors');
257 $action = '';
258 }
259 }
260 }
261 } elseif ($action == 'reopen' && $usercancreate) {
262 // Reopen a closed order
264 if (getDolGlobalInt('ORDER_REOPEN_TO_DRAFT')) {
265 $idwarehouse = GETPOSTINT('idwarehouse');
266 $result = $object->setDraft($user, $idwarehouse);
267 if ($result < 0) {
268 setEventMessages($object->error, $object->errors, 'errors');
269 }
270 } else {
271 $result = $object->set_reopen($user);
272 if ($result > 0) {
273 setEventMessages($langs->trans('OrderReopened', $object->ref), null);
274 } else {
275 setEventMessages($object->error, $object->errors, 'errors');
276 }
277 }
278 }
279 } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $usercandelete) {
280 // Remove order
281 $result = $object->delete($user);
282 if ($result > 0) {
283 header('Location: list.php?restore_lastsearch_values=1');
284 exit;
285 } else {
286 setEventMessages($object->error, $object->errors, 'errors');
287 }
288 } elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
289 // Remove a product line
290 $result = $object->deleteLine($user, $lineid);
291 if ($result > 0) {
292 // reorder lines
293 $object->line_order(true);
294 // Define output language
295 $outputlangs = $langs;
296 $newlang = '';
297 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
298 $newlang = GETPOST('lang_id', 'aZ09');
299 }
300 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
301 $newlang = $object->thirdparty->default_lang;
302 }
303 if (!empty($newlang)) {
304 $outputlangs = new Translate("", $conf);
305 $outputlangs->setDefaultLang($newlang);
306 }
307 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
308 $ret = $object->fetch($object->id); // Reload to get new records
309 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
310 }
311
312 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
313 exit;
314 } else {
315 setEventMessages($object->error, $object->errors, 'errors');
316 }
317 } elseif ($action == 'confirm_delete_subtotalline' && $confirm == 'yes' && $usercancreate) {
318 $result = $object->deleteSubtotalLine($langs, GETPOSTINT('lineid'), (bool) GETPOST('deletecorrespondingsubtotalline'), $user);
319 if ($result > 0) {
320 // reorder lines
321 $object->line_order(true);
322 // Define output language
323 $outputlangs = $langs;
324 $newlang = '';
325 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
326 $newlang = GETPOST('lang_id', 'aZ09');
327 }
328 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
329 $newlang = $object->thirdparty->default_lang;
330 }
331 if (!empty($newlang)) {
332 $outputlangs = new Translate("", $conf);
333 $outputlangs->setDefaultLang($newlang);
334 }
335 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
336 $ret = $object->fetch($object->id); // Reload to get new records
337 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
338 }
339
340 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
341 exit;
342 } else {
343 setEventMessages($object->error, $object->errors, 'errors');
344 }
345 } elseif ($action == 'classin' && $usercancreate) {
346 // Link to a project
347 $object->setProject(GETPOSTINT('projectid'));
348 } elseif ($action == 'add' && $usercancreate) {
349 // Add order
350 $datecommande = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
351 $date_delivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
352
353 if ($datecommande == '') {
354 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Date')), null, 'errors');
355 $action = 'create';
356 $error++;
357 }
358
359 if ($socid < 1) {
360 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Customer")), null, 'errors');
361 $action = 'create';
362 $error++;
363 }
364
365 if (!$error) {
366 $object->socid = $socid;
367 $object->fetch_thirdparty();
368
369 $db->begin();
370
371 $object->date_commande = $datecommande;
372 $object->note_private = GETPOST('note_private', 'restricthtml');
373 $object->note_public = GETPOST('note_public', 'restricthtml');
374 $object->source = GETPOSTINT('source_id');
375 $object->fk_project = GETPOSTINT('projectid');
376 $object->ref_client = GETPOST('ref_client', 'alpha');
377 $object->model_pdf = GETPOST('model');
378 $object->cond_reglement_id = GETPOSTINT('cond_reglement_id');
379 $object->deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
380 $object->mode_reglement_id = GETPOSTINT('mode_reglement_id');
381 $object->fk_account = GETPOSTINT('fk_account');
382 $object->availability_id = GETPOSTINT('availability_id');
383 $object->demand_reason_id = GETPOSTINT('demand_reason_id');
384 $object->delivery_date = $date_delivery;
385 $object->shipping_method_id = GETPOSTINT('shipping_method_id');
386 $object->warehouse_id = GETPOSTINT('warehouse_id');
387 $object->fk_delivery_address = GETPOSTINT('fk_address');
388 $object->contact_id = GETPOSTINT('contactid');
389 $object->fk_incoterms = GETPOSTINT('incoterm_id');
390 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
391 $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
392 $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx');
393 // Fill array 'array_options' with data from add form
394 $ret = $extrafields->setOptionalsFromPost(null, $object);
395 if ($ret < 0) {
396 $error++;
397 }
398
399 // If creation from another object of another module (Example: origin=propal, originid=1)
400 if (!empty($origin) && !empty($originid)) {
401 // Parse element/subelement (ex: project_task)
402 $element = $subelement = $origin;
403 $regs = array();
404 if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
405 $element = $regs[1];
406 $subelement = $regs[2];
407 }
408
409 // For compatibility
410 if ($element == 'order') {
411 $element = $subelement = 'commande';
412 }
413 if ($element == 'propal') {
414 $element = 'comm/propal';
415 $subelement = 'propal';
416 }
417 if ($element == 'contract') {
418 $element = $subelement = 'contrat';
419 }
420
421 $object->origin = $origin; // deprecated
422 $object->origin_type = $origin;
423 $object->origin_id = $originid;
424
425 // Possibility to add external linked objects with hooks
426 $object->linked_objects[$object->origin_type] = $object->origin_id;
427 $other_linked_objects = GETPOST('other_linked_objects', 'array');
428 if (!empty($other_linked_objects)) {
429 $object->linked_objects = array_merge($object->linked_objects, $other_linked_objects);
430 }
431
432 if (!$error) {
433 $object_id = $object->create($user);
434
435 if ($object_id > 0) {
436 dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
437
438 $classname = ucfirst($subelement);
439 $srcobject = new $classname($db);
440 '@phan-var-force Commande|Propal|Contrat $srcobject';
443 dol_syslog("Try to find source object origin=" . $object->origin . " originid=" . $object->origin_id . " to add lines");
444 $result = $srcobject->fetch($object->origin_id);
445 if ($result > 0) {
446 $lines = $srcobject->lines;
447 if (empty($lines) && method_exists($srcobject, 'fetch_lines')) {
448 $srcobject->fetch_lines();
449 $lines = $srcobject->lines;
450 }
451
452 $fk_parent_line = 0;
453 $num = count($lines);
454
455 for ($i = 0; $i < $num; $i++) {
456 if (!in_array($lines[$i]->id, $selectedLines)) {
457 continue; // Skip unselected lines
458 }
459
460 $label = (!empty($lines[$i]->label) ? $lines[$i]->label : '');
461 $desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : '');
462 $product_type = (!empty($lines[$i]->product_type) ? $lines[$i]->product_type : 0);
463
464 // Dates
465 // TODO mutualiser
466 $date_start = $lines[$i]->date_debut_prevue;
467 if ($lines[$i]->date_debut_reel) {
468 $date_start = $lines[$i]->date_debut_reel;
469 }
470 if ($lines[$i]->date_start) {
471 $date_start = $lines[$i]->date_start;
472 }
473 $date_end = $lines[$i]->date_fin_prevue;
474 if ($lines[$i]->date_fin_reel) {
475 $date_end = $lines[$i]->date_fin_reel;
476 }
477 if ($lines[$i]->date_end) {
478 $date_end = $lines[$i]->date_end;
479 }
480
481 // Reset fk_parent_line for no child products and special product
482 if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
483 $fk_parent_line = 0;
484 }
485
486 // Extrafields
487 if (method_exists($lines[$i], 'fetch_optionals')) { // For avoid conflicts if trigger used
488 $lines[$i]->fetch_optionals();
489 $array_options = $lines[$i]->array_options;
490 }
491
492 $tva_tx = $lines[$i]->tva_tx;
493 if (!empty($lines[$i]->vat_src_code) && !preg_match('/\‍(/', $tva_tx)) {
494 $tva_tx .= ' (' . $lines[$i]->vat_src_code . ')';
495 }
496
497 $result = $object->addline(
498 $desc,
499 $lines[$i]->subprice,
500 $lines[$i]->qty,
501 $tva_tx,
502 $lines[$i]->localtax1_tx,
503 $lines[$i]->localtax2_tx,
504 $lines[$i]->fk_product,
505 $lines[$i]->remise_percent,
506 $lines[$i]->info_bits,
507 $lines[$i]->fk_remise_except,
508 'HT',
509 0,
511 $date_end,
512 $product_type,
513 $lines[$i]->rang,
514 $lines[$i]->special_code,
515 $fk_parent_line,
516 $lines[$i]->fk_fournprice,
517 $lines[$i]->pa_ht,
518 $label,
519 $array_options,
520 $lines[$i]->fk_unit,
521 $object->origin,
522 $lines[$i]->rowid,
523 0,
524 $lines[$i]->ref_ext,
525 0
526 );
527
528 if ($result < 0) {
529 $error++;
530 break;
531 }
532
533 foreach ($object->lines as $line) {
534 if ($line->id == $result) {
535 $line->extraparams = $lines[$i]->extraparams;
536 $line->setExtraParameters();
537 }
538 }
539
540 // Defined the new fk_parent_line
541 if ($result > 0 && $lines[$i]->product_type == 9) {
542 $fk_parent_line = $result;
543 }
544 }
545 } else {
546 setEventMessages($srcobject->error, $srcobject->errors, 'errors');
547 $error++;
548 }
549
550 // Now we create same links to contact than the ones found on origin object
551 /* Useless, already into the create
552 if (getDolGlobalString('MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN')) {
553 $originforcontact = $object->origin;
554 $originidforcontact = $object->origin_id;
555 if ($originforcontact == 'shipping') // shipment and order share the same contacts. If creating from shipment we take data of order
556 {
557 $originforcontact=$srcobject->origin;
558 $originidforcontact=$srcobject->origin_id;
559 }
560 $sqlcontact = "SELECT code, fk_socpeople FROM ".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as ctc";
561 $sqlcontact.= " WHERE element_id = ".((int) $originidforcontact)." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$db->escape($originforcontact)."'";
562
563 $resqlcontact = $db->query($sqlcontact);
564 if ($resqlcontact)
565 {
566 while($objcontact = $db->fetch_object($resqlcontact))
567 {
568 //print $objcontact->code.'-'.$objcontact->fk_socpeople."\n";
569 $object->add_contact($objcontact->fk_socpeople, $objcontact->code);
570 }
571 }
572 else dol_print_error($resqlcontact);
573 }*/
574
575 // Hooks
576 $parameters = array('objFrom' => $srcobject);
577 // Note that $action and $object may be modified by hook
578 $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action);
579 if ($reshook < 0) {
580 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
581 $error++;
582 }
583 } else {
584 setEventMessages($object->error, $object->errors, 'errors');
585 $error++;
586 }
587 } else {
588 // Required extrafield left blank, error message already defined by setOptionalsFromPost()
589 $action = 'create';
590 }
591 } else {
592 if (!$error) {
593 $object_id = $object->create($user);
594 }
595 }
596
597 // Insert default contacts if defined
598 if ($object_id > 0) {
599 if (GETPOSTINT('contactid')) {
600 // $result = $object->add_contact(GETPOSTINT('contactid'), 'CUSTOMER', 'external');
601 $result = $object->add_contact(GETPOSTINT('contactid'), $type_contact_code, 'external');
602 if ($result < 0) {
603 setEventMessages($langs->trans("ErrorFailedToAddContact"), null, 'errors');
604 $error++;
605 }
606 }
607
608 $id = $object_id;
609 $action = '';
610 }
611
612 if (isModEnabled('category')) {
613 $categories = GETPOST('categories', 'array');
614 if (method_exists($object, 'setCategories')) {
615 $object->setCategories($categories);
616 }
617 }
618
619 // End of object creation, we show it
620 if ($object_id > 0 && !$error) {
621 $db->commit();
622 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object_id);
623 exit();
624 } else {
625 $db->rollback();
626 $action = 'create';
627 setEventMessages($object->error, $object->errors, 'errors');
628 }
629 }
630 } elseif ($action == 'classifybilled' && $usercancreate) {
631 $ret = $object->classifyBilled($user);
632
633 if ($ret < 0) {
634 setEventMessages($object->error, $object->errors, 'errors');
635 }
636 } elseif ($action == 'classifyunbilled' && $usercancreate) {
637 $ret = $object->classifyUnBilled($user);
638 if ($ret < 0) {
639 setEventMessages($object->error, $object->errors, 'errors');
640 }
641 } elseif ($action == 'setref_client' && $usercancreate) {
642 // Positionne ref commande client
643 $result = $object->set_ref_client($user, GETPOST('ref_client'));
644 if ($result < 0) {
645 setEventMessages($object->error, $object->errors, 'errors');
646 }
647 } elseif ($action == 'setremise' && $usercancreate) {
648 $result = $object->setDiscount($user, price2num(GETPOST('remise'), 2));
649 if ($result < 0) {
650 setEventMessages($object->error, $object->errors, 'errors');
651 }
652 } elseif ($action == 'setabsolutediscount' && $usercancreate) {
653 if (GETPOST('remise_id')) {
654 if ($object->id > 0) {
655 $object->insert_discount(GETPOSTINT('remise_id'));
656 } else {
657 dol_print_error($db, $object->error);
658 }
659 }
660 } elseif ($action == 'setdate' && $usercancreate) {
661 $date = dol_mktime(0, 0, 0, GETPOSTINT('order_month'), GETPOSTINT('order_day'), GETPOSTINT('order_year'));
662
663 $result = $object->set_date($user, $date);
664 if ($result < 0) {
665 setEventMessages($object->error, $object->errors, 'errors');
666 }
667 } elseif ($action == 'setdate_livraison' && $usercancreate) {
668 $date_delivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
669
670 $object->fetch($id);
671 $result = $object->setDeliveryDate($user, $date_delivery);
672 if ($result < 0) {
673 setEventMessages($object->error, $object->errors, 'errors');
674 }
675 } elseif ($action == 'setmode' && $usercancreate) {
676 $result = $object->setPaymentMethods(GETPOSTINT('mode_reglement_id'));
677 if ($result < 0) {
678 setEventMessages($object->error, $object->errors, 'errors');
679 }
680 } elseif ($action == 'setposinfo' && $usercancreate) {
681 $object->fetch($id);
682 $object->module_source = GETPOST('posmodule');
683 $object->pos_source = GETPOST('posterminal');
684 $result = $object->update($user);
685 if ($result < 0) {
686 dol_print_error($db, $object->error);
687 }
688 } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
689 // Multicurrency Code
690 $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
691 } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
692 // Multicurrency rate
693 $result = $object->setMulticurrencyRate(GETPOSTFLOAT('multicurrency_tx'), GETPOSTINT('calculation_mode'));
694 } elseif ($action == 'setavailability' && $usercancreate) {
695 $result = $object->availability(GETPOSTINT('availability_id'));
696 if ($result < 0) {
697 setEventMessages($object->error, $object->errors, 'errors');
698 }
699 } elseif ($action == 'setdemandreason' && $usercancreate) {
700 $result = $object->demand_reason(GETPOSTINT('demand_reason_id'));
701 if ($result < 0) {
702 setEventMessages($object->error, $object->errors, 'errors');
703 }
704 } elseif ($action == 'setconditions' && $usercancreate) {
705 $result = $object->setPaymentTerms(GETPOSTINT('cond_reglement_id'), GETPOSTFLOAT('cond_reglement_id_deposit_percent'));
706 if ($result < 0) {
707 dol_print_error($db, $object->error);
708 } else {
709 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
710 // Define output language
711 $outputlangs = $langs;
712 $newlang = GETPOST('lang_id', 'alpha');
713 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
714 $newlang = $object->thirdparty->default_lang;
715 }
716 if (!empty($newlang)) {
717 $outputlangs = new Translate("", $conf);
718 $outputlangs->setDefaultLang($newlang);
719 }
720
721 $ret = $object->fetch($object->id); // Reload to get new records
722 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
723 }
724 }
725 } elseif ($action == 'set_incoterms' && isModEnabled('incoterm') && $usercancreate) {
726 // Set incoterm
727 $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms'));
728 if ($result < 0) {
729 setEventMessages($object->error, $object->errors, 'errors');
730 }
731 } elseif ($action == 'setbankaccount' && $usercancreate) {
732 // bank account
733 $result = $object->setBankAccount(GETPOSTINT('fk_account'));
734 if ($result < 0) {
735 setEventMessages($object->error, $object->errors, 'errors');
736 }
737 } elseif ($action == 'setshippingmethod' && $usercancreate) {
738 // shipping method
739 $result = $object->setShippingMethod(GETPOSTINT('shipping_method_id'));
740 if ($result < 0) {
741 setEventMessages($object->error, $object->errors, 'errors');
742 }
743 } elseif ($action == 'setwarehouse' && $usercancreate) {
744 // warehouse
745 $result = $object->setWarehouse(GETPOSTINT('warehouse_id'));
746 if ($result < 0) {
747 setEventMessages($object->error, $object->errors, 'errors');
748 }
749 } elseif ($action == 'settags' && isModEnabled('category') && $usercancreate) {
750 $result = $object->setCategories(GETPOST('categories', 'array'));
751 if ($result < 0) {
752 setEventMessages($object->error, $object->errors, 'errors');
753 }
754 } elseif ($action == 'addline' && GETPOST('updateallvatlinesblock', 'alpha') && GETPOST('vatforblocklines', 'alpha') !== '' && $usercancreate) {
755 $tx_tva = GETPOST('vatforblocklines') ? GETPOST('vatforblocklines') : 0;
756 $object->updateSubtotalLineBlockLines($langs, $object->getRangOfLine($lineid), 'tva', $tx_tva);
757 } elseif ($action == 'addline' && GETPOST('updatealldiscountlinesblock', 'alpha') && GETPOST('discountforblocklines', 'alpha') !== '' && $usercancreate) {
758 $discount = GETPOST('discountforblocklines') ? GETPOST('discountforblocklines') : 0;
759 $object->updateSubtotalLineBlockLines($langs, $object->getRangOfLine($lineid), 'discount', $discount);
760 } elseif ($action == 'addline' && GETPOST('submitforalllines', 'aZ09') && (GETPOST('alldate_start', 'alpha') || GETPOST('alldate_end', 'alpha')) && $usercancreate) {
761 // Define date start and date end for all line
762 $alldate_start = dol_mktime(GETPOSTINT('alldate_starthour'), GETPOSTINT('alldate_startmin'), 0, GETPOSTINT('alldate_startmonth'), GETPOSTINT('alldate_startday'), GETPOSTINT('alldate_startyear'));
763 $alldate_end = dol_mktime(GETPOSTINT('alldate_endhour'), GETPOSTINT('alldate_endmin'), 0, GETPOSTINT('alldate_endmonth'), GETPOSTINT('alldate_endday'), GETPOSTINT('alldate_endyear'));
764 foreach ($object->lines as $line) {
765 if ($line->special_code == SUBTOTALS_SPECIAL_CODE) {
766 continue;
767 }
768 if ($line->product_type == 1) { // only service line
769 $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $alldate_start, $alldate_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
770 }
771 }
772 } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('vatforalllines', 'alpha') !== '' && $usercancreate) {
773 // Define vat_rate
774 $vat_rate = (GETPOST('vatforalllines') ? GETPOST('vatforalllines') : 0);
775 $vat_rate = str_replace('*', '', $vat_rate);
776 $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
777 $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
778 foreach ($object->lines as $line) {
779 if ($line->special_code == SUBTOTALS_SPECIAL_CODE) {
780 continue;
781 }
782 $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
783 }
784 } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) {
785 // Define remise_percent
786 $remise_percent = (GETPOST('remiseforalllines') ? GETPOST('remiseforalllines') : 0);
787 $remise_percent = str_replace('*', '', $remise_percent);
788 foreach ($object->lines as $line) {
789 if ($line->special_code == SUBTOTALS_SPECIAL_CODE) {
790 continue;
791 }
792 $tvatx = $line->tva_tx;
793 if (!empty($line->vat_src_code)) {
794 $tvatx .= ' (' . $line->vat_src_code . ')';
795 }
796 $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, (float) $remise_percent, $tvatx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
797 }
798 } elseif ($action == 'addline' && $usercancreate && (
799 (GETPOST('submitforallmargins', 'alpha') && GETPOST('marginforalllines', 'alpha') !== '') ||
800 (GETPOST('submitforallmark', 'alpha') && GETPOST('markforalllines', 'alpha') !== '')
801 )) {
802 $outlangs = $langs;
803 // Define margin
804 $margin_rate = GETPOSTISSET('marginforalllines') ? GETPOST('marginforalllines', 'int') : '';
805 $mark_rate = GETPOSTISSET('markforalllines') ? GETPOST('markforalllines', 'int') : '';
806 foreach ($object->lines as &$line) {
807 if ($line->subprice > 0) {
808 if ($line->special_code == SUBTOTALS_SPECIAL_CODE) {
809 continue;
810 }
811 $subprice_multicurrency = $line->subprice;
812 if (is_numeric($margin_rate) && $margin_rate > 0) {
813 $line->subprice = (float) price2num((float) $line->pa_ht * (1 + (float) $margin_rate / 100), 'MU');
814 } elseif (is_numeric($mark_rate) && $mark_rate > 0) {
815 $line->subprice = (float) ($line->pa_ht / (1 - ((float) $mark_rate / 100)));
816 } else {
817 $line->subprice = (float) $line->pa_ht;
818 }
819
820 $prod = new Product($db);
821 $res = $prod->fetch($line->fk_product);
822 if ($res > 0) {
823 if ($prod->price_min > $line->subprice) {
824 $price_subprice = price($line->subprice, 0, $outlangs, 1, -1, -1, 'auto');
825 $price_price_min = price($prod->price_min, 0, $outlangs, 1, -1, -1, 'auto');
826 setEventMessages($prod->ref . ' - ' . $prod->label . ' (' . $price_subprice . ' < ' . $price_price_min . ' ' . strtolower($langs->trans("MinPrice")) . ')' . "\n", null, 'warnings');
827 } else {
828 setEventMessages($prod->error, $prod->errors, 'errors');
829 }
830 } else {
831 setEventMessages($prod->error, $prod->errors, 'errors');
832 }
833 // Manage $line->subprice and $line->multicurrency_subprice
834 $multicurrency_subprice = (float) $line->subprice * $line->multicurrency_subprice / $subprice_multicurrency;
835 // Update DB
836 $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->product_ref, $line->special_code, $line->array_options, $line->fk_unit, $multicurrency_subprice);
837 // Update $object with new margin info
838 if ($result > 0) {
839 if (is_numeric($margin_rate) && empty($mark_rate)) {
840 $line->marge_tx = $margin_rate;
841 } elseif (is_numeric($mark_rate) && empty($margin_rate)) {
842 $line->marque_tx = $mark_rate;
843 }
844 $line->total_ht = $line->qty * (float) $line->subprice;
845 $line->total_tva = $line->tva_tx * $line->qty * (float) $line->subprice;
846 $line->total_ttc = (1 + $line->tva_tx) * $line->qty * (float) $line->subprice;
847 // Manage $line->subprice and $line->multicurrency_subprice
848 $line->multicurrency_total_ht = $line->qty * (float) $subprice_multicurrency * $line->multicurrency_subprice / $line->subprice;
849 $line->multicurrency_total_tva = $line->tva_tx * $line->qty * (float) $subprice_multicurrency * $line->multicurrency_subprice / $line->subprice;
850 $line->multicurrency_total_ttc = (1 + $line->tva_tx) * $line->qty * (float) $subprice_multicurrency * $line->multicurrency_subprice / $line->subprice;
851 // Used previous $line->subprice and $line->multicurrency_subprice above, now they can be set to their new values
852 $line->multicurrency_subprice = $multicurrency_subprice;
853 } else {
854 setEventMessages($object->error, $object->errors, 'errors');
855 }
856 }
857 }
858 } elseif ($action == 'confirm_addtitleline' && $usercancreate) {
859 // Handling adding a new title line for subtotals module
860
861 $langs->load('subtotals');
862
863 $desc = GETPOST('subtotallinedesc', 'alphanohtml');
864 $depth = GETPOSTINT('subtotallinelevel') ?? 1;
865
866 $subtotal_options = array();
867
868 foreach (Commande::$TITLE_OPTIONS as $option) {
869 $value = GETPOST($option, 'alphanohtml');
870 if ($value) {
871 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
872 }
873 }
874
875 // Insert line
876 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
877
878 if ($result >= 0) {
879 if ($result == 0) {
880 setEventMessages($object->error, $object->errors, 'warnings');
881 }
882 $ret = $object->fetch($object->id); // Reload to get new records
883 $object->fetch_thirdparty();
884
885 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
886 // Define output language
887 $outputlangs = $langs;
888 $newlang = GETPOST('lang_id', 'alpha');
889 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
890 $newlang = $object->thirdparty->default_lang;
891 }
892 if (!empty($newlang)) {
893 $outputlangs = new Translate("", $conf);
894 $outputlangs->setDefaultLang($newlang);
895 }
896
897 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
898 }
899 } else {
900 setEventMessages($object->error, $object->errors, 'errors');
901 }
902 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $id);
903 exit();
904 } elseif ($action == 'confirm_addsubtotalline' && $usercancreate) {
905 // Handling adding a new subtotal line for subtotals module
906
907 $langs->load('subtotals');
908
909 $choosen_line = GETPOST('subtotaltitleline', 'alphanohtml');
910 foreach ($object->lines as $line) {
911 if ($line->desc == $choosen_line && $line->special_code == SUBTOTALS_SPECIAL_CODE) {
912 $desc = $line->desc;
913 $depth = -$line->qty;
914 }
915 }
916
917 $subtotal_options = array();
918
919 foreach (Commande::$SUBTOTAL_OPTIONS as $option) {
920 $value = GETPOST($option, 'alphanohtml');
921 if ($value) {
922 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
923 }
924 }
925
926 // Insert line
927 if (isset($desc) && isset($depth)) {
928 $result = $object->addSubtotalLine($langs, $desc, (int) $depth, $subtotal_options);
929 } else {
930 $result = -1;
931 $object->errors[] = $langs->trans("CorrespondingTitleNotFound");
932 }
933
934 if ($result >= 0) {
935 $ret = $object->fetch($object->id); // Reload to get new records
936 $object->fetch_thirdparty();
937
938 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
939 // Define output language
940 $outputlangs = $langs;
941 $newlang = GETPOST('lang_id', 'alpha');
942 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
943 $newlang = $object->thirdparty->default_lang;
944 }
945 if (!empty($newlang)) {
946 $outputlangs = new Translate("", $conf);
947 $outputlangs->setDefaultLang($newlang);
948 }
949
950 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
951 }
952 } else {
953 setEventMessages($object->error, $object->errors, 'errors');
954 }
955 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $id);
956 exit();
957 } elseif ($action == 'addline' && !GETPOST('submitforalllines', 'alpha') && $usercancreate) { // Add a new line
958 $langs->load('errors');
959 $error = 0;
960
961 // Set if we used free entry or predefined product
962 $predef = '';
963 $line_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
964
965 $price_ht = '';
966 $price_ht_devise = '';
967 $price_ttc = '';
968 $price_ttc_devise = '';
969
970 if (GETPOST('price_ht') !== '') {
971 $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
972 }
973 if (GETPOST('multicurrency_price_ht') !== '') {
974 $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
975 }
976 if (GETPOST('price_ttc') !== '') {
977 $price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
978 }
979 if (GETPOST('multicurrency_price_ttc') !== '') {
980 $price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
981 }
982
983 $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09');
984 if ($prod_entry_mode == 'free') {
985 $idprod = 0;
986 } else {
987 $idprod = GETPOSTINT('idprod');
988
989 if (getDolGlobalString('MAIN_DISABLE_FREE_LINES') && $idprod <= 0) {
990 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
991 $error++;
992 }
993 }
994
995 $tva_tx = GETPOST('tva_tx', 'alpha');
996
997 $qty = price2num(GETPOST('qty' . $predef, 'alpha'), 'MS', 2);
998
999 $remise_percent = (GETPOSTISSET('remise_percent' . $predef) ? price2num(GETPOST('remise_percent' . $predef, 'alpha'), '', 2) : 0);
1000 if (empty($remise_percent)) {
1001 $remise_percent = 0;
1002 }
1003
1004 // Extrafields
1005 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1006 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
1007 // Unset extrafield
1008 if (is_array($extralabelsline)) {
1009 // Get extra fields
1010 foreach ($extralabelsline as $key => $value) {
1011 unset($_POST["options_" . $key]);
1012 }
1013 }
1014
1015 $price_to_test_sign = ($price_ht ? $price_ht : $price_ttc);
1016
1017 if ((empty($idprod) || $idprod < 0) && ($price_to_test_sign < 0) && ($qty < 0)) {
1018 $langs->load("errors");
1019 setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1020 $error++;
1021 }
1022 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
1023 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
1024 $error++;
1025 }
1026 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && $price_ht === '' && $price_ht_devise === '' && $price_ttc === '' && $price_ttc_devise === '') { // Unit price can be 0 but not ''. Also price can be negative for order.
1027 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
1028 $error++;
1029 }
1030 if ($qty == '') {
1031 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1032 $error++;
1033 }
1034
1035 if ($qty < 0 && !getDolGlobalString('ORDER_ENABLE_NEGATIVE_QTY')) {
1036 setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1037 $error++;
1038 }
1039
1040 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($line_desc)) {
1041 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
1042 $error++;
1043 }
1044
1045 if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
1046 if ($combinations = GETPOST('combinations', 'array:alphanohtml')) {
1047 //Check if there is a product with the given combination
1048 $prodcomb = new ProductCombination($db);
1049
1050 if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
1051 $idprod = $res->fk_product_child;
1052 } else {
1053 setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
1054 $error++;
1055 }
1056 }
1057 }
1058
1059 if (!$error && (!empty($line_desc) || (!empty($idprod) && $idprod > 0))) {
1060 $pu_ht = 0;
1061 $pu_ttc = 0;
1062 $pu_ht_devise = 0;
1063 $pu_ttc_devise = 0;
1064 $price_min = 0;
1065 $price_min_ttc = 0;
1066 $tva_npr = 0;
1067 $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
1068
1069 // Clean parameters
1070 $date_start = dol_mktime(GETPOSTINT('date_start' . $predef . 'hour'), GETPOSTINT('date_start' . $predef . 'min'), GETPOSTINT('date_start' . $predef . 'sec'), GETPOSTINT('date_start' . $predef . 'month'), GETPOSTINT('date_start' . $predef . 'day'), GETPOSTINT('date_start' . $predef . 'year'));
1071 $date_end = dol_mktime(GETPOSTINT('date_end' . $predef . 'hour'), GETPOSTINT('date_end' . $predef . 'min'), GETPOSTINT('date_end' . $predef . 'sec'), GETPOSTINT('date_end' . $predef . 'month'), GETPOSTINT('date_end' . $predef . 'day'), GETPOSTINT('date_end' . $predef . 'year'));
1072
1073 $db->begin();
1074
1075 // Ecrase $pu par celui du produit
1076 // Ecrase $desc par celui du produit
1077 // Ecrase $base_price_type par celui du produit
1078 if (!empty($idprod) && $idprod > 0) {
1079 $prod = new Product($db);
1080 $prod->fetch($idprod);
1081
1082 $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
1083
1084 // Update if prices fields are defined
1085 /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
1086 $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
1087 if (empty($tva_tx)) {
1088 $tva_npr = 0;
1089 }*/
1090
1091 // Price unique per product
1092 $pu_ht = $prod->price;
1093 $pu_ttc = $prod->price_ttc;
1094 $price_min = $prod->price_min;
1095 $price_min_ttc = $prod->price_min_ttc;
1096 $price_base_type = $prod->price_base_type;
1097
1098 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1099 // If price per customer
1100 require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1101
1102 $prodcustprice = new ProductCustomerPrice($db);
1103
1104 $filter = array('t.fk_product' => (string) $prod->id, 't.fk_soc' => (string) $object->thirdparty->id);
1105
1106 // If a price per customer exist
1107 $pricebycustomerexist = false;
1108 $result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
1109 if ($result >= 0) {
1110 // If there is some prices specific to the customer
1111 if (count($prodcustprice->lines) > 0) {
1112 $date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
1113 foreach ($prodcustprice->lines as $k => $custprice_line) {
1114 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1115 $pricebycustomerexist = true;
1116 $pu_ht = price($custprice_line->price);
1117 $pu_ttc = price($custprice_line->price_ttc);
1118 $price_min = price($custprice_line->price_min);
1119 $price_min_ttc = price($custprice_line->price_min_ttc);
1120 $price_base_type = $custprice_line->price_base_type;
1121 /*$tva_tx = $custprice_line->tva_tx;
1122 if ($custprice_line->default_vat_code && !preg_match('/\‍(.*\‍)/', (string) $tva_tx)) {
1123 $tva_tx .= ' (' . $custprice_line->default_vat_code . ')';
1124 }
1125 $tva_npr = $custprice_line->recuperableonly;
1126 if (empty($tva_tx)) {
1127 $tva_npr = 0;
1128 }*/
1129 break;
1130 }
1131 }
1132 }
1133 } else {
1134 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
1135 }
1136
1137 if (!$pricebycustomerexist && !empty($object->thirdparty->price_level)) { // If price per segment
1138 $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
1139 $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
1140 $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
1141 $price_min_ttc = $prod->multiprices_min_ttc[$object->thirdparty->price_level];
1142 $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
1143 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
1144 if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) {
1145 $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level];
1146 }
1147 if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) {
1148 $tva_npr = $prod->multiprices_recuperableonly[$object->thirdparty->price_level];
1149 }
1150 }
1151 }
1152 } elseif (getDolGlobalString('PRODUIT_MULTIPRICES') && !empty($object->thirdparty->price_level)) { // If price per segment
1153 $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
1154 $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
1155 $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
1156 $price_min_ttc = $prod->multiprices_min_ttc[$object->thirdparty->price_level];
1157 $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
1158 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
1159 if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) {
1160 $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level];
1161 }
1162 if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) {
1163 $tva_npr = $prod->multiprices_recuperableonly[$object->thirdparty->price_level];
1164 }
1165 }
1166 } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
1167 // If price per customer
1168 require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1169
1170 $prodcustprice = new ProductCustomerPrice($db);
1171
1172 $filter = array('t.fk_product' => (string) $prod->id, 't.fk_soc' => (string) $object->thirdparty->id);
1173
1174 $result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
1175 if ($result >= 0) {
1176 // If there is some prices specific to the customer
1177 if (count($prodcustprice->lines) > 0) {
1178 $date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
1179 foreach ($prodcustprice->lines as $k => $custprice_line) {
1180 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1181 $pu_ht = price($custprice_line->price);
1182 $pu_ttc = price($custprice_line->price_ttc);
1183 $price_min = price($custprice_line->price_min);
1184 $price_min_ttc = price($custprice_line->price_min_ttc);
1185 $price_base_type = $custprice_line->price_base_type;
1186 /*$tva_tx = $custprice_line->tva_tx;
1187 if ($custprice_line->default_vat_code && !preg_match('/\‍(.*\‍)/', $tva_tx)) {
1188 $tva_tx .= ' (' . $custprice_line->default_vat_code . ')';
1189 }
1190 $tva_npr = $custprice_line->recuperableonly;
1191 if (empty($tva_tx)) {
1192 $tva_npr = 0;
1193 }*/
1194 break;
1195 }
1196 }
1197 }
1198 } else {
1199 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
1200 }
1201 } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY')) {
1202 // If price per quantity
1203 if ($prod->prices_by_qty[0]) { // yes, this product has some prices per quantity
1204 // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
1205 $pqp = GETPOSTINT('pbq');
1206
1207 // Search price into product_price_by_qty from $prod->id
1208 foreach ($prod->prices_by_qty_list[0] as $priceforthequantityarray) {
1209 if ($priceforthequantityarray['rowid'] != $pqp) {
1210 continue;
1211 }
1212 // We found the price
1213 if ($priceforthequantityarray['price_base_type'] == 'HT') {
1214 $pu_ht = $priceforthequantityarray['unitprice'];
1215 } else {
1216 $pu_ttc = $priceforthequantityarray['unitprice'];
1217 }
1218 // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
1219 break;
1220 }
1221 }
1222 } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
1223 // If price per quantity and customer
1224 if ($prod->prices_by_qty[$object->thirdparty->price_level]) { // yes, this product has some prices per quantity
1225 // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
1226 $pqp = GETPOSTINT('pbq');
1227 // Search price into product_price_by_qty from $prod->id
1228 foreach ($prod->prices_by_qty_list[$object->thirdparty->price_level] as $priceforthequantityarray) {
1229 if ($priceforthequantityarray['rowid'] != $pqp) {
1230 continue;
1231 }
1232 // We found the price
1233 if ($priceforthequantityarray['price_base_type'] == 'HT') {
1234 $pu_ht = $priceforthequantityarray['unitprice'];
1235 } else {
1236 $pu_ttc = $priceforthequantityarray['unitprice'];
1237 }
1238 // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
1239 break;
1240 }
1241 }
1242 }
1243
1244 $tmpvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
1245 $tmpprodvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', (string) $prod->tva_tx));
1246
1247 // Set unit price to use
1248 if (!empty($price_ht) || (string) $price_ht === '0') {
1249 $pu_ht = (float) price2num($price_ht, 'MU');
1250 $pu_ttc = (float) price2num((float) $pu_ht * (1 + ((float) $tmpvat / 100)), 'MU');
1251 } elseif (!empty($price_ht_devise) || (string) $price_ht_devise === '0') {
1252 $pu_ht_devise = price2num($price_ht_devise, 'MU');
1253 $pu_ttc_devise = (float) price2num((float) $pu_ht_devise * (1 + ((float) $tmpvat / 100)), 'MU');
1254 $pu_ht = '';
1255 $pu_ttc = '';
1256 } elseif (!empty($price_ttc) || (string) $price_ttc === '0') {
1257 $pu_ttc = (float) price2num($price_ttc, 'MU');
1258 $pu_ht = (float) price2num((float) $pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU');
1259 } elseif (!empty($price_ttc_devise) || (string) $price_ttc_devise === '0') {
1260 $pu_ttc_devise = (float) price2num($price_ttc_devise, 'MU');
1261 $pu_ht_devise = (float) price2num((float) $pu_ttc_devise / (1 + ((float) $tmpvat / 100)), 'MU');
1262 $pu_ht = '';
1263 $pu_ttc = '';
1264 } elseif ($tmpvat != $tmpprodvat) {
1265 // Is this still used ?
1266 if ($price_base_type != 'HT') {
1267 $pu_ht = (float) price2num((float) $pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU');
1268 } else {
1269 $pu_ttc = (float) price2num((float) $pu_ht * (1 + ((float) $tmpvat / 100)), 'MU');
1270 }
1271 }
1272
1273 $desc = '';
1274
1275 // Define output language
1276 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1277 $outputlangs = $langs;
1278 $newlang = '';
1279 if (/* empty($newlang) && */GETPOST('lang_id', 'aZ09')) {
1280 $newlang = GETPOST('lang_id', 'aZ09');
1281 }
1282 if (empty($newlang)) {
1283 $newlang = $object->thirdparty->default_lang;
1284 }
1285 if (!empty($newlang)) {
1286 $outputlangs = new Translate("", $conf);
1287 $outputlangs->setDefaultLang($newlang);
1288 }
1289
1290 $desc = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
1291 } else {
1292 $desc = $prod->description;
1293 }
1294
1295 if (getDolGlobalInt('PRODUIT_AUTOFILL_DESC') == 0) {
1296 // 'DoNotAutofillButAutoConcat'
1297 $desc = dol_concatdesc($desc, $line_desc, false, getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION') ? true : false);
1298 } else {
1299 //'AutoFillFormFieldBeforeSubmit' or 'DoNotUseDescriptionOfProdut' => User has already done the modification they want
1300 $desc = $line_desc;
1301 }
1302
1303 // Add custom code and origin country into description
1304 if (!getDolGlobalString('MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE') && (!empty($prod->customcode) || !empty($prod->country_code))) {
1305 $tmptxt = '(';
1306 // Define output language
1307 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1308 $outputlangs = $langs;
1309 $newlang = '';
1310 if (/* empty($newlang) && */GETPOST('lang_id', 'alpha')) {
1311 $newlang = GETPOST('lang_id', 'alpha');
1312 }
1313 if (empty($newlang)) {
1314 $newlang = $object->thirdparty->default_lang;
1315 }
1316 if (!empty($newlang)) {
1317 $outputlangs = new Translate("", $conf);
1318 $outputlangs->setDefaultLang($newlang);
1319 $outputlangs->load('products');
1320 }
1321 if (!empty($prod->customcode)) {
1322 $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomsCode") . ': ' . $prod->customcode;
1323 }
1324 if (!empty($prod->customcode) && !empty($prod->country_code)) {
1325 $tmptxt .= ' - ';
1326 }
1327 if (!empty($prod->country_code)) {
1328 $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, '', $db, $outputlangs, 0);
1329 }
1330 } else {
1331 if (!empty($prod->customcode)) {
1332 $tmptxt .= $langs->transnoentitiesnoconv("CustomsCode") . ': ' . $prod->customcode;
1333 }
1334 if (!empty($prod->customcode) && !empty($prod->country_code)) {
1335 $tmptxt .= ' - ';
1336 }
1337 if (!empty($prod->country_code)) {
1338 $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, '', $db, $langs, 0);
1339 }
1340 }
1341 $tmptxt .= ')';
1342 $desc = dol_concatdesc($desc, $tmptxt);
1343 }
1344
1345 $type = $prod->type;
1346 $fk_unit = $prod->fk_unit;
1347 } else {
1348 $pu_ht = price2num($price_ht, 'MU');
1349 $pu_ttc = price2num($price_ttc, 'MU');
1350 $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
1351 $tva_tx = str_replace('*', '', $tva_tx);
1352 if (empty($tva_tx)) {
1353 $tva_npr = 0;
1354 }
1355 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1356 $desc = $line_desc;
1357 $type = GETPOST('type');
1358 $fk_unit = GETPOST('units', 'alpha');
1359 $pu_ht_devise = price2num($price_ht_devise, 'MU');
1360 $pu_ttc_devise = price2num($price_ttc_devise, 'MU');
1361
1362 if ($pu_ttc && !$pu_ht) {
1363 $price_base_type = 'TTC';
1364 }
1365 }
1366
1367 $info_bits = 0;
1368 if ($tva_npr) {
1369 $info_bits |= 0x01;
1370 }
1371
1372 // Local Taxes
1373 $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
1374 $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
1375
1376 // Margin
1377 $fournprice = (int) (GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : 0); // This can be id of supplier price, or 'pmpprice' or 'costprice', or 'inputprice', we force to keep ID only
1378 $buyingprice = price2num((GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''), '', 2); // If buying_price is '0', we must keep this value
1379
1380 // Prepare a price equivalent for minimum price check
1381 $pu_equivalent = $pu_ht;
1382 $pu_equivalent_ttc = $pu_ttc;
1383
1384 $currency_tx = $object->multicurrency_tx;
1385
1386 // Check if we have a foreign currency
1387 // If so, we update the pu_equiv as the equivalent price in base currency
1388 if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1389 $pu_equivalent = (float) $pu_ht_devise / (float) $currency_tx;
1390 }
1391 if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1392 $pu_equivalent_ttc = (float) $pu_ttc_devise / (float) $currency_tx;
1393 }
1394
1395 // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
1396 /*
1397 if ($pu_equivalent) {
1398 $tmp = calcul_price_total(1, $pu_equivalent, 0, $tva_tx, -1, -1, 0, 'HT', $info_bits, $type);
1399 $pu_equivalent_ttc = ...
1400 } else {
1401 $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $tva_tx, -1, -1, 0, 'TTC', $info_bits, $type);
1402 $pu_equivalent_ht = ...
1403 }
1404 */
1405
1406 //var_dump(price2num($price_min)); var_dump(price2num($pu_ht)); var_dump($remise_percent);
1407 //var_dump(price2num($price_min_ttc)); var_dump(price2num($pu_ttc)); var_dump($remise_percent);exit;
1408
1409 $desc = dol_htmlcleanlastbr($desc);
1410
1411 // Check price is not lower than minimum
1412 if ($usermustrespectpricemin) {
1413 if ($pu_equivalent && $price_min && (((float) price2num($pu_equivalent) * (1 - $remise_percent / 100)) < (float) price2num($price_min)) && $price_base_type == 'HT') {
1414 $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1415 setEventMessages($mesg, null, 'errors');
1416 $error++;
1417 } elseif ($pu_equivalent_ttc && $price_min_ttc && (((float) price2num($pu_equivalent_ttc) * (1 - $remise_percent / 100)) < (float) price2num($price_min_ttc)) && $price_base_type == 'TTC') {
1418 $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1419 setEventMessages($mesg, null, 'errors');
1420 $error++;
1421 }
1422 }
1423
1424 if (!$error) {
1425 // Insert line
1426 $result = $object->addline($desc, $pu_ht, (float) $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $info_bits, 0, $price_base_type, $pu_ttc, $date_start, $date_end, $type, min($rank, count($object->lines) + 1), 0, GETPOSTINT('fk_parent_line'), (int) $fournprice, $buyingprice, $label, $array_options, $fk_unit, '', 0, (float) $pu_ht_devise);
1427
1428 if ($result > 0) {
1429 $db->commit();
1430
1431 $ret = $object->fetch($object->id); // Reload to get new records
1432 if ($ret > 0) {
1433 $object->fetch_thirdparty();
1434 }
1435
1436 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1437 // Define output language
1438 $outputlangs = $langs;
1439 $newlang = GETPOST('lang_id', 'alpha');
1440 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1441 $newlang = $object->thirdparty->default_lang;
1442 }
1443 if (!empty($newlang)) {
1444 $outputlangs = new Translate("", $conf);
1445 $outputlangs->setDefaultLang($newlang);
1446 }
1447
1448 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1449 }
1450
1451 unset($_POST['prod_entry_mode']);
1452
1453 unset($_POST['qty']);
1454 unset($_POST['type']);
1455 unset($_POST['remise_percent']);
1456 unset($_POST['price_ht']);
1457 unset($_POST['multicurrency_price_ht']);
1458 unset($_POST['price_ttc']);
1459 unset($_POST['tva_tx']);
1460 unset($_POST['product_ref']);
1461 unset($_POST['product_label']);
1462 unset($_POST['product_desc']);
1463 unset($_POST['fournprice']);
1464 unset($_POST['buying_price']);
1465 unset($_POST['np_marginRate']);
1466 unset($_POST['np_markRate']);
1467 unset($_POST['dp_desc']);
1468 unset($_POST['idprod']);
1469 unset($_POST['units']);
1470
1471 unset($_POST['date_starthour']);
1472 unset($_POST['date_startmin']);
1473 unset($_POST['date_startsec']);
1474 unset($_POST['date_startday']);
1475 unset($_POST['date_startmonth']);
1476 unset($_POST['date_startyear']);
1477 unset($_POST['date_endhour']);
1478 unset($_POST['date_endmin']);
1479 unset($_POST['date_endsec']);
1480 unset($_POST['date_endday']);
1481 unset($_POST['date_endmonth']);
1482 unset($_POST['date_endyear']);
1483 } else {
1484 $db->rollback();
1485
1486 setEventMessages($object->error, $object->errors, 'errors');
1487 }
1488 }
1489 }
1490 } elseif ($action == 'updatetitleline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1491 // Handling updating a title line for subtotals module
1492
1493 $langs->load('subtotals');
1494
1495 $desc = GETPOST('line_desc', 'alphanohtml') ?? $langs->trans("Title");
1496 $depth = GETPOSTINT('line_depth') ?? 1;
1497
1498 $subtotal_options = array();
1499
1500 foreach (Commande::$TITLE_OPTIONS as $option) {
1501 $value = GETPOST($option, 'alphanohtml');
1502 if ($value) {
1503 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1504 }
1505 }
1506
1507 // Update line
1508 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1509
1510 if ($result >= 0) {
1511 if ($result == 0) {
1512 setEventMessages($object->error, $object->errors, 'warnings');
1513 }
1514 $ret = $object->fetch($object->id); // Reload to get new records
1515 $object->fetch_thirdparty();
1516
1517 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1518 // Define output language
1519 $outputlangs = $langs;
1520 $newlang = GETPOST('lang_id', 'alpha');
1521 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1522 $newlang = $object->thirdparty->default_lang;
1523 }
1524 if (!empty($newlang)) {
1525 $outputlangs = new Translate("", $conf);
1526 $outputlangs->setDefaultLang($newlang);
1527 }
1528
1529 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1530 }
1531 } else {
1532 setEventMessages($object->error, $object->errors, 'errors');
1533 }
1534 } elseif ($action == 'updatesubtotalline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1535 // Handling updating a subtotal line for subtotals module
1536
1537 $langs->load('subtotals');
1538
1539 $desc = GETPOST('line_desc', 'alphanohtml');
1540 $depth = GETPOSTINT('line_depth');
1541
1542 $subtotal_options = array();
1543
1544 foreach (Commande::$SUBTOTAL_OPTIONS as $option) {
1545 $value = GETPOST($option, 'alphanohtml');
1546 if ($value) {
1547 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1548 }
1549 }
1550
1551 // Update line
1552 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1553
1554 if ($result > 0) {
1555 $ret = $object->fetch($object->id); // Reload to get new records
1556 $object->fetch_thirdparty();
1557
1558 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1559 // Define output language
1560 $outputlangs = $langs;
1561 $newlang = GETPOST('lang_id', 'alpha');
1562 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1563 $newlang = $object->thirdparty->default_lang;
1564 }
1565 if (!empty($newlang)) {
1566 $outputlangs = new Translate("", $conf);
1567 $outputlangs->setDefaultLang($newlang);
1568 }
1569
1570 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1571 }
1572 } else {
1573 setEventMessages($object->error, $object->errors, 'errors');
1574 }
1575 } elseif ($action == 'updateline' && $usercancreate && GETPOST('save')) {
1576 // Update a line
1577
1578 // Clean parameters
1579 $date_start = '';
1580 $date_end = '';
1581 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), GETPOSTINT('date_startsec'), GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
1582 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), GETPOSTINT('date_endsec'), GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
1583
1584 $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml'));
1585
1586 // Define info_bits
1587 $info_bits = 0;
1588 if (preg_match('/\*/', GETPOST('tva_tx'))) {
1589 $info_bits |= 0x01;
1590 }
1591
1592 // Define vat_rate
1593 $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx', 'alpha') : 0);
1594 $vat_rate = str_replace('*', '', $vat_rate);
1595 $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
1596 $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
1597 $pu_ht = price2num(GETPOST('price_ht'), '', 2);
1598 $pu_ttc = price2num(GETPOST('price_ttc'), '', 2);
1599
1600 $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
1601 $pu_ttc_devise = price2num(GETPOST('multicurrency_subprice_ttc'), '', 2);
1602
1603 $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1604
1605 // Prepare a price equivalent for minimum price check
1606 $pu_equivalent = $pu_ht;
1607 $pu_equivalent_ttc = $pu_ttc;
1608
1609 $currency_tx = $object->multicurrency_tx;
1610
1611 // Check if we have a foreign currency
1612 // If so, we update the pu_equiv as the equivalent price in base currency
1613 if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1614 $pu_equivalent = (float) $pu_ht_devise / (float) $currency_tx;
1615 }
1616 if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1617 $pu_equivalent_ttc = (float) $pu_ttc_devise / (float) $currency_tx;
1618 }
1619
1620 // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
1621 /*
1622 if ($pu_equivalent) {
1623 $tmp = calcul_price_total(1, $pu_equivalent, 0, $vat_rate, -1, -1, 0, 'HT', $info_bits, $type);
1624 $pu_equivalent_ttc = ...
1625 } else {
1626 $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $vat_rate, -1, -1, 0, 'TTC', $info_bits, $type);
1627 $pu_equivalent_ht = ...
1628 }
1629 */
1630
1631 // Add buying price
1632 $fournprice = (int) (GETPOST('fournprice') ? GETPOST('fournprice') : ''); // This can be id of supplier price, or 'pmpprice' or 'costprice', or 'inputprice', we force to keep ID only
1633 $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we must keep this value
1634
1635 // Extrafields Lines
1636 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1637 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
1638 // Unset extrafield POST Data
1639 if (is_array($extralabelsline)) {
1640 foreach ($extralabelsline as $key => $value) {
1641 unset($_POST["options_" . $key]);
1642 }
1643 }
1644
1645 // Define special_code for special lines
1646 $special_code = GETPOSTINT('special_code');
1647 if (!GETPOST('qty')) {
1648 $special_code = 3;
1649 }
1650
1651 $remise_percent = GETPOST('remise_percent') != '' ? price2num(GETPOST('remise_percent'), '', 2) : 0;
1652
1653 $pu = $pu_ht;
1654 $price_base_type = 'HT';
1655 if (empty($pu) && !empty($pu_ttc)) {
1656 $pu = $pu_ttc;
1657 $price_base_type = 'TTC';
1658 }
1659
1660 // Check minimum price
1661 $productid = GETPOSTINT('productid');
1662 if (!empty($productid)) {
1663 $product = new Product($db);
1664 $product->fetch($productid);
1665
1666 $type = $product->type;
1667
1668 $price_min = $product->price_min;
1669 if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($object->thirdparty->price_level)) {
1670 $price_min = $product->multiprices_min[$object->thirdparty->price_level];
1671 }
1672 $price_min_ttc = $product->price_min_ttc;
1673 if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($object->thirdparty->price_level)) {
1674 $price_min_ttc = $product->multiprices_min_ttc[$object->thirdparty->price_level];
1675 }
1676
1677 $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
1678
1679 // Check price is not lower than minimum
1680 if ($usermustrespectpricemin) {
1681 if ($pu_equivalent && $price_min && (((float) price2num($pu_equivalent) * (1 - (float) $remise_percent / 100)) < (float) price2num($price_min)) && $price_base_type == 'HT') {
1682 $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1683 setEventMessages($mesg, null, 'errors');
1684 $error++;
1685 $action = 'editline';
1686 } elseif ($pu_equivalent_ttc && $price_min_ttc && (((float) price2num($pu_equivalent_ttc) * (1 - (float) $remise_percent / 100)) < (float) price2num($price_min_ttc)) && $price_base_type == 'TTC') {
1687 $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1688 setEventMessages($mesg, null, 'errors');
1689 $error++;
1690 $action = 'editline';
1691 }
1692 }
1693 } else {
1694 $type = GETPOST('type');
1695 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1696
1697 // Check parameters
1698 if (GETPOST('type') < 0) {
1699 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1700 $error++;
1701 $action = 'editline';
1702 }
1703 }
1704
1705 if ($qty < 0 && !getDolGlobalString('ORDER_ENABLE_NEGATIVE_QTY')) {
1706 setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1707 $error++;
1708 $action = 'editline';
1709 }
1710
1711 $object->loadExpeditions();
1712 if (isset($object->expeditions[GETPOST('lineid', 'int')])) {
1713 if ($qty < $object->expeditions[GETPOST('lineid', 'int')]) {
1714 setEventMessages($langs->trans('ErrorQtyOrderedLessQtyShipped'), null, 'errors');
1715 $error++;
1716 $action = 'editline';
1717 }
1718 }
1719
1720 if (!$error) {
1721 $db->begin();
1722
1723 if (!$user->hasRight('margins', 'creer')) {
1724 foreach ($object->lines as &$line) {
1725 if ($line->id == GETPOSTINT('lineid')) {
1726 $fournprice = $line->fk_fournprice;
1727 $buyingprice = $line->pa_ht;
1728 break;
1729 }
1730 }
1731 }
1732
1733 $result = $object->updateline(GETPOSTINT('lineid'), $description, (float) $pu, (float) $qty, (float) $remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, $price_base_type, $info_bits, $date_start, $date_end, $type, GETPOSTINT('fk_parent_line'), 0, (int) $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOSTINT('units'), (float) $pu_ht_devise);
1734
1735
1736 if ($result >= 0) {
1737 $db->commit();
1738
1739 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1740 // Define output language
1741 $outputlangs = $langs;
1742 $newlang = '';
1743 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1744 $newlang = GETPOST('lang_id', 'aZ09');
1745 }
1746 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1747 $newlang = $object->thirdparty->default_lang;
1748 }
1749 if (!empty($newlang)) {
1750 $outputlangs = new Translate("", $conf);
1751 $outputlangs->setDefaultLang($newlang);
1752 }
1753
1754 $ret = $object->fetch($object->id); // Reload to get new records
1755 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1756 }
1757
1758 unset($_POST['qty']);
1759 unset($_POST['type']);
1760 unset($_POST['productid']);
1761 unset($_POST['remise_percent']);
1762 unset($_POST['price_ht']);
1763 unset($_POST['multicurrency_price_ht']);
1764 unset($_POST['price_ttc']);
1765 unset($_POST['tva_tx']);
1766 unset($_POST['product_ref']);
1767 unset($_POST['product_label']);
1768 unset($_POST['product_desc']);
1769 unset($_POST['fournprice']);
1770 unset($_POST['buying_price']);
1771
1772 unset($_POST['date_starthour']);
1773 unset($_POST['date_startmin']);
1774 unset($_POST['date_startsec']);
1775 unset($_POST['date_startday']);
1776 unset($_POST['date_startmonth']);
1777 unset($_POST['date_startyear']);
1778 unset($_POST['date_endhour']);
1779 unset($_POST['date_endmin']);
1780 unset($_POST['date_endsec']);
1781 unset($_POST['date_endday']);
1782 unset($_POST['date_endmonth']);
1783 unset($_POST['date_endyear']);
1784 } else {
1785 $db->rollback();
1786
1787 setEventMessages($object->error, $object->errors, 'errors');
1788 }
1789 }
1790 } elseif ($action == 'updateline' && $usercancreate && GETPOST('cancel', 'alpha')) {
1791 header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // To re-display card in edit mode
1792 exit();
1793 } elseif ($action == 'confirm_validate' && $confirm == 'yes' && $usercanvalidate) {
1794 $idwarehouse = GETPOSTINT('idwarehouse');
1795
1796 $qualified_for_stock_change = 0;
1797 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1798 $qualified_for_stock_change = $object->hasProductsOrServices(2);
1799 } else {
1800 $qualified_for_stock_change = $object->hasProductsOrServices(1);
1801 }
1802
1803 // Check parameters
1804 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
1805 if (!$idwarehouse || $idwarehouse == -1) {
1806 $error++;
1807 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1808 $action = '';
1809 }
1810 }
1811
1812 if (!$error) {
1813 $locationTarget = '';
1814
1815 $db->begin();
1816
1817 $result = $object->valid($user, $idwarehouse);
1818 if ($result >= 0) {
1819 $error = 0;
1820 $deposit = null;
1821
1822 $deposit_percent_from_payment_terms = (float) getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
1823
1824 if (
1825 GETPOST('generate_deposit', 'alpha') == 'on' && !empty($deposit_percent_from_payment_terms)
1826 && isModEnabled('invoice') && $user->hasRight('facture', 'creer')
1827 ) {
1828 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
1829
1830 $date = dol_mktime(0, 0, 0, GETPOSTINT('datefmonth'), GETPOSTINT('datefday'), GETPOSTINT('datefyear'));
1831 $forceFields = array();
1832
1833 if (GETPOSTISSET('date_pointoftax')) {
1834 $forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOSTINT('date_pointoftaxmonth'), GETPOSTINT('date_pointoftaxday'), GETPOSTINT('date_pointoftaxyear'));
1835 }
1836
1837 $deposit = Facture::createDepositFromOrigin($object, $date, GETPOSTINT('cond_reglement_id'), $user, 0, GETPOSTINT('validate_generated_deposit') == 'on', $forceFields);
1838
1839 if ($deposit) {
1840 setEventMessage('DepositGenerated');
1841 $locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
1842 } else {
1843 $error++;
1844 setEventMessages($object->error, $object->errors, 'errors');
1845 }
1846 }
1847
1848 // Define output language
1849 if (! $error) {
1850 $db->commit();
1851
1852 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1853 $outputlangs = $langs;
1854 $newlang = '';
1855 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1856 $newlang = GETPOST('lang_id', 'aZ09');
1857 }
1858 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1859 $newlang = $object->thirdparty->default_lang;
1860 }
1861 if (!empty($newlang)) {
1862 $outputlangs = new Translate("", $conf);
1863 $outputlangs->setDefaultLang($newlang);
1864 }
1865 $model = $object->model_pdf;
1866 $ret = $object->fetch($id); // Reload to get new records
1867
1868 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1869
1870 if ($deposit) {
1871 $deposit->fetch($deposit->id); // Reload to get new records
1872 $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1873 }
1874 }
1875
1876 if ($locationTarget) {
1877 header('Location: ' . $locationTarget);
1878 exit;
1879 }
1880 } else {
1881 $db->rollback();
1882 }
1883 } else {
1884 $db->rollback();
1885 setEventMessages($object->error, $object->errors, 'errors');
1886 }
1887 }
1888 } elseif ($action == 'confirm_modif' && $usercancreate) {
1889 // Go back to draft status
1890 $idwarehouse = GETPOST('idwarehouse');
1891
1892 $qualified_for_stock_change = 0;
1893 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1894 $qualified_for_stock_change = $object->hasProductsOrServices(2);
1895 } else {
1896 $qualified_for_stock_change = $object->hasProductsOrServices(1);
1897 }
1898
1899 // Check parameters
1900 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
1901 if (!$idwarehouse || $idwarehouse == -1) {
1902 $error++;
1903 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1904 $action = '';
1905 }
1906 }
1907
1908 if (!$error) {
1909 $result = $object->setDraft($user, $idwarehouse);
1910 if ($result >= 0) {
1911 // Define output language
1912 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1913 $outputlangs = $langs;
1914 $newlang = '';
1915 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1916 $newlang = GETPOST('lang_id', 'aZ09');
1917 }
1918 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1919 $newlang = $object->thirdparty->default_lang;
1920 }
1921 if (!empty($newlang)) {
1922 $outputlangs = new Translate("", $conf);
1923 $outputlangs->setDefaultLang($newlang);
1924 }
1925 $model = $object->model_pdf;
1926 $ret = $object->fetch($id); // Reload to get new records
1927
1928 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1929 }
1930 } else {
1931 setEventMessages($object->error, $object->errors, 'errors');
1932 }
1933 }
1934 } elseif ($action == 'confirm_shipped' && $confirm == 'yes' && $usercanclose) {
1935 $result = $object->cloture($user);
1936 if ($result < 0) {
1937 setEventMessages($object->error, $object->errors, 'errors');
1938 }
1939 } elseif ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanvalidate) {
1940 $idwarehouse = GETPOSTINT('idwarehouse');
1941
1942 $qualified_for_stock_change = 0;
1943 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1944 $qualified_for_stock_change = $object->hasProductsOrServices(2);
1945 } else {
1946 $qualified_for_stock_change = $object->hasProductsOrServices(1);
1947 }
1948
1949 // Check parameters
1950 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
1951 if (!$idwarehouse || $idwarehouse == -1) {
1952 $error++;
1953 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1954 $action = '';
1955 }
1956 }
1957
1958 if (!$error) {
1959 $result = $object->cancel($user, $idwarehouse);
1960
1961 if ($result < 0) {
1962 setEventMessages($object->error, $object->errors, 'errors');
1963 }
1964 }
1965 }
1966
1967 if ($action == 'update_extras' && $permissiontoeditextra) {
1968 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
1969
1970 $attribute_name = GETPOST('attribute', 'aZ09');
1971
1972 // Fill array 'array_options' with data from update form
1973 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
1974 if ($ret < 0) {
1975 $error++;
1976 }
1977
1978 if (!$error) {
1979 // Actions on extra fields
1980 $result = $object->updateExtraField($attribute_name, 'ORDER_MODIFY');
1981 if ($result < 0) {
1982 setEventMessages($object->error, $object->errors, 'errors');
1983 $error++;
1984 }
1985 }
1986
1987 if ($error) {
1988 $action = 'edit_extras';
1989 }
1990 }
1991
1992 // Add lines from objectlinked
1993 if ($action == 'import_lines_from_object' && $usercancreate && $object->status == Commande::STATUS_DRAFT) {
1994 $fromElement = GETPOST('fromelement');
1995 $fromElementid = GETPOST('fromelementid');
1996 $importLines = GETPOST('line_checkbox');
1997
1998 if (!empty($importLines) && is_array($importLines) && !empty($fromElement) && ctype_alpha($fromElement) && !empty($fromElementid)) {
1999 if ($fromElement == 'commande') {
2000 dol_include_once('/' . $fromElement . '/class/' . $fromElement . '.class.php');
2001 $lineClassName = 'OrderLine';
2002 } elseif ($fromElement == 'propal') {
2003 dol_include_once('/comm/' . $fromElement . '/class/' . $fromElement . '.class.php');
2004 $lineClassName = 'PropaleLigne';
2005 } elseif ($fromElement == 'facture') {
2006 dol_include_once('/compta/' . $fromElement . '/class/' . $fromElement . '.class.php');
2007 $lineClassName = 'FactureLigne';
2008 }
2009 $nextRang = count($object->lines) + 1;
2010 $importCount = 0;
2011 $error = 0;
2012 foreach ($importLines as $lineId) {
2013 $lineId = intval($lineId);
2014 $originLine = new $lineClassName($db);
2015 if (intval($fromElementid) > 0 && $originLine->fetch($lineId) > 0) {
2016 $originLine->fetch_optionals();
2017 $desc = $originLine->desc;
2018 $pu_ht = $originLine->subprice;
2019 $qty = $originLine->qty;
2020 $txtva = $originLine->tva_tx;
2021 $txlocaltax1 = $originLine->localtax1_tx;
2022 $txlocaltax2 = $originLine->localtax2_tx;
2023 $fk_product = $originLine->fk_product;
2024 $remise_percent = $originLine->remise_percent;
2025 $date_start = $originLine->date_start;
2026 $date_end = $originLine->date_end;
2027 $fk_code_ventilation = 0;
2028 $info_bits = $originLine->info_bits;
2029 $fk_remise_except = $originLine->fk_remise_except;
2030 $price_base_type = 'HT';
2031 $pu_ttc = 0;
2032 $type = $originLine->product_type;
2033 $rang = $nextRang++;
2034 $special_code = $originLine->special_code;
2035 $origin = $originLine->element;
2036 $origin_id = $originLine->id;
2037 $fk_parent_line = 0;
2038 $fk_fournprice = $originLine->fk_fournprice;
2039 $pa_ht = $originLine->pa_ht;
2040 $label = $originLine->label;
2041 $array_options = $originLine->array_options;
2042 $situation_percent = 100;
2043 $fk_prev_id = '';
2044 $fk_unit = $originLine->fk_unit;
2045 $pu_ht_devise = $originLine->multicurrency_subprice;
2046
2047 $res = $object->addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $info_bits, $fk_remise_except, $price_base_type, $pu_ttc, $date_start, $date_end, $type, $rang, $special_code, $fk_parent_line, $fk_fournprice, $pa_ht, $label, $array_options, $fk_unit, $origin, $origin_id, $pu_ht_devise);
2048
2049 if ($res > 0) {
2050 $importCount++;
2051 } else {
2052 $error++;
2053 }
2054 } else {
2055 $error++;
2056 }
2057 }
2058
2059 if ($error) {
2060 setEventMessages($langs->trans('ErrorsOnXLines', $error), null, 'errors');
2061 }
2062 }
2063 }
2064
2065 // Actions when printing a doc from card
2066 include DOL_DOCUMENT_ROOT . '/core/actions_printing.inc.php';
2067
2068 // Actions to build doc
2069 $upload_dir = !empty($conf->commande->multidir_output[$object->entity ?? $conf->entity]) ? $conf->commande->multidir_output[$object->entity ?? $conf->entity] : $conf->commande->dir_output;
2070 $permissiontoadd = $usercancreate;
2071 include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
2072
2073 // Actions to send emails
2074 $triggersendname = 'ORDER_SENTBYMAIL';
2075 $paramname = 'id';
2076 $autocopy = 'MAIN_MAIL_AUTOCOPY_ORDER_TO'; // used to know the automatic BCC to add
2077 $trackid = 'ord' . $object->id;
2078 include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
2079
2080
2081 if (!$error && getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB') && $usercancreate) {
2082 if ($action == 'addcontact') { // Test on permission already done
2083 if ($object->id > 0) {
2084 $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
2085 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
2086 $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
2087 }
2088
2089 if ($result >= 0) {
2090 header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
2091 exit();
2092 } else {
2093 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
2094 $langs->load("errors");
2095 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
2096 } else {
2097 setEventMessages($object->error, $object->errors, 'errors');
2098 }
2099 }
2100 } elseif ($action == 'swapstatut') { // Test on permission already done
2101 // bascule du statut d'un contact
2102 if ($object->id > 0) {
2103 $result = $object->swapContactStatus(GETPOSTINT('ligne'));
2104 } else {
2106 }
2107 } elseif ($action == 'deletecontact') { // Test on permission already done
2108 // Efface un contact
2109 $result = $object->delete_contact($lineid);
2110
2111 if ($result >= 0) {
2112 header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
2113 exit();
2114 } else {
2116 }
2117 }
2118 }
2119}
2120
2121
2122/*
2123 * View
2124 */
2125
2126$title = $object->ref . " - " . $langs->trans('Card');
2127if ($action == 'create') {
2128 $title = $langs->trans("NewOrder");
2129}
2130$help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge';
2131
2132llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-order page-card');
2133
2134$form = new Form($db);
2135$formfile = new FormFile($db);
2136$formorder = new FormOrder($db);
2137$formmargin = new FormMargin($db);
2138$formproduct = new FormProduct($db);
2139if (isModEnabled('project')) {
2140 $formproject = new FormProjets($db);
2141}
2142
2143// Mode creation
2144if ($action == 'create' && $usercancreate) {
2145 print load_fiche_titre($langs->trans('CreateOrder'), '', 'order');
2146
2147 $soc = new Societe($db);
2148 if ($socid > 0) {
2149 $res = $soc->fetch($socid);
2150 }
2151
2152 $currency_code = $conf->currency;
2153
2154 $cond_reglement_id = GETPOSTINT('cond_reglement_id');
2155 $deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
2156 $mode_reglement_id = GETPOSTINT('mode_reglement_id');
2157 $fk_account = GETPOSTINT('fk_account');
2158
2159 if (!empty($origin) && !empty($originid)) {
2160 // Parse element/subelement (ex: project_task)
2161 $element = $subelement = $origin;
2162 $regs = array();
2163 if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
2164 $element = $regs[1];
2165 $subelement = $regs[2];
2166 }
2167
2168 if ($element == 'project') {
2169 $projectid = $originid;
2170
2171 if (!$cond_reglement_id) {
2172 $cond_reglement_id = $soc->cond_reglement_id;
2173 }
2174 if (!$deposit_percent) {
2175 $deposit_percent = $soc->deposit_percent;
2176 }
2177 if (!$mode_reglement_id) {
2178 $mode_reglement_id = $soc->mode_reglement_id;
2179 }
2180 if (!$remise_percent) {
2181 $remise_percent = $soc->remise_percent;
2182 }
2183 } else {
2184 // For compatibility
2185 if ($element == 'order' || $element == 'commande') {
2186 $element = $subelement = 'commande';
2187 } elseif ($element == 'propal') {
2188 $element = 'comm/propal';
2189 $subelement = 'propal';
2190 } elseif ($element == 'contract') {
2191 $element = $subelement = 'contrat';
2192 }
2193
2194 dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
2195
2196 $classname = ucfirst($subelement);
2197 $objectsrc = new $classname($db);
2198 '@phan-var-force Commande|Propal|Contrat $objectsrc'; // Can possibly be other class but CommonObject is too general
2199 $objectsrc->fetch($originid);
2200 if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
2201 $objectsrc->fetch_lines();
2202 }
2203 $objectsrc->fetch_thirdparty();
2204
2205 // Replicate extrafields
2206 $objectsrc->fetch_optionals();
2207 $object->array_options = $objectsrc->array_options;
2208
2209 $projectid = (int) $objectsrc->fk_project;
2210 $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
2211
2212 $soc = $objectsrc->thirdparty;
2213 $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
2214 $deposit_percent = (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : null));
2215 $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
2216 $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0));
2217 $availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : 0);
2218 $shipping_method_id = (!empty($objectsrc->shipping_method_id) ? $objectsrc->shipping_method_id : (!empty($soc->shipping_method_id) ? $soc->shipping_method_id : 0));
2219 $warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0));
2220 $demand_reason_id = (!empty($objectsrc->demand_reason_id) ? $objectsrc->demand_reason_id : (!empty($soc->demand_reason_id) ? $soc->demand_reason_id : 0));
2221 $dateorder = getDolGlobalString('MAIN_AUTOFILL_DATE_ORDER') ? '' : -1;
2222
2223 $date_delivery = (!empty($objectsrc->delivery_date) ? $objectsrc->delivery_date : '');
2224
2225 if (isModEnabled("multicurrency")) {
2226 if (!empty($objectsrc->multicurrency_code)) {
2227 $currency_code = $objectsrc->multicurrency_code;
2228 }
2229 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX') && !empty($objectsrc->multicurrency_tx)) {
2230 $currency_tx = $objectsrc->multicurrency_tx;
2231 }
2232 }
2233
2234 $note_private = $object->getDefaultCreateValueFor('note_private', (!empty($objectsrc->note_private) ? $objectsrc->note_private : null));
2235 $note_public = $object->getDefaultCreateValueFor('note_public', (!empty($objectsrc->note_public) ? $objectsrc->note_public : null));
2236
2237 // Object source contacts list
2238 $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
2239 }
2240 } else {
2241 $cond_reglement_id = empty($soc->cond_reglement_id) ? $cond_reglement_id : $soc->cond_reglement_id;
2242 $deposit_percent = empty($soc->deposit_percent) ? $deposit_percent : $soc->deposit_percent;
2243 $mode_reglement_id = empty($soc->mode_reglement_id) ? $mode_reglement_id : $soc->mode_reglement_id;
2244 $fk_account = empty($soc->mode_reglement_id) ? $fk_account : $soc->fk_account;
2245 $availability_id = 0;
2246 $shipping_method_id = $soc->shipping_method_id;
2247 $warehouse_id = $soc->fk_warehouse;
2248 $demand_reason_id = $soc->demand_reason_id;
2249 $dateorder = getDolGlobalString('MAIN_AUTOFILL_DATE_ORDER') ? '' : -1;
2250
2251 if (isModEnabled("multicurrency") && !empty($soc->multicurrency_code)) {
2252 $currency_code = $soc->multicurrency_code;
2253 }
2254
2255 $note_private = $object->getDefaultCreateValueFor('note_private');
2256 $note_public = $object->getDefaultCreateValueFor('note_public');
2257 }
2258
2259 // If form was posted (but error returned), we must reuse the value posted in priority (standard Dolibarr behaviour)
2260 if (!GETPOST('changecompany')) {
2261 if (GETPOSTISSET('cond_reglement_id')) {
2262 $cond_reglement_id = GETPOSTINT('cond_reglement_id');
2263 }
2264 if (GETPOSTISSET('deposit_percent')) {
2265 $deposit_percent = GETPOSTFLOAT('deposit_percent');
2266 }
2267 if (GETPOSTISSET('mode_reglement_id')) {
2268 $mode_reglement_id = GETPOSTINT('mode_reglement_id');
2269 }
2270 if (GETPOSTISSET('cond_reglement_id')) {
2271 $fk_account = GETPOSTINT('fk_account');
2272 }
2273 }
2274
2275 // Warehouse default if null
2276 if ($soc->fk_warehouse > 0) {
2277 $warehouse_id = $soc->fk_warehouse;
2278 }
2279 if (isModEnabled('stock') && empty($warehouse_id) && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
2280 if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) {
2281 $warehouse_id = getDolGlobalString('MAIN_DEFAULT_WAREHOUSE');
2282 }
2283 if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && !empty($user->fk_warehouse)) {
2284 $warehouse_id = $user->fk_warehouse;
2285 }
2286 }
2287
2288 print '<form name="crea_commande" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
2289 print '<input type="hidden" name="token" value="' . newToken() . '">';
2290 print '<input type="hidden" name="action" value="add">';
2291 print '<input type="hidden" name="changecompany" value="0">'; // will be set to 1 by javascript so we know post is done after a company change
2292 print '<input type="hidden" name="remise_percent" value="' . $soc->remise_percent . '">';
2293 print '<input type="hidden" name="origin" value="' . $origin . '">';
2294 print '<input type="hidden" name="originid" value="' . $originid . '">';
2295 print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
2296 if (!empty($currency_tx)) {
2297 print '<input type="hidden" name="originmulticurrency_tx" value="' . $currency_tx . '">';
2298 }
2299
2300 print dol_get_fiche_head([]);
2301
2302 // Call Hook tabContentCreateOrder
2303 $parameters = array();
2304 // Note that $action and $object may be modified by hook
2305 $reshook = $hookmanager->executeHooks('tabContentCreateOrder', $parameters, $object, $action);
2306 if (empty($reshook)) {
2307 print '<table class="border centpercent">';
2308
2309 // Reference
2310 //print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td>' . $langs->trans("Draft") . '</td></tr>';
2311
2312 // Thirdparty
2313 print '<tr>';
2314 print '<td class="fieldrequired">' . $langs->trans('Customer') . '</td>';
2315 if ($socid > 0) {
2316 print '<td>';
2317 print $soc->getNomUrl(1, 'customer');
2318 print '<input type="hidden" name="socid" value="' . $soc->id . '">';
2319 print '</td>';
2320 } else {
2321 print '<td class="valuefieldcreate">';
2322 $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))';
2323 print img_picto('', 'company', 'class="pictofixedwidth"') . $form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
2324 // reload page to retrieve customer information
2325 if (!getDolGlobalString('RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED')) {
2326 print '<script>
2327 $(document).ready(function() {
2328 $("#socid").change(function() {
2329 console.log("We have changed the company - Reload page");
2330 var socid = $(this).val();
2331 // reload page
2332 $("input[name=action]").val("create");
2333 $("input[name=changecompany]").val("1");
2334 $("form[name=crea_commande]").submit();
2335 });
2336 });
2337 </script>';
2338 }
2339 print ' <a href="' . DOL_URL_ROOT . '/societe/card.php?action=create&customer=3&fournisseur=0&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?action=create') . '"><span class="fa fa-plus-circle valignmiddle paddingleft" title="' . $langs->trans("AddThirdParty") . '"></span></a>';
2340 print '</td>';
2341 }
2342 print '</tr>' . "\n";
2343
2344 // Reference of order on customer side
2345 if (getDolGlobalString('MAIN_ASK_CUSTOMER_REF_OF_SALE_ORDER_AT_CREATION') || getDolGlobalString('MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER')) {
2346 print '<tr><td>';
2347 if (getDolGlobalString('MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER') && !empty($origin) && !empty($originid)) {
2348 print $langs->trans('RefProposal') . '</td><td>';
2349 print '<input type="text" name="ref_client" value="' . $ref_client . '">';
2350 } else {
2351 print $form->textwithpicto($langs->trans('RefCustomer'), $langs->trans('RefOfOnCustomerSide', $langs->transnoentitiesnoconv("Order"))) . '</td><td>';
2352 print '<input type="text" name="ref_client" value="' . GETPOST('ref_client') . '">';
2353 }
2354 print '</td></tr>';
2355 }
2356
2357 // Contact of order
2358 if ($socid > 0) {
2359 // Contacts (ask contact only if thirdparty already defined).
2360 // print "<tr><td>".$langs->trans("DefaultContact").'</td><td>';
2361 print "<tr><td>";
2362 print $form->textwithpicto($langs->trans("DefaultContact"), $langs->trans("TypeContact_commande_external_" . $type_contact_code));
2363 print '</td><td>';
2364 print img_picto('', 'contact', 'class="pictofixedwidth"');
2365 //print $form->selectcontacts($soc->id, $contactid, 'contactid', 1, empty($srccontactslist) ? "" : $srccontactslist, '', 1, 'maxwidth300 widthcentpercentminusx');
2366 print $form->select_contact($soc->id, $contactid, 'contactid', 1, empty($srccontactslist) ? "" : $srccontactslist, '', 1, 'maxwidth300 widthcentpercentminusx', true);
2367 print '</td></tr>';
2368
2369 // Line with information on Third Party Discounts
2370 print '<tr><td>' . $langs->trans('Discounts') . '</td><td>';
2371
2372 $absolute_discount = $soc->getAvailableDiscounts();
2373
2374 $thirdparty = $soc;
2375 $discount_type = 0;
2376 $backtopage = $_SERVER["PHP_SELF"] . '?socid=' . $thirdparty->id . '&action=' . $action . '&origin=' . urlencode((string) (GETPOST('origin'))) . '&originid=' . urlencode((string) (GETPOSTINT('originid')));
2377 include DOL_DOCUMENT_ROOT . '/core/tpl/object_discounts.tpl.php';
2378
2379 print '</td></tr>';
2380 }
2381
2382 // Date
2383 $dateorder = (getDolGlobalString('MAIN_DO_NOT_AUTOFILL_DATE_ORDER') ? -1 : ''); // By default '' so we will autofill date. -1 means keep empty.
2384
2385 print '<tr><td class="fieldrequired">' . $langs->trans('Date') . '</td><td>';
2386 print img_picto('', 'action', 'class="pictofixedwidth"');
2387 print $form->selectDate($dateorder, 're', 0, 0, 0, "crea_commande", 1, 1); // Always autofill date with current date
2388 print '</td></tr>';
2389
2390 // Date delivery planned
2391 print '<tr><td>' . $langs->trans("DateDeliveryPlanned") . '</td>';
2392 print '<td colspan="3">';
2393 $date_delivery = ($date_delivery ? $date_delivery : $object->delivery_date);
2394 print img_picto('', 'action', 'class="pictofixedwidth"');
2395 print $form->selectDate($date_delivery ? $date_delivery : -1, 'liv_', 1, 1, 1);
2396 print "</td>\n";
2397 print '</tr>';
2398
2399 // Delivery delay
2400 print '<tr class="fielddeliverydelay"><td>' . $langs->trans('AvailabilityPeriod') . '</td><td>';
2401 print img_picto('', 'clock', 'class="pictofixedwidth"');
2402 $form->selectAvailabilityDelay((GETPOSTISSET('availability_id') ? GETPOST('availability_id') : $availability_id), 'availability_id', '', 1, 'maxwidth200 widthcentpercentminusx');
2403 print '</td></tr>';
2404
2405 // Terms of payment
2406 print '<tr><td class="nowrap">' . $langs->trans('PaymentConditionsShort') . '</td><td>';
2407 print img_picto('', 'payment', 'class="pictofixedwidth"');
2408 print $form->getSelectConditionsPaiements((int) $cond_reglement_id, 'cond_reglement_id', 1, 1, 0, 'maxwidth200 widthcentpercentminusx', (float) $deposit_percent);
2409 print '</td></tr>';
2410
2411 // Payment mode
2412 print '<tr><td>' . $langs->trans('PaymentMode') . '</td><td>';
2413 print img_picto('', 'bank', 'class="pictofixedwidth"');
2414 print $form->select_types_paiements((string) $mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1);
2415 print '</td></tr>';
2416
2417 // Bank Account
2418 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_ORDER') && isModEnabled("bank")) {
2419 print '<tr><td>' . $langs->trans('BankAccount') . '</td><td>';
2420 print img_picto('', 'bank_account', 'class="pictofixedwidth"') . $form->select_comptes((int) $fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1);
2421 print '</td></tr>';
2422 }
2423
2424 // Shipping Method
2425 if (isModEnabled('shipping')) {
2426 print '<tr><td>' . $langs->trans('SendingMethod') . '</td><td>';
2427 print img_picto('', 'object_dolly', 'class="pictofixedwidth"');
2428 $form->selectShippingMethod(((GETPOSTISSET('shipping_method_id') && GETPOSTINT('shipping_method_id') != 0) ? GETPOST('shipping_method_id') : $shipping_method_id), 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx');
2429 print '</td></tr>';
2430 }
2431
2432 // Warehouse
2433 if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
2434 print '<tr><td>' . $langs->trans('Warehouse') . '</td><td>';
2435 print img_picto('', 'stock', 'class="pictofixedwidth"') . $formproduct->selectWarehouses(((GETPOSTISSET('warehouse_id') && !GETPOSTINT('changecompany')) ? GETPOST('warehouse_id') : $warehouse_id), 'warehouse_id', '', 1, 0, 0, '', 0, 0, array(), 'maxwidth500 widthcentpercentminusxx');
2436 print '</td></tr>';
2437 }
2438
2439 // Source / Channel - What trigger creation
2440 print '<tr><td>' . $langs->trans('Source') . '</td><td>';
2441 print img_picto('', 'question', 'class="pictofixedwidth"');
2442 $form->selectInputReason((GETPOSTISSET('demand_reason_id') ? GETPOST('demand_reason_id') : $demand_reason_id), 'demand_reason_id', '', 1, 'maxwidth200 widthcentpercentminusx');
2443 print '</td></tr>';
2444
2445 // TODO How record was recorded OrderMode (llx_c_input_method)
2446
2447 // Project
2448 if (isModEnabled('project')) {
2449 $langs->load("projects");
2450 print '<tr>';
2451 print '<td>'.$langs->trans("Project").'</td><td>';
2452 print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects((($soc->id > 0 && !getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_CUSTOMERS')) ? $soc->id : -1), (GETPOSTISSET('projectid') ? GETPOST('projectid') : $projectid), 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500 widthcentpercentminusxx');
2453 print ' <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>';
2454 print '</td>';
2455 print '</tr>';
2456 }
2457
2458 // Incoterms
2459 if (isModEnabled('incoterm')) {
2460 print '<tr>';
2461 print '<td><label for="incoterm_id">' . $form->textwithpicto($langs->trans("IncotermLabel"), !empty($objectsrc->fk_incoterms) ? (string) $objectsrc->fk_incoterms : (string) $soc->fk_incoterms, 1) . '</label></td>';
2462 print '<td class="maxwidthonsmartphone">';
2463 $incoterm_id = GETPOST('incoterm_id');
2464 $location_incoterms = GETPOST('location_incoterms');
2465 if (empty($incoterm_id)) {
2466 $incoterm_id = (!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms);
2467 $location_incoterms = (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : $soc->location_incoterms);
2468 }
2469 print img_picto('', 'incoterm', 'class="pictofixedwidth"');
2470 print $form->select_incoterms($incoterm_id, $location_incoterms);
2471 print '</td></tr>';
2472 }
2473
2474 // Other attributes
2475 $parameters = array();
2476 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2477 $parameters['objectsrc'] = $objectsrc;
2478 }
2479 $parameters['socid'] = $socid;
2480
2481 // Note that $action and $object may be modified by hook
2482 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
2483 print $hookmanager->resPrint;
2484 if (empty($reshook)) {
2485 if (getDolGlobalString('THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER') && !empty($soc->id)) {
2486 // copy from thirdparty
2487 $tpExtrafields = new ExtraFields($db);
2488 $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element);
2489 if ($soc->fetch_optionals() > 0) {
2490 $object->array_options = array_merge($object->array_options, $soc->array_options);
2491 }
2492 }
2493
2494 print $object->showOptionals($extrafields, 'create', $parameters);
2495 }
2496
2497 // Template to use by default
2498 include_once DOL_DOCUMENT_ROOT . '/core/modules/commande/modules_commande.php';
2500 if (is_array($list) && count($list) > 0) {
2501 print '<tr><td>' . $langs->trans('DefaultModel') . '</td>';
2502 print '<td>';
2503 $preselected = getDolGlobalString('COMMANDE_ADDON_PDF');
2504 print img_picto('', 'pdf', 'class="pictofixedwidth"');
2505 print $form->selectarray('model', $list, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
2506 print "</td></tr>";
2507 }
2508
2509 // Multicurrency
2510 if (isModEnabled("multicurrency")) {
2511 print '<tr>';
2512 print '<td>' . $form->editfieldkey("Currency", 'multicurrency_code', '', $object, 0) . '</td>';
2513 print '<td class="maxwidthonsmartphone">';
2514 print img_picto('', 'currency', 'class="pictofixedwidth"') . $form->selectMultiCurrency(((GETPOSTISSET('multicurrency_code') && !GETPOST('changecompany')) ? GETPOST('multicurrency_code') : $currency_code), 'multicurrency_code', 0, '', false, 'maxwidth200 widthcentpercentminusx');
2515 print '</td></tr>';
2516 }
2517
2518 // Categories
2519 if (isModEnabled('category')) {
2520 print '<tr><td>' . $langs->trans("Categories") . '</td><td colspan="3">';
2521 print $form->selectCategories(Categorie::TYPE_ORDER, 'categories', $object);
2522 print "</td></tr>";
2523 }
2524
2525 // Note public
2526 print '<tr>';
2527 print '<td class="tdtop">' . $langs->trans('NotePublic') . '</td>';
2528 print '<td>';
2529
2530 $doleditor = new DolEditor('note_public', (string) $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
2531 print $doleditor->Create(1);
2532 // print '<textarea name="note_public" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_public.'</textarea>';
2533 print '</td></tr>';
2534
2535 // Note private
2536 if (empty($user->socid)) {
2537 print '<tr>';
2538 print '<td class="tdtop">' . $langs->trans('NotePrivate') . '</td>';
2539 print '<td>';
2540
2541 $doleditor = new DolEditor('note_private', (string) $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
2542 print $doleditor->Create(1);
2543 // print '<textarea name="note" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'</textarea>';
2544 print '</td></tr>';
2545 }
2546
2547 if (!empty($origin) && !empty($originid) && is_object($objectsrc) && !empty($classname)) {
2548 // TODO for compatibility
2549 if ($origin == 'contrat') {
2550 // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
2551 $objectsrc->update_price(1);
2552 }
2553
2554 print "\n<!-- " . $classname . " info -->\n";
2555 print '<input type="hidden" name="amount" value="' . $objectsrc->total_ht . '">' . "\n";
2556 print '<input type="hidden" name="total" value="' . $objectsrc->total_ttc . '">' . "\n";
2557 print '<input type="hidden" name="tva" value="' . $objectsrc->total_tva . '">' . "\n";
2558 print '<input type="hidden" name="origin" value="' . $objectsrc->element . '">';
2559 print '<input type="hidden" name="originid" value="' . $objectsrc->id . '">';
2560
2561 switch ($classname) {
2562 case 'Propal':
2563 $newclassname = 'CommercialProposal';
2564 break;
2565 case 'Commande':
2566 $newclassname = 'Order';
2567 break;
2568 case 'Expedition':
2569 $newclassname = 'Sending';
2570 break;
2571 case 'Contrat':
2572 $newclassname = 'Contract';
2573 break;
2574 default:
2575 $newclassname = $classname;
2576 }
2577
2578 print '<tr><td>' . $langs->trans($newclassname) . '</td><td>' . $objectsrc->getNomUrl(1) . '</td></tr>';
2579
2580 // Amount
2581 print '<tr><td>' . $langs->trans('AmountHT') . '</td><td>' . price($objectsrc->total_ht) . '</td></tr>';
2582 print '<tr><td>' . $langs->trans('AmountVAT') . '</td><td>' . price($objectsrc->total_tva) . "</td></tr>";
2583 if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1 RE
2584 print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td><td>' . price($objectsrc->total_localtax1) . "</td></tr>";
2585 }
2586
2587 if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2 IRPF
2588 print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td><td>' . price($objectsrc->total_localtax2) . "</td></tr>";
2589 }
2590
2591 print '<tr><td>' . $langs->trans('AmountTTC') . '</td><td>' . price($objectsrc->total_ttc) . "</td></tr>";
2592
2593 if (isModEnabled("multicurrency")) {
2594 print '<tr><td>' . $langs->trans('MulticurrencyAmountHT') . '</td><td>' . price($objectsrc->multicurrency_total_ht) . '</td></tr>';
2595 print '<tr><td>' . $langs->trans('MulticurrencyAmountVAT') . '</td><td>' . price($objectsrc->multicurrency_total_tva) . "</td></tr>";
2596 print '<tr><td>' . $langs->trans('MulticurrencyAmountTTC') . '</td><td>' . price($objectsrc->multicurrency_total_ttc) . "</td></tr>";
2597 }
2598 }
2599
2600 print "\n";
2601
2602 print '</table>';
2603 }
2604
2605 print dol_get_fiche_end();
2606
2607 print $form->buttonsSaveCancel("CreateDraft");
2608
2609 // Show origin lines
2610 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2611 $title = $langs->trans('ProductsAndServices');
2612 print load_fiche_titre($title);
2613
2614 print '<div class="div-table-responsive-no-min">';
2615 print '<table class="noborder centpercent">';
2616
2617 $objectsrc->printOriginLinesList('', $selectedLines);
2618
2619 print '</table>';
2620 print '</div>';
2621 }
2622
2623 print '</form>';
2624} else {
2625 // Mode view
2626 $now = dol_now();
2627
2628 if ($object->id > 0) {
2629 $product_static = new Product($db);
2630
2631 $soc = new Societe($db);
2632 $soc->fetch($object->socid);
2633
2634 $author = new User($db);
2635 $author->fetch($object->user_author_id);
2636
2637 $object->fetch_thirdparty();
2638 $res = $object->fetch_optionals();
2639
2640 $head = commande_prepare_head($object);
2641 print dol_get_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, $object->picto, 0, '', '', 0, '', 1);
2642
2643 $formconfirm = '';
2644
2645 // Confirmation to delete
2646 if ($action == 'delete') {
2647 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1);
2648 }
2649
2650 // Confirmation of validation
2651 if ($action == 'validate') {
2652 // We check that object has a temporary ref
2653 $ref = substr($object->ref, 1, 4);
2654 if ($ref == 'PROV' || $ref == '') {
2655 $numref = $object->getNextNumRef($soc);
2656 if (empty($numref)) {
2657 $error++;
2658 setEventMessages($object->error, $object->errors, 'errors');
2659 }
2660 } else {
2661 $numref = (string) $object->ref;
2662 }
2663
2664 $text = $langs->trans('ConfirmValidateOrder', $numref);
2665 if (isModEnabled('notification')) {
2666 require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
2667 $notify = new Notify($db);
2668 $text .= '<br>';
2669 $text .= $notify->confirmMessage('ORDER_VALIDATE', $object->socid, $object);
2670 }
2671
2672 $qualified_for_stock_change = 0;
2673 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2674 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2675 } else {
2676 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2677 }
2678
2679 $formquestion = array();
2680 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
2681 $langs->load("stocks");
2682 $forcecombo = 0;
2683 if ($conf->browser->name == 'ie') {
2684 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2685 }
2686 $formquestion = array(
2687 // 'text' => $langs->trans("ConfirmClone"),
2688 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2689 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2690 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOSTINT('idwarehouse') ? GETPOSTINT('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2691 );
2692 }
2693
2694 // mandatoryPeriod
2695 $nbMandated = 0;
2696 foreach ($object->lines as $line) {
2697 $res = $line->fetch_product();
2698 if ($res > 0) {
2699 if ($line->product->isService() && $line->product->isMandatoryPeriod() && (empty($line->date_start) || empty($line->date_end))) {
2700 $nbMandated++;
2701 break;
2702 }
2703 }
2704 }
2705 if ($nbMandated > 0) {
2706 if (getDolGlobalString('SERVICE_STRICT_MANDATORY_PERIOD')) {
2707 setEventMessages($langs->trans("mandatoryPeriodNeedTobeSetMsgValidate"), null, 'errors');
2708 $error++;
2709 } else {
2710 $text .= '<div><span class="clearboth nowraponall warning">' . img_warning() . $langs->trans("mandatoryPeriodNeedTobeSetMsgValidate") . '</span></div>';
2711 }
2712 }
2713
2714 if (getDolGlobalInt('SALE_ORDER_SUGGEST_DOWN_PAYMENT_INVOICE_CREATION')) {
2715 // This is a hidden option:
2716 // Suggestion to create invoice during order validation is not enabled by default.
2717 // Such choice should be managed by the workflow module and trigger. This option generates conflicts with some setup.
2718 // It may also break step of creating an order when invoicing must be done from proposals and not from orders
2719 $deposit_percent_from_payment_terms = (float) getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
2720
2721 if (!empty($deposit_percent_from_payment_terms) && isModEnabled('invoice') && $user->hasRight('facture', 'creer')) {
2722 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
2723
2724 $object->fetchObjectLinked();
2725
2726 $eligibleForDepositGeneration = true;
2727
2728 if (array_key_exists('facture', $object->linkedObjects)) {
2729 foreach ($object->linkedObjects['facture'] as $invoice) {
2730 '@phan-var-force Facture $invoice';
2731 if ($invoice->type == Facture::TYPE_DEPOSIT) {
2732 $eligibleForDepositGeneration = false;
2733 break;
2734 }
2735 }
2736 }
2737
2738 if ($eligibleForDepositGeneration && array_key_exists('propal', $object->linkedObjects)) {
2739 foreach ($object->linkedObjects['propal'] as $proposal) {
2740 $proposal->fetchObjectLinked();
2741
2742 if (array_key_exists('facture', $proposal->linkedObjects)) {
2743 foreach ($proposal->linkedObjects['facture'] as $invoice) {
2744 '@phan-var-force Facture $invoice';
2745 if ($invoice->type == Facture::TYPE_DEPOSIT) {
2746 $eligibleForDepositGeneration = false;
2747 break 2;
2748 }
2749 }
2750 }
2751 }
2752 }
2753
2754 if ($eligibleForDepositGeneration) {
2755 $formquestion[] = array(
2756 'type' => 'checkbox',
2757 'tdclass' => '',
2758 'name' => 'generate_deposit',
2759 'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
2760 );
2761
2762 $formquestion[] = array(
2763 'type' => 'date',
2764 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2765 'name' => 'datef',
2766 'label' => $langs->trans('DateInvoice'),
2767 'value' => dol_now(),
2768 'datenow' => true
2769 );
2770
2771 if (getDolGlobalString('INVOICE_POINTOFTAX_DATE')) {
2772 $formquestion[] = array(
2773 'type' => 'date',
2774 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2775 'name' => 'date_pointoftax',
2776 'label' => $langs->trans('DatePointOfTax'),
2777 'value' => dol_now(),
2778 'datenow' => true
2779 );
2780 }
2781
2782 $paymentTermsSelect = $form->getSelectConditionsPaiements(0, 'cond_reglement_id', -1, 0, 0, 'minwidth200');
2783
2784 $formquestion[] = array(
2785 'type' => 'other',
2786 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2787 'name' => 'cond_reglement_id',
2788 'label' => $langs->trans('PaymentTerm'),
2789 'value' => $paymentTermsSelect
2790 );
2791
2792 $formquestion[] = array(
2793 'type' => 'checkbox',
2794 'tdclass' => 'showonlyifgeneratedeposit',
2795 'name' => 'validate_generated_deposit',
2796 'label' => $langs->trans('ValidateGeneratedDeposit')
2797 );
2798
2799 $formquestion[] = array(
2800 'type' => 'onecolumn',
2801 'value' => '
2802 <script>
2803 $(document).ready(function() {
2804 $("[name=generate_deposit]").change(function () {
2805 let $self = $(this);
2806 let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
2807
2808 if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
2809 $target.show();
2810 } else {
2811 $target.hide();
2812 }
2813
2814 return true;
2815 });
2816 });
2817 </script>
2818 '
2819 );
2820 }
2821 }
2822 }
2823
2824 if (!$error) {
2825 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('ValidateOrder'), $text, 'confirm_validate', $formquestion, 0, 1, 240);
2826 }
2827 }
2828
2829 // Confirm back to draft status
2830 if ($action == 'modif') {
2831 $qualified_for_stock_change = 0;
2832 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2833 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2834 } else {
2835 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2836 }
2837
2838 $text = $langs->trans('ConfirmUnvalidateOrder', $object->ref);
2839 $formquestion = array();
2840 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
2841 $langs->load("stocks");
2842 $forcecombo = 0;
2843 if ($conf->browser->name == 'ie') {
2844 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2845 }
2846 $formquestion = [
2847 // 'text' => $langs->trans("ConfirmClone"),
2848 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2849 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2850 [
2851 'type' => 'other',
2852 'name' => 'idwarehouse',
2853 'label' => $langs->trans("SelectWarehouseForStockIncrease"),
2854 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ? GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo)
2855 ]
2856 ];
2857 }
2858
2859 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('UnvalidateOrder'), $text, 'confirm_modif', $formquestion, "yes", 1, 220);
2860 }
2861
2862 // Confirmation of closing
2863 if ($action == 'shipped') {
2864 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('CloseOrder'), $langs->trans('ConfirmCloseOrder'), 'confirm_shipped', '', 0, 1);
2865 }
2866
2867 // Confirmation of cancellation
2868 if ($action == 'cancel') {
2869 $qualified_for_stock_change = 0;
2870 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2871 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2872 } else {
2873 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2874 }
2875
2876 $text = $langs->trans('ConfirmCancelOrder', $object->ref);
2877 $formquestion = array();
2878 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
2879 $langs->load("stocks");
2880 $forcecombo = 0;
2881 if ($conf->browser->name == 'ie') {
2882 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2883 }
2884 $formquestion = array(
2885 // 'text' => $langs->trans("ConfirmClone"),
2886 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2887 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2888 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ? GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2889 );
2890 }
2891
2892 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans("Cancel"), $text, 'confirm_cancel', $formquestion, 0, 1);
2893 }
2894
2895 // Confirmation to delete line
2896 if ($action == 'ask_deleteline') {
2897 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2898 }
2899
2900 // Generate form to delete a subtotal line
2901 if ($action == 'ask_subtotal_deleteline') {
2902 $langs->load("subtotals");
2903 $title = "DeleteSubtotalLine";
2904 $question = "ConfirmDeleteSubtotalLine";
2905 if (GETPOST('type') == 'title') {
2906 $formconfirm = array(array('type' => 'checkbox', 'name' => 'deletecorrespondingsubtotalline', 'label' => $langs->trans("DeleteCorrespondingSubtotalLine"), 'value' => 0));
2907 $title = "DeleteTitleLine";
2908 $question = "ConfirmDeleteTitleLine";
2909 }
2910 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans($title), $langs->trans($question), 'confirm_delete_subtotalline', $formconfirm, 'no', 1);
2911 }
2912
2913 // Clone confirmation
2914 if ($action == 'clone') {
2915 $filter = '(s.client:IN:1,2,3)';
2916 // Create an array for form
2917 $formquestion = array(
2918 array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOSTINT('socid'), 'socid', $filter, '', 0, 0, array(), 0, 'maxwidth300'))
2919 );
2920 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2921 }
2922
2923 // Subtotal line form
2924 if ($action == 'add_title_line') {
2925 $langs->load('subtotals');
2926 $type = 'title';
2927 $depth_array = $object->getPossibleLevels($langs);
2928 include DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_create.tpl.php';
2929 } elseif ($action == 'add_subtotal_line') {
2930 $langs->load('subtotals');
2931 $type = 'subtotal';
2932 $titles = $object->getPossibleTitles();
2933 include DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_create.tpl.php';
2934 }
2935
2936 // Call Hook formConfirm
2937 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2938 // Note that $action and $object may be modified by hook
2939 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
2940 if (empty($reshook)) {
2941 $formconfirm .= $hookmanager->resPrint;
2942 } elseif ($reshook > 0) {
2943 $formconfirm = $hookmanager->resPrint;
2944 }
2945
2946 // Print form confirm
2947 print $formconfirm;
2948
2949
2950 // Order card
2951
2952 $linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php?restore_lastsearch_values=1' . (!empty($socid) ? '&socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
2953
2954 $morehtmlref = '<div class="refidno">';
2955 // Ref customer
2956 $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, (int) $usercancreate, 'string', '', 0, 1);
2957 $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, (int) $usercancreate, 'string' . (isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1);
2958 // Thirdparty
2959 $morehtmlref .= '<br>' . $soc->getNomUrl(1, 'customer');
2960 if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
2961 $morehtmlref .= ' (<a href="' . DOL_URL_ROOT . '/commande/list.php?socid=' . $object->thirdparty->id . '&search_societe=' . urlencode($object->thirdparty->name) . '">' . $langs->trans("OtherOrders") . '</a>)';
2962 }
2963 // Project
2964 if (isModEnabled('project')) {
2965 $langs->load("projects");
2966 $morehtmlref .= '<br>';
2967 if ($usercancreate) {
2968 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2969 if ($action != 'classify') {
2970 $morehtmlref .= '<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> ';
2971 }
2972 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
2973 } else {
2974 if (!empty($object->fk_project)) {
2975 $proj = new Project($db);
2976 $proj->fetch($object->fk_project);
2977 $morehtmlref .= $proj->getNomUrl(1);
2978 if ($proj->title) {
2979 $morehtmlref .= '<span class="opacitymedium"> - ' . dol_escape_htmltag($proj->title) . '</span>';
2980 }
2981 }
2982 }
2983 }
2984 $morehtmlref .= '</div>';
2985
2986 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2987
2988 // Call Hook tabContentViewOrder
2989 $parameters = array();
2990 // Note that $action and $object may be modified by hook
2991 $reshook = $hookmanager->executeHooks('tabContentViewOrder', $parameters, $object, $action);
2992 if (empty($reshook)) {
2993 print '<div class="fichecenter">';
2994 print '<div class="fichehalfleft">';
2995 print '<div class="underbanner clearboth"></div>';
2996
2997 print '<table class="border tableforfield centpercent">';
2998
2999 // POS
3000 if (isModEnabled('takepos') || $object->module_source || getDolGlobalString('ORDER_ALLOW_POS_SOURCE_EDIT')) {
3001 $langs->load("cashdesk");
3002 print '<tr><td class="fieldname_type">';
3003 print '<table class="nobordernopadding centpercent"><tr><td>';
3004 print $form->textwithpicto($langs->trans('PointOfSale'), $langs->trans('POSInfo'));
3005 print '</td>';
3006 if ($action != 'editposinfo' && $usercancreate) {
3007 print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editposinfo&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->trans('SetPOSInfo'), 1) . '</a></td>';
3008 }
3009 print '</tr></table>';
3010 print '</td><td class="valuefield fieldname_type">';
3011 print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" name="formposinfo">';
3012 print '<input type="hidden" name="action" value="setposinfo">';
3013 print '<input type="hidden" name="token" value="' . newToken() . '">';
3014 if ($action == 'editposinfo') {
3015 print '<input type="text" class="maxwidth150" name="posmodule" placeholder="' . $langs->trans("POSModule") . '" value="' . $object->module_source . '"> ';
3016 print '<input type="text" class="maxwidth100" name="posterminal" placeholder="' . $langs->trans("Terminal") . '" value="' . $object->pos_source . '">';
3017 print '<input type="submit" class="button" name="submitposinfo" value="' . $langs->trans("Submit") . '">';
3018 } else {
3019 if ($object->module_source) {
3020 print '<span class="opacitymediumbycolor paddingleft">' . dolPrintHTML(ucfirst($object->module_source) . ' - ' . $langs->transnoentitiesnoconv("Terminal") . ' ' . $object->pos_source) . '</span>';
3021 }
3022 }
3023 print '</form>';
3024 print '</td></tr>';
3025 }
3026
3027 if ($soc->outstanding_limit) {
3028 // Outstanding Bill
3029 print '<tr><td class="titlefield">';
3030 print $langs->trans('OutstandingBill');
3031 print '</td><td class="valuefield">';
3032 $arrayoutstandingbills = $soc->getOutstandingBills();
3033 print price($arrayoutstandingbills['opened']) . ' / ';
3034 print price($soc->outstanding_limit, 0, '', 1, -1, -1, $conf->currency);
3035 print '</td>';
3036 print '</tr>';
3037 }
3038
3039 // Relative and absolute discounts
3040 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
3041 $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
3042 $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
3043 } else {
3044 $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
3045 $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
3046 }
3047
3048 $addrelativediscount = '<a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditRelativeDiscounts") . '</a>';
3049 $addabsolutediscount = '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditGlobalDiscounts") . '</a>';
3050 $addcreditnote = '<a href="' . DOL_URL_ROOT . '/compta/facture/card.php?action=create&socid=' . $soc->id . '&type=2&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("AddCreditNote") . '</a>';
3051
3052 print '<tr><td class="titlefield">' . $langs->trans('Discounts') . '</td><td class="valuefield">';
3053
3054 $absolute_discount = $soc->getAvailableDiscounts(null, $filterabsolutediscount);
3055 $absolute_creditnote = $soc->getAvailableDiscounts(null, $filtercreditnote);
3056 $absolute_discount = price2num($absolute_discount, 'MT');
3057 $absolute_creditnote = price2num($absolute_creditnote, 'MT');
3058
3059 $thirdparty = $soc;
3060 $discount_type = 0;
3061 $backtopage = $_SERVER["PHP_SELF"] . '?id=' . $object->id;
3062 include DOL_DOCUMENT_ROOT . '/core/tpl/object_discounts.tpl.php';
3063
3064 print '</td></tr>';
3065
3066 // Date
3067 print '<tr><td>';
3068 $editenable = $usercancreate && $object->status == Commande::STATUS_DRAFT;
3069 print $form->editfieldkey("Date", 'date', '', $object, (int) $editenable);
3070 print '</td><td class="valuefield">';
3071 if ($action == 'editdate') {
3072 print '<form name="setdate" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
3073 print '<input type="hidden" name="token" value="' . newToken() . '">';
3074 print '<input type="hidden" name="action" value="setdate">';
3075 print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
3076 print $form->selectDate($object->date, 'order_', 0, 0, 0, "setdate");
3077 print '<input type="submit" class="button button-edit" value="' . $langs->trans('Modify') . '">';
3078 print '</form>';
3079 } else {
3080 print $object->date ? dol_print_date($object->date, 'day') : '&nbsp;';
3081 if ($object->hasDelay() && empty($object->delivery_date)) { // If there is a delivery date planned, warning should be on this date
3082 print ' ' . img_picto($langs->trans("Late") . ' : ' . $object->showDelay(), "warning");
3083 }
3084 }
3085 print '</td>';
3086 print '</tr>';
3087
3088 // Delivery date planned
3089 print '<tr><td>';
3090 $editenable = $usercancreate;
3091 print $form->editfieldkey("DateDeliveryPlanned", 'date_livraison', '', $object, (int) $editenable);
3092 print '</td><td class="valuefield">';
3093 if ($action == 'editdate_livraison') {
3094 print '<form name="setdate_livraison" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
3095 print '<input type="hidden" name="token" value="' . newToken() . '">';
3096 print '<input type="hidden" name="action" value="setdate_livraison">';
3097 print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
3098 print $form->selectDate($object->delivery_date ? $object->delivery_date : -1, 'liv_', 1, 1, 0, "setdate_livraison", 1, 0);
3099 print '<input type="submit" class="button button-edit" value="' . $langs->trans('Modify') . '">';
3100 print '</form>';
3101 } else {
3102 print $object->delivery_date ? dol_print_date($object->delivery_date, 'dayhour') : '&nbsp;';
3103 if ($object->hasDelay() && !empty($object->delivery_date)) {
3104 print ' ' . img_picto($langs->trans("Late") . ' : ' . $object->showDelay(), "warning");
3105 }
3106 }
3107 // --- SHIPPABLE icon ---
3108 if (isModEnabled('stock') && isModEnabled('shipping') && !getDolGlobalString('ORDER_DISABLE_SHIPPABLE_ICON_ON_CARD') && !empty($object->delivery_date)) {
3109 $shippableInfos = $object->getShippableInfos();
3110
3111 if (!empty($shippableInfos['has_product'])) {
3112 print ' ';
3113 print $form->textwithtooltip('', $shippableInfos['textinfo'], 2, 1, $shippableInfos['texticon'], '', 2);
3114
3115 if (!empty($shippableInfos['warning'])) {
3116 print ' ';
3117 print $form->textwithtooltip('', $langs->trans("NotEnoughForAllOrders"), 2, 1, img_picto('', 'error', '', 0, 0, 0, '', '2'), '', 2);
3118 }
3119 }
3120 }
3121 print '</td>';
3122 print '</tr>';
3123
3124 // Delivery delay
3125 print '<tr class="fielddeliverydelay"><td>';
3126 $editenable = $usercancreate;
3127 print $form->editfieldkey("AvailabilityPeriod", 'availability', '', $object, (int) $editenable);
3128 print '</td><td class="valuefield">';
3129 if ($action == 'editavailability') {
3130 $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->availability_id, 'availability_id', 1);
3131 } else {
3132 $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->availability_id, 'none', 1);
3133 }
3134 print '</td></tr>';
3135
3136 // Shipping Method
3137 if (isModEnabled('shipping')) {
3138 print '<tr><td>';
3139 $editenable = $usercancreate;
3140 print $form->editfieldkey("SendingMethod", 'shippingmethod', '', $object, (int) $editenable);
3141 print '</td><td class="valuefield">';
3142 if ($action == 'editshippingmethod') {
3143 $form->formSelectShippingMethod($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->shipping_method_id, 'shipping_method_id', 1);
3144 } else {
3145 $form->formSelectShippingMethod($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->shipping_method_id, 'none');
3146 }
3147 print '</td>';
3148 print '</tr>';
3149 }
3150
3151 // Warehouse
3152 if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
3153 $langs->load('stocks');
3154 print '<tr><td>';
3155 $editenable = $usercancreate;
3156 print $form->editfieldkey("Warehouse", 'warehouse', '', $object, (int) $editenable);
3157 print '</td><td class="valuefield">';
3158 if ($action == 'editwarehouse') {
3159 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->warehouse_id, 'warehouse_id', 1);
3160 } else {
3161 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->warehouse_id, 'none');
3162 }
3163 print '</td>';
3164 print '</tr>';
3165 }
3166
3167 // Source reason (why we have an order)
3168 print '<tr><td>';
3169 $editenable = $usercancreate;
3170 print $form->editfieldkey("Source", 'demandreason', '', $object, (int) $editenable);
3171 print '</td><td class="valuefield">';
3172 if ($action == 'editdemandreason') {
3173 $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->demand_reason_id, 'demand_reason_id', 1);
3174 } else {
3175 $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->demand_reason_id, 'none');
3176 }
3177 print '</td></tr>';
3178
3179 // Terms of payment
3180 print '<tr><td>';
3181 $editenable = $usercancreate;
3182 print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, (int) $editenable);
3183 print '</td><td class="valuefield">';
3184 if ($action == 'editconditions') {
3185 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
3186 } else {
3187 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent);
3188 }
3189 print '</td>';
3190
3191 print '</tr>';
3192
3193 // Mode of payment
3194 print '<tr><td>';
3195 $editenable = $usercancreate;
3196 print $form->editfieldkey("PaymentMode", 'mode', '', $object, (int) $editenable);
3197 print '</td><td class="valuefield">';
3198 if ($action == 'editmode') {
3199 $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
3200 } else {
3201 $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->mode_reglement_id, 'none');
3202 }
3203 print '</td></tr>';
3204
3205 // TODO Order mode (how we receive order). Not yet implemented
3206 /*
3207 print '<tr><td>';
3208 $editenable = $usercancreate;
3209 print $form->editfieldkey("SourceMode", 'inputmode', '', $object, $editenable);
3210 print '</td><td>';
3211 if ($action == 'editinputmode') {
3212 $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'input_mode_id', 1);
3213 } else {
3214 $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'none');
3215 }
3216 print '</td></tr>';
3217 */
3218
3219 $tmparray = $object->getTotalWeightVolume();
3220 $totalWeight = $tmparray['weight'];
3221 $totalVolume = $tmparray['volume'];
3222 if ($totalWeight) {
3223 print '<tr><td>' . $langs->trans("CalculatedWeight") . '</td>';
3224 print '<td class="valuefield">';
3225 print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, getDolGlobalInt('MAIN_WEIGHT_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_WEIGHT_DEFAULT_UNIT', 'no'));
3226 print '</td></tr>';
3227 }
3228 if ($totalVolume) {
3229 print '<tr><td>' . $langs->trans("CalculatedVolume") . '</td>';
3230 print '<td class="valuefield">';
3231 print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_VOLUME_DEFAULT_UNIT', 'no'));
3232 print '</td></tr>';
3233 }
3234
3235 // TODO How record was recorded OrderMode (llx_c_input_method)
3236
3237 // Incoterms
3238 if (isModEnabled('incoterm')) {
3239 print '<tr><td>';
3240 $editenable = $usercancreate;
3241 print $form->editfieldkey("IncotermLabel", 'incoterm', '', $object, (int) $editenable);
3242 print '</td>';
3243 print '<td class="valuefield">';
3244 if ($action != 'editincoterm') {
3245 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
3246 } else {
3247 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'] . '?id=' . $object->id);
3248 }
3249 print '</td></tr>';
3250 }
3251
3252 // Bank Account
3253 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_ORDER') && isModEnabled("bank")) {
3254 print '<tr><td>';
3255 $editenable = $usercancreate;
3256 print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, (int) $editenable);
3257 print '</td><td class="valuefield">';
3258 if ($action == 'editbankaccount') {
3259 $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_account, 'fk_account', 1);
3260 } else {
3261 $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_account, 'none');
3262 }
3263 print '</td>';
3264 print '</tr>';
3265 }
3266
3267 // Tags-Categories
3268 if (isModEnabled('category')) {
3269 print '<tr><td>';
3270 print '<table class="nobordernopadding centpercent"><tr><td>';
3271 print $langs->trans("Categories");
3272 print '<td><td class="right">';
3273 if ($usercancreate) {
3274 print '<a class="editfielda" href="' . DOL_URL_ROOT . '/commande/card.php?id=' . $object->id . '&action=edittags&token=' . newToken() . '">' . img_edit() . '</a>';
3275 } else {
3276 print '&nbsp;';
3277 }
3278 print '</td></tr></table>';
3279 print '</td>';
3280 print '<td>';
3281 if ($action == 'edittags') {
3282 print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
3283 print '<input type="hidden" name="action" value="settags">';
3284 print '<input type="hidden" name="token" value="' . newToken() . '">';
3285 print $form->selectCategories(Categorie::TYPE_ORDER, 'categories', $object);
3286 print '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
3287 print '</form>';
3288 } else {
3289 print $form->showCategories($object->id, Categorie::TYPE_ORDER, 1);
3290 }
3291 print "</td></tr>";
3292 }
3293
3294 // Other attributes
3295 include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
3296
3297 print '</table>';
3298
3299 print '</div>';
3300 print '<div class="fichehalfright">';
3301 print '<div class="underbanner clearboth"></div>';
3302
3303 print '<table class="border tableforfield centpercent">';
3304
3305 include DOL_DOCUMENT_ROOT . '/core/tpl/object_currency_amount.tpl.php';
3306
3307 $alert = '';
3308 if (getDolGlobalString('ORDER_MANAGE_MIN_AMOUNT') && $object->total_ht < $object->thirdparty->order_min_amount) {
3309 $alert = ' ' . img_warning($langs->trans('OrderMinAmount') . ': ' . price($object->thirdparty->order_min_amount));
3310 }
3311
3312 print '<tr>';
3313 print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
3314 print '<td class="nowrap amountcard right">' . price($object->total_ht, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
3315 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3316 // Multicurrency Amount HT
3317 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3318 }
3319 print '</tr>';
3320
3321 print '<tr>';
3322 print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
3323 print '<td class="nowrap amountcard right">' . price($object->total_tva, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
3324 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3325 // Multicurrency Amount VAT
3326 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3327 }
3328 print '</tr>';
3329
3330 // Amount Local Taxes
3331 if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
3332 print '<tr>';
3333 print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
3334 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
3335 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3336 $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
3337
3338 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax1, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3339 }
3340 print '</tr>';
3341 }
3342
3343 // Amount Local Taxes
3344 if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
3345 print '<tr>';
3346 print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
3347 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
3348 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3349 $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
3350
3351 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax2, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3352 }
3353 print '</tr>';
3354 }
3355
3356 print '<tr>';
3357 print '<td>' . $langs->trans('AmountTTC') . '</td>';
3358 print '<td class="valuefield nowrap right amountcard">' . price($object->total_ttc, 1, '', 1, -1, -1, $conf->currency) . '</td>';
3359 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3360 // Multicurrency Amount TTC
3361 print '<td class="valuefield nowrap right amountcard">' . price($object->multicurrency_total_ttc, 1, '', 1, -1, -1, $object->multicurrency_code) . '</td>';
3362 }
3363 print '</tr>' . "\n";
3364
3365 print '</table>';
3366
3367 // Statut
3368 //print '<tr><td>' . $langs->trans('Status') . '</td><td>' . $object->getLibStatut(4) . '</td></tr>';
3369
3370 // Margin Infos
3371 if (isModEnabled('margin')) {
3372 $formmargin->displayMarginInfos($object);
3373 }
3374
3375
3376 print '</div>';
3377 print '</div>'; // Close fichecenter
3378
3379 print '<div class="clearboth"></div><br>';
3380
3381 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
3382 $blocname = 'contacts';
3383 $title = $langs->trans('ContactsAddresses');
3384 include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
3385 }
3386
3387 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
3388 $blocname = 'notes';
3389 $title = $langs->trans('Notes');
3390 include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
3391 }
3392
3393 /*
3394 * Lines
3395 */
3396
3397 // Get object lines
3398 $result = $object->getLinesArray();
3399
3400 // Add products/services form
3401 //$forceall = 1;
3402 global $inputalsopricewithtax;
3403 $inputalsopricewithtax = 1;
3404
3405 print '<form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="POST">
3406 <input type="hidden" name="token" value="' . newToken() . '">
3407 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline') . '">
3408 <input type="hidden" name="mode" value="">
3409 <input type="hidden" name="page_y" value="">
3410 <input type="hidden" name="id" value="' . $object->id . '">
3411 <input type="hidden" name="backtopage" value="' . $backtopage . '">
3412 ';
3413
3414 if (!empty($conf->use_javascript_ajax) && $object->status == Commande::STATUS_DRAFT) {
3415 if (isModEnabled('subtotals')) {
3416 include DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_ajaxrow.tpl.php';
3417 } else {
3418 include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
3419 }
3420 }
3421
3422 print '<div class="div-table-responsive-no-min">';
3423 print '<table id="tablelines" class="noborder noshadow" width="100%">';
3424
3425 // Show object lines
3426 if (!empty($object->lines)) {
3427 $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
3428 }
3429
3430 /*
3431 * Form to add new line
3432 */
3433 if ($object->status == Commande::STATUS_DRAFT && $usercancreate && $action != 'selectlines') {
3434 if ($action != 'editline') {
3435 // Add free products/services
3436
3437 $parameters = array();
3438 // Note that $action and $object may be modified by hook
3439 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action);
3440 if ($reshook < 0) {
3441 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
3442 }
3443 if (empty($reshook)) {
3444 $object->formAddObjectLine(1, $mysoc, $soc);
3445 }
3446 } else {
3447 $parameters = array();
3448 $reshook = $hookmanager->executeHooks('formEditObjectLine', $parameters, $object, $action);
3449 }
3450 }
3451 print '</table>';
3452 print '</div>';
3453
3454 print "</form>\n";
3455 }
3456
3457 print dol_get_fiche_end();
3458
3459 /*
3460 * Buttons for actions
3461 */
3462 if ($action != 'presend' && $action != 'editline') {
3463 print '<div class="tabsAction">';
3464
3465 $parameters = array();
3466 $arrayforbutaction = array();
3467 // Note that $action and $object may be modified by hook
3468 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
3469 if (empty($reshook)) {
3470 $numlines = count($object->lines);
3471
3472 // Reopen a closed order
3473 if (($object->status == Commande::STATUS_CLOSED || $object->status == Commande::STATUS_CANCELED) && $usercancreate && (!$object->billed || !getDolGlobalInt('ORDER_DONT_REOPEN_BILLED'))) {
3474 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"] . '?action=reopen&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3475 }
3476
3477 // Send
3478 if (empty($user->socid)) {
3479 if ($object->status > Commande::STATUS_DRAFT || getDolGlobalString('COMMANDE_SENDBYEMAIL_FOR_ALL_STATUS')) {
3480 if ($usercansend) {
3481 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER["PHP_SELF"] . '?action=presend&token=' . newToken() . '&id=' . $object->id . '&mode=init#formmailbeforetitle', '');
3482 } else {
3483 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER['PHP_SELF'] . '#', '', false);
3484 }
3485 }
3486 }
3487
3488 // Subtotal
3489 if ($object->status == Commande::STATUS_DRAFT && isModEnabled('subtotals')
3490 && (getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element)) || getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element)))) {
3491 $langs->load('subtotals');
3492
3493 $url_button = array();
3494
3495 $url_button[] = array(
3496 'lang' => 'subtotals',
3497 'enabled' => (isModEnabled('order') && $object->status == Commande::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element))),
3498 'perm' => (bool) $usercancreate,
3499 'label' => $langs->trans('AddTitleLine'),
3500 'url' => '/commande/card.php?id=' . $object->id . '&action=add_title_line&token=' . newToken()
3501 );
3502
3503 $url_button[] = array(
3504 'lang' => 'subtotals',
3505 'enabled' => (isModEnabled('order') && $object->status == Commande::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element))),
3506 'perm' => (bool) $usercancreate,
3507 'label' => $langs->trans('AddSubtotalLine'),
3508 'url' => '/commande/card.php?id=' . $object->id . '&action=add_subtotal_line&token=' . newToken()
3509 );
3510 print dolGetButtonAction('', $langs->trans('Subtotal'), 'default', $url_button, '', true);
3511 }
3512
3513 // Valid
3514 if ($object->status == Commande::STATUS_DRAFT && ($object->total_ttc >= 0 || getDolGlobalString('ORDER_ENABLE_NEGATIVE')) && $usercanvalidate) {
3515 if ($numlines > 0) {
3516 print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"] . '?action=validate&amp;token=' . newToken() . '&amp;id=' . $object->id, (string) $object->id, 1);
3517 } else {
3518 $langs->load("errors");
3519 print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"] . '?action=validate&amp;token=' . newToken() . '&amp;id=' . $object->id, (string) $object->id, -1);
3520 }
3521 }
3522 // Edit
3523 if (($object->status == Commande::STATUS_VALIDATED || ($object->status == Commande::STATUS_SHIPMENTONPROCESS && getDolGlobalString('EDIT_ORDER_SHIPMENT_ON_PROCESS'))) && $usercancreate) {
3524 print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"] . '?action=modif&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3525 }
3526
3527 // Create a purchase order
3528
3529 if (!getDolGlobalInt('COMMANDE_DISABLE_ADD_PURCHASE_ORDER')) {
3530 $arrayforbutaction[] = array(
3531 'lang' => 'orders',
3532 'enabled' => (isModEnabled("supplier_order") && $object->status > Commande::STATUS_DRAFT),
3533 'perm' => $usercancreatepurchaseorder,
3534 'label' => 'AddPurchaseOrder',
3535 'url' => '/fourn/commande/card.php?action=create&amp;origin=' . urlencode($object->element) . '&amp;originid=' . ((int) $object->id)
3536 );
3537 }
3538
3539 /*if (isModEnabled("supplier_order") && $object->status > Commande::STATUS_DRAFT && $object->getNbOfServicesLines() > 0) {
3540 if ($usercancreatepurchaseorder) { isModEnabled("supplier_order") && $object->status > Commande::STATUS_DRAFT && $object->getNbOfServicesLines() > 0
3541 print dolGetButtonAction('', $langs->trans('AddPurchaseOrder'), 'default', DOL_URL_ROOT.'/fourn/commande/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id, '');
3542 }
3543 }*/
3544
3545 // Create intervention
3546 if (!getDolGlobalInt('COMMANDE_DISABLE_ADD_INTERVENTION')) {
3547 $arrayforbutaction[] = array(
3548 'lang' => 'interventions',
3549 'enabled' => (isModEnabled("intervention") && $object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0),
3550 'perm' => ($user->hasRight('ficheinter', 'creer') == 1),
3551 'label' => 'AddIntervention',
3552 'url' => '/fichinter/card.php?action=create&origin=' . urlencode($object->element) . '&originid=' . ((int) $object->id) . '&socid=' . ((int) $object->socid),
3553 );
3554 }
3555
3556 // Create contract
3557 if (!getDolGlobalInt('COMMANDE_DISABLE_ADD_CONTRACT')) {
3558 $arrayforbutaction[] = [
3559 'lang' => 'contracts',
3560 'enabled' => (isModEnabled("contract") && ($object->status == Commande::STATUS_VALIDATED || $object->status == Commande::STATUS_SHIPMENTONPROCESS || $object->status == Commande::STATUS_CLOSED)),
3561 'perm' => ($user->hasRight('contrat', 'creer') == 1),
3562 'label' => 'AddContract',
3563 'url' => '/contrat/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid,
3564 ];
3565 }
3566 /*if (isModEnabled('contract') && ($object->status == Commande::STATUS_VALIDATED || $object->status == Commande::STATUS_SHIPMENTONPROCESS || $object->status == Commande::STATUS_CLOSED)) {
3567 $langs->load("contracts");
3568
3569 if ($user->hasRight('contrat', 'creer')) {
3570 print dolGetButtonAction('', $langs->trans('AddContract'), 'default', DOL_URL_ROOT.'/contrat/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
3571 }
3572 }*/
3573
3574 $numshipping = 0;
3575
3576 // Create shipment
3577 if (isModEnabled('shipping')) {
3578 $numshipping = $object->countNbOfShipments();
3579
3580 if ($object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3581 if ((getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION') && $user->hasRight('expedition', 'creer')) || (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') && $user->hasRight('expedition', 'delivery', 'creer'))) {
3582 // Add button to create shipment into the combo
3583 $arrayforbutaction[] = array(
3584 'lang' => 'sendings',
3585 'enabled' => (isModEnabled("shipping") && ($object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || getDolGlobalString('STOCK_SUPPORTS_SERVICES')))),
3586 'perm' => $user->hasRight('expedition', 'creer'),
3587 'label' => 'CreateShipment',
3588 'url' => '/expedition/shipment.php?id=' . $object->id
3589 );
3590 } else {
3591 //c$langs->load("errors");
3592 //print dolGetButtonAction($langs->trans('ErrorModuleSetupNotComplete'), $langs->trans('CreateShipment'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
3593 $arrayforbutaction[] = array(
3594 'lang' => 'sendings',
3595 'enabled' => (isModEnabled("shipping") && ($object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || getDolGlobalString('STOCK_SUPPORTS_SERVICES')))),
3596 'perm' => 0,
3597 'label' => 'CreateShipment',
3598 'url' => '/expedition/shipment.php?id=' . $object->id
3599 );
3600 }
3601 }
3602 }
3603
3604 // Create bill
3605 $arrayforbutaction[] = array(
3606 'lang' => 'bills',
3607 'enabled' => (isModEnabled('invoice') && $object->status > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0),
3608 'perm' => ($user->hasRight('facture', 'creer') && !getDolGlobalInt('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')),
3609 'label' => 'CreateBill',
3610 'url' => '/compta/facture/card.php?action=create&amp;token=' . newToken() . '&amp;origin=' . urlencode($object->element) . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid
3611 );
3612 /*
3613 if (isModEnabled('facture') && $object->status > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) {
3614 if (isModEnabled('facture') && $user->hasRight('facture', 'creer') && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) {
3615 print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT.'/compta/facture/card.php?action=create&amp;token='.newToken().'&amp;origin='.urlencode($object->element).'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
3616 }
3617 }*/
3618
3619 $actionButtonsParameters = [
3620 "areDropdownButtons" => !getDolGlobalInt("MAIN_REMOVE_DROPDOWN_CREATE_BUTTONS_ON_ORDER")
3621 ];
3622
3623 if ($numlines > 0) {
3624 print dolGetButtonAction('', $langs->trans("Create"), 'default', $arrayforbutaction, (string) $object->id, 1, $actionButtonsParameters);
3625 } else {
3626 print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans("Create"), 'default', $arrayforbutaction, (string) $object->id, 0, $actionButtonsParameters);
3627 }
3628
3629 // Set to shipped
3630 if (($object->status == Commande::STATUS_VALIDATED || $object->status == Commande::STATUS_SHIPMENTONPROCESS) && $usercanclose) {
3631 print dolGetButtonAction('', $langs->trans('ClassifyShipped'), 'default', $_SERVER["PHP_SELF"] . '?action=shipped&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3632 }
3633
3634 // Set billed or unbilled
3635 // Note: Even if module invoice is not enabled, we should be able to use button "Classified billed"
3636 if ($object->status > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) {
3637 if ($usercancreate && $object->status >= Commande::STATUS_VALIDATED && !getDolGlobalString('ORDER_DISABLE_CLASSIFY_BILLED_FROM_ORDER') && !getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')) {
3638 print dolGetButtonAction('', $langs->trans('ClassifyBilled'), 'default', $_SERVER["PHP_SELF"] . '?action=classifybilled&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3639 }
3640 }
3641 if ($object->status > Commande::STATUS_DRAFT && $object->billed) {
3642 if ($usercancreate && $object->status >= Commande::STATUS_VALIDATED && !getDolGlobalString('ORDER_DISABLE_CLASSIFY_BILLED_FROM_ORDER') && !getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')) {
3643 print dolGetButtonAction('', $langs->trans('ClassifyUnBilled'), 'delete', $_SERVER["PHP_SELF"] . '?action=classifyunbilled&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3644 }
3645 }
3646
3647 // Clone
3648 if ($usercancreate) {
3649 print dolGetButtonAction('', $langs->trans('ToClone'), 'clone', $_SERVER["PHP_SELF"] . '?action=clone&token=' . newToken() . '&id=' . $object->id . '&socid=' . $object->socid, '');
3650 }
3651
3652 // Cancel order
3653 if ($object->status == Commande::STATUS_VALIDATED && !empty($usercancancel)) {
3654 print '<a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=cancel&token=' . newToken() . '">' . $langs->trans("CancelOrder") . '</a>';
3655 }
3656
3657 // Delete order
3658 if ($usercandelete) {
3659 if ($numshipping == 0) {
3660 print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"] . '?action=delete&token=' . newToken() . '&id=' . $object->id, '');
3661 } else {
3662 print dolGetButtonAction($langs->trans('ShippingExist'), $langs->trans('Delete'), 'default', $_SERVER['PHP_SELF'] . '#', '', false);
3663 }
3664 }
3665 }
3666 print '</div>';
3667 }
3668
3669 // Select mail models is same action as presend
3670 if (GETPOST('modelselected')) {
3671 $action = 'presend';
3672 }
3673
3674 if ($action != 'presend') {
3675 print '<div class="fichecenter"><div class="fichehalfleft">';
3676 print '<a name="builddoc"></a>'; // ancre
3677 // Documents
3678 $objref = dol_sanitizeFileName($object->ref);
3679 $relativepath = $objref . '/' . $objref . '.pdf';
3680 $filedir = $conf->commande->multidir_output[$object->entity ?? $conf->entity] . '/' . $objref;
3681 $urlsource = dolBuildUrl($_SERVER["PHP_SELF"], ["id" => $object->id]);
3682 $genallowed = $usercanread;
3683 $delallowed = $usercancreate;
3684 $tooltipAfterComboOfModels = '';
3685 if (getDolGlobalString('MAIN_PDF_ADD_TERMSOFSALE_ORDER')) {
3686 $tooltipAfterComboOfModels = $langs->trans("AccordingToYourSetupTheFileWillBeConcatenated", getDolGlobalString('MAIN_INFO_ORDER_TERMSOFSALE'));
3687 }
3688
3689 print $formfile->showdocuments('commande', $objref, $filedir, $urlsource, $genallowed, (int) $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang, '', $object, 0, 'remove_file', $tooltipAfterComboOfModels);
3690
3691
3692 // Show links to link elements
3693 $tmparray = $form->showLinkToObjectBlock($object, array(), array('order'), 1);
3694 $linktoelem = $tmparray['linktoelem'];
3695 $htmltoenteralink = $tmparray['htmltoenteralink'];
3696 print $htmltoenteralink;
3697
3698 $compatibleImportElementsList = false;
3699 if (
3700 $usercancreate
3701 && $object->status == Commande::STATUS_DRAFT
3702 ) {
3703 $compatibleImportElementsList = array('commande', 'propal', 'facture', 'subscription'); // import from linked elements
3704 }
3705 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
3706
3707 // Show online payment link
3708 // The list can be complete by the hook 'doValidatePayment' executed inside getValidOnlinePaymentMethods()
3709 include_once DOL_DOCUMENT_ROOT . '/core/lib/payments.lib.php';
3710 $validpaymentmethod = getValidOnlinePaymentMethods('');
3711 $useonlinepayment = count($validpaymentmethod);
3712
3713 if (getDolGlobalString('ORDER_HIDE_ONLINE_PAYMENT_ON_ORDER')) {
3714 $useonlinepayment = 0;
3715 }
3716 if ($object->status != Commande::STATUS_DRAFT && $useonlinepayment) {
3717 print '<br><!-- Link to pay -->';
3718 require_once DOL_DOCUMENT_ROOT . '/core/lib/payments.lib.php';
3719 print showOnlinePaymentUrl('order', $object->ref) . '<br>';
3720 }
3721
3722 print '</div><div class="fichehalfright">';
3723
3724 $MAXEVENT = 10;
3725
3726 //button to go to messaging from the events box
3727 $morehtmlcenter = dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', dolBuildUrl(DOL_URL_ROOT . '/commande/messaging.php', ['id' => $object->id]));
3728 $morehtmlcenter .= dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dolBuildUrl(DOL_URL_ROOT . '/commande/agenda.php', ['id' => $object->id]));
3729
3730 // List of actions on element
3731 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
3732 $formactions = new FormActions($db);
3733 $somethingshown = $formactions->showactions($object, 'order', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter); // Show all action for thirdparty
3734
3735 print '</div></div>';
3736 }
3737
3738 // Presend form
3739 $modelmail = 'order_send';
3740 $defaulttopic = 'SendOrderRef';
3741 $diroutput = getMultidirOutput($object);
3742 $trackid = 'ord' . $object->id;
3743
3744 include DOL_DOCUMENT_ROOT . '/core/tpl/card_presend.tpl.php';
3745 }
3746}
3747
3748// End of page
3749llxFooter();
3750$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage customers orders.
const STATUS_SHIPMENTONPROCESS
Shipment on process.
const STATUS_CLOSED
Closed (Sent, billed or not)
const STATUS_CANCELED
Canceled status.
const STATUS_DRAFT
Draft status.
const STATUS_VALIDATED
Validated status.
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
static createDepositFromOrigin(CommonObject $origin, $date, $payment_terms_id, User $user, $notrigger=0, $autoValidateDeposit=false, $overrideFields=array())
Creates a deposit from a proposal or an order by grouping lines by VAT rates.
const TYPE_DEPOSIT
Deposit invoice.
Class to manage building of HTML components.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class to manage "other" html components Only common components are here.
Class to manage HTML output components for orders Before adding component here, check they are not in...
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 the table of subscription to notifications.
Class ProductCombination Used to represent the relation between a product and one of its variants.
File of class to manage predefined price products or services by customer.
Class to manage products or services.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
global $mysoc
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.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
$date_start
Variables from include:
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dolPrintHTML($s, $allowiframe=0, $moreallowedtags=array())
Return a string (that can be on several lines) ready to be output on a HTML page.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
getMultidirOutput($object, $module='', $forobject=0, $mode='output')
Return the full path of the directory where a module (or an object of a module) stores its files.
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular VAT rate, when selling a product with vat $vatrate,...
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...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
commande_prepare_head(Commande $object)
Prepare array with list of tabs.
Definition order.lib.php:36
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.