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