dolibarr 24.0.1
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$result = restrictedArea($user, 'commande', $id);
144
145$object = new Commande($db);
146
147// fetch optionals attributes and labels
148$extrafields->fetch_name_optionals_label($object->table_element);
149
150// Load object
151include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
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 ($prod->prices_by_qty[$object->thirdparty->price_level]) { // yes, this product has some prices per quantity
1229 // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
1230 $pqp = GETPOSTINT('pbq');
1231 // Search price into product_price_by_qty from $prod->id
1232 foreach ($prod->prices_by_qty_list[$object->thirdparty->price_level] as $priceforthequantityarray) {
1233 if ($priceforthequantityarray['rowid'] != $pqp) {
1234 continue;
1235 }
1236 // We found the price
1237 if ($priceforthequantityarray['price_base_type'] == 'HT') {
1238 $pu_ht = $priceforthequantityarray['unitprice'];
1239 } else {
1240 $pu_ttc = $priceforthequantityarray['unitprice'];
1241 }
1242 // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
1243 break;
1244 }
1245 }
1246 }
1247
1248 $tmpvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
1249 $tmpprodvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', (string) $prod->tva_tx));
1250
1251 // Set unit price to use
1252 if (!empty($price_ht) || (string) $price_ht === '0') {
1253 $pu_ht = (float) price2num($price_ht, 'MU');
1254 $pu_ttc = (float) price2num((float) $pu_ht * (1 + ((float) $tmpvat / 100)), 'MU');
1255 } elseif (!empty($price_ht_devise) || (string) $price_ht_devise === '0') {
1256 $pu_ht_devise = price2num($price_ht_devise, 'MU');
1257 $pu_ttc_devise = (float) price2num((float) $pu_ht_devise * (1 + ((float) $tmpvat / 100)), 'MU');
1258 $pu_ht = '';
1259 $pu_ttc = '';
1260 } elseif (!empty($price_ttc) || (string) $price_ttc === '0') {
1261 $pu_ttc = (float) price2num($price_ttc, 'MU');
1262 $pu_ht = (float) price2num((float) $pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU');
1263 } elseif (!empty($price_ttc_devise) || (string) $price_ttc_devise === '0') {
1264 $pu_ttc_devise = (float) price2num($price_ttc_devise, 'MU');
1265 $pu_ht_devise = (float) price2num((float) $pu_ttc_devise / (1 + ((float) $tmpvat / 100)), 'MU');
1266 $pu_ht = '';
1267 $pu_ttc = '';
1268 } elseif ($tmpvat != $tmpprodvat) {
1269 // Is this still used ?
1270 if ($price_base_type != 'HT') {
1271 $pu_ht = (float) price2num((float) $pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU');
1272 } else {
1273 $pu_ttc = (float) price2num((float) $pu_ht * (1 + ((float) $tmpvat / 100)), 'MU');
1274 }
1275 }
1276
1277 $desc = '';
1278
1279 // Define output language
1280 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1281 $outputlangs = $langs;
1282 $newlang = '';
1283 if (/* empty($newlang) && */GETPOST('lang_id', 'aZ09')) {
1284 $newlang = GETPOST('lang_id', 'aZ09');
1285 }
1286 if (empty($newlang)) {
1287 $newlang = $object->thirdparty->default_lang;
1288 }
1289 if (!empty($newlang)) {
1290 $outputlangs = new Translate("", $conf);
1291 $outputlangs->setDefaultLang($newlang);
1292 }
1293
1294 $desc = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
1295 } else {
1296 $desc = $prod->description;
1297 }
1298
1299 if (getDolGlobalInt('PRODUIT_AUTOFILL_DESC') == 0) {
1300 // 'DoNotAutofillButAutoConcat'
1301 $desc = dol_concatdesc($desc, $line_desc, false, getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION') ? true : false);
1302 } else {
1303 //'AutoFillFormFieldBeforeSubmit' or 'DoNotUseDescriptionOfProdut' => User has already done the modification they want
1304 $desc = $line_desc;
1305 }
1306
1307 // Add custom code and origin country into description
1308 if (!getDolGlobalString('MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE') && (!empty($prod->customcode) || !empty($prod->country_code))) {
1309 $tmptxt = '(';
1310 // Define output language
1311 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1312 $outputlangs = $langs;
1313 $newlang = '';
1314 if (/* empty($newlang) && */GETPOST('lang_id', 'alpha')) {
1315 $newlang = GETPOST('lang_id', 'alpha');
1316 }
1317 if (empty($newlang)) {
1318 $newlang = $object->thirdparty->default_lang;
1319 }
1320 if (!empty($newlang)) {
1321 $outputlangs = new Translate("", $conf);
1322 $outputlangs->setDefaultLang($newlang);
1323 $outputlangs->load('products');
1324 }
1325 if (!empty($prod->customcode)) {
1326 $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomsCode") . ': ' . $prod->customcode;
1327 }
1328 if (!empty($prod->customcode) && !empty($prod->country_code)) {
1329 $tmptxt .= ' - ';
1330 }
1331 if (!empty($prod->country_code)) {
1332 $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, '', $db, $outputlangs, 0);
1333 }
1334 } else {
1335 if (!empty($prod->customcode)) {
1336 $tmptxt .= $langs->transnoentitiesnoconv("CustomsCode") . ': ' . $prod->customcode;
1337 }
1338 if (!empty($prod->customcode) && !empty($prod->country_code)) {
1339 $tmptxt .= ' - ';
1340 }
1341 if (!empty($prod->country_code)) {
1342 $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, '', $db, $langs, 0);
1343 }
1344 }
1345 $tmptxt .= ')';
1346 $desc = dol_concatdesc($desc, $tmptxt);
1347 }
1348
1349 $type = $prod->type;
1350 $fk_unit = $prod->fk_unit;
1351 } else {
1352 $pu_ht = price2num($price_ht, 'MU');
1353 $pu_ttc = price2num($price_ttc, 'MU');
1354 $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
1355 $tva_tx = str_replace('*', '', $tva_tx);
1356 if (empty($tva_tx)) {
1357 $tva_npr = 0;
1358 }
1359 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1360 $desc = $line_desc;
1361 $type = GETPOST('type');
1362 $fk_unit = GETPOST('units', 'alpha');
1363 $pu_ht_devise = price2num($price_ht_devise, 'MU');
1364 $pu_ttc_devise = price2num($price_ttc_devise, 'MU');
1365
1366 if ($pu_ttc && !$pu_ht) {
1367 $price_base_type = 'TTC';
1368 }
1369 }
1370
1371 $info_bits = 0;
1372 if ($tva_npr) {
1373 $info_bits |= 0x01;
1374 }
1375
1376 // Local Taxes
1377 $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
1378 $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
1379
1380 // Margin
1381 $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
1382 $buyingprice = price2num((GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''), '', 2); // If buying_price is '0', we must keep this value
1383
1384 // Prepare a price equivalent for minimum price check
1385 $pu_equivalent = $pu_ht;
1386 $pu_equivalent_ttc = $pu_ttc;
1387
1388 $currency_tx = $object->multicurrency_tx;
1389
1390 // Check if we have a foreign currency
1391 // If so, we update the pu_equiv as the equivalent price in base currency
1392 if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1393 $pu_equivalent = (float) $pu_ht_devise / (float) $currency_tx;
1394 }
1395 if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1396 $pu_equivalent_ttc = (float) $pu_ttc_devise / (float) $currency_tx;
1397 }
1398
1399 // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
1400 /*
1401 if ($pu_equivalent) {
1402 $tmp = calcul_price_total(1, $pu_equivalent, 0, $tva_tx, -1, -1, 0, 'HT', $info_bits, $type);
1403 $pu_equivalent_ttc = ...
1404 } else {
1405 $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $tva_tx, -1, -1, 0, 'TTC', $info_bits, $type);
1406 $pu_equivalent_ht = ...
1407 }
1408 */
1409
1410 //var_dump(price2num($price_min)); var_dump(price2num($pu_ht)); var_dump($remise_percent);
1411 //var_dump(price2num($price_min_ttc)); var_dump(price2num($pu_ttc)); var_dump($remise_percent);exit;
1412
1413 $desc = dol_htmlcleanlastbr($desc);
1414
1415 // Check price is not lower than minimum
1416 if ($usermustrespectpricemin) {
1417 if ($pu_equivalent && $price_min && (((float) price2num($pu_equivalent) * (1 - $remise_percent / 100)) < (float) price2num($price_min)) && $price_base_type == 'HT') {
1418 $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1419 setEventMessages($mesg, null, 'errors');
1420 $error++;
1421 } 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') {
1422 $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1423 setEventMessages($mesg, null, 'errors');
1424 $error++;
1425 }
1426 }
1427
1428 if (!$error) {
1429 // Insert line
1430 $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);
1431
1432 if ($result > 0) {
1433 $db->commit();
1434
1435 $ret = $object->fetch($object->id); // Reload to get new records
1436 if ($ret > 0) {
1437 $object->fetch_thirdparty();
1438 }
1439
1440 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1441 // Define output language
1442 $outputlangs = $langs;
1443 $newlang = GETPOST('lang_id', 'alpha');
1444 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1445 $newlang = $object->thirdparty->default_lang;
1446 }
1447 if (!empty($newlang)) {
1448 $outputlangs = new Translate("", $conf);
1449 $outputlangs->setDefaultLang($newlang);
1450 }
1451
1452 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1453 }
1454
1455 unset($_POST['prod_entry_mode']);
1456
1457 unset($_POST['qty']);
1458 unset($_POST['type']);
1459 unset($_POST['remise_percent']);
1460 unset($_POST['price_ht']);
1461 unset($_POST['multicurrency_price_ht']);
1462 unset($_POST['price_ttc']);
1463 unset($_POST['tva_tx']);
1464 unset($_POST['product_ref']);
1465 unset($_POST['product_label']);
1466 unset($_POST['product_desc']);
1467 unset($_POST['fournprice']);
1468 unset($_POST['buying_price']);
1469 unset($_POST['np_marginRate']);
1470 unset($_POST['np_markRate']);
1471 unset($_POST['dp_desc']);
1472 unset($_POST['idprod']);
1473 unset($_POST['units']);
1474
1475 unset($_POST['date_starthour']);
1476 unset($_POST['date_startmin']);
1477 unset($_POST['date_startsec']);
1478 unset($_POST['date_startday']);
1479 unset($_POST['date_startmonth']);
1480 unset($_POST['date_startyear']);
1481 unset($_POST['date_endhour']);
1482 unset($_POST['date_endmin']);
1483 unset($_POST['date_endsec']);
1484 unset($_POST['date_endday']);
1485 unset($_POST['date_endmonth']);
1486 unset($_POST['date_endyear']);
1487 } else {
1488 $db->rollback();
1489
1490 setEventMessages($object->error, $object->errors, 'errors');
1491 }
1492 }
1493 }
1494 } elseif ($action == 'updatetitleline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1495 // Handling updating a title line for subtotals module
1496
1497 $langs->load('subtotals');
1498
1499 $desc = GETPOST('line_desc', 'alphanohtml') ?? $langs->trans("Title");
1500 $depth = GETPOSTINT('line_depth') ?? 1;
1501
1502 $subtotal_options = array();
1503
1504 foreach (Commande::$TITLE_OPTIONS as $option) {
1505 $value = GETPOST($option, 'alphanohtml');
1506 if ($value) {
1507 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1508 }
1509 }
1510
1511 // Update line
1512 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1513
1514 if ($result >= 0) {
1515 if ($result == 0) {
1516 setEventMessages($object->error, $object->errors, 'warnings');
1517 }
1518 $ret = $object->fetch($object->id); // Reload to get new records
1519 $object->fetch_thirdparty();
1520
1521 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1522 // Define output language
1523 $outputlangs = $langs;
1524 $newlang = GETPOST('lang_id', 'alpha');
1525 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1526 $newlang = $object->thirdparty->default_lang;
1527 }
1528 if (!empty($newlang)) {
1529 $outputlangs = new Translate("", $conf);
1530 $outputlangs->setDefaultLang($newlang);
1531 }
1532
1533 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1534 }
1535 } else {
1536 setEventMessages($object->error, $object->errors, 'errors');
1537 }
1538 } elseif ($action == 'updatesubtotalline' && GETPOSTISSET("save") && $usercancreate && !GETPOST('cancel', 'alpha')) {
1539 // Handling updating a subtotal line for subtotals module
1540
1541 $langs->load('subtotals');
1542
1543 $desc = GETPOST('line_desc', 'alphanohtml');
1544 $depth = GETPOSTINT('line_depth');
1545
1546 $subtotal_options = array();
1547
1548 foreach (Commande::$SUBTOTAL_OPTIONS as $option) {
1549 $value = GETPOST($option, 'alphanohtml');
1550 if ($value) {
1551 $subtotal_options[$option] = $value == 'on' ? 1 : $value;
1552 }
1553 }
1554
1555 // Update line
1556 $result = $object->updateSubtotalLine($langs, GETPOSTINT('lineid'), $desc, $depth, $subtotal_options);
1557
1558 if ($result > 0) {
1559 $ret = $object->fetch($object->id); // Reload to get new records
1560 $object->fetch_thirdparty();
1561
1562 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1563 // Define output language
1564 $outputlangs = $langs;
1565 $newlang = GETPOST('lang_id', 'alpha');
1566 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1567 $newlang = $object->thirdparty->default_lang;
1568 }
1569 if (!empty($newlang)) {
1570 $outputlangs = new Translate("", $conf);
1571 $outputlangs->setDefaultLang($newlang);
1572 }
1573
1574 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1575 }
1576 } else {
1577 setEventMessages($object->error, $object->errors, 'errors');
1578 }
1579 } elseif ($action == 'updateline' && $usercancreate && GETPOST('save')) {
1580 // Update a line
1581
1582 // Clean parameters
1583 $date_start = '';
1584 $date_end = '';
1585 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), GETPOSTINT('date_startsec'), GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
1586 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), GETPOSTINT('date_endsec'), GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
1587
1588 $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml'));
1589
1590 // Define info_bits
1591 $info_bits = 0;
1592 if (preg_match('/\*/', GETPOST('tva_tx'))) {
1593 $info_bits |= 0x01;
1594 }
1595
1596 // Define vat_rate
1597 $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx', 'alpha') : 0);
1598 $vat_rate = str_replace('*', '', $vat_rate);
1599 $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
1600 $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
1601 $pu_ht = price2num(GETPOST('price_ht'), '', 2);
1602 $pu_ttc = price2num(GETPOST('price_ttc'), '', 2);
1603
1604 $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
1605 $pu_ttc_devise = price2num(GETPOST('multicurrency_subprice_ttc'), '', 2);
1606
1607 $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1608
1609 // Prepare a price equivalent for minimum price check
1610 $pu_equivalent = $pu_ht;
1611 $pu_equivalent_ttc = $pu_ttc;
1612
1613 $currency_tx = $object->multicurrency_tx;
1614
1615 // Check if we have a foreign currency
1616 // If so, we update the pu_equiv as the equivalent price in base currency
1617 if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1618 $pu_equivalent = (float) $pu_ht_devise / (float) $currency_tx;
1619 }
1620 if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '' && !empty((float) $currency_tx)) {
1621 $pu_equivalent_ttc = (float) $pu_ttc_devise / (float) $currency_tx;
1622 }
1623
1624 // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
1625 /*
1626 if ($pu_equivalent) {
1627 $tmp = calcul_price_total(1, $pu_equivalent, 0, $vat_rate, -1, -1, 0, 'HT', $info_bits, $type);
1628 $pu_equivalent_ttc = ...
1629 } else {
1630 $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $vat_rate, -1, -1, 0, 'TTC', $info_bits, $type);
1631 $pu_equivalent_ht = ...
1632 }
1633 */
1634
1635 // Add buying price
1636 $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
1637 $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we must keep this value
1638
1639 // Extrafields Lines
1640 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1641 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
1642 // Unset extrafield POST Data
1643 if (is_array($extralabelsline)) {
1644 foreach ($extralabelsline as $key => $value) {
1645 unset($_POST["options_" . $key]);
1646 }
1647 }
1648
1649 // Define special_code for special lines
1650 $special_code = GETPOSTINT('special_code');
1651 if (!GETPOST('qty')) {
1652 $special_code = 3;
1653 }
1654
1655 $remise_percent = GETPOST('remise_percent') != '' ? price2num(GETPOST('remise_percent'), '', 2) : 0;
1656
1657 $pu = $pu_ht;
1658 $price_base_type = 'HT';
1659 if (empty($pu) && !empty($pu_ttc)) {
1660 $pu = $pu_ttc;
1661 $price_base_type = 'TTC';
1662 }
1663
1664 // Check minimum price
1665 $productid = GETPOSTINT('productid');
1666 if (!empty($productid)) {
1667 $product = new Product($db);
1668 $product->fetch($productid);
1669
1670 $type = $product->type;
1671
1672 $price_min = $product->price_min;
1673 if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($object->thirdparty->price_level)) {
1674 $price_min = $product->multiprices_min[$object->thirdparty->price_level];
1675 }
1676 $price_min_ttc = $product->price_min_ttc;
1677 if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($object->thirdparty->price_level)) {
1678 $price_min_ttc = $product->multiprices_min_ttc[$object->thirdparty->price_level];
1679 }
1680
1681 $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
1682
1683 // Check price is not lower than minimum
1684 if ($usermustrespectpricemin) {
1685 if ($pu_equivalent && $price_min && (((float) price2num($pu_equivalent) * (1 - (float) $remise_percent / 100)) < (float) price2num($price_min)) && $price_base_type == 'HT') {
1686 $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1687 setEventMessages($mesg, null, 'errors');
1688 $error++;
1689 $action = 'editline';
1690 } 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') {
1691 $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1692 setEventMessages($mesg, null, 'errors');
1693 $error++;
1694 $action = 'editline';
1695 }
1696 }
1697 } else {
1698 $type = GETPOST('type');
1699 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1700
1701 // Check parameters
1702 if (GETPOST('type') < 0) {
1703 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1704 $error++;
1705 $action = 'editline';
1706 }
1707 }
1708
1709 if ($qty < 0 && !getDolGlobalString('ORDER_ENABLE_NEGATIVE_QTY')) {
1710 setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1711 $error++;
1712 $action = 'editline';
1713 }
1714
1715 $object->loadExpeditions();
1716 if (isset($object->expeditions[GETPOST('lineid', 'int')])) {
1717 if ($qty < $object->expeditions[GETPOST('lineid', 'int')]) {
1718 setEventMessages($langs->trans('ErrorQtyOrderedLessQtyShipped'), null, 'errors');
1719 $error++;
1720 $action = 'editline';
1721 }
1722 }
1723
1724 if (!$error) {
1725 $db->begin();
1726
1727 if (!$user->hasRight('margins', 'creer')) {
1728 foreach ($object->lines as &$line) {
1729 if ($line->id == GETPOSTINT('lineid')) {
1730 $fournprice = $line->fk_fournprice;
1731 $buyingprice = $line->pa_ht;
1732 break;
1733 }
1734 }
1735 }
1736
1737 $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);
1738
1739
1740 if ($result >= 0) {
1741 $db->commit();
1742
1743 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1744 // Define output language
1745 $outputlangs = $langs;
1746 $newlang = '';
1747 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1748 $newlang = GETPOST('lang_id', 'aZ09');
1749 }
1750 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1751 $newlang = $object->thirdparty->default_lang;
1752 }
1753 if (!empty($newlang)) {
1754 $outputlangs = new Translate("", $conf);
1755 $outputlangs->setDefaultLang($newlang);
1756 }
1757
1758 $ret = $object->fetch($object->id); // Reload to get new records
1759 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1760 }
1761
1762 unset($_POST['qty']);
1763 unset($_POST['type']);
1764 unset($_POST['productid']);
1765 unset($_POST['remise_percent']);
1766 unset($_POST['price_ht']);
1767 unset($_POST['multicurrency_price_ht']);
1768 unset($_POST['price_ttc']);
1769 unset($_POST['tva_tx']);
1770 unset($_POST['product_ref']);
1771 unset($_POST['product_label']);
1772 unset($_POST['product_desc']);
1773 unset($_POST['fournprice']);
1774 unset($_POST['buying_price']);
1775
1776 unset($_POST['date_starthour']);
1777 unset($_POST['date_startmin']);
1778 unset($_POST['date_startsec']);
1779 unset($_POST['date_startday']);
1780 unset($_POST['date_startmonth']);
1781 unset($_POST['date_startyear']);
1782 unset($_POST['date_endhour']);
1783 unset($_POST['date_endmin']);
1784 unset($_POST['date_endsec']);
1785 unset($_POST['date_endday']);
1786 unset($_POST['date_endmonth']);
1787 unset($_POST['date_endyear']);
1788 } else {
1789 $db->rollback();
1790
1791 setEventMessages($object->error, $object->errors, 'errors');
1792 }
1793 }
1794 } elseif ($action == 'updateline' && $usercancreate && GETPOST('cancel', 'alpha')) {
1795 header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // To re-display card in edit mode
1796 exit();
1797 } elseif ($action == 'confirm_validate' && $confirm == 'yes' && $usercanvalidate) {
1798 $idwarehouse = GETPOSTINT('idwarehouse');
1799
1800 $qualified_for_stock_change = 0;
1801 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1802 $qualified_for_stock_change = $object->hasProductsOrServices(2);
1803 } else {
1804 $qualified_for_stock_change = $object->hasProductsOrServices(1);
1805 }
1806
1807 // Check parameters
1808 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
1809 if (!$idwarehouse || $idwarehouse == -1) {
1810 $error++;
1811 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1812 $action = '';
1813 }
1814 }
1815
1816 if (!$error) {
1817 $locationTarget = '';
1818
1819 $db->begin();
1820
1821 $result = $object->valid($user, $idwarehouse);
1822 if ($result >= 0) {
1823 $error = 0;
1824 $deposit = null;
1825
1826 $deposit_percent_from_payment_terms = (float) getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
1827
1828 if (
1829 GETPOST('generate_deposit', 'alpha') == 'on' && !empty($deposit_percent_from_payment_terms)
1830 && isModEnabled('invoice') && $user->hasRight('facture', 'creer')
1831 ) {
1832 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
1833
1834 $date = dol_mktime(0, 0, 0, GETPOSTINT('datefmonth'), GETPOSTINT('datefday'), GETPOSTINT('datefyear'));
1835 $forceFields = array();
1836
1837 if (GETPOSTISSET('date_pointoftax')) {
1838 $forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOSTINT('date_pointoftaxmonth'), GETPOSTINT('date_pointoftaxday'), GETPOSTINT('date_pointoftaxyear'));
1839 }
1840
1841 $deposit = Facture::createDepositFromOrigin($object, $date, GETPOSTINT('cond_reglement_id'), $user, 0, GETPOSTINT('validate_generated_deposit') == 'on', $forceFields);
1842
1843 if ($deposit) {
1844 setEventMessage('DepositGenerated');
1845 $locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
1846 } else {
1847 $error++;
1848 setEventMessages($object->error, $object->errors, 'errors');
1849 }
1850 }
1851
1852 // Define output language
1853 if (! $error) {
1854 $db->commit();
1855
1856 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1857 $outputlangs = $langs;
1858 $newlang = '';
1859 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1860 $newlang = GETPOST('lang_id', 'aZ09');
1861 }
1862 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1863 $newlang = $object->thirdparty->default_lang;
1864 }
1865 if (!empty($newlang)) {
1866 $outputlangs = new Translate("", $conf);
1867 $outputlangs->setDefaultLang($newlang);
1868 }
1869 $model = $object->model_pdf;
1870 $ret = $object->fetch($id); // Reload to get new records
1871
1872 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1873
1874 if ($deposit) {
1875 $deposit->fetch($deposit->id); // Reload to get new records
1876 $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1877 }
1878 }
1879
1880 if ($locationTarget) {
1881 header('Location: ' . $locationTarget);
1882 exit;
1883 }
1884 } else {
1885 $db->rollback();
1886 }
1887 } else {
1888 $db->rollback();
1889 setEventMessages($object->error, $object->errors, 'errors');
1890 }
1891 }
1892 } elseif ($action == 'confirm_modif' && $usercancreate) {
1893 // Go back to draft status
1894 $idwarehouse = GETPOST('idwarehouse');
1895
1896 $qualified_for_stock_change = 0;
1897 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1898 $qualified_for_stock_change = $object->hasProductsOrServices(2);
1899 } else {
1900 $qualified_for_stock_change = $object->hasProductsOrServices(1);
1901 }
1902
1903 // Check parameters
1904 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
1905 if (!$idwarehouse || $idwarehouse == -1) {
1906 $error++;
1907 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1908 $action = '';
1909 }
1910 }
1911
1912 if (!$error) {
1913 $result = $object->setDraft($user, $idwarehouse);
1914 if ($result >= 0) {
1915 // Define output language
1916 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1917 $outputlangs = $langs;
1918 $newlang = '';
1919 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1920 $newlang = GETPOST('lang_id', 'aZ09');
1921 }
1922 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1923 $newlang = $object->thirdparty->default_lang;
1924 }
1925 if (!empty($newlang)) {
1926 $outputlangs = new Translate("", $conf);
1927 $outputlangs->setDefaultLang($newlang);
1928 }
1929 $model = $object->model_pdf;
1930 $ret = $object->fetch($id); // Reload to get new records
1931
1932 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1933 }
1934 } else {
1935 setEventMessages($object->error, $object->errors, 'errors');
1936 }
1937 }
1938 } elseif ($action == 'confirm_shipped' && $confirm == 'yes' && $usercanclose) {
1939 $result = $object->cloture($user);
1940 if ($result < 0) {
1941 setEventMessages($object->error, $object->errors, 'errors');
1942 }
1943 } elseif ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanvalidate) {
1944 $idwarehouse = GETPOSTINT('idwarehouse');
1945
1946 $qualified_for_stock_change = 0;
1947 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1948 $qualified_for_stock_change = $object->hasProductsOrServices(2);
1949 } else {
1950 $qualified_for_stock_change = $object->hasProductsOrServices(1);
1951 }
1952
1953 // Check parameters
1954 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
1955 if (!$idwarehouse || $idwarehouse == -1) {
1956 $error++;
1957 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1958 $action = '';
1959 }
1960 }
1961
1962 if (!$error) {
1963 $result = $object->cancel($user, $idwarehouse);
1964
1965 if ($result < 0) {
1966 setEventMessages($object->error, $object->errors, 'errors');
1967 }
1968 }
1969 }
1970
1971 if ($action == 'update_extras' && $permissiontoeditextra) {
1972 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
1973
1974 $attribute_name = GETPOST('attribute', 'aZ09');
1975
1976 // Fill array 'array_options' with data from update form
1977 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
1978 if ($ret < 0) {
1979 $error++;
1980 }
1981
1982 if (!$error) {
1983 // Actions on extra fields
1984 $result = $object->updateExtraField($attribute_name, 'ORDER_MODIFY');
1985 if ($result < 0) {
1986 setEventMessages($object->error, $object->errors, 'errors');
1987 $error++;
1988 }
1989 }
1990
1991 if ($error) {
1992 $action = 'edit_extras';
1993 }
1994 }
1995
1996 // Add lines from objectlinked
1997 if ($action == 'import_lines_from_object' && $usercancreate && $object->status == Commande::STATUS_DRAFT) {
1998 $fromElement = GETPOST('fromelement');
1999 $fromElementid = GETPOST('fromelementid');
2000 $importLines = GETPOST('line_checkbox');
2001
2002 if (!empty($importLines) && is_array($importLines) && !empty($fromElement) && preg_match('/^[a-zA-Z]+$/', $fromElement) && !empty($fromElementid)) {
2003 if ($fromElement == 'commande') {
2004 dol_include_once('/' . $fromElement . '/class/' . $fromElement . '.class.php');
2005 $lineClassName = 'OrderLine';
2006 } elseif ($fromElement == 'propal') {
2007 dol_include_once('/comm/' . $fromElement . '/class/' . $fromElement . '.class.php');
2008 $lineClassName = 'PropaleLigne';
2009 } elseif ($fromElement == 'facture') {
2010 dol_include_once('/compta/' . $fromElement . '/class/' . $fromElement . '.class.php');
2011 $lineClassName = 'FactureLigne';
2012 }
2013 $nextRang = count($object->lines) + 1;
2014 $importCount = 0;
2015 $error = 0;
2016 foreach ($importLines as $lineId) {
2017 $lineId = intval($lineId);
2018 $originLine = new $lineClassName($db);
2019 if (intval($fromElementid) > 0 && $originLine->fetch($lineId) > 0) {
2020 $originLine->fetch_optionals();
2021 $desc = $originLine->desc;
2022 $pu_ht = $originLine->subprice;
2023 $qty = $originLine->qty;
2024 $txtva = $originLine->tva_tx;
2025 $txlocaltax1 = $originLine->localtax1_tx;
2026 $txlocaltax2 = $originLine->localtax2_tx;
2027 $fk_product = $originLine->fk_product;
2028 $remise_percent = $originLine->remise_percent;
2029 $date_start = $originLine->date_start;
2030 $date_end = $originLine->date_end;
2031 $fk_code_ventilation = 0;
2032 $info_bits = $originLine->info_bits;
2033 $fk_remise_except = $originLine->fk_remise_except;
2034 $price_base_type = 'HT';
2035 $pu_ttc = 0;
2036 $type = $originLine->product_type;
2037 $rang = $nextRang++;
2038 $special_code = $originLine->special_code;
2039 $origin = $originLine->element;
2040 $origin_id = $originLine->id;
2041 $fk_parent_line = 0;
2042 $fk_fournprice = $originLine->fk_fournprice;
2043 $pa_ht = $originLine->pa_ht;
2044 $label = $originLine->label;
2045 $array_options = $originLine->array_options;
2046 $situation_percent = 100;
2047 $fk_prev_id = '';
2048 $fk_unit = $originLine->fk_unit;
2049 $pu_ht_devise = $originLine->multicurrency_subprice;
2050
2051 $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);
2052
2053 if ($res > 0) {
2054 $importCount++;
2055 } else {
2056 $error++;
2057 }
2058 } else {
2059 $error++;
2060 }
2061 }
2062
2063 if ($error) {
2064 setEventMessages($langs->trans('ErrorsOnXLines', $error), null, 'errors');
2065 }
2066 }
2067 }
2068
2069 // Actions when printing a doc from card
2070 include DOL_DOCUMENT_ROOT . '/core/actions_printing.inc.php';
2071
2072 // Actions to build doc
2073 $upload_dir = !empty($conf->commande->multidir_output[$object->entity ?? $conf->entity]) ? $conf->commande->multidir_output[$object->entity ?? $conf->entity] : $conf->commande->dir_output;
2074 $permissiontoadd = $usercancreate;
2075 include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
2076
2077 // Actions to send emails
2078 $triggersendname = 'ORDER_SENTBYMAIL';
2079 $paramname = 'id';
2080 $autocopy = 'MAIN_MAIL_AUTOCOPY_ORDER_TO'; // used to know the automatic BCC to add
2081 $trackid = 'ord' . $object->id;
2082 include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
2083
2084
2085 if (!$error && getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB') && $usercancreate) {
2086 if ($action == 'addcontact') { // Test on permission already done
2087 if ($object->id > 0) {
2088 $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
2089 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
2090 $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
2091 }
2092
2093 if ($result >= 0) {
2094 header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
2095 exit();
2096 } else {
2097 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
2098 $langs->load("errors");
2099 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
2100 } else {
2101 setEventMessages($object->error, $object->errors, 'errors');
2102 }
2103 }
2104 } elseif ($action == 'swapstatut') { // Test on permission already done
2105 // bascule du statut d'un contact
2106 if ($object->id > 0) {
2107 $result = $object->swapContactStatus(GETPOSTINT('ligne'));
2108 } else {
2110 }
2111 } elseif ($action == 'deletecontact') { // Test on permission already done
2112 // Efface un contact
2113 $result = $object->delete_contact($lineid);
2114
2115 if ($result >= 0) {
2116 header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
2117 exit();
2118 } else {
2120 }
2121 }
2122 }
2123}
2124
2125
2126/*
2127 * View
2128 */
2129
2130$title = $object->ref . " - " . $langs->trans('Card');
2131if ($action == 'create') {
2132 $title = $langs->trans("NewOrder");
2133}
2134$help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge';
2135
2136llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-order page-card');
2137
2138$form = new Form($db);
2139$formfile = new FormFile($db);
2140$formorder = new FormOrder($db);
2141$formmargin = new FormMargin($db);
2142$formproduct = new FormProduct($db);
2143if (isModEnabled('project')) {
2144 $formproject = new FormProjets($db);
2145}
2146
2147// Mode creation
2148if ($action == 'create' && $usercancreate) {
2149 print load_fiche_titre($langs->trans('CreateOrder'), '', 'order');
2150
2151 $soc = new Societe($db);
2152 if ($socid > 0) {
2153 $res = $soc->fetch($socid);
2154 }
2155
2156 $currency_code = $conf->currency;
2157
2158 $cond_reglement_id = GETPOSTINT('cond_reglement_id');
2159 $deposit_percent = GETPOSTFLOAT('cond_reglement_id_deposit_percent');
2160 $mode_reglement_id = GETPOSTINT('mode_reglement_id');
2161 $fk_account = GETPOSTINT('fk_account');
2162
2163 if (!empty($origin) && !empty($originid)) {
2164 // Parse element/subelement (ex: project_task)
2165 $element = $subelement = $origin;
2166 $regs = array();
2167 if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
2168 $element = $regs[1];
2169 $subelement = $regs[2];
2170 }
2171
2172 if ($element == 'project') {
2173 $projectid = $originid;
2174
2175 if (!$cond_reglement_id) {
2176 $cond_reglement_id = $soc->cond_reglement_id;
2177 }
2178 if (!$deposit_percent) {
2179 $deposit_percent = $soc->deposit_percent;
2180 }
2181 if (!$mode_reglement_id) {
2182 $mode_reglement_id = $soc->mode_reglement_id;
2183 }
2184 if (!$remise_percent) {
2185 $remise_percent = $soc->remise_percent;
2186 }
2187 } else {
2188 // For compatibility
2189 if ($element == 'order' || $element == 'commande') {
2190 $element = $subelement = 'commande';
2191 } elseif ($element == 'propal') {
2192 $element = 'comm/propal';
2193 $subelement = 'propal';
2194 } elseif ($element == 'contract') {
2195 $element = $subelement = 'contrat';
2196 }
2197
2198 dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
2199
2200 $classname = ucfirst($subelement);
2201 $objectsrc = new $classname($db);
2202 '@phan-var-force Commande|Propal|Contrat $objectsrc'; // Can possibly be other class but CommonObject is too general
2203 $objectsrc->fetch($originid);
2204 if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
2205 $objectsrc->fetch_lines();
2206 }
2207 $objectsrc->fetch_thirdparty();
2208
2209 // Replicate extrafields
2210 $objectsrc->fetch_optionals();
2211 $object->array_options = $objectsrc->array_options;
2212
2213 $projectid = (int) $objectsrc->fk_project;
2214 $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
2215
2216 $soc = $objectsrc->thirdparty;
2217 $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
2218 $deposit_percent = (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : null));
2219 $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
2220 $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0));
2221 $availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : 0);
2222 $shipping_method_id = (!empty($objectsrc->shipping_method_id) ? $objectsrc->shipping_method_id : (!empty($soc->shipping_method_id) ? $soc->shipping_method_id : 0));
2223 $warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0));
2224 $demand_reason_id = (!empty($objectsrc->demand_reason_id) ? $objectsrc->demand_reason_id : (!empty($soc->demand_reason_id) ? $soc->demand_reason_id : 0));
2225 $dateorder = getDolGlobalString('MAIN_AUTOFILL_DATE_ORDER') ? '' : -1;
2226
2227 $date_delivery = (!empty($objectsrc->delivery_date) ? $objectsrc->delivery_date : '');
2228
2229 if (isModEnabled("multicurrency")) {
2230 if (!empty($objectsrc->multicurrency_code)) {
2231 $currency_code = $objectsrc->multicurrency_code;
2232 }
2233 if (getDolGlobalString('MULTICURRENCY_USE_ORIGIN_TX') && !empty($objectsrc->multicurrency_tx)) {
2234 $currency_tx = $objectsrc->multicurrency_tx;
2235 }
2236 }
2237
2238 $note_private = $object->getDefaultCreateValueFor('note_private', (!empty($objectsrc->note_private) ? $objectsrc->note_private : null));
2239 $note_public = $object->getDefaultCreateValueFor('note_public', (!empty($objectsrc->note_public) ? $objectsrc->note_public : null));
2240
2241 // Object source contacts list
2242 $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
2243 }
2244 } else {
2245 $cond_reglement_id = empty($soc->cond_reglement_id) ? $cond_reglement_id : $soc->cond_reglement_id;
2246 $deposit_percent = empty($soc->deposit_percent) ? $deposit_percent : $soc->deposit_percent;
2247 $mode_reglement_id = empty($soc->mode_reglement_id) ? $mode_reglement_id : $soc->mode_reglement_id;
2248 $fk_account = empty($soc->mode_reglement_id) ? $fk_account : $soc->fk_account;
2249 $availability_id = 0;
2250 $shipping_method_id = empty($soc->shipping_method_id) ? $shipping_method_id : $soc->shipping_method_id;
2251 $warehouse_id = $soc->fk_warehouse;
2252 $demand_reason_id = $soc->demand_reason_id;
2253 $dateorder = getDolGlobalString('MAIN_AUTOFILL_DATE_ORDER') ? '' : -1;
2254
2255 if (isModEnabled("multicurrency") && !empty($soc->multicurrency_code)) {
2256 $currency_code = $soc->multicurrency_code;
2257 }
2258
2259 $note_private = $object->getDefaultCreateValueFor('note_private');
2260 $note_public = $object->getDefaultCreateValueFor('note_public');
2261 }
2262
2263 // If form was posted (but error returned), we must reuse the value posted in priority (standard Dolibarr behaviour)
2264 if (!GETPOST('changecompany')) {
2265 if (GETPOSTISSET('cond_reglement_id')) {
2266 $cond_reglement_id = GETPOSTINT('cond_reglement_id');
2267 }
2268 if (GETPOSTISSET('deposit_percent')) {
2269 $deposit_percent = GETPOSTFLOAT('deposit_percent');
2270 }
2271 if (GETPOSTISSET('mode_reglement_id')) {
2272 $mode_reglement_id = GETPOSTINT('mode_reglement_id');
2273 }
2274 if (GETPOSTISSET('cond_reglement_id')) {
2275 $fk_account = GETPOSTINT('fk_account');
2276 }
2277 }
2278
2279 // Warehouse default if null
2280 if ($soc->fk_warehouse > 0) {
2281 $warehouse_id = $soc->fk_warehouse;
2282 }
2283 if (isModEnabled('stock') && empty($warehouse_id) && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
2284 if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) {
2285 $warehouse_id = getDolGlobalString('MAIN_DEFAULT_WAREHOUSE');
2286 }
2287 if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && !empty($user->fk_warehouse)) {
2288 $warehouse_id = $user->fk_warehouse;
2289 }
2290 }
2291
2292 print '<form name="crea_commande" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
2293 print '<input type="hidden" name="token" value="' . newToken() . '">';
2294 print '<input type="hidden" name="action" value="add">';
2295 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
2296 print '<input type="hidden" name="remise_percent" value="' . $soc->remise_percent . '">';
2297 print '<input type="hidden" name="origin" value="' . $origin . '">';
2298 print '<input type="hidden" name="originid" value="' . $originid . '">';
2299 print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
2300 if (!empty($currency_tx)) {
2301 print '<input type="hidden" name="originmulticurrency_tx" value="' . $currency_tx . '">';
2302 }
2303
2304 print dol_get_fiche_head([]);
2305
2306 // Call Hook tabContentCreateOrder
2307 $parameters = array();
2308 // Note that $action and $object may be modified by hook
2309 $reshook = $hookmanager->executeHooks('tabContentCreateOrder', $parameters, $object, $action);
2310 if (empty($reshook)) {
2311 print '<table class="border centpercent">';
2312
2313 // Reference
2314 //print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td>' . $langs->trans("Draft") . '</td></tr>';
2315
2316 // Thirdparty
2317 print '<tr>';
2318 print '<td class="fieldrequired">' . $langs->trans('Customer') . '</td>';
2319 if ($socid > 0) {
2320 print '<td>';
2321 print $soc->getNomUrl(1, 'customer');
2322 print '<input type="hidden" name="socid" value="' . $soc->id . '">';
2323 print '</td>';
2324 } else {
2325 print '<td class="valuefieldcreate">';
2326 $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))';
2327 print img_picto('', 'company', 'class="pictofixedwidth"') . $form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
2328 // reload page to retrieve customer information
2329 if (!getDolGlobalString('RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED')) {
2330 print '<script>
2331 $(document).ready(function() {
2332 $("#socid").change(function() {
2333 console.log("We have changed the company - Reload page");
2334 var socid = $(this).val();
2335 // reload page
2336 $("input[name=action]").val("create");
2337 $("input[name=changecompany]").val("1");
2338 $("form[name=crea_commande]").submit();
2339 });
2340 });
2341 </script>';
2342 }
2343 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>';
2344 print '</td>';
2345 }
2346 print '</tr>' . "\n";
2347
2348 // Reference of order on customer side
2349 if (getDolGlobalString('MAIN_ASK_CUSTOMER_REF_OF_SALE_ORDER_AT_CREATION') || getDolGlobalString('MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER')) {
2350 print '<tr><td>';
2351 if (getDolGlobalString('MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER') && !empty($origin) && !empty($originid)) {
2352 print $langs->trans('RefProposal') . '</td><td>';
2353 print '<input type="text" name="ref_client" value="' . $ref_client . '">';
2354 } else {
2355 print $form->textwithpicto($langs->trans('RefCustomer'), $langs->trans('RefOfOnCustomerSide', $langs->transnoentitiesnoconv("Order"))) . '</td><td>';
2356 print '<input type="text" name="ref_client" value="' . GETPOST('ref_client') . '">';
2357 }
2358 print '</td></tr>';
2359 }
2360
2361 // Contact of order
2362 if ($socid > 0) {
2363 // Contacts (ask contact only if thirdparty already defined).
2364 // print "<tr><td>".$langs->trans("DefaultContact").'</td><td>';
2365 print "<tr><td>";
2366 print $form->textwithpicto($langs->trans("DefaultContact"), $langs->trans("TypeContact_commande_external_" . $type_contact_code));
2367 print '</td><td>';
2368 print img_picto('', 'contact', 'class="pictofixedwidth"');
2369 //print $form->selectcontacts($soc->id, $contactid, 'contactid', 1, empty($srccontactslist) ? "" : $srccontactslist, '', 1, 'maxwidth300 widthcentpercentminusx');
2370 print $form->select_contact($soc->id, $contactid, 'contactid', 1, empty($srccontactslist) ? "" : $srccontactslist, '', 1, 'maxwidth300 widthcentpercentminusx', true);
2371 print '</td></tr>';
2372
2373 // Line with information on Third Party Discounts
2374 print '<tr><td>' . $langs->trans('Discounts') . '</td><td>';
2375
2376 $absolute_discount = $soc->getAvailableDiscounts();
2377
2378 $thirdparty = $soc;
2379 $discount_type = 0;
2380 $backtopage = $_SERVER["PHP_SELF"] . '?socid=' . $thirdparty->id . '&action=' . $action . '&origin=' . urlencode((string) (GETPOST('origin'))) . '&originid=' . urlencode((string) (GETPOSTINT('originid')));
2381 include DOL_DOCUMENT_ROOT . '/core/tpl/object_discounts.tpl.php';
2382
2383 print '</td></tr>';
2384 }
2385
2386 // Date
2387 $dateorder = (getDolGlobalString('MAIN_DO_NOT_AUTOFILL_DATE_ORDER') ? -1 : ''); // By default '' so we will autofill date. -1 means keep empty.
2388
2389 print '<tr><td class="fieldrequired">' . $langs->trans('Date') . '</td><td>';
2390 print img_picto('', 'action', 'class="pictofixedwidth"');
2391 print $form->selectDate($dateorder, 're', 0, 0, 0, "crea_commande", 1, 1); // Always autofill date with current date
2392 print '</td></tr>';
2393
2394 // Date delivery planned
2395 print '<tr><td>' . $langs->trans("DateDeliveryPlanned") . '</td>';
2396 print '<td colspan="3">';
2397 $date_delivery = ($date_delivery ? $date_delivery : $object->delivery_date);
2398 print img_picto('', 'action', 'class="pictofixedwidth"');
2399 print $form->selectDate($date_delivery ? $date_delivery : -1, 'liv_', 1, 1, 1);
2400 print "</td>\n";
2401 print '</tr>';
2402
2403 // Delivery delay
2404 print '<tr class="fielddeliverydelay"><td>' . $langs->trans('AvailabilityPeriod') . '</td><td>';
2405 print img_picto('', 'clock', 'class="pictofixedwidth"');
2406 $form->selectAvailabilityDelay((GETPOSTISSET('availability_id') ? GETPOST('availability_id') : $availability_id), 'availability_id', '', 1, 'maxwidth200 widthcentpercentminusx');
2407 print '</td></tr>';
2408
2409 // Terms of payment
2410 print '<tr><td class="nowrap">' . $langs->trans('PaymentConditionsShort') . '</td><td>';
2411 print img_picto('', 'payment', 'class="pictofixedwidth"');
2412 print $form->getSelectConditionsPaiements((int) $cond_reglement_id, 'cond_reglement_id', 1, 1, 0, 'maxwidth200 widthcentpercentminusx', (float) $deposit_percent);
2413 print '</td></tr>';
2414
2415 // Payment mode
2416 print '<tr><td>' . $langs->trans('PaymentMode') . '</td><td>';
2417 print img_picto('', 'bank', 'class="pictofixedwidth"');
2418 print $form->select_types_paiements((string) $mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1);
2419 print '</td></tr>';
2420
2421 // Bank Account
2422 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_ORDER') && isModEnabled("bank")) {
2423 print '<tr><td>' . $langs->trans('BankAccount') . '</td><td>';
2424 print img_picto('', 'bank_account', 'class="pictofixedwidth"') . $form->select_comptes((int) $fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1);
2425 print '</td></tr>';
2426 }
2427
2428 // Shipping Method
2429 if (isModEnabled('shipping')) {
2430 print '<tr><td>' . $langs->trans('SendingMethod') . '</td><td>';
2431 print img_picto('', 'object_dolly', 'class="pictofixedwidth"');
2432 $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
2433 print '</td></tr>';
2434 }
2435
2436 // Warehouse
2437 if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
2438 print '<tr><td>' . $langs->trans('Warehouse') . '</td><td>';
2439 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');
2440 print '</td></tr>';
2441 }
2442
2443 // Source / Channel - What trigger creation
2444 print '<tr><td>' . $langs->trans('Source') . '</td><td>';
2445 print img_picto('', 'question', 'class="pictofixedwidth"');
2446 $form->selectInputReason((GETPOSTISSET('demand_reason_id') ? GETPOST('demand_reason_id') : $demand_reason_id), 'demand_reason_id', '', 1, 'maxwidth200 widthcentpercentminusx');
2447 print '</td></tr>';
2448
2449 // TODO How record was recorded OrderMode (llx_c_input_method)
2450
2451 // Project
2452 if (isModEnabled('project')) {
2453 $langs->load("projects");
2454 print '<tr>';
2455 print '<td>'.$langs->trans("Project").'</td><td>';
2456 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');
2457 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>';
2458 print '</td>';
2459 print '</tr>';
2460 }
2461
2462 // Incoterms
2463 if (isModEnabled('incoterm')) {
2464 print '<tr>';
2465 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>';
2466 print '<td class="maxwidthonsmartphone">';
2467 $incoterm_id = GETPOST('incoterm_id');
2468 $location_incoterms = GETPOST('location_incoterms');
2469 if (empty($incoterm_id)) {
2470 $incoterm_id = (!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms);
2471 $location_incoterms = (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : $soc->location_incoterms);
2472 }
2473 print img_picto('', 'incoterm', 'class="pictofixedwidth"');
2474 print $form->select_incoterms($incoterm_id, $location_incoterms);
2475 print '</td></tr>';
2476 }
2477
2478 // Other attributes
2479 $parameters = array();
2480 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2481 $parameters['objectsrc'] = $objectsrc;
2482 }
2483 $parameters['socid'] = $socid;
2484
2485 // Note that $action and $object may be modified by hook
2486 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
2487 print $hookmanager->resPrint;
2488 if (empty($reshook)) {
2489 if (getDolGlobalString('THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER') && !empty($soc->id)) {
2490 // copy from thirdparty
2491 $tpExtrafields = new ExtraFields($db);
2492 $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element);
2493 if ($soc->fetch_optionals() > 0) {
2494 $object->array_options = array_merge($object->array_options, $soc->array_options);
2495 }
2496 }
2497
2498 print $object->showOptionals($extrafields, 'create', $parameters);
2499 }
2500
2501 // Template to use by default
2502 include_once DOL_DOCUMENT_ROOT . '/core/modules/commande/modules_commande.php';
2504 if (is_array($list) && count($list) > 0) {
2505 print '<tr><td>' . $langs->trans('DefaultModel') . '</td>';
2506 print '<td>';
2507 $preselected = getDolGlobalString('COMMANDE_ADDON_PDF');
2508 print img_picto('', 'pdf', 'class="pictofixedwidth"');
2509 print $form->selectarray('model', $list, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
2510 print "</td></tr>";
2511 }
2512
2513 // Multicurrency
2514 if (isModEnabled("multicurrency")) {
2515 print '<tr>';
2516 print '<td>' . $form->editfieldkey("Currency", 'multicurrency_code', '', $object, 0) . '</td>';
2517 print '<td class="maxwidthonsmartphone">';
2518 print img_picto('', 'currency', 'class="pictofixedwidth"') . $form->selectMultiCurrency(((GETPOSTISSET('multicurrency_code') && !GETPOST('changecompany')) ? GETPOST('multicurrency_code') : $currency_code), 'multicurrency_code', 0, '', false, 'maxwidth200 widthcentpercentminusx');
2519 print '</td></tr>';
2520 }
2521
2522 // Categories
2523 if (isModEnabled('category')) {
2524 print '<tr><td>' . $langs->trans("Categories") . '</td><td colspan="3">';
2525 print $form->selectCategories(Categorie::TYPE_ORDER, 'categories', $object);
2526 print "</td></tr>";
2527 }
2528
2529 // Note public
2530 print '<tr>';
2531 print '<td class="tdtop">' . $langs->trans('NotePublic') . '</td>';
2532 print '<td>';
2533
2534 $doleditor = new DolEditor('note_public', (string) $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
2535 print $doleditor->Create(1);
2536 // print '<textarea name="note_public" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_public.'</textarea>';
2537 print '</td></tr>';
2538
2539 // Note private
2540 if (empty($user->socid)) {
2541 print '<tr>';
2542 print '<td class="tdtop">' . $langs->trans('NotePrivate') . '</td>';
2543 print '<td>';
2544
2545 $doleditor = new DolEditor('note_private', (string) $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
2546 print $doleditor->Create(1);
2547 // print '<textarea name="note" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'</textarea>';
2548 print '</td></tr>';
2549 }
2550
2551 if (!empty($origin) && !empty($originid) && is_object($objectsrc) && !empty($classname)) {
2552 // TODO for compatibility
2553 if ($origin == 'contrat') {
2554 // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
2555 $objectsrc->update_price(1);
2556 }
2557
2558 print "\n<!-- " . $classname . " info -->\n";
2559 print '<input type="hidden" name="amount" value="' . $objectsrc->total_ht . '">' . "\n";
2560 print '<input type="hidden" name="total" value="' . $objectsrc->total_ttc . '">' . "\n";
2561 print '<input type="hidden" name="tva" value="' . $objectsrc->total_tva . '">' . "\n";
2562 print '<input type="hidden" name="origin" value="' . $objectsrc->element . '">';
2563 print '<input type="hidden" name="originid" value="' . $objectsrc->id . '">';
2564
2565 switch ($classname) {
2566 case 'Propal':
2567 $newclassname = 'CommercialProposal';
2568 break;
2569 case 'Commande':
2570 $newclassname = 'Order';
2571 break;
2572 case 'Expedition':
2573 $newclassname = 'Sending';
2574 break;
2575 case 'Contrat':
2576 $newclassname = 'Contract';
2577 break;
2578 default:
2579 $newclassname = $classname;
2580 }
2581
2582 print '<tr><td>' . $langs->trans($newclassname) . '</td><td>' . $objectsrc->getNomUrl(1) . '</td></tr>';
2583
2584 // Amount
2585 print '<tr><td>' . $langs->trans('AmountHT') . '</td><td>' . price($objectsrc->total_ht) . '</td></tr>';
2586 print '<tr><td>' . $langs->trans('AmountVAT') . '</td><td>' . price($objectsrc->total_tva) . "</td></tr>";
2587 if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1 RE
2588 print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td><td>' . price($objectsrc->total_localtax1) . "</td></tr>";
2589 }
2590
2591 if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2 IRPF
2592 print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td><td>' . price($objectsrc->total_localtax2) . "</td></tr>";
2593 }
2594
2595 print '<tr><td>' . $langs->trans('AmountTTC') . '</td><td>' . price($objectsrc->total_ttc) . "</td></tr>";
2596
2597 if (isModEnabled("multicurrency")) {
2598 print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht, 0, $langs, 1, -1, -1, $objectsrc->multicurrency_code).'</td></tr>';
2599 print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva, 0, $langs, 1, -1, -1, $objectsrc->multicurrency_code)."</td></tr>";
2600 print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc, 0, $langs, 1, -1, -1, $objectsrc->multicurrency_code)."</td></tr>";
2601 }
2602 }
2603
2604 print "\n";
2605
2606 print '</table>';
2607 }
2608
2609 print dol_get_fiche_end();
2610
2611 print $form->buttonsSaveCancel("CreateDraft");
2612
2613 // Show origin lines
2614 if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2615 $title = $langs->trans('ProductsAndServices');
2616 print load_fiche_titre($title);
2617
2618 print '<div class="div-table-responsive-no-min">';
2619 print '<table class="noborder centpercent">';
2620
2621 $objectsrc->printOriginLinesList('', $selectedLines);
2622
2623 print '</table>';
2624 print '</div>';
2625 }
2626
2627 print '</form>';
2628} else {
2629 // Mode view
2630 $now = dol_now();
2631
2632 if ($object->id > 0) {
2633 $product_static = new Product($db);
2634
2635 $soc = new Societe($db);
2636 $soc->fetch($object->socid);
2637
2638 $author = new User($db);
2639 $author->fetch($object->user_author_id);
2640
2641 $object->fetch_thirdparty();
2642 $res = $object->fetch_optionals();
2643
2644 $head = commande_prepare_head($object);
2645 print dol_get_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, $object->picto, 0, '', '', 0, '', 1);
2646
2647 $formconfirm = '';
2648
2649 // Confirmation to delete
2650 if ($action == 'delete') {
2651 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1);
2652 }
2653
2654 // Confirmation of validation
2655 if ($action == 'validate') {
2656 // We check that object has a temporary ref
2657 $ref = substr($object->ref, 1, 4);
2658 if ($ref == 'PROV' || $ref == '') {
2659 $numref = $object->getNextNumRef($soc);
2660 if (empty($numref)) {
2661 $error++;
2662 setEventMessages($object->error, $object->errors, 'errors');
2663 }
2664 } else {
2665 $numref = (string) $object->ref;
2666 }
2667
2668 $text = $langs->trans('ConfirmValidateOrder', $numref);
2669 if (isModEnabled('notification')) {
2670 require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
2671 $notify = new Notify($db);
2672 $text .= '<br>';
2673 $text .= $notify->confirmMessage('ORDER_VALIDATE', $object->socid, $object);
2674 }
2675
2676 $qualified_for_stock_change = 0;
2677 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2678 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2679 } else {
2680 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2681 }
2682
2683 $formquestion = array();
2684 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
2685 $langs->load("stocks");
2686 $forcecombo = 0;
2687 if ($conf->browser->name == 'ie') {
2688 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2689 }
2690 $formquestion = array(
2691 // 'text' => $langs->trans("ConfirmClone"),
2692 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2693 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2694 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOSTINT('idwarehouse') ? GETPOSTINT('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2695 );
2696 }
2697
2698 // mandatoryPeriod
2699 $nbMandated = 0;
2700 foreach ($object->lines as $line) {
2701 $res = $line->fetch_product();
2702 if ($res > 0) {
2703 if ($line->product->isService() && $line->product->isMandatoryPeriod() && (empty($line->date_start) || empty($line->date_end))) {
2704 $nbMandated++;
2705 break;
2706 }
2707 }
2708 }
2709 if ($nbMandated > 0) {
2710 if (getDolGlobalString('SERVICE_STRICT_MANDATORY_PERIOD')) {
2711 setEventMessages($langs->trans("mandatoryPeriodNeedTobeSetMsgValidate"), null, 'errors');
2712 $error++;
2713 } else {
2714 $text .= '<div><span class="clearboth nowraponall warning">' . img_warning() . $langs->trans("mandatoryPeriodNeedTobeSetMsgValidate") . '</span></div>';
2715 }
2716 }
2717
2718 if (getDolGlobalInt('SALE_ORDER_SUGGEST_DOWN_PAYMENT_INVOICE_CREATION')) {
2719 // This is a hidden option:
2720 // Suggestion to create invoice during order validation is not enabled by default.
2721 // Such choice should be managed by the workflow module and trigger. This option generates conflicts with some setup.
2722 // It may also break step of creating an order when invoicing must be done from proposals and not from orders
2723 $deposit_percent_from_payment_terms = (float) getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
2724
2725 if (!empty($deposit_percent_from_payment_terms) && isModEnabled('invoice') && $user->hasRight('facture', 'creer')) {
2726 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
2727
2728 $object->fetchObjectLinked();
2729
2730 $eligibleForDepositGeneration = true;
2731
2732 if (array_key_exists('facture', $object->linkedObjects)) {
2733 foreach ($object->linkedObjects['facture'] as $invoice) {
2734 '@phan-var-force Facture $invoice';
2735 if ($invoice->type == Facture::TYPE_DEPOSIT) {
2736 $eligibleForDepositGeneration = false;
2737 break;
2738 }
2739 }
2740 }
2741
2742 if ($eligibleForDepositGeneration && array_key_exists('propal', $object->linkedObjects)) {
2743 foreach ($object->linkedObjects['propal'] as $proposal) {
2744 $proposal->fetchObjectLinked();
2745
2746 if (array_key_exists('facture', $proposal->linkedObjects)) {
2747 foreach ($proposal->linkedObjects['facture'] as $invoice) {
2748 '@phan-var-force Facture $invoice';
2749 if ($invoice->type == Facture::TYPE_DEPOSIT) {
2750 $eligibleForDepositGeneration = false;
2751 break 2;
2752 }
2753 }
2754 }
2755 }
2756 }
2757
2758 if ($eligibleForDepositGeneration) {
2759 $formquestion[] = array(
2760 'type' => 'checkbox',
2761 'tdclass' => '',
2762 'name' => 'generate_deposit',
2763 'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
2764 );
2765
2766 $formquestion[] = array(
2767 'type' => 'date',
2768 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2769 'name' => 'datef',
2770 'label' => $langs->trans('DateInvoice'),
2771 'value' => dol_now(),
2772 'datenow' => true
2773 );
2774
2775 if (getDolGlobalString('INVOICE_POINTOFTAX_DATE')) {
2776 $formquestion[] = array(
2777 'type' => 'date',
2778 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2779 'name' => 'date_pointoftax',
2780 'label' => $langs->trans('DatePointOfTax'),
2781 'value' => dol_now(),
2782 'datenow' => true
2783 );
2784 }
2785
2786 $paymentTermsSelect = $form->getSelectConditionsPaiements(0, 'cond_reglement_id', -1, 0, 0, 'minwidth200');
2787
2788 $formquestion[] = array(
2789 'type' => 'other',
2790 'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2791 'name' => 'cond_reglement_id',
2792 'label' => $langs->trans('PaymentTerm'),
2793 'value' => $paymentTermsSelect
2794 );
2795
2796 $formquestion[] = array(
2797 'type' => 'checkbox',
2798 'tdclass' => 'showonlyifgeneratedeposit',
2799 'name' => 'validate_generated_deposit',
2800 'label' => $langs->trans('ValidateGeneratedDeposit')
2801 );
2802
2803 $formquestion[] = array(
2804 'type' => 'onecolumn',
2805 'value' => '
2806 <script>
2807 $(document).ready(function() {
2808 $("[name=generate_deposit]").change(function () {
2809 let $self = $(this);
2810 let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
2811
2812 if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
2813 $target.show();
2814 } else {
2815 $target.hide();
2816 }
2817
2818 return true;
2819 });
2820 });
2821 </script>
2822 '
2823 );
2824 }
2825 }
2826 }
2827
2828 if (!$error) {
2829 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('ValidateOrder'), $text, 'confirm_validate', $formquestion, 0, 1, 240);
2830 }
2831 }
2832
2833 // Confirm back to draft status
2834 if ($action == 'modif') {
2835 $qualified_for_stock_change = 0;
2836 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2837 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2838 } else {
2839 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2840 }
2841
2842 $text = $langs->trans('ConfirmUnvalidateOrder', $object->ref);
2843 $formquestion = array();
2844 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
2845 $langs->load("stocks");
2846 $forcecombo = 0;
2847 if ($conf->browser->name == 'ie') {
2848 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2849 }
2850 $formquestion = [
2851 // 'text' => $langs->trans("ConfirmClone"),
2852 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2853 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2854 [
2855 'type' => 'other',
2856 'name' => 'idwarehouse',
2857 'label' => $langs->trans("SelectWarehouseForStockIncrease"),
2858 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ? GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo)
2859 ]
2860 ];
2861 }
2862
2863 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('UnvalidateOrder'), $text, 'confirm_modif', $formquestion, "yes", 1, 220);
2864 }
2865
2866 // Confirmation of closing
2867 if ($action == 'shipped') {
2868 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('CloseOrder'), $langs->trans('ConfirmCloseOrder'), 'confirm_shipped', '', 0, 1);
2869 }
2870
2871 // Confirmation of cancellation
2872 if ($action == 'cancel') {
2873 $qualified_for_stock_change = 0;
2874 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
2875 $qualified_for_stock_change = $object->hasProductsOrServices(2);
2876 } else {
2877 $qualified_for_stock_change = $object->hasProductsOrServices(1);
2878 }
2879
2880 $text = $langs->trans('ConfirmCancelOrder', $object->ref);
2881 $formquestion = array();
2882 if (isModEnabled('stock') && getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') && $qualified_for_stock_change) {
2883 $langs->load("stocks");
2884 $forcecombo = 0;
2885 if ($conf->browser->name == 'ie') {
2886 $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2887 }
2888 $formquestion = array(
2889 // 'text' => $langs->trans("ConfirmClone"),
2890 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2891 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2892 array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ? GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2893 );
2894 }
2895
2896 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans("Cancel"), $text, 'confirm_cancel', $formquestion, 0, 1);
2897 }
2898
2899 // Confirmation to delete line
2900 if ($action == 'ask_deleteline') {
2901 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2902 }
2903
2904 // Generate form to delete a subtotal line
2905 if ($action == 'ask_subtotal_deleteline') {
2906 $langs->load("subtotals");
2907 $title = "DeleteSubtotalLine";
2908 $question = "ConfirmDeleteSubtotalLine";
2909 if (GETPOST('type') == 'title') {
2910 $formconfirm = array(array('type' => 'checkbox', 'name' => 'deletecorrespondingsubtotalline', 'label' => $langs->trans("DeleteCorrespondingSubtotalLine"), 'value' => 0));
2911 $title = "DeleteTitleLine";
2912 $question = "ConfirmDeleteTitleLine";
2913 }
2914 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans($title), $langs->trans($question), 'confirm_delete_subtotalline', $formconfirm, 'no', 1);
2915 }
2916
2917 // Clone confirmation
2918 if ($action == 'clone') {
2919 $filter = '(s.client:IN:1,2,3)';
2920 // Create an array for form
2921 $formquestion = array(
2922 array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOSTINT('socid'), 'socid', $filter, '', 0, 0, array(), 0, 'maxwidth300'))
2923 );
2924 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2925 }
2926
2927 // Subtotal line form
2928 if ($action == 'add_title_line') {
2929 $langs->load('subtotals');
2930 $type = 'title';
2931 $depth_array = $object->getPossibleLevels($langs);
2932 include DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_create.tpl.php';
2933 } elseif ($action == 'add_subtotal_line') {
2934 $langs->load('subtotals');
2935 $type = 'subtotal';
2936 $titles = $object->getPossibleTitles();
2937 include DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_create.tpl.php';
2938 }
2939
2940 // Call Hook formConfirm
2941 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2942 // Note that $action and $object may be modified by hook
2943 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
2944 if (empty($reshook)) {
2945 $formconfirm .= $hookmanager->resPrint;
2946 } elseif ($reshook > 0) {
2947 $formconfirm = $hookmanager->resPrint;
2948 }
2949
2950 // Print form confirm
2951 print $formconfirm;
2952
2953
2954 // Order card
2955
2956 $linkback = '<a href="' . DOL_URL_ROOT . '/commande/list.php?restore_lastsearch_values=1' . (!empty($socid) ? '&socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
2957
2958 $morehtmlref = '<div class="refidno">';
2959 // Ref customer
2960 $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, (int) $usercancreate, 'string', '', 0, 1);
2961 $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);
2962 // Thirdparty
2963 $morehtmlref .= '<br>' . $soc->getNomUrl(1, 'customer');
2964 if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
2965 $morehtmlref .= ' (<a href="' . DOL_URL_ROOT . '/commande/list.php?socid=' . ((int) $object->thirdparty->id) . '">' . $langs->trans("OtherOrders") . '</a>)';
2966 }
2967 // Project
2968 if (isModEnabled('project')) {
2969 $langs->load("projects");
2970 $morehtmlref .= '<br>';
2971 if ($usercancreate) {
2972 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2973 if ($action != 'classify') {
2974 $morehtmlref .= '<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> ';
2975 }
2976 $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');
2977 } else {
2978 if (!empty($object->fk_project)) {
2979 $proj = new Project($db);
2980 $proj->fetch($object->fk_project);
2981 $morehtmlref .= $proj->getNomUrl(1);
2982 if ($proj->title) {
2983 $morehtmlref .= '<span class="opacitymedium"> - ' . dol_escape_htmltag($proj->title) . '</span>';
2984 }
2985 }
2986 }
2987 }
2988 $morehtmlref .= '</div>';
2989
2990 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2991
2992 // Call Hook tabContentViewOrder
2993 $parameters = array();
2994 // Note that $action and $object may be modified by hook
2995 $reshook = $hookmanager->executeHooks('tabContentViewOrder', $parameters, $object, $action);
2996 if (empty($reshook)) {
2997 print '<div class="fichecenter">';
2998 print '<div class="fichehalfleft">';
2999 print '<div class="underbanner clearboth"></div>';
3000
3001 print '<table class="border tableforfield centpercent">';
3002
3003 // POS
3004 if (isModEnabled('takepos') || $object->module_source || getDolGlobalString('ORDER_ALLOW_POS_SOURCE_EDIT')) {
3005 $langs->load("cashdesk");
3006 print '<tr><td class="fieldname_type">';
3007 print '<table class="nobordernopadding centpercent"><tr><td>';
3008 print $form->textwithpicto($langs->trans('PointOfSale'), $langs->trans('POSInfo'));
3009 print '</td>';
3010 if ($action != 'editposinfo' && $usercancreate) {
3011 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>';
3012 }
3013 print '</tr></table>';
3014 print '</td><td class="valuefield fieldname_type">';
3015 print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" name="formposinfo">';
3016 print '<input type="hidden" name="action" value="setposinfo">';
3017 print '<input type="hidden" name="token" value="' . newToken() . '">';
3018 if ($action == 'editposinfo') {
3019 print '<input type="text" class="maxwidth150" name="posmodule" placeholder="' . $langs->trans("POSModule") . '" value="' . $object->module_source . '"> ';
3020 print '<input type="text" class="maxwidth100" name="posterminal" placeholder="' . $langs->trans("Terminal") . '" value="' . $object->pos_source . '">';
3021 print '<input type="submit" class="button" name="submitposinfo" value="' . $langs->trans("Submit") . '">';
3022 } else {
3023 if ($object->module_source) {
3024 print '<span class="opacitymediumbycolor paddingleft">' . dolPrintHTML(ucfirst($object->module_source) . ' - ' . $langs->transnoentitiesnoconv("Terminal") . ' ' . $object->pos_source) . '</span>';
3025 }
3026 }
3027 print '</form>';
3028 print '</td></tr>';
3029 }
3030
3031 if ($soc->outstanding_limit) {
3032 // Outstanding Bill
3033 print '<tr><td class="titlefield">';
3034 print $langs->trans('OutstandingBill');
3035 print '</td><td class="valuefield">';
3036 $arrayoutstandingbills = $soc->getOutstandingBills();
3037 print price($arrayoutstandingbills['opened']) . ' / ';
3038 print price($soc->outstanding_limit, 0, '', 1, -1, -1, $conf->currency);
3039 print '</td>';
3040 print '</tr>';
3041 }
3042
3043 // Relative and absolute discounts
3044 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
3045 $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
3046 $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be subtracted to payments only and not to total of final invoice
3047 } else {
3048 $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
3049 $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
3050 }
3051
3052 $addrelativediscount = '<a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditRelativeDiscounts") . '</a>';
3053 $addabsolutediscount = '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditGlobalDiscounts") . '</a>';
3054 $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>';
3055
3056 print '<tr><td class="titlefield">' . $langs->trans('Discounts') . '</td><td class="valuefield">';
3057
3058 $absolute_discount = $soc->getAvailableDiscounts(null, $filterabsolutediscount);
3059 $absolute_creditnote = $soc->getAvailableDiscounts(null, $filtercreditnote);
3060 $absolute_discount = price2num($absolute_discount, 'MT');
3061 $absolute_creditnote = price2num($absolute_creditnote, 'MT');
3062
3063 $thirdparty = $soc;
3064 $discount_type = 0;
3065 $backtopage = $_SERVER["PHP_SELF"] . '?id=' . $object->id;
3066 include DOL_DOCUMENT_ROOT . '/core/tpl/object_discounts.tpl.php';
3067
3068 print '</td></tr>';
3069
3070 // Date
3071 print '<tr><td>';
3072 $editenable = $usercancreate && $object->status == Commande::STATUS_DRAFT;
3073 print $form->editfieldkey("Date", 'date', '', $object, (int) $editenable);
3074 print '</td><td class="valuefield">';
3075 if ($action == 'editdate') {
3076 print '<form name="setdate" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
3077 print '<input type="hidden" name="token" value="' . newToken() . '">';
3078 print '<input type="hidden" name="action" value="setdate">';
3079 print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
3080 print $form->selectDate($object->date, 'order_', 0, 0, 0, "setdate");
3081 print '<input type="submit" class="button button-edit" value="' . $langs->trans('Modify') . '">';
3082 print '</form>';
3083 } else {
3084 print $object->date ? dol_print_date($object->date, 'day') : '&nbsp;';
3085 if ($object->hasDelay() && empty($object->delivery_date)) { // If there is a delivery date planned, warning should be on this date
3086 print ' ' . img_picto($langs->trans("Late") . ' : ' . $object->showDelay(), "warning");
3087 }
3088 }
3089 print '</td>';
3090 print '</tr>';
3091
3092 // Delivery date planned
3093 print '<tr><td>';
3094 $editenable = $usercancreate;
3095 print $form->editfieldkey("DateDeliveryPlanned", 'date_livraison', '', $object, (int) $editenable);
3096 print '</td><td class="valuefield">';
3097 if ($action == 'editdate_livraison') {
3098 print '<form name="setdate_livraison" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
3099 print '<input type="hidden" name="token" value="' . newToken() . '">';
3100 print '<input type="hidden" name="action" value="setdate_livraison">';
3101 print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
3102 print $form->selectDate($object->delivery_date ? $object->delivery_date : -1, 'liv_', 1, 1, 0, "setdate_livraison", 1, 0);
3103 print '<input type="submit" class="button button-edit" value="' . $langs->trans('Modify') . '">';
3104 print '</form>';
3105 } else {
3106 print $object->delivery_date ? dol_print_date($object->delivery_date, 'dayhour') : '&nbsp;';
3107 if ($object->hasDelay() && !empty($object->delivery_date)) {
3108 print ' ' . img_picto($langs->trans("Late") . ' : ' . $object->showDelay(), "warning");
3109 }
3110 }
3111 // --- SHIPPABLE icon ---
3112 if (isModEnabled('stock') && isModEnabled('shipping') && !getDolGlobalString('ORDER_DISABLE_SHIPPABLE_ICON_ON_CARD') && !empty($object->delivery_date)) {
3113 $shippableInfos = $object->getShippableInfos();
3114
3115 if (!empty($shippableInfos['has_product'])) {
3116 print ' ';
3117 print $form->textwithtooltip('', $shippableInfos['textinfo'], 2, 1, $shippableInfos['texticon'], '', 2);
3118
3119 if (!empty($shippableInfos['warning'])) {
3120 print ' ';
3121 print $form->textwithtooltip('', $langs->trans("NotEnoughForAllOrders"), 2, 1, img_picto('', 'error', '', 0, 0, 0, '', '2'), '', 2);
3122 }
3123 }
3124 }
3125 print '</td>';
3126 print '</tr>';
3127
3128 // Delivery delay
3129 print '<tr class="fielddeliverydelay"><td>';
3130 $editenable = $usercancreate;
3131 print $form->editfieldkey("AvailabilityPeriod", 'availability', '', $object, (int) $editenable);
3132 print '</td><td class="valuefield">';
3133 if ($action == 'editavailability') {
3134 $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->availability_id, 'availability_id', 1);
3135 } else {
3136 $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->availability_id, 'none', 1);
3137 }
3138 print '</td></tr>';
3139
3140 // Shipping Method
3141 if (isModEnabled('shipping')) {
3142 print '<tr><td>';
3143 $editenable = $usercancreate;
3144 print $form->editfieldkey("SendingMethod", 'shippingmethod', '', $object, (int) $editenable);
3145 print '</td><td class="valuefield">';
3146 if ($action == 'editshippingmethod') {
3147 $form->formSelectShippingMethod($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->shipping_method_id, 'shipping_method_id', 1);
3148 } else {
3149 $form->formSelectShippingMethod($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->shipping_method_id, 'none');
3150 }
3151 print '</td>';
3152 print '</tr>';
3153 }
3154
3155 // Warehouse
3156 if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER')) {
3157 $langs->load('stocks');
3158 print '<tr><td>';
3159 $editenable = $usercancreate;
3160 print $form->editfieldkey("Warehouse", 'warehouse', '', $object, (int) $editenable);
3161 print '</td><td class="valuefield">';
3162 if ($action == 'editwarehouse') {
3163 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->warehouse_id, 'warehouse_id', 1);
3164 } else {
3165 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->warehouse_id, 'none');
3166 }
3167 print '</td>';
3168 print '</tr>';
3169 }
3170
3171 // Source reason (why we have an order)
3172 print '<tr><td>';
3173 $editenable = $usercancreate;
3174 print $form->editfieldkey("Source", 'demandreason', '', $object, (int) $editenable);
3175 print '</td><td class="valuefield">';
3176 if ($action == 'editdemandreason') {
3177 $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->demand_reason_id, 'demand_reason_id', 1);
3178 } else {
3179 $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->demand_reason_id, 'none');
3180 }
3181 print '</td></tr>';
3182
3183 // Terms of payment
3184 print '<tr><td>';
3185 $editenable = $usercancreate;
3186 print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, (int) $editenable);
3187 print '</td><td class="valuefield">';
3188 if ($action == 'editconditions') {
3189 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
3190 } else {
3191 $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent);
3192 }
3193 print '</td>';
3194
3195 print '</tr>';
3196
3197 // Mode of payment
3198 print '<tr><td>';
3199 $editenable = $usercancreate;
3200 print $form->editfieldkey("PaymentMode", 'mode', '', $object, (int) $editenable);
3201 print '</td><td class="valuefield">';
3202 if ($action == 'editmode') {
3203 $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
3204 } else {
3205 $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->mode_reglement_id, 'none');
3206 }
3207 print '</td></tr>';
3208
3209 // TODO Order mode (how we receive order). Not yet implemented
3210 /*
3211 print '<tr><td>';
3212 $editenable = $usercancreate;
3213 print $form->editfieldkey("SourceMode", 'inputmode', '', $object, $editenable);
3214 print '</td><td>';
3215 if ($action == 'editinputmode') {
3216 $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'input_mode_id', 1);
3217 } else {
3218 $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'none');
3219 }
3220 print '</td></tr>';
3221 */
3222
3223 $tmparray = $object->getTotalWeightVolume();
3224 $totalWeight = $tmparray['weight'];
3225 $totalVolume = $tmparray['volume'];
3226 if ($totalWeight) {
3227 print '<tr><td>' . $langs->trans("CalculatedWeight") . '</td>';
3228 print '<td class="valuefield">';
3229 print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, getDolGlobalInt('MAIN_WEIGHT_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_WEIGHT_DEFAULT_UNIT', 'no'));
3230 print '</td></tr>';
3231 }
3232 if ($totalVolume) {
3233 print '<tr><td>' . $langs->trans("CalculatedVolume") . '</td>';
3234 print '<td class="valuefield">';
3235 print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_VOLUME_DEFAULT_UNIT', 'no'));
3236 print '</td></tr>';
3237 }
3238
3239 // TODO How record was recorded OrderMode (llx_c_input_method)
3240
3241 // Incoterms
3242 if (isModEnabled('incoterm')) {
3243 print '<tr><td>';
3244 $editenable = $usercancreate;
3245 print $form->editfieldkey("IncotermLabel", 'incoterm', '', $object, (int) $editenable);
3246 print '</td>';
3247 print '<td class="valuefield">';
3248 if ($action != 'editincoterm') {
3249 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
3250 } else {
3251 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'] . '?id=' . $object->id);
3252 }
3253 print '</td></tr>';
3254 }
3255
3256 // Bank Account
3257 if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_ORDER') && isModEnabled("bank")) {
3258 print '<tr><td>';
3259 $editenable = $usercancreate;
3260 print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, (int) $editenable);
3261 print '</td><td class="valuefield">';
3262 if ($action == 'editbankaccount') {
3263 $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_account, 'fk_account', 1);
3264 } else {
3265 $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_account, 'none');
3266 }
3267 print '</td>';
3268 print '</tr>';
3269 }
3270
3271 // Tags-Categories
3272 if (isModEnabled('category')) {
3273 print '<tr><td>';
3274 print '<table class="nobordernopadding centpercent"><tr><td>';
3275 print $langs->trans("Categories");
3276 print '<td><td class="right">';
3277 if ($usercancreate) {
3278 print '<a class="editfielda" href="' . DOL_URL_ROOT . '/commande/card.php?id=' . $object->id . '&action=edittags&token=' . newToken() . '">' . img_edit() . '</a>';
3279 } else {
3280 print '&nbsp;';
3281 }
3282 print '</td></tr></table>';
3283 print '</td>';
3284 print '<td>';
3285 if ($action == 'edittags') {
3286 print '<form method="POST" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
3287 print '<input type="hidden" name="action" value="settags">';
3288 print '<input type="hidden" name="token" value="' . newToken() . '">';
3289 print $form->selectCategories(Categorie::TYPE_ORDER, 'categories', $object);
3290 print '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
3291 print '</form>';
3292 } else {
3293 print $form->showCategories($object->id, Categorie::TYPE_ORDER, 1);
3294 }
3295 print "</td></tr>";
3296 }
3297
3298 // Other attributes
3299 include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
3300
3301 print '</table>';
3302
3303 print '</div>';
3304 print '<div class="fichehalfright">';
3305 print '<div class="underbanner clearboth"></div>';
3306
3307 print '<table class="border tableforfield centpercent">';
3308
3309 include DOL_DOCUMENT_ROOT . '/core/tpl/object_currency_amount.tpl.php';
3310
3311 $alert = '';
3312 if (getDolGlobalString('ORDER_MANAGE_MIN_AMOUNT') && $object->total_ht < $object->thirdparty->order_min_amount) {
3313 $alert = ' ' . img_warning($langs->trans('OrderMinAmount') . ': ' . price($object->thirdparty->order_min_amount));
3314 }
3315
3316 print '<tr>';
3317 print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
3318 print '<td class="nowrap amountcard right">' . price($object->total_ht, 0, $langs, 0, -1, -1, $conf->currency) . '</td>';
3319 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3320 // Multicurrency Amount HT
3321 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, 0, $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
3322 }
3323 print '</tr>';
3324
3325 print '<tr>';
3326 print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
3327 print '<td class="nowrap amountcard right">' . price($object->total_tva, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
3328 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3329 // Multicurrency Amount VAT
3330 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
3331 }
3332 print '</tr>';
3333
3334 // Amount Local Taxes
3335 if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
3336 print '<tr>';
3337 print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
3338 print '<td class="nowrap amountcard right">' . price($object->total_localtax1, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
3339 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3340 $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
3341
3342 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax1, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
3343 }
3344 print '</tr>';
3345 }
3346
3347 // Amount Local Taxes
3348 if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
3349 print '<tr>';
3350 print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
3351 print '<td class="nowrap amountcard right">' . price($object->total_localtax2, 0, $langs, 1, -1, -1, $conf->currency) . '</td>';
3352 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3353 $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
3354
3355 print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax2, 0, $langs, 1, -1, -1, $object->multicurrency_code) . '</td>';
3356 }
3357 print '</tr>';
3358 }
3359
3360 print '<tr>';
3361 print '<td>' . $langs->trans('AmountTTC') . '</td>';
3362 print '<td class="valuefield nowrap right amountcard">' . price($object->total_ttc, 1, '', 1, -1, -1, $conf->currency) . '</td>';
3363 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
3364 // Multicurrency Amount TTC
3365 print '<td class="valuefield nowrap right amountcard">' . price($object->multicurrency_total_ttc, 1, '', 1, -1, -1, $object->multicurrency_code) . '</td>';
3366 }
3367 print '</tr>' . "\n";
3368
3369 print '</table>';
3370
3371 // Statut
3372 //print '<tr><td>' . $langs->trans('Status') . '</td><td>' . $object->getLibStatut(4) . '</td></tr>';
3373
3374 // Margin Infos
3375 if (isModEnabled('margin')) {
3376 $formmargin->displayMarginInfos($object);
3377 }
3378
3379
3380 print '</div>';
3381 print '</div>'; // Close fichecenter
3382
3383 print '<div class="clearboth"></div><br>';
3384
3385 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
3386 $blocname = 'contacts';
3387 $title = $langs->trans('ContactsAddresses');
3388 include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
3389 }
3390
3391 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
3392 $blocname = 'notes';
3393 $title = $langs->trans('Notes');
3394 include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
3395 }
3396
3397 /*
3398 * Lines
3399 */
3400
3401 // Get object lines
3402 $result = $object->getLinesArray();
3403
3404 // Add products/services form
3405 //$forceall = 1;
3406 global $inputalsopricewithtax;
3407 $inputalsopricewithtax = 1;
3408
3409 print '<form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="POST">
3410 <input type="hidden" name="token" value="' . newToken() . '">
3411 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline') . '">
3412 <input type="hidden" name="mode" value="">
3413 <input type="hidden" name="page_y" value="">
3414 <input type="hidden" name="id" value="' . $object->id . '">
3415 <input type="hidden" name="backtopage" value="' . $backtopage . '">
3416 ';
3417
3418 if (!empty($conf->use_javascript_ajax) && $object->status == Commande::STATUS_DRAFT) {
3419 if (isModEnabled('subtotals')) {
3420 include DOL_DOCUMENT_ROOT . '/core/tpl/subtotal_ajaxrow.tpl.php';
3421 } else {
3422 include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
3423 }
3424 }
3425
3426 print '<div class="div-table-responsive-no-min">';
3427 print '<table id="tablelines" class="noborder noshadow" width="100%">';
3428
3429 // Show object lines
3430 if (!empty($object->lines)) {
3431 $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
3432 }
3433
3434 /*
3435 * Form to add new line
3436 */
3437 if ($object->status == Commande::STATUS_DRAFT && $usercancreate && $action != 'selectlines') {
3438 if ($action != 'editline') {
3439 // Add free products/services
3440
3441 $parameters = array();
3442 // Note that $action and $object may be modified by hook
3443 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action);
3444 if ($reshook < 0) {
3445 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
3446 }
3447 if (empty($reshook)) {
3448 $object->formAddObjectLine(1, $mysoc, $soc);
3449 }
3450 } else {
3451 $parameters = array();
3452 $reshook = $hookmanager->executeHooks('formEditObjectLine', $parameters, $object, $action);
3453 }
3454 }
3455 print '</table>';
3456 print '</div>';
3457
3458 print "</form>\n";
3459 }
3460
3461 print dol_get_fiche_end();
3462
3463 /*
3464 * Buttons for actions
3465 */
3466 if ($action != 'presend' && $action != 'editline') {
3467 print '<div class="tabsAction">';
3468
3469 $parameters = array();
3470 $arrayforbutaction = array();
3471 // Note that $action and $object may be modified by hook
3472 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
3473 if (empty($reshook)) {
3474 $numlines = count($object->lines);
3475
3476 // Reopen a closed order
3477 if (($object->status == Commande::STATUS_CLOSED || $object->status == Commande::STATUS_CANCELED) && $usercancreate && (!$object->billed || !getDolGlobalInt('ORDER_DONT_REOPEN_BILLED'))) {
3478 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"] . '?action=reopen&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3479 }
3480
3481 // Send
3482 if (empty($user->socid)) {
3483 if ($object->status > Commande::STATUS_DRAFT || getDolGlobalString('COMMANDE_SENDBYEMAIL_FOR_ALL_STATUS')) {
3484 if ($usercansend) {
3485 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER["PHP_SELF"] . '?action=presend&token=' . newToken() . '&id=' . $object->id . '&mode=init#formmailbeforetitle', '');
3486 } else {
3487 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER['PHP_SELF'] . '#', '', false);
3488 }
3489 }
3490 }
3491
3492 // Subtotal
3493 if ($object->status == Commande::STATUS_DRAFT && isModEnabled('subtotals')
3494 && (getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element)) || getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element)))) {
3495 $langs->load('subtotals');
3496
3497 $url_button = array();
3498
3499 $url_button[] = array(
3500 'lang' => 'subtotals',
3501 'enabled' => (isModEnabled('order') && $object->status == Commande::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_TITLE_'.strtoupper($object->element))),
3502 'perm' => (bool) $usercancreate,
3503 'label' => $langs->trans('AddTitleLine'),
3504 'url' => '/commande/card.php?id=' . $object->id . '&action=add_title_line&token=' . newToken()
3505 );
3506
3507 $url_button[] = array(
3508 'lang' => 'subtotals',
3509 'enabled' => (isModEnabled('order') && $object->status == Commande::STATUS_DRAFT && getDolGlobalInt('SUBTOTAL_'.strtoupper($object->element))),
3510 'perm' => (bool) $usercancreate,
3511 'label' => $langs->trans('AddSubtotalLine'),
3512 'url' => '/commande/card.php?id=' . $object->id . '&action=add_subtotal_line&token=' . newToken()
3513 );
3514 print dolGetButtonAction('', $langs->trans('SubTotal'), 'default', $url_button, '', true);
3515 }
3516
3517 // Valid
3518 if ($object->status == Commande::STATUS_DRAFT && ($object->total_ttc >= 0 || getDolGlobalString('ORDER_ENABLE_NEGATIVE')) && $usercanvalidate) {
3519 if ($numlines > 0) {
3520 print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"] . '?action=validate&token=' . newToken() . '&id=' . $object->id, 'action-validate', 1);
3521 } else {
3522 $langs->load("errors");
3523 print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"] . '?action=validate&token=' . newToken() . '&id=' . $object->id, 'action-validate', -1);
3524 }
3525 }
3526 // Edit
3527 if (($object->status == Commande::STATUS_VALIDATED || ($object->status == Commande::STATUS_SHIPMENTONPROCESS && getDolGlobalString('EDIT_ORDER_SHIPMENT_ON_PROCESS'))) && $usercancreate) {
3528 print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"] . '?action=modif&token=' . newToken() . '&id=' . $object->id, 'action-modif');
3529 }
3530
3531 // Create a purchase order
3532
3533 if (!getDolGlobalInt('COMMANDE_DISABLE_ADD_PURCHASE_ORDER')) {
3534 $arrayforbutaction[] = array(
3535 'lang' => 'orders',
3536 'enabled' => (isModEnabled("supplier_order") && $object->status > Commande::STATUS_DRAFT),
3537 'perm' => $usercancreatepurchaseorder,
3538 'label' => 'AddPurchaseOrder',
3539 'url' => '/fourn/commande/card.php?action=create&amp;origin=' . urlencode($object->element) . '&amp;originid=' . ((int) $object->id)
3540 );
3541 }
3542
3543 /*if (isModEnabled("supplier_order") && $object->status > Commande::STATUS_DRAFT && $object->getNbOfServicesLines() > 0) {
3544 if ($usercancreatepurchaseorder) { isModEnabled("supplier_order") && $object->status > Commande::STATUS_DRAFT && $object->getNbOfServicesLines() > 0
3545 print dolGetButtonAction('', $langs->trans('AddPurchaseOrder'), 'default', DOL_URL_ROOT.'/fourn/commande/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id, '');
3546 }
3547 }*/
3548
3549 // Create intervention
3550 if (!getDolGlobalInt('COMMANDE_DISABLE_ADD_INTERVENTION')) {
3551 $arrayforbutaction[] = array(
3552 'lang' => 'interventions',
3553 'enabled' => (isModEnabled("intervention") && $object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0),
3554 'perm' => ($user->hasRight('ficheinter', 'creer') == 1),
3555 'label' => 'AddIntervention',
3556 'url' => '/fichinter/card.php?action=create&origin=' . urlencode($object->element) . '&originid=' . ((int) $object->id) . '&socid=' . ((int) $object->socid),
3557 );
3558 }
3559
3560 // Create contract
3561 if (!getDolGlobalInt('COMMANDE_DISABLE_ADD_CONTRACT')) {
3562 $arrayforbutaction[] = [
3563 'lang' => 'contracts',
3564 'enabled' => (isModEnabled("contract") && ($object->status == Commande::STATUS_VALIDATED || $object->status == Commande::STATUS_SHIPMENTONPROCESS || $object->status == Commande::STATUS_CLOSED)),
3565 'perm' => ($user->hasRight('contrat', 'creer') == 1),
3566 'label' => 'AddContract',
3567 'url' => '/contrat/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid,
3568 ];
3569 }
3570 /*if (isModEnabled('contract') && ($object->status == Commande::STATUS_VALIDATED || $object->status == Commande::STATUS_SHIPMENTONPROCESS || $object->status == Commande::STATUS_CLOSED)) {
3571 $langs->load("contracts");
3572
3573 if ($user->hasRight('contrat', 'creer')) {
3574 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, '');
3575 }
3576 }*/
3577
3578 $numshipping = 0;
3579
3580 // Create shipment
3581 if (isModEnabled('shipping')) {
3582 $numshipping = $object->countNbOfShipments();
3583
3584 if ($object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3585 if ((getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION') && $user->hasRight('expedition', 'creer')) || (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') && $user->hasRight('expedition', 'delivery', 'creer'))) {
3586 // Add button to create shipment into the combo
3587 $arrayforbutaction[] = array(
3588 'lang' => 'sendings',
3589 'enabled' => (isModEnabled("shipping") && ($object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || getDolGlobalString('STOCK_SUPPORTS_SERVICES')))),
3590 'perm' => $user->hasRight('expedition', 'creer'),
3591 'label' => 'CreateShipment',
3592 'url' => '/expedition/shipment.php?id=' . $object->id
3593 );
3594 } else {
3595 //c$langs->load("errors");
3596 //print dolGetButtonAction($langs->trans('ErrorModuleSetupNotComplete'), $langs->trans('CreateShipment'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
3597 $arrayforbutaction[] = array(
3598 'lang' => 'sendings',
3599 'enabled' => (isModEnabled("shipping") && ($object->status > Commande::STATUS_DRAFT && $object->status < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || getDolGlobalString('STOCK_SUPPORTS_SERVICES')))),
3600 'perm' => 0,
3601 'label' => 'CreateShipment',
3602 'url' => '/expedition/shipment.php?id=' . $object->id
3603 );
3604 }
3605 }
3606 }
3607
3608 // Create bill
3609 $arrayforbutaction[] = array(
3610 'lang' => 'bills',
3611 'enabled' => (isModEnabled('invoice') && $object->status > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0),
3612 'perm' => ($user->hasRight('facture', 'creer') && !getDolGlobalInt('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')),
3613 'label' => 'CreateBill',
3614 'url' => '/compta/facture/card.php?action=create&amp;token=' . newToken() . '&amp;origin=' . urlencode($object->element) . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid
3615 );
3616 /*
3617 if (isModEnabled('facture') && $object->status > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) {
3618 if (isModEnabled('facture') && $user->hasRight('facture', 'creer') && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) {
3619 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, '');
3620 }
3621 }*/
3622
3623 $actionButtonsParameters = [
3624 "areDropdownButtons" => !getDolGlobalInt("MAIN_REMOVE_DROPDOWN_CREATE_BUTTONS_ON_ORDER")
3625 ];
3626
3627 if ($numlines > 0) {
3628 print dolGetButtonAction('', $langs->trans("Create"), 'default', $arrayforbutaction, (string) $object->id, 1, $actionButtonsParameters);
3629 } else {
3630 print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans("Create"), 'default', $arrayforbutaction, (string) $object->id, 0, $actionButtonsParameters);
3631 }
3632
3633 // Set to shipped
3634 if (($object->status == Commande::STATUS_VALIDATED || $object->status == Commande::STATUS_SHIPMENTONPROCESS) && $usercanclose) {
3635 print dolGetButtonAction('', $langs->trans('ClassifyShipped'), 'default', $_SERVER["PHP_SELF"] . '?action=shipped&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3636 }
3637
3638 // Set billed or unbilled
3639 // Note: Even if module invoice is not enabled, we should be able to use button "Classified billed"
3640 if ($object->status > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) {
3641 if ($usercancreate && $object->status >= Commande::STATUS_VALIDATED && !getDolGlobalString('ORDER_DISABLE_CLASSIFY_BILLED_FROM_ORDER') && !getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')) {
3642 print dolGetButtonAction('', $langs->trans('ClassifyBilled'), 'default', $_SERVER["PHP_SELF"] . '?action=classifybilled&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3643 }
3644 }
3645 if ($object->status > Commande::STATUS_DRAFT && $object->billed) {
3646 if ($usercancreate && $object->status >= Commande::STATUS_VALIDATED && !getDolGlobalString('ORDER_DISABLE_CLASSIFY_BILLED_FROM_ORDER') && !getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')) {
3647 print dolGetButtonAction('', $langs->trans('ClassifyUnBilled'), 'delete', $_SERVER["PHP_SELF"] . '?action=classifyunbilled&amp;token=' . newToken() . '&amp;id=' . $object->id, '');
3648 }
3649 }
3650
3651 // Clone
3652 if ($usercancreate) {
3653 print dolGetButtonAction('', $langs->trans('ToClone'), 'clone', $_SERVER["PHP_SELF"] . '?action=clone&token=' . newToken() . '&id=' . $object->id . '&socid=' . $object->socid, '');
3654 }
3655
3656 // Cancel order
3657 if ($object->status == Commande::STATUS_VALIDATED && !empty($usercancancel)) {
3658 print '<a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=cancel&token=' . newToken() . '">' . $langs->trans("CancelOrder") . '</a>';
3659 }
3660
3661 // Delete order
3662 if ($usercandelete) {
3663 if ($numshipping == 0) {
3664 print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"] . '?action=delete&token=' . newToken() . '&id=' . $object->id, '');
3665 } else {
3666 print dolGetButtonAction($langs->trans('ShippingExist'), $langs->trans('Delete'), 'default', $_SERVER['PHP_SELF'] . '#', '', false);
3667 }
3668 }
3669 }
3670 print '</div>';
3671 }
3672
3673 // Select mail models is same action as presend
3674 if (GETPOST('modelselected')) {
3675 $action = 'presend';
3676 }
3677
3678 if ($action != 'presend') {
3679 print '<div class="fichecenter"><div class="fichehalfleft">';
3680 print '<a name="builddoc"></a>'; // ancre
3681 // Documents
3682 $objref = dol_sanitizeFileName($object->ref);
3683 $relativepath = $objref . '/' . $objref . '.pdf';
3684 $filedir = $conf->commande->multidir_output[$object->entity ?? $conf->entity] . '/' . $objref;
3685 $urlsource = dolBuildUrl($_SERVER["PHP_SELF"], ["id" => $object->id]);
3686 $genallowed = $usercanread;
3687 $delallowed = $usercancreate;
3688 $tooltipAfterComboOfModels = '';
3689 if (getDolGlobalString('MAIN_PDF_ADD_TERMSOFSALE_ORDER')) {
3690 $tooltipAfterComboOfModels = $langs->trans("AccordingToYourSetupTheFileWillBeConcatenated", getDolGlobalString('MAIN_INFO_ORDER_TERMSOFSALE'));
3691 }
3692
3693 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);
3694
3695
3696 // Show links to link elements
3697 $tmparray = $form->showLinkToObjectBlock($object, array(), array('order'), 1);
3698 $linktoelem = $tmparray['linktoelem'];
3699 $htmltoenteralink = $tmparray['htmltoenteralink'];
3700 print $htmltoenteralink;
3701
3702 $compatibleImportElementsList = false;
3703 if (
3704 $usercancreate
3705 && $object->status == Commande::STATUS_DRAFT
3706 ) {
3707 $compatibleImportElementsList = array('commande', 'propal', 'facture', 'subscription'); // import from linked elements
3708 }
3709 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
3710
3711 // Show online payment link
3712 // The list can be complete by the hook 'doValidatePayment' executed inside getValidOnlinePaymentMethods()
3713 include_once DOL_DOCUMENT_ROOT . '/core/lib/payments.lib.php';
3714 $validpaymentmethod = getValidOnlinePaymentMethods('');
3715 $useonlinepayment = count($validpaymentmethod);
3716
3717 if (getDolGlobalString('ORDER_HIDE_ONLINE_PAYMENT_ON_ORDER')) {
3718 $useonlinepayment = 0;
3719 }
3720 if ($object->status != Commande::STATUS_DRAFT && $useonlinepayment) {
3721 print '<br><!-- Link to pay -->';
3722 require_once DOL_DOCUMENT_ROOT . '/core/lib/payments.lib.php';
3723 print showOnlinePaymentUrl('order', $object->ref) . '<br>';
3724 }
3725
3726 print '</div><div class="fichehalfright">';
3727
3728 $MAXEVENT = 10;
3729
3730 //button to go to messaging from the events box
3731 $morehtmlcenter = dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', dolBuildUrl(DOL_URL_ROOT . '/commande/messaging.php', ['id' => $object->id]));
3732 $morehtmlcenter .= dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dolBuildUrl(DOL_URL_ROOT . '/commande/agenda.php', ['id' => $object->id]));
3733
3734 // List of actions on element
3735 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
3736 $formactions = new FormActions($db);
3737 $somethingshown = $formactions->showactions($object, 'order', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter); // Show all action for thirdparty
3738
3739 print '</div></div>';
3740 }
3741
3742 // Presend form
3743 $modelmail = 'order_send';
3744 $defaulttopic = 'SendOrderRef';
3745 $diroutput = getMultidirOutput($object);
3746 $trackid = 'ord' . $object->id;
3747
3748 include DOL_DOCUMENT_ROOT . '/core/tpl/card_presend.tpl.php';
3749 }
3750}
3751
3752// End of page
3753llxFooter();
3754$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, $mode=0)
Check permissions of a user to show a page and an object.