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