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