dolibarr  18.0.6
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-2013 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-2021 Frédéric France <frederic.france@netlogic.fr>
16  * Copyright (C) 2022 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
17  * Copyright (C) 2023 Benjamin Falière <benjamin.faliere@altairis.fr>
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <https://www.gnu.org/licenses/>.
31  */
32 
39 // Load Dolibarr environment
40 require '../main.inc.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
42 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
43 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
44 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formorder.class.php';
45 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmargin.class.php';
46 require_once DOL_DOCUMENT_ROOT.'/core/modules/commande/modules_commande.php';
47 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
48 require_once DOL_DOCUMENT_ROOT.'/core/lib/order.lib.php';
49 
50 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
51 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
52 
53 if (isModEnabled("propal")) {
54  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
55 }
56 
57 if (isModEnabled('project')) {
58  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
59  require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
60 }
61 
62 if (isModEnabled('variants')) {
63  require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
64 }
65 
66 
67 // Load translation files required by the page
68 $langs->loadLangs(array('orders', 'sendings', 'companies', 'bills', 'propal', 'deliveries', 'products', 'other'));
69 
70 if (isModEnabled('incoterm')) {
71  $langs->load('incoterm');
72 }
73 if (isModEnabled('margin')) {
74  $langs->load('margins');
75 }
76 if (isModEnabled('productbatch')) {
77  $langs->load('productbatch');
78 }
79 
80 
81 $id = (GETPOST('id', 'int') ? GETPOST('id', 'int') : GETPOST('orderid', 'int'));
82 $ref = GETPOST('ref', 'alpha');
83 $socid = GETPOST('socid', 'int');
84 $action = GETPOST('action', 'aZ09');
85 $cancel = GETPOST('cancel', 'alpha');
86 $confirm = GETPOST('confirm', 'alpha');
87 $backtopage = GETPOST('backtopage', 'alpha');
88 
89 $lineid = GETPOST('lineid', 'int');
90 $contactid = GETPOST('contactid', 'int');
91 $projectid = GETPOST('projectid', 'int');
92 $origin = GETPOST('origin', 'alpha');
93 $originid = (GETPOST('originid', 'int') ? GETPOST('originid', 'int') : GETPOST('origin_id', 'int')); // For backward compatibility
94 $rank = (GETPOST('rank', 'int') > 0) ? GETPOST('rank', 'int') : -1;
95 
96 // PDF
97 $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
98 $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
99 $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
100 
101 // Security check
102 if (!empty($user->socid)) {
103  $socid = $user->socid;
104 }
105 
106 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
107 $hookmanager->initHooks(array('ordercard', 'globalcard'));
108 
109 $result = restrictedArea($user, 'commande', $id);
110 
111 $object = new Commande($db);
112 $extrafields = new ExtraFields($db);
113 
114 // fetch optionals attributes and labels
115 $extrafields->fetch_name_optionals_label($object->table_element);
116 
117 // Load object
118 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
119 
120 // Permissions / Rights
121 $usercanread = $user->hasRight("commande", "lire");
122 $usercancreate = $user->hasRight("commande", "creer");
123 $usercandelete = $user->hasRight("commande", "supprimer");
124 
125 // Advanced permissions
126 $usercanclose = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($usercancreate)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->hasRight('commande', 'order_advance', 'close')));
127 $usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->hasRight('commande', 'order_advance', 'validate')));
128 $usercancancel = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->hasRight('commande', 'order_advance', 'annuler')));
129 $usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->hasRight('commande', 'order_advance', 'send'));
130 $usercangeneretedoc = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->hasRight('commande', 'order_advance', 'generetedoc'));
131 
132 $usermustrespectpricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
133 $usercancreatepurchaseorder = ($user->hasRight('fournisseur', 'commande', 'creer') || $user->hasRight('supplier_order', 'creer'));
134 
135 $permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php
136 $permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php
137 $permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
138 
139 
140 $error = 0;
141 
142 $date_delivery = dol_mktime(GETPOST('liv_hour', 'int'), GETPOST('liv_min', 'int'), 0, GETPOST('liv_month', 'int'), GETPOST('liv_day', 'int'), GETPOST('liv_year', 'int'));
143 
144 
145 /*
146  * Actions
147  */
148 
149 $parameters = array('socid' => $socid);
150 // Note that $action and $object may be modified by some hooks
151 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
152 if ($reshook < 0) {
153  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
154 }
155 
156 if (empty($reshook)) {
157  $backurlforlist = DOL_URL_ROOT.'/commande/list.php';
158 
159  if (empty($backtopage) || ($cancel && empty($id))) {
160  if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
161  if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
162  $backtopage = $backurlforlist;
163  } else {
164  $backtopage = DOL_URL_ROOT.'/commande/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
165  }
166  }
167  }
168 
169  if ($cancel) {
170  if (!empty($backtopageforcancel)) {
171  header("Location: ".$backtopageforcancel);
172  exit;
173  } elseif (!empty($backtopage)) {
174  header("Location: ".$backtopage);
175  exit;
176  }
177  $action = '';
178  }
179 
180  include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once
181 
182  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
183 
184  include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once
185 
186  // Action clone object
187  if ($action == 'confirm_clone' && $confirm == 'yes' && $usercancreate) {
188  if (1 == 0 && !GETPOST('clone_content') && !GETPOST('clone_receivers')) {
189  setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
190  } else {
191  if ($object->id > 0) {
192  // Because createFromClone modifies the object, we must clone it so that we can restore it later
193  $orig = clone $object;
194 
195  $result = $object->createFromClone($user, $socid);
196  if ($result > 0) {
197  header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result);
198  exit;
199  } else {
200  setEventMessages($object->error, $object->errors, 'errors');
201  $object = $orig;
202  $action = '';
203  }
204  }
205  }
206  } elseif ($action == 'reopen' && $usercancreate) {
207  // Reopen a closed order
208  if ($object->statut == Commande::STATUS_CANCELED || $object->statut == Commande::STATUS_CLOSED) {
209  $result = $object->set_reopen($user);
210  if ($result > 0) {
211  setEventMessages($langs->trans('OrderReopened', $object->ref), null);
212  } else {
213  setEventMessages($object->error, $object->errors, 'errors');
214  }
215  }
216  } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $usercandelete) {
217  // Remove order
218  $result = $object->delete($user);
219  if ($result > 0) {
220  header('Location: list.php?restore_lastsearch_values=1');
221  exit;
222  } else {
223  setEventMessages($object->error, $object->errors, 'errors');
224  }
225  } elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
226  // Remove a product line
227  $result = $object->deleteline($user, $lineid);
228  if ($result > 0) {
229  // reorder lines
230  $object->line_order(true);
231  // Define output language
232  $outputlangs = $langs;
233  $newlang = '';
234  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
235  $newlang = GETPOST('lang_id', 'aZ09');
236  }
237  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
238  $newlang = $object->thirdparty->default_lang;
239  }
240  if (!empty($newlang)) {
241  $outputlangs = new Translate("", $conf);
242  $outputlangs->setDefaultLang($newlang);
243  }
244  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
245  $ret = $object->fetch($object->id); // Reload to get new records
246  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
247  }
248 
249  header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
250  exit;
251  } else {
252  setEventMessages($object->error, $object->errors, 'errors');
253  }
254  } elseif ($action == 'classin' && $usercancreate) {
255  // Link to a project
256  $object->setProject(GETPOST('projectid', 'int'));
257  } elseif ($action == 'add' && $usercancreate) {
258  // Add order
259  $datecommande = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
260  $date_delivery = dol_mktime(GETPOST('liv_hour', 'int'), GETPOST('liv_min', 'int'), 0, GETPOST('liv_month', 'int'), GETPOST('liv_day', 'int'), GETPOST('liv_year', 'int'));
261  $selectedLines = GETPOST('toselect', 'array');
262 
263  if ($datecommande == '') {
264  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Date')), null, 'errors');
265  $action = 'create';
266  $error++;
267  }
268 
269  if ($socid < 1) {
270  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Customer")), null, 'errors');
271  $action = 'create';
272  $error++;
273  }
274 
275  if (!$error) {
276  $object->socid = $socid;
277  $object->fetch_thirdparty();
278 
279  $db->begin();
280 
281  $object->date_commande = $datecommande;
282  $object->note_private = GETPOST('note_private', 'restricthtml');
283  $object->note_public = GETPOST('note_public', 'restricthtml');
284  $object->source = GETPOST('source_id');
285  $object->fk_project = GETPOST('projectid', 'int');
286  $object->ref_client = GETPOST('ref_client', 'alpha');
287  $object->model_pdf = GETPOST('model');
288  $object->cond_reglement_id = GETPOST('cond_reglement_id');
289  $object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
290  $object->mode_reglement_id = GETPOST('mode_reglement_id');
291  $object->fk_account = GETPOST('fk_account', 'int');
292  $object->availability_id = GETPOST('availability_id');
293  $object->demand_reason_id = GETPOST('demand_reason_id');
294  $object->date_livraison = $date_delivery; // deprecated
295  $object->delivery_date = $date_delivery;
296  $object->shipping_method_id = GETPOST('shipping_method_id', 'int');
297  $object->warehouse_id = GETPOST('warehouse_id', 'int');
298  $object->fk_delivery_address = GETPOST('fk_address');
299  $object->contact_id = GETPOST('contactid');
300  $object->fk_incoterms = GETPOST('incoterm_id', 'int');
301  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
302  $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
303  $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
304  // Fill array 'array_options' with data from add form
305  if (!$error) {
306  $ret = $extrafields->setOptionalsFromPost(null, $object);
307  if ($ret < 0) {
308  $error++;
309  }
310  }
311 
312  // If creation from another object of another module (Example: origin=propal, originid=1)
313  if (!empty($origin) && !empty($originid)) {
314  // Parse element/subelement (ex: project_task)
315  $element = $subelement = $origin;
316  $regs = array();
317  if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
318  $element = $regs [1];
319  $subelement = $regs [2];
320  }
321 
322  // For compatibility
323  if ($element == 'order') {
324  $element = $subelement = 'commande';
325  }
326  if ($element == 'propal') {
327  $element = 'comm/propal';
328  $subelement = 'propal';
329  }
330  if ($element == 'contract') {
331  $element = $subelement = 'contrat';
332  }
333 
334  $object->origin = $origin;
335  $object->origin_id = $originid;
336 
337  // Possibility to add external linked objects with hooks
338  $object->linked_objects [$object->origin] = $object->origin_id;
339  $other_linked_objects = GETPOST('other_linked_objects', 'array');
340  if (!empty($other_linked_objects)) {
341  $object->linked_objects = array_merge($object->linked_objects, $other_linked_objects);
342  }
343 
344  if (!$error) {
345  $object_id = $object->create($user);
346 
347  if ($object_id > 0) {
348  dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
349 
350  $classname = ucfirst($subelement);
351  $srcobject = new $classname($db);
352 
353  dol_syslog("Try to find source object origin=".$object->origin." originid=".$object->origin_id." to add lines");
354  $result = $srcobject->fetch($object->origin_id);
355  if ($result > 0) {
356  $lines = $srcobject->lines;
357  if (empty($lines) && method_exists($srcobject, 'fetch_lines')) {
358  $srcobject->fetch_lines();
359  $lines = $srcobject->lines;
360  }
361 
362  $fk_parent_line = 0;
363  $num = count($lines);
364 
365  for ($i = 0; $i < $num; $i++) {
366  if (!in_array($lines[$i]->id, $selectedLines)) {
367  continue; // Skip unselected lines
368  }
369 
370  $label = (!empty($lines[$i]->label) ? $lines[$i]->label : '');
371  $desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : '');
372  $product_type = (!empty($lines[$i]->product_type) ? $lines[$i]->product_type : 0);
373 
374  // Dates
375  // TODO mutualiser
376  $date_start = $lines[$i]->date_debut_prevue;
377  if ($lines[$i]->date_debut_reel) {
378  $date_start = $lines[$i]->date_debut_reel;
379  }
380  if ($lines[$i]->date_start) {
381  $date_start = $lines[$i]->date_start;
382  }
383  $date_end = $lines[$i]->date_fin_prevue;
384  if ($lines[$i]->date_fin_reel) {
385  $date_end = $lines[$i]->date_fin_reel;
386  }
387  if ($lines[$i]->date_end) {
388  $date_end = $lines[$i]->date_end;
389  }
390 
391  // Reset fk_parent_line for no child products and special product
392  if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
393  $fk_parent_line = 0;
394  }
395 
396  // Extrafields
397  if (method_exists($lines[$i], 'fetch_optionals')) { // For avoid conflicts if trigger used
398  $lines[$i]->fetch_optionals();
399  $array_options = $lines[$i]->array_options;
400  }
401 
402  $tva_tx = $lines[$i]->tva_tx;
403  if (!empty($lines[$i]->vat_src_code) && !preg_match('/\‍(/', $tva_tx)) {
404  $tva_tx .= ' ('.$lines[$i]->vat_src_code.')';
405  }
406 
407  $result = $object->addline(
408  $desc,
409  $lines[$i]->subprice,
410  $lines[$i]->qty,
411  $tva_tx,
412  $lines[$i]->localtax1_tx,
413  $lines[$i]->localtax2_tx,
414  $lines[$i]->fk_product,
415  $lines[$i]->remise_percent,
416  $lines[$i]->info_bits,
417  $lines[$i]->fk_remise_except,
418  'HT',
419  0,
420  $date_start,
421  $date_end,
422  $product_type,
423  $lines[$i]->rang,
424  $lines[$i]->special_code,
425  $fk_parent_line,
426  $lines[$i]->fk_fournprice,
427  $lines[$i]->pa_ht,
428  $label,
429  $array_options,
430  $lines[$i]->fk_unit,
431  $object->origin,
432  $lines[$i]->rowid
433  );
434 
435  if ($result < 0) {
436  $error++;
437  break;
438  }
439 
440  // Defined the new fk_parent_line
441  if ($result > 0 && $lines[$i]->product_type == 9) {
442  $fk_parent_line = $result;
443  }
444  }
445  } else {
446  setEventMessages($srcobject->error, $srcobject->errors, 'errors');
447  $error++;
448  }
449 
450  // Now we create same links to contact than the ones found on origin object
451  /* Useless, already into the create
452  if (!empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN))
453  {
454  $originforcontact = $object->origin;
455  $originidforcontact = $object->origin_id;
456  if ($originforcontact == 'shipping') // shipment and order share the same contacts. If creating from shipment we take data of order
457  {
458  $originforcontact=$srcobject->origin;
459  $originidforcontact=$srcobject->origin_id;
460  }
461  $sqlcontact = "SELECT code, fk_socpeople FROM ".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as ctc";
462  $sqlcontact.= " WHERE element_id = ".((int) $originidforcontact)." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$db->escape($originforcontact)."'";
463 
464  $resqlcontact = $db->query($sqlcontact);
465  if ($resqlcontact)
466  {
467  while($objcontact = $db->fetch_object($resqlcontact))
468  {
469  //print $objcontact->code.'-'.$objcontact->fk_socpeople."\n";
470  $object->add_contact($objcontact->fk_socpeople, $objcontact->code);
471  }
472  }
473  else dol_print_error($resqlcontact);
474  }*/
475 
476  // Hooks
477  $parameters = array('objFrom' => $srcobject);
478  // Note that $action and $object may be modified by hook
479  $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action);
480  if ($reshook < 0) {
481  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
482  $error++;
483  }
484  } else {
485  setEventMessages($object->error, $object->errors, 'errors');
486  $error++;
487  }
488  } else {
489  // Required extrafield left blank, error message already defined by setOptionalsFromPost()
490  $action = 'create';
491  }
492  } else {
493  if (!$error) {
494  $object_id = $object->create($user);
495  }
496  }
497 
498  // Insert default contacts if defined
499  if ($object_id > 0) {
500  if (GETPOST('contactid', 'int')) {
501  $result = $object->add_contact(GETPOST('contactid', 'int'), 'CUSTOMER', 'external');
502  if ($result < 0) {
503  setEventMessages($langs->trans("ErrorFailedToAddContact"), null, 'errors');
504  $error++;
505  }
506  }
507 
508  $id = $object_id;
509  $action = '';
510  }
511 
512  // End of object creation, we show it
513  if ($object_id > 0 && !$error) {
514  $db->commit();
515  header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object_id);
516  exit();
517  } else {
518  $db->rollback();
519  $action = 'create';
520  setEventMessages($object->error, $object->errors, 'errors');
521  }
522  }
523  } elseif ($action == 'classifybilled' && $usercancreate) {
524  $ret = $object->classifyBilled($user);
525 
526  if ($ret < 0) {
527  setEventMessages($object->error, $object->errors, 'errors');
528  }
529  } elseif ($action == 'classifyunbilled' && $usercancreate) {
530  $ret = $object->classifyUnBilled($user);
531  if ($ret < 0) {
532  setEventMessages($object->error, $object->errors, 'errors');
533  }
534  } elseif ($action == 'setref_client' && $usercancreate) {
535  // Positionne ref commande client
536  $result = $object->set_ref_client($user, GETPOST('ref_client'));
537  if ($result < 0) {
538  setEventMessages($object->error, $object->errors, 'errors');
539  }
540  } elseif ($action == 'setremise' && $usercancreate) {
541  $result = $object->setDiscount($user, price2num(GETPOST('remise'), 2));
542  if ($result < 0) {
543  setEventMessages($object->error, $object->errors, 'errors');
544  }
545  } elseif ($action == 'setabsolutediscount' && $usercancreate) {
546  if (GETPOST('remise_id')) {
547  if ($object->id > 0) {
548  $object->insert_discount(GETPOST('remise_id'));
549  } else {
550  dol_print_error($db, $object->error);
551  }
552  }
553  } elseif ($action == 'setdate' && $usercancreate) {
554  $date = dol_mktime(0, 0, 0, GETPOST('order_month', 'int'), GETPOST('order_day', 'int'), GETPOST('order_year', 'int'));
555 
556  $result = $object->set_date($user, $date);
557  if ($result < 0) {
558  setEventMessages($object->error, $object->errors, 'errors');
559  }
560  } elseif ($action == 'setdate_livraison' && $usercancreate) {
561  $date_delivery = dol_mktime(GETPOST('liv_hour', 'int'), GETPOST('liv_min', 'int'), 0, GETPOST('liv_month', 'int'), GETPOST('liv_day', 'int'), GETPOST('liv_year', 'int'));
562 
563  $object->fetch($id);
564  $result = $object->setDeliveryDate($user, $date_delivery);
565  if ($result < 0) {
566  setEventMessages($object->error, $object->errors, 'errors');
567  }
568  } elseif ($action == 'setmode' && $usercancreate) {
569  $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
570  if ($result < 0) {
571  setEventMessages($object->error, $object->errors, 'errors');
572  }
573  } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
574  // Multicurrency Code
575  $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
576  } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
577  // Multicurrency rate
578  $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx')), GETPOST('calculation_mode', 'int'));
579  } elseif ($action == 'setavailability' && $usercancreate) {
580  $result = $object->availability(GETPOST('availability_id'));
581  if ($result < 0) {
582  setEventMessages($object->error, $object->errors, 'errors');
583  }
584  } elseif ($action == 'setdemandreason' && $usercancreate) {
585  $result = $object->demand_reason(GETPOST('demand_reason_id'));
586  if ($result < 0) {
587  setEventMessages($object->error, $object->errors, 'errors');
588  }
589  } elseif ($action == 'setconditions' && $usercancreate) {
590  $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'alpha'));
591  if ($result < 0) {
592  dol_print_error($db, $object->error);
593  } else {
594  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
595  // Define output language
596  $outputlangs = $langs;
597  $newlang = GETPOST('lang_id', 'alpha');
598  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
599  $newlang = $object->thirdparty->default_lang;
600  }
601  if (!empty($newlang)) {
602  $outputlangs = new Translate("", $conf);
603  $outputlangs->setDefaultLang($newlang);
604  }
605 
606  $ret = $object->fetch($object->id); // Reload to get new records
607  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
608  }
609  }
610  } elseif ($action == 'set_incoterms' && isModEnabled('incoterm')) {
611  // Set incoterm
612  $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
613  if ($result < 0) {
614  setEventMessages($object->error, $object->errors, 'errors');
615  }
616  } elseif ($action == 'setbankaccount' && $usercancreate) {
617  // bank account
618  $result = $object->setBankAccount(GETPOST('fk_account', 'int'));
619  if ($result < 0) {
620  setEventMessages($object->error, $object->errors, 'errors');
621  }
622  } elseif ($action == 'setshippingmethod' && $usercancreate) {
623  // shipping method
624  $result = $object->setShippingMethod(GETPOST('shipping_method_id', 'int'));
625  if ($result < 0) {
626  setEventMessages($object->error, $object->errors, 'errors');
627  }
628  } elseif ($action == 'setwarehouse' && $usercancreate) {
629  // warehouse
630  $result = $object->setWarehouse(GETPOST('warehouse_id', 'int'));
631  if ($result < 0) {
632  setEventMessages($object->error, $object->errors, 'errors');
633  }
634  } elseif ($action == 'setremisepercent' && $usercancreate) {
635  $result = $object->setDiscount($user, price2num(GETPOST('remise_percent'), '', 2));
636  } elseif ($action == 'setremiseabsolue' && $usercancreate) {
637  $result = $object->set_remise_absolue($user, price2num(GETPOST('remise_absolue'), 'MU', 2));
638  } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('vatforalllines', 'alpha') !== '') {
639  // Define vat_rate
640  $vat_rate = (GETPOST('vatforalllines') ? GETPOST('vatforalllines') : 0);
641  $vat_rate = str_replace('*', '', $vat_rate);
642  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
643  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
644  foreach ($object->lines as $line) {
645  $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
646  }
647  } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) {
648  // Define remise_percent
649  $remise_percent = (GETPOST('remiseforalllines') ? GETPOST('remiseforalllines') : 0);
650  $remise_percent = str_replace('*', '', $remise_percent);
651  foreach ($object->lines as $line) {
652  $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $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->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice);
653  }
654  } elseif ($action == 'addline' && $usercancreate) { // Add a new line
655  $langs->load('errors');
656  $error = 0;
657 
658  // Set if we used free entry or predefined product
659  $predef = '';
660  $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
661 
662  $price_ht = '';
663  $price_ht_devise = '';
664  $price_ttc = '';
665  $price_ttc_devise = '';
666  $pu_ht = '';
667  $pu_ttc = '';
668  $pu_ht_devise = '';
669  $pu_ttc_devise = '';
670 
671  if (GETPOST('price_ht') !== '') {
672  $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
673  }
674  if (GETPOST('multicurrency_price_ht') !== '') {
675  $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
676  }
677  if (GETPOST('price_ttc') !== '') {
678  $price_ttc = price2num(GETPOST('price_ttc'), 'MU', 2);
679  }
680  if (GETPOST('multicurrency_price_ttc') !== '') {
681  $price_ttc_devise = price2num(GETPOST('multicurrency_price_ttc'), 'CU', 2);
682  }
683 
684  $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09');
685  if ($prod_entry_mode == 'free') {
686  $idprod = 0;
687  } else {
688  $idprod = GETPOST('idprod', 'int');
689 
690  if (!empty($conf->global->MAIN_DISABLE_FREE_LINES) && $idprod <= 0) {
691  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
692  $error++;
693  }
694  }
695 
696  $tva_tx = GETPOST('tva_tx', 'alpha');
697 
698  $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
699 
700  $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0);
701  if (empty($remise_percent)) {
702  $remise_percent = 0;
703  }
704 
705  // Extrafields
706  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
707  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
708  // Unset extrafield
709  if (is_array($extralabelsline)) {
710  // Get extra fields
711  foreach ($extralabelsline as $key => $value) {
712  unset($_POST["options_".$key]);
713  }
714  }
715 
716  if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ($qty < 0)) {
717  setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
718  $error++;
719  }
720  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
721  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
722  $error++;
723  }
724  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.
725  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
726  $error++;
727  }
728  if ($qty == '') {
729  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
730  $error++;
731  }
732  if ($qty < 0) {
733  setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
734  $error++;
735  }
736  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
737  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
738  $error++;
739  }
740 
741  if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
742  if ($combinations = GETPOST('combinations', 'array')) {
743  //Check if there is a product with the given combination
744  $prodcomb = new ProductCombination($db);
745 
746  if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
747  $idprod = $res->fk_product_child;
748  } else {
749  setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
750  $error++;
751  }
752  }
753  }
754 
755  if (!$error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
756  // Clean parameters
757  $date_start = dol_mktime(GETPOST('date_start'.$predef.'hour'), GETPOST('date_start'.$predef.'min'), GETPOST('date_start'.$predef.'sec'), GETPOST('date_start'.$predef.'month'), GETPOST('date_start'.$predef.'day'), GETPOST('date_start'.$predef.'year'));
758  $date_end = dol_mktime(GETPOST('date_end'.$predef.'hour'), GETPOST('date_end'.$predef.'min'), GETPOST('date_end'.$predef.'sec'), GETPOST('date_end'.$predef.'month'), GETPOST('date_end'.$predef.'day'), GETPOST('date_end'.$predef.'year'));
759  $price_base_type = (GETPOST('price_base_type', 'alpha') ?GETPOST('price_base_type', 'alpha') : 'HT');
760 
761  // Ecrase $pu par celui du produit
762  // Ecrase $desc par celui du produit
763  // Ecrase $base_price_type par celui du produit
764  if (!empty($idprod) && $idprod > 0) {
765  $prod = new Product($db);
766  $prod->fetch($idprod);
767 
768  $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
769 
770  // Update if prices fields are defined
771  /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
772  $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
773  if (empty($tva_tx)) {
774  $tva_npr = 0;
775  }*/
776 
777  $pu_ht = $prod->price;
778  $pu_ttc = $prod->price_ttc;
779  $price_min = $prod->price_min;
780  $price_min_ttc = $prod->price_min_ttc;
781  $price_base_type = $prod->price_base_type;
782 
783  // If price per segment
784  if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) {
785  $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
786  $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
787  $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
788  $price_min_ttc = $prod->multiprices_min_ttc[$object->thirdparty->price_level];
789  $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
790  if (!empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { // using this option is a bug. kept for backward compatibility
791  if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) {
792  $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level];
793  }
794  if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) {
795  $tva_npr = $prod->multiprices_recuperableonly[$object->thirdparty->price_level];
796  }
797  }
798  } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
799  // If price per customer
800  require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php';
801 
802  $prodcustprice = new Productcustomerprice($db);
803 
804  $filter = array('t.fk_product' => $prod->id, 't.fk_soc' => $object->thirdparty->id);
805 
806  $result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
807  if ($result >= 0) {
808  if (count($prodcustprice->lines) > 0) {
809  $pu_ht = price($prodcustprice->lines[0]->price);
810  $pu_ttc = price($prodcustprice->lines[0]->price_ttc);
811  $price_min = price($prodcustprice->lines[0]->price_min);
812  $price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc);
813  $price_base_type = $prodcustprice->lines[0]->price_base_type;
814  $tva_tx = $prodcustprice->lines[0]->tva_tx;
815  if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\‍(.*\‍)/', $tva_tx)) {
816  $tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
817  }
818  $tva_npr = $prodcustprice->lines[0]->recuperableonly;
819  if (empty($tva_tx)) {
820  $tva_npr = 0;
821  }
822  }
823  } else {
824  setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
825  }
826  } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) {
827  // If price per quantity
828  if ($prod->prices_by_qty[0]) { // yes, this product has some prices per quantity
829  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
830  $pqp = GETPOST('pbq', 'int');
831 
832  // Search price into product_price_by_qty from $prod->id
833  foreach ($prod->prices_by_qty_list[0] as $priceforthequantityarray) {
834  if ($priceforthequantityarray['rowid'] != $pqp) {
835  continue;
836  }
837  // We found the price
838  if ($priceforthequantityarray['price_base_type'] == 'HT') {
839  $pu_ht = $priceforthequantityarray['unitprice'];
840  } else {
841  $pu_ttc = $priceforthequantityarray['unitprice'];
842  }
843  // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
844  break;
845  }
846  }
847  } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) {
848  // If price per quantity and customer
849  if ($prod->prices_by_qty[$object->thirdparty->price_level]) { // yes, this product has some prices per quantity
850  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
851  $pqp = GETPOST('pbq', 'int');
852  // Search price into product_price_by_qty from $prod->id
853  foreach ($prod->prices_by_qty_list[$object->thirdparty->price_level] as $priceforthequantityarray) {
854  if ($priceforthequantityarray['rowid'] != $pqp) {
855  continue;
856  }
857  // We found the price
858  if ($priceforthequantityarray['price_base_type'] == 'HT') {
859  $pu_ht = $priceforthequantityarray['unitprice'];
860  } else {
861  $pu_ttc = $priceforthequantityarray['unitprice'];
862  }
863  // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
864  break;
865  }
866  }
867  }
868 
869  $tmpvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
870  $tmpprodvat = (float) price2num(preg_replace('/\s*\‍(.*\‍)/', '', $prod->tva_tx));
871 
872  // Set unit price to use
873  if (!empty($price_ht) || $price_ht === '0') {
874  $pu_ht = price2num($price_ht, 'MU');
875  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
876  } elseif (!empty($price_ttc) || $price_ttc === '0') {
877  $pu_ttc = price2num($price_ttc, 'MU');
878  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
879  } elseif ($tmpvat != $tmpprodvat) {
880  // Is this still used ?
881  if ($price_base_type != 'HT') {
882  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
883  } else {
884  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
885  }
886  }
887 
888  $desc = '';
889 
890  // Define output language
891  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
892  $outputlangs = $langs;
893  $newlang = '';
894  if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
895  $newlang = GETPOST('lang_id', 'aZ09');
896  }
897  if (empty($newlang)) {
898  $newlang = $object->thirdparty->default_lang;
899  }
900  if (!empty($newlang)) {
901  $outputlangs = new Translate("", $conf);
902  $outputlangs->setDefaultLang($newlang);
903  }
904 
905  $desc = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
906  } else {
907  $desc = $prod->description;
908  }
909 
910  //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time
911  if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) {
912  $product_desc='';
913  }
914 
915  if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) {
916  $desc = $product_desc;
917  } else {
918  $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION));
919  }
920 
921  // Add custom code and origin country into description
922  if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) {
923  $tmptxt = '(';
924  // Define output language
925  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
926  $outputlangs = $langs;
927  $newlang = '';
928  if (empty($newlang) && GETPOST('lang_id', 'alpha')) {
929  $newlang = GETPOST('lang_id', 'alpha');
930  }
931  if (empty($newlang)) {
932  $newlang = $object->thirdparty->default_lang;
933  }
934  if (!empty($newlang)) {
935  $outputlangs = new Translate("", $conf);
936  $outputlangs->setDefaultLang($newlang);
937  $outputlangs->load('products');
938  }
939  if (!empty($prod->customcode)) {
940  $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
941  }
942  if (!empty($prod->customcode) && !empty($prod->country_code)) {
943  $tmptxt .= ' - ';
944  }
945  if (!empty($prod->country_code)) {
946  $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $outputlangs, 0);
947  }
948  } else {
949  if (!empty($prod->customcode)) {
950  $tmptxt .= $langs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
951  }
952  if (!empty($prod->customcode) && !empty($prod->country_code)) {
953  $tmptxt .= ' - ';
954  }
955  if (!empty($prod->country_code)) {
956  $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $langs, 0);
957  }
958  }
959  $tmptxt .= ')';
960  $desc = dol_concatdesc($desc, $tmptxt);
961  }
962 
963  $type = $prod->type;
964  $fk_unit = $prod->fk_unit;
965  } else {
966  $pu_ht = price2num($price_ht, 'MU');
967  $pu_ttc = price2num($price_ttc, 'MU');
968  $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
969  $tva_tx = str_replace('*', '', $tva_tx);
970  if (empty($tva_tx)) {
971  $tva_npr = 0;
972  }
973  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
974  $desc = $product_desc;
975  $type = GETPOST('type');
976  $fk_unit = GETPOST('units', 'alpha');
977  $pu_ht_devise = price2num($price_ht_devise, 'MU');
978  $pu_ttc_devise = price2num($price_ttc_devise, 'MU');
979 
980  if ($pu_ttc && !$pu_ht) {
981  $price_base_type = 'TTC';
982  }
983  }
984 
985  $info_bits = 0;
986  if ($tva_npr) {
987  $info_bits |= 0x01;
988  }
989 
990  // Local Taxes
991  $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty);
992  $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty);
993 
994  // Margin
995  $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : '');
996  $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we muste keep this value
997 
998  // Prepare a price equivalent for minimum price check
999  $pu_equivalent = $pu_ht;
1000  $pu_equivalent_ttc = $pu_ttc;
1001 
1002  $currency_tx = $object->multicurrency_tx;
1003 
1004  // Check if we have a foreign currency
1005  // If so, we update the pu_equiv as the equivalent price in base currency
1006  if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') {
1007  $pu_equivalent = $pu_ht_devise * $currency_tx;
1008  }
1009  if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') {
1010  $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx;
1011  }
1012 
1013  // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one defined
1014  /*
1015  if ($pu_equivalent) {
1016  $tmp = calcul_price_total(1, $pu_equivalent, 0, $tva_tx, -1, -1, 0, 'HT', $info_bits, $type);
1017  $pu_equivalent_ttc = ...
1018  } else {
1019  $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $tva_tx, -1, -1, 0, 'TTC', $info_bits, $type);
1020  $pu_equivalent_ht = ...
1021  }
1022  */
1023 
1024  $desc = dol_htmlcleanlastbr($desc);
1025 
1026  // Check price is not lower than minimum
1027  if ($usermustrespectpricemin) {
1028  if ($pu_equivalent && $price_min && ((price2num($pu_equivalent) * (1 - $remise_percent / 100)) < price2num($price_min)) && $price_base_type == 'HT') {
1029  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1030  setEventMessages($mesg, null, 'errors');
1031  $error++;
1032  } elseif ($pu_equivalent_ttc && $price_min_ttc && ((price2num($pu_equivalent_ttc) * (1 - $remise_percent / 100)) < price2num($price_min_ttc)) && $price_base_type == 'TTC') {
1033  $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1034  setEventMessages($mesg, null, 'errors');
1035  $error++;
1036  }
1037  }
1038 
1039  if (!$error) {
1040  // Insert line
1041  $result = $object->addline($desc, $pu_ht, $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, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $fk_unit, '', 0, $pu_ht_devise);
1042 
1043  if ($result > 0) {
1044  $ret = $object->fetch($object->id); // Reload to get new records
1045  $object->fetch_thirdparty();
1046 
1047  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1048  // Define output language
1049  $outputlangs = $langs;
1050  $newlang = GETPOST('lang_id', 'alpha');
1051  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1052  $newlang = $object->thirdparty->default_lang;
1053  }
1054  if (!empty($newlang)) {
1055  $outputlangs = new Translate("", $conf);
1056  $outputlangs->setDefaultLang($newlang);
1057  }
1058 
1059  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1060  }
1061 
1062  unset($_POST['prod_entry_mode']);
1063 
1064  unset($_POST['qty']);
1065  unset($_POST['type']);
1066  unset($_POST['remise_percent']);
1067  unset($_POST['price_ht']);
1068  unset($_POST['multicurrency_price_ht']);
1069  unset($_POST['price_ttc']);
1070  unset($_POST['tva_tx']);
1071  unset($_POST['product_ref']);
1072  unset($_POST['product_label']);
1073  unset($_POST['product_desc']);
1074  unset($_POST['fournprice']);
1075  unset($_POST['buying_price']);
1076  unset($_POST['np_marginRate']);
1077  unset($_POST['np_markRate']);
1078  unset($_POST['dp_desc']);
1079  unset($_POST['idprod']);
1080  unset($_POST['units']);
1081 
1082  unset($_POST['date_starthour']);
1083  unset($_POST['date_startmin']);
1084  unset($_POST['date_startsec']);
1085  unset($_POST['date_startday']);
1086  unset($_POST['date_startmonth']);
1087  unset($_POST['date_startyear']);
1088  unset($_POST['date_endhour']);
1089  unset($_POST['date_endmin']);
1090  unset($_POST['date_endsec']);
1091  unset($_POST['date_endday']);
1092  unset($_POST['date_endmonth']);
1093  unset($_POST['date_endyear']);
1094  } else {
1095  setEventMessages($object->error, $object->errors, 'errors');
1096  }
1097  }
1098  }
1099  } elseif ($action == 'updateline' && $usercancreate && GETPOST('save')) {
1100  // Update a line
1101  // Clean parameters
1102  $date_start = '';
1103  $date_end = '';
1104  $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
1105  $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
1106 
1107  $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml'));
1108 
1109  // Define info_bits
1110  $info_bits = 0;
1111  if (preg_match('/\*/', GETPOST('tva_tx'))) {
1112  $info_bits |= 0x01;
1113  }
1114 
1115  // Define vat_rate
1116  $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx', 'alpha') : 0);
1117  $vat_rate = str_replace('*', '', $vat_rate);
1118  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
1119  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
1120  $pu_ht = price2num(GETPOST('price_ht'), '', 2);
1121  $pu_ttc = price2num(GETPOST('price_ttc'), '', 2);
1122 
1123  $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
1124  $pu_ttc_devise = price2num(GETPOST('multicurrency_subprice_ttc'), '', 2);
1125 
1126  $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1127 
1128  // Prepare a price equivalent for minimum price check
1129  $pu_equivalent = $pu_ht;
1130  $pu_equivalent_ttc = $pu_ttc;
1131 
1132  $currency_tx = $object->multicurrency_tx;
1133 
1134  // Check if we have a foreign currency
1135  // If so, we update the pu_equiv as the equivalent price in base currency
1136  if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') {
1137  $pu_equivalent = $pu_ht_devise * $currency_tx;
1138  }
1139  if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') {
1140  $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx;
1141  }
1142 
1143  // TODO $pu_equivalent or $pu_equivalent_ttc must be calculated from the one not null taking into account all taxes
1144  /*
1145  if ($pu_equivalent) {
1146  $tmp = calcul_price_total(1, $pu_equivalent, 0, $vat_rate, -1, -1, 0, 'HT', $info_bits, $type);
1147  $pu_equivalent_ttc = ...
1148  } else {
1149  $tmp = calcul_price_total(1, $pu_equivalent_ttc, 0, $vat_rate, -1, -1, 0, 'TTC', $info_bits, $type);
1150  $pu_equivalent_ht = ...
1151  }
1152  */
1153 
1154  // Add buying price
1155  $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
1156  $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we muste keep this value
1157 
1158  // Extrafields Lines
1159  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1160  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
1161  // Unset extrafield POST Data
1162  if (is_array($extralabelsline)) {
1163  foreach ($extralabelsline as $key => $value) {
1164  unset($_POST["options_".$key]);
1165  }
1166  }
1167 
1168  // Define special_code for special lines
1169  $special_code = GETPOST('special_code');
1170  if (!GETPOST('qty')) {
1171  $special_code = 3;
1172  }
1173 
1174  $remise_percent = GETPOST('remise_percent') != '' ? price2num(GETPOST('remise_percent'), '', 2) : 0;
1175 
1176  // Check minimum price
1177  $productid = GETPOST('productid', 'int');
1178  if (!empty($productid)) {
1179  $product = new Product($db);
1180  $product->fetch($productid);
1181 
1182  $type = $product->type;
1183 
1184  $price_min = $product->price_min;
1185  if ((!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && !empty($object->thirdparty->price_level)) {
1186  $price_min = $product->multiprices_min[$object->thirdparty->price_level];
1187  }
1188  $price_min_ttc = $product->price_min_ttc;
1189  if ((!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && !empty($object->thirdparty->price_level)) {
1190  $price_min_ttc = $product->multiprices_min_ttc[$object->thirdparty->price_level];
1191  }
1192 
1193  $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
1194 
1195  // Check price is not lower than minimum
1196  if ($usermustrespectpricemin) {
1197  if ($pu_equivalent && $price_min && ((price2num($pu_equivalent) * (1 - $remise_percent / 100)) < price2num($price_min)) && $price_base_type == 'HT') {
1198  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1199  setEventMessages($mesg, null, 'errors');
1200  $error++;
1201  $action = 'editline';
1202  } elseif ($pu_equivalent_ttc && $price_min_ttc && ((price2num($pu_equivalent_ttc) * (1 - $remise_percent / 100)) < price2num($price_min_ttc)) && $price_base_type == 'TTC') {
1203  $mesg = $langs->trans("CantBeLessThanMinPriceInclTax", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1204  setEventMessages($mesg, null, 'errors');
1205  $error++;
1206  $action = 'editline';
1207  }
1208  }
1209  } else {
1210  $type = GETPOST('type');
1211  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1212 
1213  // Check parameters
1214  if (GETPOST('type') < 0) {
1215  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1216  $error++;
1217  $action = 'editline';
1218  }
1219  }
1220 
1221  if ($qty < 0) {
1222  setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1223  $error++;
1224  $action = 'editline';
1225  }
1226 
1227  if (!$error) {
1228  if (empty($user->rights->margins->creer)) {
1229  foreach ($object->lines as &$line) {
1230  if ($line->id == GETPOST('lineid', 'int')) {
1231  $fournprice = $line->fk_fournprice;
1232  $buyingprice = $line->pa_ht;
1233  break;
1234  }
1235  }
1236  }
1237 
1238  $price_base_type = 'HT';
1239  $pu = $pu_ht;
1240  if (empty($pu) && !empty($pu_ttc)) {
1241  $pu = $pu_ttc;
1242  $price_base_type = 'TTC';
1243  }
1244 
1245  $result = $object->updateline(GETPOST('lineid', 'int'), $description, $pu, $qty, $remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, $price_base_type, $info_bits, $date_start, $date_end, $type, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOST('units'), $pu_ht_devise);
1246 
1247  if ($result >= 0) {
1248  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1249  // Define output language
1250  $outputlangs = $langs;
1251  $newlang = '';
1252  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1253  $newlang = GETPOST('lang_id', 'aZ09');
1254  }
1255  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1256  $newlang = $object->thirdparty->default_lang;
1257  }
1258  if (!empty($newlang)) {
1259  $outputlangs = new Translate("", $conf);
1260  $outputlangs->setDefaultLang($newlang);
1261  }
1262 
1263  $ret = $object->fetch($object->id); // Reload to get new records
1264  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1265  }
1266 
1267  unset($_POST['qty']);
1268  unset($_POST['type']);
1269  unset($_POST['productid']);
1270  unset($_POST['remise_percent']);
1271  unset($_POST['price_ht']);
1272  unset($_POST['multicurrency_price_ht']);
1273  unset($_POST['price_ttc']);
1274  unset($_POST['tva_tx']);
1275  unset($_POST['product_ref']);
1276  unset($_POST['product_label']);
1277  unset($_POST['product_desc']);
1278  unset($_POST['fournprice']);
1279  unset($_POST['buying_price']);
1280 
1281  unset($_POST['date_starthour']);
1282  unset($_POST['date_startmin']);
1283  unset($_POST['date_startsec']);
1284  unset($_POST['date_startday']);
1285  unset($_POST['date_startmonth']);
1286  unset($_POST['date_startyear']);
1287  unset($_POST['date_endhour']);
1288  unset($_POST['date_endmin']);
1289  unset($_POST['date_endsec']);
1290  unset($_POST['date_endday']);
1291  unset($_POST['date_endmonth']);
1292  unset($_POST['date_endyear']);
1293  } else {
1294  setEventMessages($object->error, $object->errors, 'errors');
1295  }
1296  }
1297  } elseif ($action == 'updateline' && $usercancreate && GETPOST('cancel', 'alpha')) {
1298  header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // Pour reaffichage de la fiche en cours d'edition
1299  exit();
1300  } elseif ($action == 'confirm_validate' && $confirm == 'yes' && $usercanvalidate) {
1301  $idwarehouse = GETPOST('idwarehouse', 'int');
1302 
1303  $qualified_for_stock_change = 0;
1304  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1305  $qualified_for_stock_change = $object->hasProductsOrServices(2);
1306  } else {
1307  $qualified_for_stock_change = $object->hasProductsOrServices(1);
1308  }
1309 
1310  // Check parameters
1311  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
1312  if (!$idwarehouse || $idwarehouse == -1) {
1313  $error++;
1314  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1315  $action = '';
1316  }
1317  }
1318 
1319  if (!$error) {
1320  $locationTarget = '';
1321 
1322  $db->begin();
1323 
1324  $result = $object->valid($user, $idwarehouse);
1325  if ($result >= 0) {
1326  $error = 0;
1327  $deposit = null;
1328 
1329  $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
1330 
1331  if (
1332  GETPOST('generate_deposit', 'alpha') == 'on' && !empty($deposit_percent_from_payment_terms)
1333  && isModEnabled('facture') && !empty($user->rights->facture->creer)
1334  ) {
1335  require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
1336 
1337  $date = dol_mktime(0, 0, 0, GETPOST('datefmonth', 'int'), GETPOST('datefday', 'int'), GETPOST('datefyear', 'int'));
1338  $forceFields = array();
1339 
1340  if (GETPOSTISSET('date_pointoftax')) {
1341  $forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOST('date_pointoftaxmonth', 'int'), GETPOST('date_pointoftaxday', 'int'), GETPOST('date_pointoftaxyear', 'int'));
1342  }
1343 
1344  $deposit = Facture::createDepositFromOrigin($object, $date, GETPOST('cond_reglement_id', 'int'), $user, 0, GETPOST('validate_generated_deposit', 'alpha') == 'on', $forceFields);
1345 
1346  if ($deposit) {
1347  setEventMessage('DepositGenerated');
1348  $locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
1349  } else {
1350  $error++;
1351  setEventMessages($object->error, $object->errors, 'errors');
1352  }
1353  }
1354 
1355  // Define output language
1356  if (! $error) {
1357  $db->commit();
1358 
1359  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1360  $outputlangs = $langs;
1361  $newlang = '';
1362  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1363  $newlang = GETPOST('lang_id', 'aZ09');
1364  }
1365  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1366  $newlang = $object->thirdparty->default_lang;
1367  }
1368  if (!empty($newlang)) {
1369  $outputlangs = new Translate("", $conf);
1370  $outputlangs->setDefaultLang($newlang);
1371  }
1372  $model = $object->model_pdf;
1373  $ret = $object->fetch($id); // Reload to get new records
1374 
1375  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1376 
1377  if ($deposit) {
1378  $deposit->fetch($deposit->id); // Reload to get new records
1379  $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1380  }
1381  }
1382 
1383  if ($locationTarget) {
1384  header('Location: ' . $locationTarget);
1385  exit;
1386  }
1387  } else {
1388  $db->rollback();
1389  }
1390  } else {
1391  $db->rollback();
1392  setEventMessages($object->error, $object->errors, 'errors');
1393  }
1394  }
1395  } elseif ($action == 'confirm_modif' && $usercancreate) {
1396  // Go back to draft status
1397  $idwarehouse = GETPOST('idwarehouse');
1398 
1399  $qualified_for_stock_change = 0;
1400  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1401  $qualified_for_stock_change = $object->hasProductsOrServices(2);
1402  } else {
1403  $qualified_for_stock_change = $object->hasProductsOrServices(1);
1404  }
1405 
1406  // Check parameters
1407  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
1408  if (!$idwarehouse || $idwarehouse == -1) {
1409  $error++;
1410  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1411  $action = '';
1412  }
1413  }
1414 
1415  if (!$error) {
1416  $result = $object->setDraft($user, $idwarehouse);
1417  if ($result >= 0) {
1418  // Define output language
1419  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1420  $outputlangs = $langs;
1421  $newlang = '';
1422  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1423  $newlang = GETPOST('lang_id', 'aZ09');
1424  }
1425  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1426  $newlang = $object->thirdparty->default_lang;
1427  }
1428  if (!empty($newlang)) {
1429  $outputlangs = new Translate("", $conf);
1430  $outputlangs->setDefaultLang($newlang);
1431  }
1432  $model = $object->model_pdf;
1433  $ret = $object->fetch($id); // Reload to get new records
1434 
1435  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1436  }
1437  } else {
1438  setEventMessages($object->error, $object->errors, 'errors');
1439  }
1440  }
1441  } elseif ($action == 'confirm_shipped' && $confirm == 'yes' && $usercanclose) {
1442  $result = $object->cloture($user);
1443  if ($result < 0) {
1444  setEventMessages($object->error, $object->errors, 'errors');
1445  }
1446  } elseif ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanvalidate) {
1447  $idwarehouse = GETPOST('idwarehouse', 'int');
1448 
1449  $qualified_for_stock_change = 0;
1450  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1451  $qualified_for_stock_change = $object->hasProductsOrServices(2);
1452  } else {
1453  $qualified_for_stock_change = $object->hasProductsOrServices(1);
1454  }
1455 
1456  // Check parameters
1457  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
1458  if (!$idwarehouse || $idwarehouse == -1) {
1459  $error++;
1460  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1461  $action = '';
1462  }
1463  }
1464 
1465  if (!$error) {
1466  $result = $object->cancel($idwarehouse);
1467 
1468  if ($result < 0) {
1469  setEventMessages($object->error, $object->errors, 'errors');
1470  }
1471  }
1472  }
1473 
1474  if ($action == 'update_extras') {
1475  $object->oldcopy = dol_clone($object);
1476 
1477  // Fill array 'array_options' with data from update form
1478  $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
1479  if ($ret < 0) {
1480  $error++;
1481  }
1482 
1483  if (!$error) {
1484  // Actions on extra fields
1485  $result = $object->insertExtraFields('ORDER_MODIFY');
1486  if ($result < 0) {
1487  setEventMessages($object->error, $object->errors, 'errors');
1488  $error++;
1489  }
1490  }
1491 
1492  if ($error) {
1493  $action = 'edit_extras';
1494  }
1495  }
1496 
1497  // add lines from objectlinked
1498  if ($action == 'import_lines_from_object'
1499  && $usercancreate
1500  && $object->statut == Commande::STATUS_DRAFT
1501  ) {
1502  $fromElement = GETPOST('fromelement');
1503  $fromElementid = GETPOST('fromelementid');
1504  $importLines = GETPOST('line_checkbox');
1505 
1506  if (!empty($importLines) && is_array($importLines) && !empty($fromElement) && ctype_alpha($fromElement) && !empty($fromElementid)) {
1507  if ($fromElement == 'commande') {
1508  dol_include_once('/'.$fromElement.'/class/'.$fromElement.'.class.php');
1509  $lineClassName = 'OrderLine';
1510  } elseif ($fromElement == 'propal') {
1511  dol_include_once('/comm/'.$fromElement.'/class/'.$fromElement.'.class.php');
1512  $lineClassName = 'PropaleLigne';
1513  } elseif ($fromElement == 'facture') {
1514  dol_include_once('/compta/'.$fromElement.'/class/'.$fromElement.'.class.php');
1515  $lineClassName = 'FactureLigne';
1516  }
1517  $nextRang = count($object->lines) + 1;
1518  $importCount = 0;
1519  $error = 0;
1520  foreach ($importLines as $lineId) {
1521  $lineId = intval($lineId);
1522  $originLine = new $lineClassName($db);
1523  if (intval($fromElementid) > 0 && $originLine->fetch($lineId) > 0) {
1524  $originLine->fetch_optionals();
1525  $desc = $originLine->desc;
1526  $pu_ht = $originLine->subprice;
1527  $qty = $originLine->qty;
1528  $txtva = $originLine->tva_tx;
1529  $txlocaltax1 = $originLine->localtax1_tx;
1530  $txlocaltax2 = $originLine->localtax2_tx;
1531  $fk_product = $originLine->fk_product;
1532  $remise_percent = $originLine->remise_percent;
1533  $date_start = $originLine->date_start;
1534  $date_end = $originLine->date_end;
1535  $ventil = 0;
1536  $info_bits = $originLine->info_bits;
1537  $fk_remise_except = $originLine->fk_remise_except;
1538  $price_base_type = 'HT';
1539  $pu_ttc = 0;
1540  $type = $originLine->product_type;
1541  $rang = $nextRang++;
1542  $special_code = $originLine->special_code;
1543  $origin = $originLine->element;
1544  $origin_id = $originLine->id;
1545  $fk_parent_line = 0;
1546  $fk_fournprice = $originLine->fk_fournprice;
1547  $pa_ht = $originLine->pa_ht;
1548  $label = $originLine->label;
1549  $array_options = $originLine->array_options;
1550  $situation_percent = 100;
1551  $fk_prev_id = '';
1552  $fk_unit = $originLine->fk_unit;
1553  $pu_ht_devise = $originLine->multicurrency_subprice;
1554 
1555  $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);
1556 
1557  if ($res > 0) {
1558  $importCount++;
1559  } else {
1560  $error++;
1561  }
1562  } else {
1563  $error++;
1564  }
1565  }
1566 
1567  if ($error) {
1568  setEventMessages($langs->trans('ErrorsOnXLines', $error), null, 'errors');
1569  }
1570  }
1571  }
1572 
1573  // Actions when printing a doc from card
1574  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
1575 
1576  // Actions to build doc
1577  $upload_dir = !empty($conf->commande->multidir_output[$object->entity])?$conf->commande->multidir_output[$object->entity]:$conf->commande->dir_output;
1578  $permissiontoadd = $usercancreate;
1579  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
1580 
1581  // Actions to send emails
1582  $triggersendname = 'ORDER_SENTBYMAIL';
1583  $paramname = 'id';
1584  $autocopy = 'MAIN_MAIL_AUTOCOPY_ORDER_TO'; // used to know the automatic BCC to add
1585  $trackid = 'ord'.$object->id;
1586  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
1587 
1588 
1589  if (!$error && !empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $usercancreate) {
1590  if ($action == 'addcontact') {
1591  if ($object->id > 0) {
1592  $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
1593  $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
1594  $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
1595  }
1596 
1597  if ($result >= 0) {
1598  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1599  exit();
1600  } else {
1601  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1602  $langs->load("errors");
1603  setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
1604  } else {
1605  setEventMessages($object->error, $object->errors, 'errors');
1606  }
1607  }
1608  } elseif ($action == 'swapstatut') {
1609  // bascule du statut d'un contact
1610  if ($object->id > 0) {
1611  $result = $object->swapContactStatus(GETPOST('ligne', 'int'));
1612  } else {
1613  dol_print_error($db);
1614  }
1615  } elseif ($action == 'deletecontact') {
1616  // Efface un contact
1617  $result = $object->delete_contact($lineid);
1618 
1619  if ($result >= 0) {
1620  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1621  exit();
1622  } else {
1623  dol_print_error($db);
1624  }
1625  }
1626  }
1627 }
1628 
1629 
1630 /*
1631  * View
1632  */
1633 
1634 $title = $object->ref." - ".$langs->trans('Card');
1635 if ($action == 'create') {
1636  $title = $langs->trans("NewOrder");
1637 }
1638 $help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge';
1639 
1640 llxHeader('', $title, $help_url);
1641 
1642 $form = new Form($db);
1643 $formfile = new FormFile($db);
1644 $formorder = new FormOrder($db);
1645 $formmargin = new FormMargin($db);
1646 if (isModEnabled('project')) {
1647  $formproject = new FormProjets($db);
1648 }
1649 
1650 // Mode creation
1651 if ($action == 'create' && $usercancreate) {
1652  print load_fiche_titre($langs->trans('CreateOrder'), '', 'order');
1653 
1654  $soc = new Societe($db);
1655  if ($socid > 0) {
1656  $res = $soc->fetch($socid);
1657  }
1658 
1659  $remise_absolue = 0;
1660 
1661  $currency_code = $conf->currency;
1662 
1663  $cond_reglement_id = GETPOST('cond_reglement_id', 'int');
1664  $deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
1665  $mode_reglement_id = GETPOST('mode_reglement_id', 'int');
1666  $fk_account = GETPOST('fk_account', 'int');
1667 
1668  if (!empty($origin) && !empty($originid)) {
1669  // Parse element/subelement (ex: project_task)
1670  $element = $subelement = $origin;
1671  $regs = array();
1672  if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
1673  $element = $regs[1];
1674  $subelement = $regs[2];
1675  }
1676 
1677  if ($element == 'project') {
1678  $projectid = $originid;
1679 
1680  if (!$cond_reglement_id) {
1681  $cond_reglement_id = $soc->cond_reglement_id;
1682  }
1683  if (!$deposit_percent) {
1684  $deposit_percent = $soc->deposit_percent;
1685  }
1686  if (!$mode_reglement_id) {
1687  $mode_reglement_id = $soc->mode_reglement_id;
1688  }
1689  if (!$remise_percent) {
1690  $remise_percent = $soc->remise_percent;
1691  }
1692  /*if (!$dateorder) {
1693  // Do not set 0 here (0 for a date is 1970)
1694  $dateorder = (empty($dateinvoice) ? (empty($conf->global->MAIN_AUTOFILL_DATE_ORDER) ?-1 : '') : $dateorder);
1695  }*/
1696  } else {
1697  // For compatibility
1698  if ($element == 'order' || $element == 'commande') {
1699  $element = $subelement = 'commande';
1700  } elseif ($element == 'propal') {
1701  $element = 'comm/propal';
1702  $subelement = 'propal';
1703  } elseif ($element == 'contract') {
1704  $element = $subelement = 'contrat';
1705  }
1706 
1707  dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1708 
1709  $classname = ucfirst($subelement);
1710  $objectsrc = new $classname($db);
1711  $objectsrc->fetch($originid);
1712  if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1713  $objectsrc->fetch_lines();
1714  }
1715  $objectsrc->fetch_thirdparty();
1716 
1717  // Replicate extrafields
1718  $objectsrc->fetch_optionals();
1719  $object->array_options = $objectsrc->array_options;
1720 
1721  $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : '');
1722  $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
1723 
1724  $soc = $objectsrc->thirdparty;
1725  $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
1726  $deposit_percent = (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : null));
1727  $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
1728  $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0));
1729  $availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : 0);
1730  $shipping_method_id = (!empty($objectsrc->shipping_method_id) ? $objectsrc->shipping_method_id : (!empty($soc->shipping_method_id) ? $soc->shipping_method_id : 0));
1731  $warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0));
1732  $demand_reason_id = (!empty($objectsrc->demand_reason_id) ? $objectsrc->demand_reason_id : (!empty($soc->demand_reason_id) ? $soc->demand_reason_id : 0));
1733  $remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_percent) ? $soc->remise_percent : 0));
1734  $remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0));
1735  $dateorder = empty($conf->global->MAIN_AUTOFILL_DATE_ORDER) ? -1 : '';
1736 
1737  $date_delivery = (!empty($objectsrc->delivery_date) ? $objectsrc->delivery_date : '');
1738  if (empty($date_delivery)) {
1739  $date_delivery = (!empty($objectsrc->date_livraison) ? $objectsrc->date_livraison : '');
1740  }
1741 
1742  if (isModEnabled("multicurrency")) {
1743  if (!empty($objectsrc->multicurrency_code)) {
1744  $currency_code = $objectsrc->multicurrency_code;
1745  }
1746  if (!empty($conf->global->MULTICURRENCY_USE_ORIGIN_TX) && !empty($objectsrc->multicurrency_tx)) {
1747  $currency_tx = $objectsrc->multicurrency_tx;
1748  }
1749  }
1750 
1751  $note_private = $object->getDefaultCreateValueFor('note_private', (!empty($objectsrc->note_private) ? $objectsrc->note_private : null));
1752  $note_public = $object->getDefaultCreateValueFor('note_public', (!empty($objectsrc->note_public) ? $objectsrc->note_public : null));
1753 
1754  // Object source contacts list
1755  $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
1756  }
1757  } else {
1758  $cond_reglement_id = empty($soc->cond_reglement_id) ? $cond_reglement_id : $soc->cond_reglement_id;
1759  $deposit_percent = empty($soc->deposit_percent) ? $deposit_percent : $soc->deposit_percent;
1760  $mode_reglement_id = empty($soc->mode_reglement_id) ? $mode_reglement_id : $soc->mode_reglement_id;
1761  $fk_account = empty($soc->mode_reglement_id) ? $fk_account : $soc->fk_account;
1762  $availability_id = 0;
1763  $shipping_method_id = $soc->shipping_method_id;
1764  $warehouse_id = $soc->fk_warehouse;
1765  $demand_reason_id = $soc->demand_reason_id;
1766  $remise_percent = $soc->remise_percent;
1767  $remise_absolue = 0;
1768  $dateorder = empty($conf->global->MAIN_AUTOFILL_DATE_ORDER) ?-1 : '';
1769 
1770  if (isModEnabled("multicurrency") && !empty($soc->multicurrency_code)) {
1771  $currency_code = $soc->multicurrency_code;
1772  }
1773 
1774  $note_private = $object->getDefaultCreateValueFor('note_private');
1775  $note_public = $object->getDefaultCreateValueFor('note_public');
1776  }
1777 
1778  // If form was posted (but error returned), we must reuse the value posted in priority (standard Dolibarr behaviour)
1779  if (!GETPOST('changecompany')) {
1780  if (GETPOSTISSET('cond_reglement_id')) {
1781  $cond_reglement_id = GETPOST('cond_reglement_id', 'int');
1782  }
1783  if (GETPOSTISSET('deposit_percent')) {
1784  $deposit_percent = price2num(GETPOST('deposit_percent', 'alpha'));
1785  }
1786  if (GETPOSTISSET('mode_reglement_id')) {
1787  $mode_reglement_id = GETPOST('mode_reglement_id', 'int');
1788  }
1789  if (GETPOSTISSET('cond_reglement_id')) {
1790  $fk_account = GETPOST('fk_account', 'int');
1791  }
1792  }
1793 
1794  // Warehouse default if null
1795  if ($soc->fk_warehouse > 0) {
1796  $warehouse_id = $soc->fk_warehouse;
1797  }
1798  if (isModEnabled('stock') && empty($warehouse_id) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
1799  if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE)) {
1800  $warehouse_id = $conf->global->MAIN_DEFAULT_WAREHOUSE;
1801  }
1802  if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE_USER)) {
1803  $warehouse_id = $user->fk_warehouse;
1804  }
1805  }
1806 
1807  print '<form name="crea_commande" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1808  print '<input type="hidden" name="token" value="'.newToken().'">';
1809  print '<input type="hidden" name="action" value="add">';
1810  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
1811  print '<input type="hidden" name="remise_percent" value="'.$soc->remise_percent.'">';
1812  print '<input type="hidden" name="origin" value="'.$origin.'">';
1813  print '<input type="hidden" name="originid" value="'.$originid.'">';
1814  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1815  if (!empty($currency_tx)) {
1816  print '<input type="hidden" name="originmulticurrency_tx" value="'.$currency_tx.'">';
1817  }
1818 
1819  print dol_get_fiche_head('');
1820 
1821  print '<table class="border centpercent">';
1822 
1823  // Reference
1824  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Ref').'</td><td>'.$langs->trans("Draft").'</td></tr>';
1825 
1826  // Reference client
1827  print '<tr><td>'.$langs->trans('RefCustomer').'</td><td>';
1828  if (!empty($conf->global->MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER) && !empty($origin) && !empty($originid)) {
1829  print '<input type="text" name="ref_client" value="'.$ref_client.'"></td>';
1830  } else {
1831  print '<input type="text" name="ref_client" value="'.GETPOST('ref_client').'"></td>';
1832  }
1833  print '</tr>';
1834 
1835  // Thirdparty
1836  print '<tr>';
1837  print '<td class="fieldrequired">'.$langs->trans('Customer').'</td>';
1838  if ($socid > 0) {
1839  print '<td>';
1840  print $soc->getNomUrl(1, 'customer');
1841  print '<input type="hidden" name="socid" value="'.$soc->id.'">';
1842  print '</td>';
1843  } else {
1844  print '<td class="valuefieldcreate">';
1845  $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))';
1846  print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
1847  // reload page to retrieve customer informations
1848  if (empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) {
1849  print '<script>
1850  $(document).ready(function() {
1851  $("#socid").change(function() {
1852  console.log("We have changed the company - Reload page");
1853  var socid = $(this).val();
1854  // reload page
1855  $("input[name=action]").val("create");
1856  $("input[name=changecompany]").val("1");
1857  $("form[name=crea_commande]").submit();
1858  });
1859  });
1860  </script>';
1861  }
1862  print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
1863  print '</td>';
1864  }
1865  print '</tr>'."\n";
1866 
1867  // Contact of order
1868  if ($socid > 0) {
1869  // Contacts (ask contact only if thirdparty already defined).
1870  print "<tr><td>".$langs->trans("DefaultContact").'</td><td>';
1871  print img_picto('', 'contact', 'class="pictofixedwidth"');
1872  print $form->selectcontacts($soc->id, $contactid, 'contactid', 1, !empty($srccontactslist)?$srccontactslist:"", '', 1, 'maxwidth200 widthcentpercentminusx');
1873  print '</td></tr>';
1874 
1875  // Ligne info remises tiers
1876  print '<tr><td>'.$langs->trans('Discounts').'</td><td>';
1877 
1878  $absolute_discount = $soc->getAvailableDiscounts();
1879 
1880  $thirdparty = $soc;
1881  $discount_type = 0;
1882  $backtopage = $_SERVER["PHP_SELF"].'?socid='.$thirdparty->id.'&action='.$action.'&origin='.urlencode(GETPOST('origin')).'&originid='.urlencode(GETPOSTINT('originid'));
1883  include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
1884 
1885  print '</td></tr>';
1886  }
1887 
1888  // Date
1889  print '<tr><td class="fieldrequired">'.$langs->trans('Date').'</td><td>';
1890  print img_picto('', 'action', 'class="pictofixedwidth"');
1891  print $form->selectDate('', 're', '', '', '', "crea_commande", 1, 1); // Always autofill date with current date
1892  print '</td></tr>';
1893 
1894  // Date delivery planned
1895  print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
1896  print '<td colspan="3">';
1897  $date_delivery = ($date_delivery ? $date_delivery : $object->delivery_date);
1898  print img_picto('', 'action', 'class="pictofixedwidth"');
1899  print $form->selectDate($date_delivery ? $date_delivery : -1, 'liv_', 1, 1, 1);
1900  print "</td>\n";
1901  print '</tr>';
1902 
1903  // Delivery delay
1904  print '<tr class="fielddeliverydelay"><td>'.$langs->trans('AvailabilityPeriod').'</td><td>';
1905  print img_picto('', 'clock', 'class="pictofixedwidth"');
1906  $form->selectAvailabilityDelay((GETPOSTISSET('availability_id') ? GETPOST('availability_id') : $availability_id), 'availability_id', '', 1, 'maxwidth200 widthcentpercentminusx');
1907  print '</td></tr>';
1908 
1909  // Terms of payment
1910  print '<tr><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
1911  print img_picto('', 'payment', 'class="pictofixedwidth"');
1912  print $form->getSelectConditionsPaiements($cond_reglement_id, 'cond_reglement_id', 1, 1, 0, 'maxwidth200 widthcentpercentminusx', $deposit_percent);
1913  print '</td></tr>';
1914 
1915  // Payment mode
1916  print '<tr><td>'.$langs->trans('PaymentMode').'</td><td>';
1917  print img_picto('', 'bank', 'class="pictofixedwidth"');
1918  print $form->select_types_paiements($mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1);
1919  print '</td></tr>';
1920 
1921  // Bank Account
1922  if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && isModEnabled("banque")) {
1923  print '<tr><td>'.$langs->trans('BankAccount').'</td><td>';
1924  print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes($fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1);
1925  print '</td></tr>';
1926  }
1927 
1928  // Shipping Method
1929  if (isModEnabled('expedition')) {
1930  print '<tr><td>'.$langs->trans('SendingMethod').'</td><td>';
1931  print img_picto('', 'object_dolly', 'class="pictofixedwidth"');
1932  $form->selectShippingMethod(((GETPOSTISSET('shipping_method_id') && GETPOST('shipping_method_id', 'int') != 0) ? GETPOST('shipping_method_id') : $shipping_method_id), 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx');
1933  print '</td></tr>';
1934  }
1935 
1936  // Warehouse
1937  if (isModEnabled('stock') && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
1938  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
1939  $formproduct = new FormProduct($db);
1940  print '<tr><td>'.$langs->trans('Warehouse').'</td><td>';
1941  print img_picto('', 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses((GETPOSTISSET('warehouse_id')?GETPOST('warehouse_id'):$warehouse_id), 'warehouse_id', '', 1, 0, 0, '', 0, 0, array(), 'maxwidth500 widthcentpercentminusxx');
1942  print '</td></tr>';
1943  }
1944 
1945  // Source / Channel - What trigger creation
1946  print '<tr><td>'.$langs->trans('Channel').'</td><td>';
1947  print img_picto('', 'question', 'class="pictofixedwidth"');
1948  $form->selectInputReason((GETPOSTISSET('demand_reason_id')?GETPOST('demand_reason_id'):$demand_reason_id), 'demand_reason_id', '', 1, 'maxwidth200 widthcentpercentminusx');
1949  print '</td></tr>';
1950 
1951  // TODO How record was recorded OrderMode (llx_c_input_method)
1952 
1953  // Project
1954  if (isModEnabled('project')) {
1955  $langs->load("projects");
1956  print '<tr>';
1957  print '<td>'.$langs->trans("Project").'</td><td>';
1958  print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects(($soc->id > 0 ? $soc->id : -1), (GETPOSTISSET('projectid')?GETPOST('projectid'):$projectid), 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500 widthcentpercentminusxx');
1959  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>';
1960  print '</td>';
1961  print '</tr>';
1962  }
1963 
1964  // Incoterms
1965  if (isModEnabled('incoterm')) {
1966  print '<tr>';
1967  print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), !empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms, 1).'</label></td>';
1968  print '<td class="maxwidthonsmartphone">';
1969  $incoterm_id = GETPOST('incoterm_id');
1970  $incoterm_location = GETPOST('location_incoterms');
1971  if (empty($incoterm_id)) {
1972  $incoterm_id = (!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms);
1973  $incoterm_location = (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : $soc->location_incoterms);
1974  }
1975  print img_picto('', 'incoterm', 'class="pictofixedwidth"');
1976  print $form->select_incoterms($incoterm_id, $incoterm_location);
1977  print '</td></tr>';
1978  }
1979 
1980  // Other attributes
1981  $parameters = array();
1982  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
1983  $parameters['objectsrc'] = $objectsrc;
1984  }
1985  $parameters['socid'] = $socid;
1986 
1987  // Note that $action and $object may be modified by hook
1988  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
1989  print $hookmanager->resPrint;
1990  if (empty($reshook)) {
1991  if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER) && !empty($soc->id)) {
1992  // copy from thirdparty
1993  $tpExtrafields = new ExtraFields($db);
1994  $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element);
1995  if ($soc->fetch_optionals() > 0) {
1996  $object->array_options = array_merge($object->array_options, $soc->array_options);
1997  }
1998  }
1999 
2000  print $object->showOptionals($extrafields, 'create', $parameters);
2001  }
2002 
2003  // Template to use by default
2004  print '<tr><td>'.$langs->trans('DefaultModel').'</td>';
2005  print '<td>';
2006  include_once DOL_DOCUMENT_ROOT.'/core/modules/commande/modules_commande.php';
2007  $liste = ModelePDFCommandes::liste_modeles($db);
2008  $preselected = $conf->global->COMMANDE_ADDON_PDF;
2009  print img_picto('', 'pdf', 'class="pictofixedwidth"');
2010  print $form->selectarray('model', $liste, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
2011  print "</td></tr>";
2012 
2013  // Multicurrency
2014  if (isModEnabled("multicurrency")) {
2015  print '<tr>';
2016  print '<td>'.$form->editfieldkey("Currency", 'multicurrency_code', '', $object, 0).'</td>';
2017  print '<td class="maxwidthonsmartphone">';
2018  print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency((GETPOSTISSET('multicurrency_code')?GETPOST('multicurrency_code'):$currency_code), 'multicurrency_code', 0, '', false, 'maxwidth200 widthcentpercentminusx');
2019  print '</td></tr>';
2020  }
2021 
2022  // Note public
2023  print '<tr>';
2024  print '<td class="tdtop">'.$langs->trans('NotePublic').'</td>';
2025  print '<td>';
2026 
2027  $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PUBLIC) ? 0 : 1, ROWS_3, '90%');
2028  print $doleditor->Create(1);
2029  // print '<textarea name="note_public" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_public.'</textarea>';
2030  print '</td></tr>';
2031 
2032  // Note private
2033  if (empty($user->socid)) {
2034  print '<tr>';
2035  print '<td class="tdtop">'.$langs->trans('NotePrivate').'</td>';
2036  print '<td>';
2037 
2038  $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PRIVATE) ? 0 : 1, ROWS_3, '90%');
2039  print $doleditor->Create(1);
2040  // print '<textarea name="note" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'</textarea>';
2041  print '</td></tr>';
2042  }
2043 
2044  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2045  // TODO for compatibility
2046  if ($origin == 'contrat') {
2047  // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
2048  $objectsrc->remise_absolue = $remise_absolue;
2049  $objectsrc->remise_percent = $remise_percent;
2050  $objectsrc->update_price(1);
2051  }
2052 
2053  print "\n<!-- ".$classname." info -->";
2054  print "\n";
2055  print '<input type="hidden" name="amount" value="'.$objectsrc->total_ht.'">'."\n";
2056  print '<input type="hidden" name="total" value="'.$objectsrc->total_ttc.'">'."\n";
2057  print '<input type="hidden" name="tva" value="'.$objectsrc->total_tva.'">'."\n";
2058  print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
2059  print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
2060 
2061  switch ($classname) {
2062  case 'Propal':
2063  $newclassname = 'CommercialProposal';
2064  break;
2065  case 'Commande':
2066  $newclassname = 'Order';
2067  break;
2068  case 'Expedition':
2069  $newclassname = 'Sending';
2070  break;
2071  case 'Contrat':
2072  $newclassname = 'Contract';
2073  break;
2074  default:
2075  $newclassname = $classname;
2076  }
2077 
2078  print '<tr><td>'.$langs->trans($newclassname).'</td><td>'.$objectsrc->getNomUrl(1).'</td></tr>';
2079 
2080  // Amount
2081  print '<tr><td>'.$langs->trans('AmountHT').'</td><td>'.price($objectsrc->total_ht).'</td></tr>';
2082  print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($objectsrc->total_tva)."</td></tr>";
2083  if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1 RE
2084  print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax1)."</td></tr>";
2085  }
2086 
2087  if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2 IRPF
2088  print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax2)."</td></tr>";
2089  }
2090 
2091  print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($objectsrc->total_ttc)."</td></tr>";
2092 
2093  if (isModEnabled("multicurrency")) {
2094  print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht).'</td></tr>';
2095  print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva)."</td></tr>";
2096  print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc)."</td></tr>";
2097  }
2098  }
2099 
2100  print "\n";
2101 
2102  print '</table>';
2103 
2104  print dol_get_fiche_end();
2105 
2106  print $form->buttonsSaveCancel("CreateDraft");
2107 
2108  // Show origin lines
2109  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2110  $title = $langs->trans('ProductsAndServices');
2111  print load_fiche_titre($title);
2112 
2113  print '<div class="div-table-responsive-no-min">';
2114  print '<table class="noborder centpercent">';
2115 
2116  $objectsrc->printOriginLinesList('', $selectedLines);
2117 
2118  print '</table>';
2119  print '</div>';
2120  }
2121 
2122  print '</form>';
2123 } else {
2124  // Mode view
2125  $now = dol_now();
2126 
2127  if ($object->id > 0) {
2128  $product_static = new Product($db);
2129 
2130  $soc = new Societe($db);
2131  $soc->fetch($object->socid);
2132 
2133  $author = new User($db);
2134  $author->fetch($object->user_author_id);
2135 
2136  $object->fetch_thirdparty();
2137  $res = $object->fetch_optionals();
2138 
2139  $head = commande_prepare_head($object);
2140  print dol_get_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, 'order');
2141 
2142  $formconfirm = '';
2143 
2144  // Confirmation to delete
2145  if ($action == 'delete') {
2146  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1);
2147  }
2148 
2149  // Confirmation of validation
2150  if ($action == 'validate') {
2151  // We check that object has a temporary ref
2152  $ref = substr($object->ref, 1, 4);
2153  if ($ref == 'PROV' || $ref == '') {
2154  $numref = $object->getNextNumRef($soc);
2155  if (empty($numref)) {
2156  $error++;
2157  setEventMessages($object->error, $object->errors, 'errors');
2158  }
2159  } else {
2160  $numref = $object->ref;
2161  }
2162 
2163  $text = $langs->trans('ConfirmValidateOrder', $numref);
2164  if (isModEnabled('notification')) {
2165  require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2166  $notify = new Notify($db);
2167  $text .= '<br>';
2168  $text .= $notify->confirmMessage('ORDER_VALIDATE', $object->socid, $object);
2169  }
2170 
2171  $qualified_for_stock_change = 0;
2172  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
2173  $qualified_for_stock_change = $object->hasProductsOrServices(2);
2174  } else {
2175  $qualified_for_stock_change = $object->hasProductsOrServices(1);
2176  }
2177 
2178  $formquestion = array();
2179  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
2180  $langs->load("stocks");
2181  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2182  $formproduct = new FormProduct($db);
2183  $forcecombo = 0;
2184  if ($conf->browser->name == 'ie') {
2185  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2186  }
2187  $formquestion = array(
2188  // 'text' => $langs->trans("ConfirmClone"),
2189  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2190  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2191  array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse', 'int') ?GETPOST('idwarehouse', 'int') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2192  );
2193  }
2194 
2195  // mandatoryPeriod
2196  $nbMandated = 0;
2197  foreach ($object->lines as $line) {
2198  $res = $line->fetch_product();
2199  if ($res > 0 ) {
2200  if ($line->product->isService() && $line->product->isMandatoryPeriod() && (empty($line->date_start) || empty($line->date_end) )) {
2201  $nbMandated++;
2202  break;
2203  }
2204  }
2205  }
2206  if ($nbMandated > 0 ) $text .= '<div><span class="clearboth nowraponall warning">'.$langs->trans("mandatoryPeriodNeedTobeSetMsgValidate").'</span></div>';
2207 
2208  if (getDolGlobalInt('SALE_ORDER_SUGGEST_DOWN_PAYMENT_INVOICE_CREATION')) {
2209  // This is a hidden option:
2210  // Suggestion to create invoice during order validation is not enabled by default.
2211  // Such choice should be managed by the workflow module and trigger. This option generates conflicts with some setup.
2212  // It may also break step of creating an order when invoicing must be done from proposals and not from orders
2213  $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
2214 
2215  if (!empty($deposit_percent_from_payment_terms) && isModEnabled('facture') && !empty($user->rights->facture->creer)) {
2216  require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
2217 
2218  $object->fetchObjectLinked();
2219 
2220  $eligibleForDepositGeneration = true;
2221 
2222  if (array_key_exists('facture', $object->linkedObjects)) {
2223  foreach ($object->linkedObjects['facture'] as $invoice) {
2224  if ($invoice->type == Facture::TYPE_DEPOSIT) {
2225  $eligibleForDepositGeneration = false;
2226  break;
2227  }
2228  }
2229  }
2230 
2231  if ($eligibleForDepositGeneration && array_key_exists('propal', $object->linkedObjects)) {
2232  foreach ($object->linkedObjects['propal'] as $proposal) {
2233  $proposal->fetchObjectLinked();
2234 
2235  if (array_key_exists('facture', $proposal->linkedObjects)) {
2236  foreach ($proposal->linkedObjects['facture'] as $invoice) {
2237  if ($invoice->type == Facture::TYPE_DEPOSIT) {
2238  $eligibleForDepositGeneration = false;
2239  break 2;
2240  }
2241  }
2242  }
2243  }
2244  }
2245 
2246  if ($eligibleForDepositGeneration) {
2247  $formquestion[] = array(
2248  'type' => 'checkbox',
2249  'tdclass' => '',
2250  'name' => 'generate_deposit',
2251  'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
2252  );
2253 
2254  $formquestion[] = array(
2255  'type' => 'date',
2256  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2257  'name' => 'datef',
2258  'label' => $langs->trans('DateInvoice'),
2259  'value' => dol_now(),
2260  'datenow' => true
2261  );
2262 
2263  if (!empty($conf->global->INVOICE_POINTOFTAX_DATE)) {
2264  $formquestion[] = array(
2265  'type' => 'date',
2266  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2267  'name' => 'date_pointoftax',
2268  'label' => $langs->trans('DatePointOfTax'),
2269  'value' => dol_now(),
2270  'datenow' => true
2271  );
2272  }
2273 
2274 
2275  $paymentTermsSelect = $form->getSelectConditionsPaiements(0, 'cond_reglement_id', -1, 0, 0, 'minwidth200');
2276 
2277  $formquestion[] = array(
2278  'type' => 'other',
2279  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2280  'name' => 'cond_reglement_id',
2281  'label' => $langs->trans('PaymentTerm'),
2282  'value' => $paymentTermsSelect
2283  );
2284 
2285  $formquestion[] = array(
2286  'type' => 'checkbox',
2287  'tdclass' => 'showonlyifgeneratedeposit',
2288  'name' => 'validate_generated_deposit',
2289  'label' => $langs->trans('ValidateGeneratedDeposit')
2290  );
2291 
2292  $formquestion[] = array(
2293  'type' => 'onecolumn',
2294  'value' => '
2295  <script>
2296  $(document).ready(function() {
2297  $("[name=generate_deposit]").change(function () {
2298  let $self = $(this);
2299  let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
2300 
2301  if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
2302  $target.show();
2303  } else {
2304  $target.hide();
2305  }
2306 
2307  return true;
2308  });
2309  });
2310  </script>
2311  '
2312  );
2313  }
2314  }
2315  }
2316 
2317  if (!$error) {
2318  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_validate', $formquestion, 0, 1, 220);
2319  }
2320  }
2321 
2322  // Confirm back to draft status
2323  if ($action == 'modif') {
2324  $qualified_for_stock_change = 0;
2325  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
2326  $qualified_for_stock_change = $object->hasProductsOrServices(2);
2327  } else {
2328  $qualified_for_stock_change = $object->hasProductsOrServices(1);
2329  }
2330 
2331  $text = $langs->trans('ConfirmUnvalidateOrder', $object->ref);
2332  $formquestion = array();
2333  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
2334  $langs->load("stocks");
2335  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2336  $formproduct = new FormProduct($db);
2337  $forcecombo = 0;
2338  if ($conf->browser->name == 'ie') {
2339  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2340  }
2341  $formquestion = array(
2342  // 'text' => $langs->trans("ConfirmClone"),
2343  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2344  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2345  array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ?GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2346  );
2347  }
2348 
2349  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('UnvalidateOrder'), $text, 'confirm_modif', $formquestion, "yes", 1, 220);
2350  }
2351 
2352  /*
2353  * Confirmation de la cloture
2354  */
2355  if ($action == 'shipped') {
2356  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('CloseOrder'), $langs->trans('ConfirmCloseOrder'), 'confirm_shipped', '', 0, 1);
2357  }
2358 
2359  /*
2360  * Confirmation de l'annulation
2361  */
2362  if ($action == 'cancel') {
2363  $qualified_for_stock_change = 0;
2364  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
2365  $qualified_for_stock_change = $object->hasProductsOrServices(2);
2366  } else {
2367  $qualified_for_stock_change = $object->hasProductsOrServices(1);
2368  }
2369 
2370  $text = $langs->trans('ConfirmCancelOrder', $object->ref);
2371  $formquestion = array();
2372  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
2373  $langs->load("stocks");
2374  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2375  $formproduct = new FormProduct($db);
2376  $forcecombo = 0;
2377  if ($conf->browser->name == 'ie') {
2378  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2379  }
2380  $formquestion = array(
2381  // 'text' => $langs->trans("ConfirmClone"),
2382  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2383  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2384  array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ?GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2385  );
2386  }
2387 
2388  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans("Cancel"), $text, 'confirm_cancel', $formquestion, 0, 1);
2389  }
2390 
2391  // Confirmation to delete line
2392  if ($action == 'ask_deleteline') {
2393  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2394  }
2395 
2396  // Clone confirmation
2397  if ($action == 'clone') {
2398  $filter = '(s.client:IN:1,2,3)';
2399  // Create an array for form
2400  $formquestion = array(
2401  array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300'))
2402  );
2403  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2404  }
2405 
2406  // Call Hook formConfirm
2407  $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2408  // Note that $action and $object may be modified by hook
2409  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
2410  if (empty($reshook)) {
2411  $formconfirm .= $hookmanager->resPrint;
2412  } elseif ($reshook > 0) {
2413  $formconfirm = $hookmanager->resPrint;
2414  }
2415 
2416  // Print form confirm
2417  print $formconfirm;
2418 
2419 
2420  // Order card
2421 
2422  $linkback = '<a href="'.DOL_URL_ROOT.'/commande/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
2423 
2424  $morehtmlref = '<div class="refidno">';
2425  // Ref customer
2426  $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string', '', 0, 1);
2427  $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':'.$conf->global->THIRDPARTY_REF_INPUT_SIZE : ''), '', null, null, '', 1);
2428  // Thirdparty
2429  $morehtmlref .= '<br>'.$soc->getNomUrl(1, 'customer');
2430  if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) {
2431  $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/commande/list.php?socid='.$object->thirdparty->id.'&search_societe='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherOrders").'</a>)';
2432  }
2433  // Project
2434  if (isModEnabled('project')) {
2435  $langs->load("projects");
2436  $morehtmlref .= '<br>';
2437  if ($usercancreate) {
2438  $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2439  if ($action != 'classify') {
2440  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
2441  }
2442  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
2443  } else {
2444  if (!empty($object->fk_project)) {
2445  $proj = new Project($db);
2446  $proj->fetch($object->fk_project);
2447  $morehtmlref .= $proj->getNomUrl(1);
2448  if ($proj->title) {
2449  $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
2450  }
2451  }
2452  }
2453  }
2454  $morehtmlref .= '</div>';
2455 
2456 
2457  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2458 
2459 
2460  print '<div class="fichecenter">';
2461  print '<div class="fichehalfleft">';
2462  print '<div class="underbanner clearboth"></div>';
2463 
2464  print '<table class="border tableforfield centpercent">';
2465 
2466  if ($soc->outstanding_limit) {
2467  // Outstanding Bill
2468  print '<tr><td class="titlefield">';
2469  print $langs->trans('OutstandingBill');
2470  print '</td><td class="valuefield">';
2471  $arrayoutstandingbills = $soc->getOutstandingBills();
2472  print price($arrayoutstandingbills['opened']).' / ';
2473  print price($soc->outstanding_limit, 0, '', 1, - 1, - 1, $conf->currency);
2474  print '</td>';
2475  print '</tr>';
2476  }
2477 
2478  // Relative and absolute discounts
2479  if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
2480  $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2481  $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2482  } else {
2483  $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
2484  $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
2485  }
2486 
2487  $addrelativediscount = '<a href="'.DOL_URL_ROOT.'/comm/remise.php?id='.$soc->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"]).'?facid='.$object->id.'">'.$langs->trans("EditRelativeDiscounts").'</a>';
2488  $addabsolutediscount = '<a href="'.DOL_URL_ROOT.'/comm/remx.php?id='.$soc->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"]).'?facid='.$object->id.'">'.$langs->trans("EditGlobalDiscounts").'</a>';
2489  $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>';
2490 
2491  print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td class="valuefield">';
2492 
2493  $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount);
2494  $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote);
2495  $absolute_discount = price2num($absolute_discount, 'MT');
2496  $absolute_creditnote = price2num($absolute_creditnote, 'MT');
2497 
2498  $thirdparty = $soc;
2499  $discount_type = 0;
2500  $backtopage = $_SERVER["PHP_SELF"].'?id='.$object->id;
2501  include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
2502 
2503  print '</td></tr>';
2504 
2505  // Date
2506  print '<tr><td>';
2507  $editenable = $usercancreate && $object->statut == Commande::STATUS_DRAFT;
2508  print $form->editfieldkey("Date", 'date', '', $object, $editenable);
2509  print '</td><td class="valuefield">';
2510  if ($action == 'editdate') {
2511  print '<form name="setdate" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2512  print '<input type="hidden" name="token" value="'.newToken().'">';
2513  print '<input type="hidden" name="action" value="setdate">';
2514  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2515  print $form->selectDate($object->date, 'order_', '', '', '', "setdate");
2516  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2517  print '</form>';
2518  } else {
2519  print $object->date ? dol_print_date($object->date, 'day') : '&nbsp;';
2520  if ($object->hasDelay() && empty($object->delivery_date)) { // If there is a delivery date planned, warning should be on this date
2521  print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2522  }
2523  }
2524  print '</td>';
2525  print '</tr>';
2526 
2527  // Delivery date planed
2528  print '<tr><td>';
2529  $editenable = $usercancreate;
2530  print $form->editfieldkey("DateDeliveryPlanned", 'date_livraison', '', $object, $editenable);
2531  print '</td><td class="valuefield">';
2532  if ($action == 'editdate_livraison') {
2533  print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2534  print '<input type="hidden" name="token" value="'.newToken().'">';
2535  print '<input type="hidden" name="action" value="setdate_livraison">';
2536  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2537  print $form->selectDate($object->delivery_date ? $object->delivery_date : -1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0);
2538  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2539  print '</form>';
2540  } else {
2541  print $object->delivery_date ? dol_print_date($object->delivery_date, 'dayhour') : '&nbsp;';
2542  if ($object->hasDelay() && !empty($object->delivery_date)) {
2543  print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2544  }
2545  }
2546  print '</td>';
2547  print '</tr>';
2548 
2549  // Delivery delay
2550  print '<tr class="fielddeliverydelay"><td>';
2551  $editenable = $usercancreate;
2552  print $form->editfieldkey("AvailabilityPeriod", 'availability', '', $object, $editenable);
2553  print '</td><td class="valuefield">';
2554  if ($action == 'editavailability') {
2555  $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'availability_id', 1);
2556  } else {
2557  $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'none', 1);
2558  }
2559  print '</td></tr>';
2560 
2561  // Shipping Method
2562  if (isModEnabled('expedition')) {
2563  print '<tr><td>';
2564  $editenable = $usercancreate;
2565  print $form->editfieldkey("SendingMethod", 'shippingmethod', '', $object, $editenable);
2566  print '</td><td class="valuefield">';
2567  if ($action == 'editshippingmethod') {
2568  $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
2569  } else {
2570  $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'none');
2571  }
2572  print '</td>';
2573  print '</tr>';
2574  }
2575 
2576  // Warehouse
2577  if (isModEnabled('stock') && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
2578  $langs->load('stocks');
2579  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2580  $formproduct = new FormProduct($db);
2581  print '<tr><td>';
2582  $editenable = $usercancreate;
2583  print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $editenable);
2584  print '</td><td class="valuefield">';
2585  if ($action == 'editwarehouse') {
2586  $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1);
2587  } else {
2588  $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'none');
2589  }
2590  print '</td>';
2591  print '</tr>';
2592  }
2593 
2594  // Source reason (why we have an order)
2595  print '<tr><td>';
2596  $editenable = $usercancreate;
2597  print $form->editfieldkey("Source", 'demandreason', '', $object, $editenable);
2598  print '</td><td class="valuefield">';
2599  if ($action == 'editdemandreason') {
2600  $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'demand_reason_id', 1);
2601  } else {
2602  $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'none');
2603  }
2604  print '</td></tr>';
2605 
2606  // Terms of payment
2607  print '<tr><td>';
2608  $editenable = $usercancreate;
2609  print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, $editenable);
2610  print '</td><td class="valuefield">';
2611  if ($action == 'editconditions') {
2612  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
2613  } else {
2614  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent);
2615  }
2616  print '</td>';
2617 
2618  print '</tr>';
2619 
2620  // Mode of payment
2621  print '<tr><td>';
2622  $editenable = $usercancreate;
2623  print $form->editfieldkey("PaymentMode", 'mode', '', $object, $editenable);
2624  print '</td><td class="valuefield">';
2625  if ($action == 'editmode') {
2626  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
2627  } else {
2628  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'none');
2629  }
2630  print '</td></tr>';
2631 
2632  // Multicurrency
2633  if (isModEnabled("multicurrency")) {
2634  // Multicurrency code
2635  print '<tr>';
2636  print '<td>';
2637  $editenable = $usercancreate && $object->statut == Commande::STATUS_DRAFT;
2638  print $form->editfieldkey("Currency", 'multicurrencycode', '', $object, $editenable);
2639  print '</td><td class="valuefield">';
2640  if ($action == 'editmulticurrencycode') {
2641  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'multicurrency_code');
2642  } else {
2643  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'none');
2644  }
2645  print '</td></tr>';
2646 
2647  // Multicurrency rate
2648  if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
2649  print '<tr>';
2650  print '<td>';
2651  $editenable = $usercancreate && $object->multicurrency_code && $object->multicurrency_code != $conf->currency && $object->statut == $object::STATUS_DRAFT;
2652  print $form->editfieldkey("CurrencyRate", 'multicurrencyrate', '', $object, $editenable);
2653  print '</td><td class="valuefield">';
2654  if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
2655  if ($action == 'actualizemulticurrencyrate') {
2656  list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
2657  }
2658  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
2659  } else {
2660  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
2661  if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
2662  print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
2663  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
2664  print '</div>';
2665  }
2666  }
2667  print '</td></tr>';
2668  }
2669  }
2670 
2671  // TODO Order mode (how we receive order). Not yet implemented
2672  /*
2673  print '<tr><td>';
2674  $editenable = $usercancreate;
2675  print $form->editfieldkey("SourceMode", 'inputmode', '', $object, $editenable);
2676  print '</td><td>';
2677  if ($action == 'editinputmode') {
2678  $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'input_mode_id', 1);
2679  } else {
2680  $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'none');
2681  }
2682  print '</td></tr>';
2683  */
2684 
2685  $tmparray = $object->getTotalWeightVolume();
2686  $totalWeight = $tmparray['weight'];
2687  $totalVolume = $tmparray['volume'];
2688  if ($totalWeight) {
2689  print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
2690  print '<td class="valuefield">';
2691  print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND) ? $conf->global->MAIN_WEIGHT_DEFAULT_ROUND : -1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? $conf->global->MAIN_WEIGHT_DEFAULT_UNIT : 'no');
2692  print '</td></tr>';
2693  }
2694  if ($totalVolume) {
2695  print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
2696  print '<td class="valuefield">';
2697  print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no');
2698  print '</td></tr>';
2699  }
2700 
2701  // TODO How record was recorded OrderMode (llx_c_input_method)
2702 
2703  // Incoterms
2704  if (isModEnabled('incoterm')) {
2705  print '<tr><td>';
2706  $editenable = $usercancreate;
2707  print $form->editfieldkey("IncotermLabel", 'incoterm', '', $object, $editenable);
2708  print '</td>';
2709  print '<td class="valuefield">';
2710  if ($action != 'editincoterm') {
2711  print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
2712  } else {
2713  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2714  }
2715  print '</td></tr>';
2716  }
2717 
2718  // Bank Account
2719  if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && isModEnabled("banque")) {
2720  print '<tr><td>';
2721  $editenable = $usercancreate;
2722  print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, $editenable);
2723  print '</td><td class="valuefield">';
2724  if ($action == 'editbankaccount') {
2725  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
2726  } else {
2727  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
2728  }
2729  print '</td>';
2730  print '</tr>';
2731  }
2732 
2733  // Other attributes
2734  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2735 
2736  print '</table>';
2737 
2738  print '</div>';
2739  print '<div class="fichehalfright">';
2740  print '<div class="underbanner clearboth"></div>';
2741 
2742  print '<table class="border tableforfield centpercent">';
2743 
2744  $alert = '';
2745  if (!empty($conf->global->ORDER_MANAGE_MIN_AMOUNT) && $object->total_ht < $object->thirdparty->order_min_amount) {
2746  $alert = ' ' . img_warning($langs->trans('OrderMinAmount') . ': ' . price($object->thirdparty->order_min_amount));
2747  }
2748 
2749  print '<tr>';
2750  print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
2751  print '<td class="nowrap amountcard right">' . price($object->total_ht, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2752  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2753  // Multicurrency Amount HT
2754  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2755  }
2756  print '</tr>';
2757 
2758  print '<tr>';
2759  print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
2760  print '<td class="nowrap amountcard right">' . price($object->total_tva, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2761  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2762  // Multicurrency Amount VAT
2763  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2764  }
2765  print '</tr>';
2766 
2767  // Amount Local Taxes
2768  if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
2769  print '<tr>';
2770  print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
2771  print '<td class="nowrap amountcard right">' . price($object->total_localtax1, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2772  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2773  $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
2774 
2775  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2776  }
2777  print '</tr>';
2778 
2779  // Amount Local Taxes
2780  if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
2781  print '<tr>';
2782  print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
2783  print '<td class="nowrap amountcard right">' . price($object->total_localtax2, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2784  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2785  $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
2786 
2787  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2788  }
2789  print '</tr>';
2790  }
2791  }
2792 
2793  print '<tr>';
2794  print '<td>' . $langs->trans('AmountTTC') . '</td>';
2795  print '<td class="valuefield nowrap right amountcard">' . price($object->total_ttc, 1, '', 1, -1, -1, $conf->currency) . '</td>';
2796  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2797  // Multicurrency Amount TTC
2798  print '<td class="valuefield nowrap right amountcard">' . price($object->multicurrency_total_ttc, 1, '', 1, -1, -1, $object->multicurrency_code) . '</td>';
2799  }
2800  print '</tr>'."\n";
2801 
2802  print '</table>';
2803 
2804  // Statut
2805  //print '<tr><td>' . $langs->trans('Status') . '</td><td>' . $object->getLibStatut(4) . '</td></tr>';
2806 
2807  // Margin Infos
2808  if (isModEnabled('margin')) {
2809  $formmargin->displayMarginInfos($object);
2810  }
2811 
2812 
2813  print '</div>';
2814  print '</div>'; // Close fichecenter
2815 
2816  print '<div class="clearboth"></div><br>';
2817 
2818  if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
2819  $blocname = 'contacts';
2820  $title = $langs->trans('ContactsAddresses');
2821  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2822  }
2823 
2824  if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
2825  $blocname = 'notes';
2826  $title = $langs->trans('Notes');
2827  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2828  }
2829 
2830  /*
2831  * Lines
2832  */
2833 
2834  // Get object lines
2835  $result = $object->getLinesArray();
2836 
2837  // Add products/services form
2838  //$forceall = 1;
2839  global $inputalsopricewithtax;
2840  $inputalsopricewithtax = 1;
2841 
2842  print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">
2843  <input type="hidden" name="token" value="' . newToken().'">
2844  <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
2845  <input type="hidden" name="mode" value="">
2846  <input type="hidden" name="page_y" value="">
2847  <input type="hidden" name="id" value="' . $object->id.'">
2848  <input type="hidden" name="backtopage" value="'.$backtopage.'">
2849  ';
2850 
2851  if (!empty($conf->use_javascript_ajax) && $object->statut == Commande::STATUS_DRAFT) {
2852  include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
2853  }
2854 
2855  print '<div class="div-table-responsive-no-min">';
2856  print '<table id="tablelines" class="noborder noshadow" width="100%">';
2857 
2858  // Show object lines
2859  if (!empty($object->lines)) {
2860  $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
2861  }
2862 
2863  $numlines = count($object->lines);
2864 
2865  /*
2866  * Form to add new line
2867  */
2868  if ($object->statut == Commande::STATUS_DRAFT && $usercancreate && $action != 'selectlines') {
2869  if ($action != 'editline') {
2870  // Add free products/services
2871 
2872  $parameters = array();
2873  // Note that $action and $object may be modified by hook
2874  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action);
2875  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2876  if (empty($reshook))
2877  $object->formAddObjectLine(1, $mysoc, $soc);
2878  }
2879  }
2880  print '</table>';
2881  print '</div>';
2882 
2883  print "</form>\n";
2884 
2885  print dol_get_fiche_end();
2886 
2887  /*
2888  * Buttons for actions
2889  */
2890  if ($action != 'presend' && $action != 'editline') {
2891  print '<div class="tabsAction">';
2892 
2893  $parameters = array();
2894  // Note that $action and $object may be modified by hook
2895  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
2896  if (empty($reshook)) {
2897  // Reopen a closed order
2898  if (($object->statut == Commande::STATUS_CLOSED || $object->statut == Commande::STATUS_CANCELED) && $usercancreate) {
2899  print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&amp;token='.newToken().'&amp;id='.$object->id, '');
2900  }
2901 
2902  // Send
2903  if (empty($user->socid)) {
2904  if ($object->statut > Commande::STATUS_DRAFT || !empty($conf->global->COMMANDE_SENDBYEMAIL_FOR_ALL_STATUS)) {
2905  if ($usercansend) {
2906  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?action=presend&token='.newToken().'&id='.$object->id.'&mode=init#formmailbeforetitle', '');
2907  } else {
2908  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2909  }
2910  }
2911  }
2912 
2913  // Valid
2914  if ($object->statut == Commande::STATUS_DRAFT && ($object->total_ttc >= 0 || !empty($conf->global->ORDER_ENABLE_NEGATIVE)) && $numlines > 0 && $usercanvalidate) {
2915  print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&amp;token='.newToken().'&amp;id='.$object->id, '');
2916  }
2917  // Edit
2918  if ($object->statut == Commande::STATUS_VALIDATED && $usercancreate) {
2919  print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?action=modif&amp;token='.newToken().'&amp;id='.$object->id, '');
2920  }
2921  // Create event
2922  /*if (isModEnabled('agenda') && !empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD))
2923  {
2924  // Add hidden condition because this is not a
2925  // "workflow" action so should appears somewhere else on
2926  // page.
2927  print '<a class="butAction" href="' . DOL_URL_ROOT . '/comm/action/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans("AddAction") . '</a>';
2928  }*/
2929 
2930  // Create a purchase order
2931  if (!empty($conf->global->WORKFLOW_CAN_CREATE_PURCHASE_ORDER_FROM_SALE_ORDER)) {
2932  if (isModEnabled("supplier_order") && $object->statut > Commande::STATUS_DRAFT && $object->getNbOfServicesLines() > 0) {
2933  if ($usercancreatepurchaseorder) {
2934  print dolGetButtonAction('', $langs->trans('AddPurchaseOrder'), 'default', DOL_URL_ROOT.'/fourn/commande/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id, '');
2935  }
2936  }
2937  }
2938 
2939  // Create intervention
2940  if (isModEnabled('ficheinter')) {
2941  $langs->load("interventions");
2942 
2943  if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0) {
2944  if ($user->hasRight('ficheinter', 'creer')) {
2945  print dolGetButtonAction('', $langs->trans('AddIntervention'), 'default', DOL_URL_ROOT.'/fichinter/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
2946  } else {
2947  print dolGetButtonAction($langs->trans('NotAllowed'), $langs->trans('AddIntervention'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2948  }
2949  }
2950  }
2951 
2952  // Create contract
2953  if (isModEnabled('contrat') && ($object->statut == Commande::STATUS_VALIDATED || $object->statut == Commande::STATUS_SHIPMENTONPROCESS || $object->statut == Commande::STATUS_CLOSED)) {
2954  $langs->load("contracts");
2955 
2956  if ($user->hasRight('contrat', 'creer')) {
2957  print dolGetButtonAction('', $langs->trans('AddContract'), 'default', DOL_URL_ROOT.'/contrat/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
2958  }
2959  }
2960 
2961  // Ship
2962  $numshipping = 0;
2963  if (isModEnabled('expedition')) {
2964  $numshipping = $object->countNbOfShipments();
2965 
2966  if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || !empty($conf->global->STOCK_SUPPORTS_SERVICES))) {
2967  if ((getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION') && $user->hasRight('expedition', 'creer')) || (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') && $user->hasRight('expedition', 'delivery', 'creer'))) {
2968  if ($user->hasRight('expedition', 'creer')) {
2969  print dolGetButtonAction('', $langs->trans('CreateShipment'), 'default', DOL_URL_ROOT.'/expedition/shipment.php?id='.$object->id, '');
2970  } else {
2971  print dolGetButtonAction($langs->trans('NotAllowed'), $langs->trans('CreateShipment'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2972  }
2973  } else {
2974  $langs->load("errors");
2975  print dolGetButtonAction($langs->trans('ErrorModuleSetupNotComplete'), $langs->trans('CreateShipment'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2976  }
2977  }
2978  }
2979 
2980  // Set to shipped
2981  if (($object->statut == Commande::STATUS_VALIDATED || $object->statut == Commande::STATUS_SHIPMENTONPROCESS) && $usercanclose) {
2982  print dolGetButtonAction('', $langs->trans('ClassifyShipped'), 'default', $_SERVER["PHP_SELF"].'?action=shipped&amp;token='.newToken().'&amp;id='.$object->id, '');
2983  }
2984  // Create bill and Classify billed
2985  // Note: Even if module invoice is not enabled, we should be able to use button "Classified billed"
2986  if ($object->statut > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) {
2987  if (isModEnabled('facture') && $user->hasRight('facture', 'creer') && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) {
2988  print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT.'/compta/facture/card.php?action=create&amp;token='.newToken().'&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
2989  }
2990  if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) {
2991  print dolGetButtonAction('', $langs->trans('ClassifyBilled'), 'default', $_SERVER["PHP_SELF"].'?action=classifybilled&amp;token='.newToken().'&amp;id='.$object->id, '');
2992  }
2993  }
2994  if ($object->statut > Commande::STATUS_DRAFT && $object->billed) {
2995  if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) {
2996  print dolGetButtonAction('', $langs->trans('ClassifyUnBilled'), 'default', $_SERVER["PHP_SELF"].'?action=classifyunbilled&amp;token='.newToken().'&amp;id='.$object->id, '');
2997  }
2998  }
2999  // Clone
3000  if ($usercancreate) {
3001  print dolGetButtonAction('', $langs->trans('ToClone'), 'default', $_SERVER["PHP_SELF"].'?action=clone&amp;token='.newToken().'&amp;id='.$object->id.'&amp;socid='.$object->socid, '');
3002  }
3003 
3004  // Cancel order
3005  if ($object->statut == Commande::STATUS_VALIDATED && !empty($usercancancel)) {
3006  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=cancel&token='.newToken().'">'.$langs->trans("Cancel").'</a>';
3007  }
3008 
3009  // Delete order
3010  if ($usercandelete) {
3011  if ($numshipping == 0) {
3012  print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id, '');
3013  } else {
3014  print dolGetButtonAction($langs->trans('ShippingExist'), $langs->trans('Delete'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
3015  }
3016  }
3017  }
3018  print '</div>';
3019  }
3020 
3021  // Select mail models is same action as presend
3022  if (GETPOST('modelselected')) {
3023  $action = 'presend';
3024  }
3025 
3026  if ($action != 'presend') {
3027  print '<div class="fichecenter"><div class="fichehalfleft">';
3028  print '<a name="builddoc"></a>'; // ancre
3029  // Documents
3030  $objref = dol_sanitizeFileName($object->ref);
3031  $relativepath = $objref.'/'.$objref.'.pdf';
3032  $filedir = $conf->commande->multidir_output[$object->entity].'/'.$objref;
3033  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
3034  $genallowed = $usercanread;
3035  $delallowed = $usercancreate;
3036  print $formfile->showdocuments('commande', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang, '', $object);
3037 
3038 
3039  // Show links to link elements
3040  $linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
3041 
3042  $compatibleImportElementsList = false;
3043  if ($usercancreate
3044  && $object->statut == Commande::STATUS_DRAFT) {
3045  $compatibleImportElementsList = array('commande', 'propal', 'facture'); // import from linked elements
3046  }
3047  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
3048 
3049  // Show online payment link
3050  $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox'));
3051  if (!empty($conf->global->ORDER_HIDE_ONLINE_PAYMENT_ON_ORDER)) {
3052  $useonlinepayment = 0;
3053  }
3054  if ($object->statut != Commande::STATUS_DRAFT && $useonlinepayment) {
3055  print '<br><!-- Link to pay -->';
3056  require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
3057  print showOnlinePaymentUrl('order', $object->ref).'<br>';
3058  }
3059 
3060  print '</div><div class="fichehalfright">';
3061 
3062  $MAXEVENT = 10;
3063 
3064  $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/commande/agenda.php?id='.$object->id);
3065 
3066  // List of actions on element
3067  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
3068  $formactions = new FormActions($db);
3069  $somethingshown = $formactions->showactions($object, 'order', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter); // Show all action for thirdparty
3070 
3071  print '</div></div>';
3072  }
3073 
3074  // Presend form
3075  $modelmail = 'order_send';
3076  $defaulttopic = 'SendOrderRef';
3077  $diroutput = getMultidirOutput($object);
3078  $trackid = 'ord'.$object->id;
3079 
3080  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
3081  }
3082 }
3083 
3084 // End of page
3085 llxFooter();
3086 $db->close();
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
if(preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) if(preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) if($action=='set') elseif($action=='specimen') elseif($action=='setmodel') elseif($action=='del') elseif($action=='setdoc') $formactions
View.
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
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.
Classe permettant la generation de composants html autre Only common components are here.
Class to manage HTML output components for orders Before adding component here, check they are not in...
Class with static methods for building HTML components related to products Only components common to ...
Class to manage building of HTML components.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
static getIdAndTxFromCode($dbs, $code, $date_document='')
Get id and rate of currency from code.
Class to manage notifications.
Class ProductCombination Used to represent a product combination.
Class to manage products or services.
File of class to manage predefined price products or services by customer.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:48
getCountry($searchkey, $withcode='', $dbtouse=0, $outputlangs='', $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
$parameters
Actions.
Definition: card.php:83
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) if(!function_exists('str_starts_with')) if(!function_exists('str_ends_with')) if(!function_exists('str_contains')) getMultidirOutput($object, $module='')
Return the full path of the directory where a module (or an object of a module) stores its files.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
GETPOSTINT($paramname, $method=0)
Return value of a param into GET or POST supervariable.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
getDictionaryValue($tablename, $field, $id, $checkentity=false, $rowidfield='rowid')
Return the value of a filed into a dictionary for the record $id.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$formconfirm
if ($action == 'delbookkeepingyear') {
div float
Buy price without taxes.
Definition: style.css.php:926
commande_prepare_head(Commande $object)
Prepare array with list of tabs.
Definition: order.lib.php:34
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.