dolibarr  19.0.0-dev
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', 'int');
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', 'int');
289  $object->deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
290  $object->mode_reglement_id = GETPOST('mode_reglement_id', 'int');
291  $object->fk_account = GETPOST('fk_account', 'int');
292  $object->availability_id = GETPOST('availability_id');
293  $object->demand_reason_id = GETPOST('demand_reason_id', 'int');
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', 'int');
299  $object->contact_id = GETPOST('contactid', 'int');
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  // Prepare a price equivalent for minimum price check
699  $pu_equivalent = $pu_ht;
700  $pu_equivalent_ttc = $pu_ttc;
701  $currency_tx = $object->multicurrency_tx;
702 
703  // Check if we have a foreing currency
704  // If so, we update the pu_equiv as the equivalent price in base currency
705  if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') {
706  $pu_equivalent = $pu_ht_devise * $currency_tx;
707  }
708  if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') {
709  $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx;
710  }
711 
712  $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
713 
714  $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0);
715  if (empty($remise_percent)) {
716  $remise_percent = 0;
717  }
718 
719  // Extrafields
720  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
721  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
722  // Unset extrafield
723  if (is_array($extralabelsline)) {
724  // Get extra fields
725  foreach ($extralabelsline as $key => $value) {
726  unset($_POST["options_".$key]);
727  }
728  }
729 
730  if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ($qty < 0)) {
731  setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
732  $error++;
733  }
734  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
735  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
736  $error++;
737  }
738  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.
739  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
740  $error++;
741  }
742  if ($qty == '') {
743  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
744  $error++;
745  }
746  if ($qty < 0) {
747  setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
748  $error++;
749  }
750  if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
751  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
752  $error++;
753  }
754 
755  if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
756  if ($combinations = GETPOST('combinations', 'array')) {
757  //Check if there is a product with the given combination
758  $prodcomb = new ProductCombination($db);
759 
760  if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
761  $idprod = $res->fk_product_child;
762  } else {
763  setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
764  $error++;
765  }
766  }
767  }
768 
769  if (!$error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
770  // Clean parameters
771  $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'));
772  $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'));
773  $price_base_type = (GETPOST('price_base_type', 'alpha') ?GETPOST('price_base_type', 'alpha') : 'HT');
774 
775  // Ecrase $pu par celui du produit
776  // Ecrase $desc par celui du produit
777  // Ecrase $base_price_type par celui du produit
778  if (!empty($idprod) && $idprod > 0) {
779  $prod = new Product($db);
780  $prod->fetch($idprod);
781 
782  $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
783 
784  // Update if prices fields are defined
785  /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
786  $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
787  if (empty($tva_tx)) {
788  $tva_npr = 0;
789  }*/
790 
791  $pu_ht = $prod->price;
792  $pu_ttc = $prod->price_ttc;
793  $price_min = $prod->price_min;
794  $price_min_ttc = $prod->price_min_ttc;
795  $price_base_type = $prod->price_base_type;
796 
797  // If price per segment
798  if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) {
799  $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
800  $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
801  $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
802  $price_min_ttc = $prod->multiprices_min_ttc[$object->thirdparty->price_level];
803  $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
804  if (!empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { // using this option is a bug. kept for backward compatibility
805  if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) {
806  $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level];
807  }
808  if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) {
809  $tva_npr = $prod->multiprices_recuperableonly[$object->thirdparty->price_level];
810  }
811  }
812  } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
813  // If price per customer
814  require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php';
815 
816  $prodcustprice = new Productcustomerprice($db);
817 
818  $filter = array('t.fk_product' => $prod->id, 't.fk_soc' => $object->thirdparty->id);
819 
820  $result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
821  if ($result >= 0) {
822  if (count($prodcustprice->lines) > 0) {
823  $pu_ht = price($prodcustprice->lines[0]->price);
824  $pu_ttc = price($prodcustprice->lines[0]->price_ttc);
825  $price_min = price($prodcustprice->lines[0]->price_min);
826  $price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc);
827  $price_base_type = $prodcustprice->lines[0]->price_base_type;
828  $tva_tx = $prodcustprice->lines[0]->tva_tx;
829  if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\‍(.*\‍)/', $tva_tx)) {
830  $tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
831  }
832  $tva_npr = $prodcustprice->lines[0]->recuperableonly;
833  if (empty($tva_tx)) {
834  $tva_npr = 0;
835  }
836  }
837  } else {
838  setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
839  }
840  } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) {
841  // If price per quantity
842  if ($prod->prices_by_qty[0]) { // yes, this product has some prices per quantity
843  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
844  $pqp = GETPOST('pbq', 'int');
845 
846  // Search price into product_price_by_qty from $prod->id
847  foreach ($prod->prices_by_qty_list[0] as $priceforthequantityarray) {
848  if ($priceforthequantityarray['rowid'] != $pqp) {
849  continue;
850  }
851  // We found the price
852  if ($priceforthequantityarray['price_base_type'] == 'HT') {
853  $pu_ht = $priceforthequantityarray['unitprice'];
854  } else {
855  $pu_ttc = $priceforthequantityarray['unitprice'];
856  }
857  // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
858  break;
859  }
860  }
861  } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) {
862  // If price per quantity and customer
863  if ($prod->prices_by_qty[$object->thirdparty->price_level]) { // yes, this product has some prices per quantity
864  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
865  $pqp = GETPOST('pbq', 'int');
866  // Search price into product_price_by_qty from $prod->id
867  foreach ($prod->prices_by_qty_list[$object->thirdparty->price_level] as $priceforthequantityarray) {
868  if ($priceforthequantityarray['rowid'] != $pqp) {
869  continue;
870  }
871  // We found the price
872  if ($priceforthequantityarray['price_base_type'] == 'HT') {
873  $pu_ht = $priceforthequantityarray['unitprice'];
874  } else {
875  $pu_ttc = $priceforthequantityarray['unitprice'];
876  }
877  // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
878  break;
879  }
880  }
881  }
882 
883  $tmpvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx));
884  $tmpprodvat = price2num(preg_replace('/\s*\‍(.*\‍)/', '', $prod->tva_tx));
885 
886  // Set unit price to use
887  if (!empty($price_ht) || $price_ht === '0') {
888  $pu_ht = price2num($price_ht, 'MU');
889  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
890  } elseif (!empty($price_ttc) || $price_ttc === '0') {
891  $pu_ttc = price2num($price_ttc, 'MU');
892  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
893  } elseif ($tmpvat != $tmpprodvat) {
894  // Is this still used ?
895  if ($price_base_type != 'HT') {
896  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
897  } else {
898  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
899  }
900  }
901 
902  $desc = '';
903 
904  // Define output language
905  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
906  $outputlangs = $langs;
907  $newlang = '';
908  if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
909  $newlang = GETPOST('lang_id', 'aZ09');
910  }
911  if (empty($newlang)) {
912  $newlang = $object->thirdparty->default_lang;
913  }
914  if (!empty($newlang)) {
915  $outputlangs = new Translate("", $conf);
916  $outputlangs->setDefaultLang($newlang);
917  }
918 
919  $desc = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
920  } else {
921  $desc = $prod->description;
922  }
923 
924  //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time
925  if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) {
926  $product_desc='';
927  }
928 
929  if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) {
930  $desc = $product_desc;
931  } else {
932  $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION));
933  }
934 
935  // Add custom code and origin country into description
936  if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) {
937  $tmptxt = '(';
938  // Define output language
939  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
940  $outputlangs = $langs;
941  $newlang = '';
942  if (empty($newlang) && GETPOST('lang_id', 'alpha')) {
943  $newlang = GETPOST('lang_id', 'alpha');
944  }
945  if (empty($newlang)) {
946  $newlang = $object->thirdparty->default_lang;
947  }
948  if (!empty($newlang)) {
949  $outputlangs = new Translate("", $conf);
950  $outputlangs->setDefaultLang($newlang);
951  $outputlangs->load('products');
952  }
953  if (!empty($prod->customcode)) {
954  $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
955  }
956  if (!empty($prod->customcode) && !empty($prod->country_code)) {
957  $tmptxt .= ' - ';
958  }
959  if (!empty($prod->country_code)) {
960  $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $outputlangs, 0);
961  }
962  } else {
963  if (!empty($prod->customcode)) {
964  $tmptxt .= $langs->transnoentitiesnoconv("CustomCode").': '.$prod->customcode;
965  }
966  if (!empty($prod->customcode) && !empty($prod->country_code)) {
967  $tmptxt .= ' - ';
968  }
969  if (!empty($prod->country_code)) {
970  $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, 0, $db, $langs, 0);
971  }
972  }
973  $tmptxt .= ')';
974  $desc = dol_concatdesc($desc, $tmptxt);
975  }
976 
977  $type = $prod->type;
978  $fk_unit = $prod->fk_unit;
979  } else {
980  $pu_ht = price2num($price_ht, 'MU');
981  $pu_ttc = price2num($price_ttc, 'MU');
982  $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
983  $tva_tx = str_replace('*', '', $tva_tx);
984  if (empty($tva_tx)) {
985  $tva_npr = 0;
986  }
987  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
988  $desc = $product_desc;
989  $type = GETPOST('type');
990  $fk_unit = GETPOST('units', 'alpha');
991  $pu_ht_devise = price2num($price_ht_devise, 'MU');
992  $pu_ttc_devise = price2num($price_ttc_devise, 'MU');
993 
994  if ($pu_ttc && !$pu_ht) {
995  $price_base_type = 'TTC';
996  }
997  }
998 
999  // Margin
1000  $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : '');
1001  $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we muste keep this value
1002 
1003  // Local Taxes
1004  $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty);
1005  $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty);
1006 
1007  $info_bits = 0;
1008  if ($tva_npr) {
1009  $info_bits |= 0x01;
1010  }
1011 
1012  $desc = dol_htmlcleanlastbr($desc);
1013 
1014  if ($usermustrespectpricemin) {
1015  if ($pu_equivalent && $price_min && ((price2num($pu_equivalent) * (1 - $remise_percent / 100)) < price2num($price_min))) {
1016  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1017  setEventMessages($mesg, null, 'errors');
1018  $error++;
1019  } elseif ($pu_equivalent_ttc && $price_min_ttc && ((price2num($pu_equivalent_ttc) * (1 - $remise_percent / 100)) < price2num($price_min_ttc))) {
1020  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1021  setEventMessages($mesg, null, 'errors');
1022  $error++;
1023  }
1024  }
1025 
1026  if (!$error) {
1027  // Insert line
1028  $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);
1029 
1030  if ($result > 0) {
1031  $ret = $object->fetch($object->id); // Reload to get new records
1032  $object->fetch_thirdparty();
1033 
1034  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1035  // Define output language
1036  $outputlangs = $langs;
1037  $newlang = GETPOST('lang_id', 'alpha');
1038  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1039  $newlang = $object->thirdparty->default_lang;
1040  }
1041  if (!empty($newlang)) {
1042  $outputlangs = new Translate("", $conf);
1043  $outputlangs->setDefaultLang($newlang);
1044  }
1045 
1046  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1047  }
1048 
1049  unset($_POST['prod_entry_mode']);
1050 
1051  unset($_POST['qty']);
1052  unset($_POST['type']);
1053  unset($_POST['remise_percent']);
1054  unset($_POST['price_ht']);
1055  unset($_POST['multicurrency_price_ht']);
1056  unset($_POST['price_ttc']);
1057  unset($_POST['tva_tx']);
1058  unset($_POST['product_ref']);
1059  unset($_POST['product_label']);
1060  unset($_POST['product_desc']);
1061  unset($_POST['fournprice']);
1062  unset($_POST['buying_price']);
1063  unset($_POST['np_marginRate']);
1064  unset($_POST['np_markRate']);
1065  unset($_POST['dp_desc']);
1066  unset($_POST['idprod']);
1067  unset($_POST['units']);
1068 
1069  unset($_POST['date_starthour']);
1070  unset($_POST['date_startmin']);
1071  unset($_POST['date_startsec']);
1072  unset($_POST['date_startday']);
1073  unset($_POST['date_startmonth']);
1074  unset($_POST['date_startyear']);
1075  unset($_POST['date_endhour']);
1076  unset($_POST['date_endmin']);
1077  unset($_POST['date_endsec']);
1078  unset($_POST['date_endday']);
1079  unset($_POST['date_endmonth']);
1080  unset($_POST['date_endyear']);
1081  } else {
1082  setEventMessages($object->error, $object->errors, 'errors');
1083  }
1084  }
1085  }
1086  } elseif ($action == 'updateline' && $usercancreate && GETPOST('save')) {
1087  // Update a line
1088  // Clean parameters
1089  $date_start = '';
1090  $date_end = '';
1091  $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
1092  $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
1093  $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml'));
1094  $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx', 'alpha') : 0);
1095  $vat_rate = str_replace('*', '', $vat_rate);
1096 
1097  $pu_ht = price2num(GETPOST('price_ht'), '', 2);
1098  $pu_ttc = price2num(GETPOST('price_ttc'), '', 2);
1099 
1100  $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
1101  $pu_ttc_devise = price2num(GETPOST('multicurrency_subprice_ttc'), '', 2);
1102 
1103  $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
1104 
1105  // Prepare a price equivalent for minimum price check
1106  $pu_equivalent = $pu_ht;
1107  $pu_equivalent_ttc = $pu_ttc;
1108  $currency_tx = $object->multicurrency_tx;
1109 
1110  // Check if we have a foreing currency
1111  // If so, we update the pu_equiv as the equivalent price in base currency
1112  if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') {
1113  $pu_equivalent = $pu_ht_devise * $currency_tx;
1114  }
1115  if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') {
1116  $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx;
1117  }
1118 
1119  // Define info_bits
1120  $info_bits = 0;
1121  if (preg_match('/\*/', $vat_rate)) {
1122  $info_bits |= 0x01;
1123  }
1124 
1125  // Define vat_rate
1126  $vat_rate = str_replace('*', '', $vat_rate);
1127  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
1128  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
1129 
1130  // Add buying price
1131  $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
1132  $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we muste keep this value
1133 
1134  // Extrafields Lines
1135  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1136  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
1137  // Unset extrafield POST Data
1138  if (is_array($extralabelsline)) {
1139  foreach ($extralabelsline as $key => $value) {
1140  unset($_POST["options_".$key]);
1141  }
1142  }
1143 
1144  // Define special_code for special lines
1145  $special_code = GETPOST('special_code');
1146  if (!GETPOST('qty')) {
1147  $special_code = 3;
1148  }
1149 
1150  $remise_percent = GETPOST('remise_percent') != '' ? price2num(GETPOST('remise_percent'), '', 2) : 0;
1151 
1152  // Check minimum price
1153  $productid = GETPOST('productid', 'int');
1154  if (!empty($productid)) {
1155  $product = new Product($db);
1156  $product->fetch($productid);
1157 
1158  $type = $product->type;
1159 
1160  $price_min = $product->price_min;
1161  if ((!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && !empty($object->thirdparty->price_level)) {
1162  $price_min = $product->multiprices_min[$object->thirdparty->price_level];
1163  }
1164  $price_min_ttc = $product->price_min_ttc;
1165  if ((!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && !empty($object->thirdparty->price_level)) {
1166  $price_min_ttc = $product->multiprices_min_ttc[$object->thirdparty->price_level];
1167  }
1168 
1169  $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
1170 
1171  if ($usermustrespectpricemin) {
1172  if ($pu_equivalent && $price_min && ((price2num($pu_equivalent) * (1 - $remise_percent / 100)) < price2num($price_min))) {
1173  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1174  setEventMessages($mesg, null, 'errors');
1175  $error++;
1176  $action = 'editline';
1177  } elseif ($pu_equivalent_ttc && $price_min_ttc && ((price2num($pu_equivalent_ttc) * (1 - $remise_percent / 100)) < price2num($price_min_ttc))) {
1178  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
1179  setEventMessages($mesg, null, 'errors');
1180  $error++;
1181  $action = 'editline';
1182  }
1183  }
1184  } else {
1185  $type = GETPOST('type');
1186  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1187 
1188  // Check parameters
1189  if (GETPOST('type') < 0) {
1190  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1191  $error++;
1192  $action = 'editline';
1193  }
1194  }
1195 
1196  if ($qty < 0) {
1197  setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1198  $error++;
1199  $action = 'editline';
1200  }
1201 
1202  if (!$error) {
1203  if (empty($user->rights->margins->creer)) {
1204  foreach ($object->lines as &$line) {
1205  if ($line->id == GETPOST('lineid', 'int')) {
1206  $fournprice = $line->fk_fournprice;
1207  $buyingprice = $line->pa_ht;
1208  break;
1209  }
1210  }
1211  }
1212 
1213  $price_base_type = 'HT';
1214  $pu = $pu_ht;
1215  if (empty($pu) && !empty($pu_ttc)) {
1216  $pu = $pu_ttc;
1217  $price_base_type = 'TTC';
1218  }
1219 
1220  $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);
1221 
1222  if ($result >= 0) {
1223  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1224  // Define output language
1225  $outputlangs = $langs;
1226  $newlang = '';
1227  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1228  $newlang = GETPOST('lang_id', 'aZ09');
1229  }
1230  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1231  $newlang = $object->thirdparty->default_lang;
1232  }
1233  if (!empty($newlang)) {
1234  $outputlangs = new Translate("", $conf);
1235  $outputlangs->setDefaultLang($newlang);
1236  }
1237 
1238  $ret = $object->fetch($object->id); // Reload to get new records
1239  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1240  }
1241 
1242  unset($_POST['qty']);
1243  unset($_POST['type']);
1244  unset($_POST['productid']);
1245  unset($_POST['remise_percent']);
1246  unset($_POST['price_ht']);
1247  unset($_POST['multicurrency_price_ht']);
1248  unset($_POST['price_ttc']);
1249  unset($_POST['tva_tx']);
1250  unset($_POST['product_ref']);
1251  unset($_POST['product_label']);
1252  unset($_POST['product_desc']);
1253  unset($_POST['fournprice']);
1254  unset($_POST['buying_price']);
1255 
1256  unset($_POST['date_starthour']);
1257  unset($_POST['date_startmin']);
1258  unset($_POST['date_startsec']);
1259  unset($_POST['date_startday']);
1260  unset($_POST['date_startmonth']);
1261  unset($_POST['date_startyear']);
1262  unset($_POST['date_endhour']);
1263  unset($_POST['date_endmin']);
1264  unset($_POST['date_endsec']);
1265  unset($_POST['date_endday']);
1266  unset($_POST['date_endmonth']);
1267  unset($_POST['date_endyear']);
1268  } else {
1269  setEventMessages($object->error, $object->errors, 'errors');
1270  }
1271  }
1272  } elseif ($action == 'updateline' && $usercancreate && GETPOST('cancel', 'alpha')) {
1273  header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // Pour reaffichage de la fiche en cours d'edition
1274  exit();
1275  } elseif ($action == 'confirm_validate' && $confirm == 'yes' && $usercanvalidate) {
1276  $idwarehouse = GETPOST('idwarehouse', 'int');
1277 
1278  $qualified_for_stock_change = 0;
1279  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1280  $qualified_for_stock_change = $object->hasProductsOrServices(2);
1281  } else {
1282  $qualified_for_stock_change = $object->hasProductsOrServices(1);
1283  }
1284 
1285  // Check parameters
1286  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
1287  if (!$idwarehouse || $idwarehouse == -1) {
1288  $error++;
1289  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1290  $action = '';
1291  }
1292  }
1293 
1294  if (!$error) {
1295  $locationTarget = '';
1296  $db->begin();
1297  $result = $object->valid($user, $idwarehouse);
1298  if ($result >= 0) {
1299  $error = 0;
1300  $deposit = null;
1301 
1302  $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
1303 
1304  if (
1305  GETPOST('generate_deposit', 'alpha') == 'on' && !empty($deposit_percent_from_payment_terms)
1306  && isModEnabled('facture') && !empty($user->rights->facture->creer)
1307  ) {
1308  require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
1309 
1310  $date = dol_mktime(0, 0, 0, GETPOST('datefmonth', 'int'), GETPOST('datefday', 'int'), GETPOST('datefyear', 'int'));
1311  $forceFields = array();
1312 
1313  if (GETPOSTISSET('date_pointoftax')) {
1314  $forceFields['date_pointoftax'] = dol_mktime(0, 0, 0, GETPOST('date_pointoftaxmonth', 'int'), GETPOST('date_pointoftaxday', 'int'), GETPOST('date_pointoftaxyear', 'int'));
1315  }
1316 
1317  $deposit = Facture::createDepositFromOrigin($object, $date, GETPOST('cond_reglement_id', 'int'), $user, 0, GETPOST('validate_generated_deposit', 'alpha') == 'on', $forceFields);
1318 
1319  if ($deposit) {
1320  setEventMessage('DepositGenerated');
1321  $locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
1322  } else {
1323  $error++;
1324  setEventMessages($object->error, $object->errors, 'errors');
1325  }
1326  }
1327 
1328  // Define output language
1329  if (! $error) {
1330  $db->commit();
1331 
1332  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1333  $outputlangs = $langs;
1334  $newlang = '';
1335  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1336  $newlang = GETPOST('lang_id', 'aZ09');
1337  }
1338  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1339  $newlang = $object->thirdparty->default_lang;
1340  }
1341  if (!empty($newlang)) {
1342  $outputlangs = new Translate("", $conf);
1343  $outputlangs->setDefaultLang($newlang);
1344  }
1345  $model = $object->model_pdf;
1346  $ret = $object->fetch($id); // Reload to get new records
1347 
1348  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1349 
1350  if ($deposit) {
1351  $deposit->fetch($deposit->id); // Reload to get new records
1352  $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1353  }
1354  }
1355 
1356  if ($locationTarget) {
1357  header('Location: ' . $locationTarget);
1358  exit;
1359  }
1360  } else {
1361  $db->rollback();
1362  }
1363  } else {
1364  $db->rollback();
1365  setEventMessages($object->error, $object->errors, 'errors');
1366  }
1367  }
1368  } elseif ($action == 'confirm_modif' && $usercancreate) {
1369  // Go back to draft status
1370  $idwarehouse = GETPOST('idwarehouse');
1371 
1372  $qualified_for_stock_change = 0;
1373  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1374  $qualified_for_stock_change = $object->hasProductsOrServices(2);
1375  } else {
1376  $qualified_for_stock_change = $object->hasProductsOrServices(1);
1377  }
1378 
1379  // Check parameters
1380  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
1381  if (!$idwarehouse || $idwarehouse == -1) {
1382  $error++;
1383  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1384  $action = '';
1385  }
1386  }
1387 
1388  if (!$error) {
1389  $result = $object->setDraft($user, $idwarehouse);
1390  if ($result >= 0) {
1391  // Define output language
1392  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1393  $outputlangs = $langs;
1394  $newlang = '';
1395  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1396  $newlang = GETPOST('lang_id', 'aZ09');
1397  }
1398  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1399  $newlang = $object->thirdparty->default_lang;
1400  }
1401  if (!empty($newlang)) {
1402  $outputlangs = new Translate("", $conf);
1403  $outputlangs->setDefaultLang($newlang);
1404  }
1405  $model = $object->model_pdf;
1406  $ret = $object->fetch($id); // Reload to get new records
1407 
1408  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1409  }
1410  } else {
1411  setEventMessages($object->error, $object->errors, 'errors');
1412  }
1413  }
1414  } elseif ($action == 'confirm_shipped' && $confirm == 'yes' && $usercanclose) {
1415  $result = $object->cloture($user);
1416  if ($result < 0) {
1417  setEventMessages($object->error, $object->errors, 'errors');
1418  }
1419  } elseif ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanvalidate) {
1420  $idwarehouse = GETPOST('idwarehouse', 'int');
1421 
1422  $qualified_for_stock_change = 0;
1423  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1424  $qualified_for_stock_change = $object->hasProductsOrServices(2);
1425  } else {
1426  $qualified_for_stock_change = $object->hasProductsOrServices(1);
1427  }
1428 
1429  // Check parameters
1430  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
1431  if (!$idwarehouse || $idwarehouse == -1) {
1432  $error++;
1433  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
1434  $action = '';
1435  }
1436  }
1437 
1438  if (!$error) {
1439  $result = $object->cancel($idwarehouse);
1440 
1441  if ($result < 0) {
1442  setEventMessages($object->error, $object->errors, 'errors');
1443  }
1444  }
1445  }
1446 
1447  if ($action == 'update_extras') {
1448  $object->oldcopy = dol_clone($object);
1449 
1450  // Fill array 'array_options' with data from update form
1451  $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
1452  if ($ret < 0) {
1453  $error++;
1454  }
1455 
1456  if (!$error) {
1457  // Actions on extra fields
1458  $result = $object->insertExtraFields('ORDER_MODIFY');
1459  if ($result < 0) {
1460  setEventMessages($object->error, $object->errors, 'errors');
1461  $error++;
1462  }
1463  }
1464 
1465  if ($error) {
1466  $action = 'edit_extras';
1467  }
1468  }
1469 
1470  // add lines from objectlinked
1471  if ($action == 'import_lines_from_object'
1472  && $usercancreate
1473  && $object->statut == Commande::STATUS_DRAFT
1474  ) {
1475  $fromElement = GETPOST('fromelement');
1476  $fromElementid = GETPOST('fromelementid');
1477  $importLines = GETPOST('line_checkbox');
1478 
1479  if (!empty($importLines) && is_array($importLines) && !empty($fromElement) && ctype_alpha($fromElement) && !empty($fromElementid)) {
1480  if ($fromElement == 'commande') {
1481  dol_include_once('/'.$fromElement.'/class/'.$fromElement.'.class.php');
1482  $lineClassName = 'OrderLine';
1483  } elseif ($fromElement == 'propal') {
1484  dol_include_once('/comm/'.$fromElement.'/class/'.$fromElement.'.class.php');
1485  $lineClassName = 'PropaleLigne';
1486  } elseif ($fromElement == 'facture') {
1487  dol_include_once('/compta/'.$fromElement.'/class/'.$fromElement.'.class.php');
1488  $lineClassName = 'FactureLigne';
1489  }
1490  $nextRang = count($object->lines) + 1;
1491  $importCount = 0;
1492  $error = 0;
1493  foreach ($importLines as $lineId) {
1494  $lineId = intval($lineId);
1495  $originLine = new $lineClassName($db);
1496  if (intval($fromElementid) > 0 && $originLine->fetch($lineId) > 0) {
1497  $originLine->fetch_optionals();
1498  $desc = $originLine->desc;
1499  $pu_ht = $originLine->subprice;
1500  $qty = $originLine->qty;
1501  $txtva = $originLine->tva_tx;
1502  $txlocaltax1 = $originLine->localtax1_tx;
1503  $txlocaltax2 = $originLine->localtax2_tx;
1504  $fk_product = $originLine->fk_product;
1505  $remise_percent = $originLine->remise_percent;
1506  $date_start = $originLine->date_start;
1507  $date_end = $originLine->date_end;
1508  $ventil = 0;
1509  $info_bits = $originLine->info_bits;
1510  $fk_remise_except = $originLine->fk_remise_except;
1511  $price_base_type = 'HT';
1512  $pu_ttc = 0;
1513  $type = $originLine->product_type;
1514  $rang = $nextRang++;
1515  $special_code = $originLine->special_code;
1516  $origin = $originLine->element;
1517  $origin_id = $originLine->id;
1518  $fk_parent_line = 0;
1519  $fk_fournprice = $originLine->fk_fournprice;
1520  $pa_ht = $originLine->pa_ht;
1521  $label = $originLine->label;
1522  $array_options = $originLine->array_options;
1523  $situation_percent = 100;
1524  $fk_prev_id = '';
1525  $fk_unit = $originLine->fk_unit;
1526  $pu_ht_devise = $originLine->multicurrency_subprice;
1527 
1528  $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);
1529 
1530  if ($res > 0) {
1531  $importCount++;
1532  } else {
1533  $error++;
1534  }
1535  } else {
1536  $error++;
1537  }
1538  }
1539 
1540  if ($error) {
1541  setEventMessages($langs->trans('ErrorsOnXLines', $error), null, 'errors');
1542  }
1543  }
1544  }
1545 
1546  // Actions when printing a doc from card
1547  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
1548 
1549  // Actions to build doc
1550  $upload_dir = !empty($conf->commande->multidir_output[$object->entity])?$conf->commande->multidir_output[$object->entity]:$conf->commande->dir_output;
1551  $permissiontoadd = $usercancreate;
1552  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
1553 
1554  // Actions to send emails
1555  $triggersendname = 'ORDER_SENTBYMAIL';
1556  $paramname = 'id';
1557  $autocopy = 'MAIN_MAIL_AUTOCOPY_ORDER_TO'; // used to know the automatic BCC to add
1558  $trackid = 'ord'.$object->id;
1559  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
1560 
1561 
1562  if (!$error && !empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $usercancreate) {
1563  if ($action == 'addcontact') {
1564  if ($object->id > 0) {
1565  $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
1566  $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
1567  $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
1568  }
1569 
1570  if ($result >= 0) {
1571  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1572  exit();
1573  } else {
1574  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1575  $langs->load("errors");
1576  setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
1577  } else {
1578  setEventMessages($object->error, $object->errors, 'errors');
1579  }
1580  }
1581  } elseif ($action == 'swapstatut') {
1582  // bascule du statut d'un contact
1583  if ($object->id > 0) {
1584  $result = $object->swapContactStatus(GETPOST('ligne', 'int'));
1585  } else {
1586  dol_print_error($db);
1587  }
1588  } elseif ($action == 'deletecontact') {
1589  // Efface un contact
1590  $result = $object->delete_contact($lineid);
1591 
1592  if ($result >= 0) {
1593  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
1594  exit();
1595  } else {
1596  dol_print_error($db);
1597  }
1598  }
1599  }
1600 }
1601 
1602 
1603 /*
1604  * View
1605  */
1606 
1607 $title = $object->ref." - ".$langs->trans('Card');
1608 if ($action == 'create') {
1609  $title = $langs->trans("NewOrder");
1610 }
1611 $help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge';
1612 
1613 llxHeader('', $title, $help_url);
1614 
1615 $form = new Form($db);
1616 $formfile = new FormFile($db);
1617 $formorder = new FormOrder($db);
1618 $formmargin = new FormMargin($db);
1619 if (isModEnabled('project')) {
1620  $formproject = new FormProjets($db);
1621 }
1622 
1623 // Mode creation
1624 if ($action == 'create' && $usercancreate) {
1625  print load_fiche_titre($langs->trans('CreateOrder'), '', 'order');
1626 
1627  $soc = new Societe($db);
1628  if ($socid > 0) {
1629  $res = $soc->fetch($socid);
1630  }
1631 
1632  $remise_absolue = 0;
1633 
1634  $currency_code = $conf->currency;
1635 
1636  $cond_reglement_id = GETPOST('cond_reglement_id', 'int');
1637  $deposit_percent = GETPOST('cond_reglement_id_deposit_percent', 'alpha');
1638  $mode_reglement_id = GETPOST('mode_reglement_id', 'int');
1639  $fk_account = GETPOST('fk_account', 'int');
1640 
1641  if (!empty($origin) && !empty($originid)) {
1642  // Parse element/subelement (ex: project_task)
1643  $element = $subelement = $origin;
1644  $regs = array();
1645  if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
1646  $element = $regs[1];
1647  $subelement = $regs[2];
1648  }
1649 
1650  if ($element == 'project') {
1651  $projectid = $originid;
1652 
1653  if (!$cond_reglement_id) {
1654  $cond_reglement_id = $soc->cond_reglement_id;
1655  }
1656  if (!$deposit_percent) {
1657  $deposit_percent = $soc->deposit_percent;
1658  }
1659  if (!$mode_reglement_id) {
1660  $mode_reglement_id = $soc->mode_reglement_id;
1661  }
1662  if (!$remise_percent) {
1663  $remise_percent = $soc->remise_percent;
1664  }
1665  /*if (!$dateorder) {
1666  // Do not set 0 here (0 for a date is 1970)
1667  $dateorder = (empty($dateinvoice) ? (empty($conf->global->MAIN_AUTOFILL_DATE_ORDER) ?-1 : '') : $dateorder);
1668  }*/
1669  } else {
1670  // For compatibility
1671  if ($element == 'order' || $element == 'commande') {
1672  $element = $subelement = 'commande';
1673  } elseif ($element == 'propal') {
1674  $element = 'comm/propal';
1675  $subelement = 'propal';
1676  } elseif ($element == 'contract') {
1677  $element = $subelement = 'contrat';
1678  }
1679 
1680  dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
1681 
1682  $classname = ucfirst($subelement);
1683  $objectsrc = new $classname($db);
1684  $objectsrc->fetch($originid);
1685  if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
1686  $objectsrc->fetch_lines();
1687  }
1688  $objectsrc->fetch_thirdparty();
1689 
1690  // Replicate extrafields
1691  $objectsrc->fetch_optionals();
1692  $object->array_options = $objectsrc->array_options;
1693 
1694  $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : '');
1695  $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
1696 
1697  $soc = $objectsrc->thirdparty;
1698  $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
1699  $deposit_percent = (!empty($objectsrc->deposit_percent) ? $objectsrc->deposit_percent : (!empty($soc->deposit_percent) ? $soc->deposit_percent : null));
1700  $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
1701  $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0));
1702  $availability_id = (!empty($objectsrc->availability_id) ? $objectsrc->availability_id : 0);
1703  $shipping_method_id = (!empty($objectsrc->shipping_method_id) ? $objectsrc->shipping_method_id : (!empty($soc->shipping_method_id) ? $soc->shipping_method_id : 0));
1704  $warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0));
1705  $demand_reason_id = (!empty($objectsrc->demand_reason_id) ? $objectsrc->demand_reason_id : (!empty($soc->demand_reason_id) ? $soc->demand_reason_id : 0));
1706  $remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_percent) ? $soc->remise_percent : 0));
1707  $remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0));
1708  $dateorder = empty($conf->global->MAIN_AUTOFILL_DATE_ORDER) ? -1 : '';
1709 
1710  $date_delivery = (!empty($objectsrc->delivery_date) ? $objectsrc->delivery_date : '');
1711  if (empty($date_delivery)) {
1712  $date_delivery = (!empty($objectsrc->date_livraison) ? $objectsrc->date_livraison : '');
1713  }
1714 
1715  if (isModEnabled("multicurrency")) {
1716  if (!empty($objectsrc->multicurrency_code)) {
1717  $currency_code = $objectsrc->multicurrency_code;
1718  }
1719  if (!empty($conf->global->MULTICURRENCY_USE_ORIGIN_TX) && !empty($objectsrc->multicurrency_tx)) {
1720  $currency_tx = $objectsrc->multicurrency_tx;
1721  }
1722  }
1723 
1724  $note_private = $object->getDefaultCreateValueFor('note_private', (!empty($objectsrc->note_private) ? $objectsrc->note_private : null));
1725  $note_public = $object->getDefaultCreateValueFor('note_public', (!empty($objectsrc->note_public) ? $objectsrc->note_public : null));
1726 
1727  // Object source contacts list
1728  $srccontactslist = $objectsrc->liste_contact(-1, 'external', 1);
1729  }
1730  } else {
1731  $cond_reglement_id = empty($soc->cond_reglement_id) ? $cond_reglement_id : $soc->cond_reglement_id;
1732  $deposit_percent = empty($soc->deposit_percent) ? $deposit_percent : $soc->deposit_percent;
1733  $mode_reglement_id = empty($soc->mode_reglement_id) ? $mode_reglement_id : $soc->mode_reglement_id;
1734  $fk_account = empty($soc->mode_reglement_id) ? $fk_account : $soc->fk_account;
1735  $availability_id = 0;
1736  $shipping_method_id = $soc->shipping_method_id;
1737  $warehouse_id = $soc->fk_warehouse;
1738  $demand_reason_id = $soc->demand_reason_id;
1739  $remise_percent = $soc->remise_percent;
1740  $remise_absolue = 0;
1741  $dateorder = empty($conf->global->MAIN_AUTOFILL_DATE_ORDER) ?-1 : '';
1742 
1743  if (isModEnabled("multicurrency") && !empty($soc->multicurrency_code)) {
1744  $currency_code = $soc->multicurrency_code;
1745  }
1746 
1747  $note_private = $object->getDefaultCreateValueFor('note_private');
1748  $note_public = $object->getDefaultCreateValueFor('note_public');
1749  }
1750 
1751  // If form was posted (but error returned), we must reuse the value posted in priority (standard Dolibarr behaviour)
1752  if (!GETPOST('changecompany')) {
1753  if (GETPOSTISSET('cond_reglement_id')) {
1754  $cond_reglement_id = GETPOST('cond_reglement_id', 'int');
1755  }
1756  if (GETPOSTISSET('deposit_percent')) {
1757  $deposit_percent = price2num(GETPOST('deposit_percent', 'alpha'));
1758  }
1759  if (GETPOSTISSET('mode_reglement_id')) {
1760  $mode_reglement_id = GETPOST('mode_reglement_id', 'int');
1761  }
1762  if (GETPOSTISSET('cond_reglement_id')) {
1763  $fk_account = GETPOST('fk_account', 'int');
1764  }
1765  }
1766 
1767  // Warehouse default if null
1768  if ($soc->fk_warehouse > 0) {
1769  $warehouse_id = $soc->fk_warehouse;
1770  }
1771  if (isModEnabled('stock') && empty($warehouse_id) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
1772  if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE)) {
1773  $warehouse_id = $conf->global->MAIN_DEFAULT_WAREHOUSE;
1774  }
1775  if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE_USER)) {
1776  $warehouse_id = $user->fk_warehouse;
1777  }
1778  }
1779 
1780  print '<form name="crea_commande" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1781  print '<input type="hidden" name="token" value="'.newToken().'">';
1782  print '<input type="hidden" name="action" value="add">';
1783  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
1784  print '<input type="hidden" name="remise_percent" value="'.$soc->remise_percent.'">';
1785  print '<input type="hidden" name="origin" value="'.$origin.'">';
1786  print '<input type="hidden" name="originid" value="'.$originid.'">';
1787  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1788  if (!empty($currency_tx)) {
1789  print '<input type="hidden" name="originmulticurrency_tx" value="'.$currency_tx.'">';
1790  }
1791 
1792  print dol_get_fiche_head('');
1793 
1794  print '<table class="border centpercent">';
1795 
1796  // Reference
1797  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Ref').'</td><td>'.$langs->trans("Draft").'</td></tr>';
1798 
1799  // Reference client
1800  print '<tr><td>'.$langs->trans('RefCustomer').'</td><td>';
1801  if (!empty($conf->global->MAIN_USE_PROPAL_REFCLIENT_FOR_ORDER) && !empty($origin) && !empty($originid)) {
1802  print '<input type="text" name="ref_client" value="'.$ref_client.'"></td>';
1803  } else {
1804  print '<input type="text" name="ref_client" value="'.GETPOST('ref_client').'"></td>';
1805  }
1806  print '</tr>';
1807 
1808  // Thirdparty
1809  print '<tr>';
1810  print '<td class="fieldrequired">'.$langs->trans('Customer').'</td>';
1811  if ($socid > 0) {
1812  print '<td>';
1813  print $soc->getNomUrl(1, 'customer');
1814  print '<input type="hidden" name="socid" value="'.$soc->id.'">';
1815  print '</td>';
1816  } else {
1817  print '<td class="valuefieldcreate">';
1818  $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))';
1819  print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
1820  // reload page to retrieve customer informations
1821  if (empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) {
1822  print '<script>
1823  $(document).ready(function() {
1824  $("#socid").change(function() {
1825  console.log("We have changed the company - Reload page");
1826  var socid = $(this).val();
1827  // reload page
1828  $("input[name=action]").val("create");
1829  $("input[name=changecompany]").val("1");
1830  $("form[name=crea_commande]").submit();
1831  });
1832  });
1833  </script>';
1834  }
1835  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>';
1836  print '</td>';
1837  }
1838  print '</tr>'."\n";
1839 
1840  // Contact of order
1841  if ($socid > 0) {
1842  // Contacts (ask contact only if thirdparty already defined).
1843  print "<tr><td>".$langs->trans("DefaultContact").'</td><td>';
1844  print img_picto('', 'contact', 'class="pictofixedwidth"');
1845  print $form->selectcontacts($soc->id, $contactid, 'contactid', 1, !empty($srccontactslist)?$srccontactslist:"", '', 1, 'maxwidth200 widthcentpercentminusx');
1846  print '</td></tr>';
1847 
1848  // Ligne info remises tiers
1849  print '<tr><td>'.$langs->trans('Discounts').'</td><td>';
1850 
1851  $absolute_discount = $soc->getAvailableDiscounts();
1852 
1853  $thirdparty = $soc;
1854  $discount_type = 0;
1855  $backtopage = urlencode($_SERVER["PHP_SELF"].'?socid='.$thirdparty->id.'&action='.$action.'&origin='.GETPOST('origin').'&originid='.GETPOST('originid'));
1856  include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
1857 
1858  print '</td></tr>';
1859  }
1860 
1861  // Date
1862  print '<tr><td class="fieldrequired">'.$langs->trans('Date').'</td><td>';
1863  print img_picto('', 'action', 'class="pictofixedwidth"');
1864  print $form->selectDate('', 're', '', '', '', "crea_commande", 1, 1); // Always autofill date with current date
1865  print '</td></tr>';
1866 
1867  // Date delivery planned
1868  print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
1869  print '<td colspan="3">';
1870  $date_delivery = ($date_delivery ? $date_delivery : $object->delivery_date);
1871  print img_picto('', 'action', 'class="pictofixedwidth"');
1872  print $form->selectDate($date_delivery ? $date_delivery : -1, 'liv_', 1, 1, 1);
1873  print "</td>\n";
1874  print '</tr>';
1875 
1876  // Delivery delay
1877  print '<tr class="fielddeliverydelay"><td>'.$langs->trans('AvailabilityPeriod').'</td><td>';
1878  print img_picto('', 'clock', 'class="pictofixedwidth"');
1879  $form->selectAvailabilityDelay((GETPOSTISSET('availability_id') ? GETPOST('availability_id') : $availability_id), 'availability_id', '', 1, 'maxwidth200 widthcentpercentminusx');
1880  print '</td></tr>';
1881 
1882  // Terms of payment
1883  print '<tr><td class="nowrap">'.$langs->trans('PaymentConditionsShort').'</td><td>';
1884  print img_picto('', 'payment', 'class="pictofixedwidth"');
1885  print $form->getSelectConditionsPaiements($cond_reglement_id, 'cond_reglement_id', 1, 1, 0, 'maxwidth200 widthcentpercentminusx', $deposit_percent);
1886  print '</td></tr>';
1887 
1888  // Payment mode
1889  print '<tr><td>'.$langs->trans('PaymentMode').'</td><td>';
1890  print img_picto('', 'bank', 'class="pictofixedwidth"');
1891  print $form->select_types_paiements($mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1);
1892  print '</td></tr>';
1893 
1894  // Bank Account
1895  if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && isModEnabled("banque")) {
1896  print '<tr><td>'.$langs->trans('BankAccount').'</td><td>';
1897  print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes($fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1);
1898  print '</td></tr>';
1899  }
1900 
1901  // Shipping Method
1902  if (isModEnabled('expedition')) {
1903  print '<tr><td>'.$langs->trans('SendingMethod').'</td><td>';
1904  print img_picto('', 'object_dolly', 'class="pictofixedwidth"');
1905  $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');
1906  print '</td></tr>';
1907  }
1908 
1909  // Warehouse
1910  if (isModEnabled('stock') && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
1911  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
1912  $formproduct = new FormProduct($db);
1913  print '<tr><td>'.$langs->trans('Warehouse').'</td><td>';
1914  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');
1915  print '</td></tr>';
1916  }
1917 
1918  // Source / Channel - What trigger creation
1919  print '<tr><td>'.$langs->trans('Channel').'</td><td>';
1920  print img_picto('', 'question', 'class="pictofixedwidth"');
1921  $form->selectInputReason((GETPOSTISSET('demand_reason_id')?GETPOST('demand_reason_id'):$demand_reason_id), 'demand_reason_id', '', 1, 'maxwidth200 widthcentpercentminusx');
1922  print '</td></tr>';
1923 
1924  // TODO How record was recorded OrderMode (llx_c_input_method)
1925 
1926  // Project
1927  if (isModEnabled('project')) {
1928  $langs->load("projects");
1929  print '<tr>';
1930  print '<td>'.$langs->trans("Project").'</td><td>';
1931  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');
1932  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>';
1933  print '</td>';
1934  print '</tr>';
1935  }
1936 
1937  // Incoterms
1938  if (isModEnabled('incoterm')) {
1939  print '<tr>';
1940  print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), !empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms, 1).'</label></td>';
1941  print '<td class="maxwidthonsmartphone">';
1942  $incoterm_id = GETPOST('incoterm_id');
1943  $incoterm_location = GETPOST('location_incoterms');
1944  if (empty($incoterm_id)) {
1945  $incoterm_id = (!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms);
1946  $incoterm_location = (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : $soc->location_incoterms);
1947  }
1948  print img_picto('', 'incoterm', 'class="pictofixedwidth"');
1949  print $form->select_incoterms($incoterm_id, $incoterm_location);
1950  print '</td></tr>';
1951  }
1952 
1953  // Other attributes
1954  $parameters = array();
1955  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
1956  $parameters['objectsrc'] = $objectsrc;
1957  }
1958  $parameters['socid'] = $socid;
1959 
1960  // Note that $action and $object may be modified by hook
1961  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
1962  print $hookmanager->resPrint;
1963  if (empty($reshook)) {
1964  if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER) && !empty($soc->id)) {
1965  // copy from thirdparty
1966  $tpExtrafields = new ExtraFields($db);
1967  $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element);
1968  if ($soc->fetch_optionals() > 0) {
1969  $object->array_options = array_merge($object->array_options, $soc->array_options);
1970  }
1971  }
1972 
1973  print $object->showOptionals($extrafields, 'create', $parameters);
1974  }
1975 
1976  // Template to use by default
1977  print '<tr><td>'.$langs->trans('DefaultModel').'</td>';
1978  print '<td>';
1979  include_once DOL_DOCUMENT_ROOT.'/core/modules/commande/modules_commande.php';
1980  $liste = ModelePDFCommandes::liste_modeles($db);
1981  $preselected = $conf->global->COMMANDE_ADDON_PDF;
1982  print img_picto('', 'pdf', 'class="pictofixedwidth"');
1983  print $form->selectarray('model', $liste, $preselected, 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
1984  print "</td></tr>";
1985 
1986  // Multicurrency
1987  if (isModEnabled("multicurrency")) {
1988  print '<tr>';
1989  print '<td>'.$form->editfieldkey("Currency", 'multicurrency_code', '', $object, 0).'</td>';
1990  print '<td class="maxwidthonsmartphone">';
1991  print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency((GETPOSTISSET('multicurrency_code')?GETPOST('multicurrency_code'):$currency_code), 'multicurrency_code', 0, '', false, 'maxwidth200 widthcentpercentminusx');
1992  print '</td></tr>';
1993  }
1994 
1995  // Note public
1996  print '<tr>';
1997  print '<td class="tdtop">'.$langs->trans('NotePublic').'</td>';
1998  print '<td>';
1999 
2000  $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%');
2001  print $doleditor->Create(1);
2002  // print '<textarea name="note_public" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_public.'</textarea>';
2003  print '</td></tr>';
2004 
2005  // Note private
2006  if (empty($user->socid)) {
2007  print '<tr>';
2008  print '<td class="tdtop">'.$langs->trans('NotePrivate').'</td>';
2009  print '<td>';
2010 
2011  $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%');
2012  print $doleditor->Create(1);
2013  // print '<textarea name="note" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'</textarea>';
2014  print '</td></tr>';
2015  }
2016 
2017  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2018  // TODO for compatibility
2019  if ($origin == 'contrat') {
2020  // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
2021  $objectsrc->remise_absolue = $remise_absolue;
2022  $objectsrc->remise_percent = $remise_percent;
2023  $objectsrc->update_price(1);
2024  }
2025 
2026  print "\n<!-- ".$classname." info -->";
2027  print "\n";
2028  print '<input type="hidden" name="amount" value="'.$objectsrc->total_ht.'">'."\n";
2029  print '<input type="hidden" name="total" value="'.$objectsrc->total_ttc.'">'."\n";
2030  print '<input type="hidden" name="tva" value="'.$objectsrc->total_tva.'">'."\n";
2031  print '<input type="hidden" name="origin" value="'.$objectsrc->element.'">';
2032  print '<input type="hidden" name="originid" value="'.$objectsrc->id.'">';
2033 
2034  switch ($classname) {
2035  case 'Propal':
2036  $newclassname = 'CommercialProposal';
2037  break;
2038  case 'Commande':
2039  $newclassname = 'Order';
2040  break;
2041  case 'Expedition':
2042  $newclassname = 'Sending';
2043  break;
2044  case 'Contrat':
2045  $newclassname = 'Contract';
2046  break;
2047  default:
2048  $newclassname = $classname;
2049  }
2050 
2051  print '<tr><td>'.$langs->trans($newclassname).'</td><td>'.$objectsrc->getNomUrl(1).'</td></tr>';
2052 
2053  // Amount
2054  print '<tr><td>'.$langs->trans('AmountHT').'</td><td>'.price($objectsrc->total_ht).'</td></tr>';
2055  print '<tr><td>'.$langs->trans('AmountVAT').'</td><td>'.price($objectsrc->total_tva)."</td></tr>";
2056  if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) { // Localtax1 RE
2057  print '<tr><td>'.$langs->transcountry("AmountLT1", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax1)."</td></tr>";
2058  }
2059 
2060  if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) { // Localtax2 IRPF
2061  print '<tr><td>'.$langs->transcountry("AmountLT2", $mysoc->country_code).'</td><td>'.price($objectsrc->total_localtax2)."</td></tr>";
2062  }
2063 
2064  print '<tr><td>'.$langs->trans('AmountTTC').'</td><td>'.price($objectsrc->total_ttc)."</td></tr>";
2065 
2066  if (isModEnabled("multicurrency")) {
2067  print '<tr><td>'.$langs->trans('MulticurrencyAmountHT').'</td><td>'.price($objectsrc->multicurrency_total_ht).'</td></tr>';
2068  print '<tr><td>'.$langs->trans('MulticurrencyAmountVAT').'</td><td>'.price($objectsrc->multicurrency_total_tva)."</td></tr>";
2069  print '<tr><td>'.$langs->trans('MulticurrencyAmountTTC').'</td><td>'.price($objectsrc->multicurrency_total_ttc)."</td></tr>";
2070  }
2071  }
2072 
2073  print "\n";
2074 
2075  print '</table>';
2076 
2077  print dol_get_fiche_end();
2078 
2079  print $form->buttonsSaveCancel("CreateDraft");
2080 
2081  // Show origin lines
2082  if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
2083  $title = $langs->trans('ProductsAndServices');
2084  print load_fiche_titre($title);
2085 
2086  print '<div class="div-table-responsive-no-min">';
2087  print '<table class="noborder centpercent">';
2088 
2089  $objectsrc->printOriginLinesList('', $selectedLines);
2090 
2091  print '</table>';
2092  print '</div>';
2093  }
2094 
2095  print '</form>';
2096 } else {
2097  // Mode view
2098  $now = dol_now();
2099 
2100  if ($object->id > 0) {
2101  $product_static = new Product($db);
2102 
2103  $soc = new Societe($db);
2104  $soc->fetch($object->socid);
2105 
2106  $author = new User($db);
2107  $author->fetch($object->user_author_id);
2108 
2109  $object->fetch_thirdparty();
2110  $res = $object->fetch_optionals();
2111 
2112  $head = commande_prepare_head($object);
2113  print dol_get_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, 'order');
2114 
2115  $formconfirm = '';
2116 
2117  // Confirmation to delete
2118  if ($action == 'delete') {
2119  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1);
2120  }
2121 
2122  // Confirmation of validation
2123  if ($action == 'validate') {
2124  // We check that object has a temporary ref
2125  $ref = substr($object->ref, 1, 4);
2126  if ($ref == 'PROV' || $ref == '') {
2127  $numref = $object->getNextNumRef($soc);
2128  if (empty($numref)) {
2129  $error++;
2130  setEventMessages($object->error, $object->errors, 'errors');
2131  }
2132  } else {
2133  $numref = $object->ref;
2134  }
2135 
2136  $text = $langs->trans('ConfirmValidateOrder', $numref);
2137  if (isModEnabled('notification')) {
2138  require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2139  $notify = new Notify($db);
2140  $text .= '<br>';
2141  $text .= $notify->confirmMessage('ORDER_VALIDATE', $object->socid, $object);
2142  }
2143 
2144  $qualified_for_stock_change = 0;
2145  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
2146  $qualified_for_stock_change = $object->hasProductsOrServices(2);
2147  } else {
2148  $qualified_for_stock_change = $object->hasProductsOrServices(1);
2149  }
2150 
2151  $formquestion = array();
2152  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
2153  $langs->load("stocks");
2154  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2155  $formproduct = new FormProduct($db);
2156  $forcecombo = 0;
2157  if ($conf->browser->name == 'ie') {
2158  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2159  }
2160  $formquestion = array(
2161  // 'text' => $langs->trans("ConfirmClone"),
2162  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2163  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2164  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))
2165  );
2166  }
2167 
2168  // mandatoryPeriod
2169  $nbMandated = 0;
2170  foreach ($object->lines as $line) {
2171  $res = $line->fetch_product();
2172  if ($res > 0 ) {
2173  if ($line->product->isService() && $line->product->isMandatoryPeriod() && (empty($line->date_start) || empty($line->date_end) )) {
2174  $nbMandated++;
2175  break;
2176  }
2177  }
2178  }
2179  if ($nbMandated > 0 ) $text .= '<div><span class="clearboth nowraponall warning">'.$langs->trans("mandatoryPeriodNeedTobeSetMsgValidate").'</span></div>';
2180 
2181  if (getDolGlobalInt('SALE_ORDER_SUGGEST_DOWN_PAYMENT_INVOICE_CREATION')) {
2182  // This is a hidden option:
2183  // Suggestion to create invoice during order validation is not enabled by default.
2184  // Such choice should be managed by the workflow module and trigger. This option generates conflicts with some setup.
2185  // It may also break step of creating an order when invoicing must be done from proposals and not from orders
2186  $deposit_percent_from_payment_terms = getDictionaryValue('c_payment_term', 'deposit_percent', $object->cond_reglement_id);
2187 
2188  if (!empty($deposit_percent_from_payment_terms) && isModEnabled('facture') && !empty($user->rights->facture->creer)) {
2189  require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
2190 
2191  $object->fetchObjectLinked();
2192 
2193  $eligibleForDepositGeneration = true;
2194 
2195  if (array_key_exists('facture', $object->linkedObjects)) {
2196  foreach ($object->linkedObjects['facture'] as $invoice) {
2197  if ($invoice->type == Facture::TYPE_DEPOSIT) {
2198  $eligibleForDepositGeneration = false;
2199  break;
2200  }
2201  }
2202  }
2203 
2204  if ($eligibleForDepositGeneration && array_key_exists('propal', $object->linkedObjects)) {
2205  foreach ($object->linkedObjects['propal'] as $proposal) {
2206  $proposal->fetchObjectLinked();
2207 
2208  if (array_key_exists('facture', $proposal->linkedObjects)) {
2209  foreach ($proposal->linkedObjects['facture'] as $invoice) {
2210  if ($invoice->type == Facture::TYPE_DEPOSIT) {
2211  $eligibleForDepositGeneration = false;
2212  break 2;
2213  }
2214  }
2215  }
2216  }
2217  }
2218 
2219  if ($eligibleForDepositGeneration) {
2220  $formquestion[] = array(
2221  'type' => 'checkbox',
2222  'tdclass' => '',
2223  'name' => 'generate_deposit',
2224  'label' => $form->textwithpicto($langs->trans('GenerateDeposit', $object->deposit_percent), $langs->trans('DepositGenerationPermittedByThePaymentTermsSelected'))
2225  );
2226 
2227  $formquestion[] = array(
2228  'type' => 'date',
2229  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2230  'name' => 'datef',
2231  'label' => $langs->trans('DateInvoice'),
2232  'value' => dol_now(),
2233  'datenow' => true
2234  );
2235 
2236  if (!empty($conf->global->INVOICE_POINTOFTAX_DATE)) {
2237  $formquestion[] = array(
2238  'type' => 'date',
2239  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2240  'name' => 'date_pointoftax',
2241  'label' => $langs->trans('DatePointOfTax'),
2242  'value' => dol_now(),
2243  'datenow' => true
2244  );
2245  }
2246 
2247 
2248  $paymentTermsSelect = $form->getSelectConditionsPaiements(0, 'cond_reglement_id', -1, 0, 0, 'minwidth200');
2249 
2250  $formquestion[] = array(
2251  'type' => 'other',
2252  'tdclass' => 'fieldrequired showonlyifgeneratedeposit',
2253  'name' => 'cond_reglement_id',
2254  'label' => $langs->trans('PaymentTerm'),
2255  'value' => $paymentTermsSelect
2256  );
2257 
2258  $formquestion[] = array(
2259  'type' => 'checkbox',
2260  'tdclass' => 'showonlyifgeneratedeposit',
2261  'name' => 'validate_generated_deposit',
2262  'label' => $langs->trans('ValidateGeneratedDeposit')
2263  );
2264 
2265  $formquestion[] = array(
2266  'type' => 'onecolumn',
2267  'value' => '
2268  <script>
2269  $(document).ready(function() {
2270  $("[name=generate_deposit]").change(function () {
2271  let $self = $(this);
2272  let $target = $(".showonlyifgeneratedeposit").parent(".tagtr");
2273 
2274  if (! $self.parents(".tagtr").is(":hidden") && $self.is(":checked")) {
2275  $target.show();
2276  } else {
2277  $target.hide();
2278  }
2279 
2280  return true;
2281  });
2282  });
2283  </script>
2284  '
2285  );
2286  }
2287  }
2288  }
2289 
2290  if (!$error) {
2291  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_validate', $formquestion, 0, 1, 220);
2292  }
2293  }
2294 
2295  // Confirm back to draft status
2296  if ($action == 'modif') {
2297  $qualified_for_stock_change = 0;
2298  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
2299  $qualified_for_stock_change = $object->hasProductsOrServices(2);
2300  } else {
2301  $qualified_for_stock_change = $object->hasProductsOrServices(1);
2302  }
2303 
2304  $text = $langs->trans('ConfirmUnvalidateOrder', $object->ref);
2305  $formquestion = array();
2306  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
2307  $langs->load("stocks");
2308  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2309  $formproduct = new FormProduct($db);
2310  $forcecombo = 0;
2311  if ($conf->browser->name == 'ie') {
2312  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2313  }
2314  $formquestion = array(
2315  // 'text' => $langs->trans("ConfirmClone"),
2316  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2317  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2318  array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ?GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2319  );
2320  }
2321 
2322  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('UnvalidateOrder'), $text, 'confirm_modif', $formquestion, "yes", 1, 220);
2323  }
2324 
2325  /*
2326  * Confirmation de la cloture
2327  */
2328  if ($action == 'shipped') {
2329  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('CloseOrder'), $langs->trans('ConfirmCloseOrder'), 'confirm_shipped', '', 0, 1);
2330  }
2331 
2332  /*
2333  * Confirmation de l'annulation
2334  */
2335  if ($action == 'cancel') {
2336  $qualified_for_stock_change = 0;
2337  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
2338  $qualified_for_stock_change = $object->hasProductsOrServices(2);
2339  } else {
2340  $qualified_for_stock_change = $object->hasProductsOrServices(1);
2341  }
2342 
2343  $text = $langs->trans('ConfirmCancelOrder', $object->ref);
2344  $formquestion = array();
2345  if (isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) && $qualified_for_stock_change) {
2346  $langs->load("stocks");
2347  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2348  $formproduct = new FormProduct($db);
2349  $forcecombo = 0;
2350  if ($conf->browser->name == 'ie') {
2351  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
2352  }
2353  $formquestion = array(
2354  // 'text' => $langs->trans("ConfirmClone"),
2355  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
2356  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
2357  array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockIncrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse') ?GETPOST('idwarehouse') : 'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
2358  );
2359  }
2360 
2361  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans("Cancel"), $text, 'confirm_cancel', $formquestion, 0, 1);
2362  }
2363 
2364  // Confirmation to delete line
2365  if ($action == 'ask_deleteline') {
2366  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
2367  }
2368 
2369  // Clone confirmation
2370  if ($action == 'clone') {
2371  $filter = '(s.client:IN:1,2,3)';
2372  // Create an array for form
2373  $formquestion = array(
2374  array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300'))
2375  );
2376  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
2377  }
2378 
2379  // Call Hook formConfirm
2380  $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
2381  // Note that $action and $object may be modified by hook
2382  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
2383  if (empty($reshook)) {
2384  $formconfirm .= $hookmanager->resPrint;
2385  } elseif ($reshook > 0) {
2386  $formconfirm = $hookmanager->resPrint;
2387  }
2388 
2389  // Print form confirm
2390  print $formconfirm;
2391 
2392 
2393  // Order card
2394 
2395  $linkback = '<a href="'.DOL_URL_ROOT.'/commande/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
2396 
2397  $morehtmlref = '<div class="refidno">';
2398  // Ref customer
2399  $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string', '', 0, 1);
2400  $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);
2401  // Thirdparty
2402  $morehtmlref .= '<br>'.$soc->getNomUrl(1, 'customer');
2403  if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) {
2404  $morehtmlref .= ' (<a href="'.DOL_URL_ROOT.'/commande/list.php?socid='.$object->thirdparty->id.'&search_societe='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherOrders").'</a>)';
2405  }
2406  // Project
2407  if (isModEnabled('project')) {
2408  $langs->load("projects");
2409  $morehtmlref .= '<br>';
2410  if ($usercancreate) {
2411  $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2412  if ($action != 'classify') {
2413  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
2414  }
2415  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
2416  } else {
2417  if (!empty($object->fk_project)) {
2418  $proj = new Project($db);
2419  $proj->fetch($object->fk_project);
2420  $morehtmlref .= $proj->getNomUrl(1);
2421  if ($proj->title) {
2422  $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
2423  }
2424  }
2425  }
2426  }
2427  $morehtmlref .= '</div>';
2428 
2429 
2430  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2431 
2432 
2433  print '<div class="fichecenter">';
2434  print '<div class="fichehalfleft">';
2435  print '<div class="underbanner clearboth"></div>';
2436 
2437  print '<table class="border tableforfield centpercent">';
2438 
2439  if ($soc->outstanding_limit) {
2440  // Outstanding Bill
2441  print '<tr><td class="titlefield">';
2442  print $langs->trans('OutstandingBill');
2443  print '</td><td class="valuefield">';
2444  $arrayoutstandingbills = $soc->getOutstandingBills();
2445  print price($arrayoutstandingbills['opened']).' / ';
2446  print price($soc->outstanding_limit, 0, '', 1, - 1, - 1, $conf->currency);
2447  print '</td>';
2448  print '</tr>';
2449  }
2450 
2451  // Relative and absolute discounts
2452  if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
2453  $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2454  $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2455  } else {
2456  $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
2457  $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
2458  }
2459 
2460  $addrelativediscount = '<a href="'.DOL_URL_ROOT.'/comm/remise.php?id='.$soc->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"]).'?facid='.$object->id.'">'.$langs->trans("EditRelativeDiscounts").'</a>';
2461  $addabsolutediscount = '<a href="'.DOL_URL_ROOT.'/comm/remx.php?id='.$soc->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"]).'?facid='.$object->id.'">'.$langs->trans("EditGlobalDiscounts").'</a>';
2462  $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>';
2463 
2464  print '<tr><td class="titlefield">'.$langs->trans('Discounts').'</td><td class="valuefield">';
2465 
2466  $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount);
2467  $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote);
2468  $absolute_discount = price2num($absolute_discount, 'MT');
2469  $absolute_creditnote = price2num($absolute_creditnote, 'MT');
2470 
2471  $thirdparty = $soc;
2472  $discount_type = 0;
2473  $backtopage = urlencode($_SERVER["PHP_SELF"].'?id='.$object->id);
2474  include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
2475 
2476  print '</td></tr>';
2477 
2478  // Date
2479  print '<tr><td>';
2480  $editenable = $usercancreate && $object->statut == Commande::STATUS_DRAFT;
2481  print $form->editfieldkey("Date", 'date', '', $object, $editenable);
2482  print '</td><td class="valuefield">';
2483  if ($action == 'editdate') {
2484  print '<form name="setdate" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2485  print '<input type="hidden" name="token" value="'.newToken().'">';
2486  print '<input type="hidden" name="action" value="setdate">';
2487  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2488  print $form->selectDate($object->date, 'order_', '', '', '', "setdate");
2489  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2490  print '</form>';
2491  } else {
2492  print $object->date ? dol_print_date($object->date, 'day') : '&nbsp;';
2493  if ($object->hasDelay() && empty($object->delivery_date)) { // If there is a delivery date planned, warning should be on this date
2494  print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2495  }
2496  }
2497  print '</td>';
2498  print '</tr>';
2499 
2500  // Delivery date planed
2501  print '<tr><td>';
2502  $editenable = $usercancreate;
2503  print $form->editfieldkey("DateDeliveryPlanned", 'date_livraison', '', $object, $editenable);
2504  print '</td><td class="valuefield">';
2505  if ($action == 'editdate_livraison') {
2506  print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2507  print '<input type="hidden" name="token" value="'.newToken().'">';
2508  print '<input type="hidden" name="action" value="setdate_livraison">';
2509  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
2510  print $form->selectDate($object->delivery_date ? $object->delivery_date : -1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0);
2511  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2512  print '</form>';
2513  } else {
2514  print $object->delivery_date ? dol_print_date($object->delivery_date, 'dayhour') : '&nbsp;';
2515  if ($object->hasDelay() && !empty($object->delivery_date)) {
2516  print ' '.img_picto($langs->trans("Late").' : '.$object->showDelay(), "warning");
2517  }
2518  }
2519  print '</td>';
2520  print '</tr>';
2521 
2522  // Delivery delay
2523  print '<tr class="fielddeliverydelay"><td>';
2524  $editenable = $usercancreate;
2525  print $form->editfieldkey("AvailabilityPeriod", 'availability', '', $object, $editenable);
2526  print '</td><td class="valuefield">';
2527  if ($action == 'editavailability') {
2528  $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'availability_id', 1);
2529  } else {
2530  $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'none', 1);
2531  }
2532  print '</td></tr>';
2533 
2534  // Shipping Method
2535  if (isModEnabled('expedition')) {
2536  print '<tr><td>';
2537  $editenable = $usercancreate;
2538  print $form->editfieldkey("SendingMethod", 'shippingmethod', '', $object, $editenable);
2539  print '</td><td class="valuefield">';
2540  if ($action == 'editshippingmethod') {
2541  $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
2542  } else {
2543  $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'none');
2544  }
2545  print '</td>';
2546  print '</tr>';
2547  }
2548 
2549  // Warehouse
2550  if (isModEnabled('stock') && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) {
2551  $langs->load('stocks');
2552  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
2553  $formproduct = new FormProduct($db);
2554  print '<tr><td>';
2555  $editenable = $usercancreate;
2556  print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $editenable);
2557  print '</td><td class="valuefield">';
2558  if ($action == 'editwarehouse') {
2559  $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1);
2560  } else {
2561  $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'none');
2562  }
2563  print '</td>';
2564  print '</tr>';
2565  }
2566 
2567  // Source reason (why we have an order)
2568  print '<tr><td>';
2569  $editenable = $usercancreate;
2570  print $form->editfieldkey("Source", 'demandreason', '', $object, $editenable);
2571  print '</td><td class="valuefield">';
2572  if ($action == 'editdemandreason') {
2573  $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'demand_reason_id', 1);
2574  } else {
2575  $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'none');
2576  }
2577  print '</td></tr>';
2578 
2579  // Terms of payment
2580  print '<tr><td>';
2581  $editenable = $usercancreate;
2582  print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, $editenable);
2583  print '</td><td class="valuefield">';
2584  if ($action == 'editconditions') {
2585  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
2586  } else {
2587  $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent);
2588  }
2589  print '</td>';
2590 
2591  print '</tr>';
2592 
2593  // Mode of payment
2594  print '<tr><td>';
2595  $editenable = $usercancreate;
2596  print $form->editfieldkey("PaymentMode", 'mode', '', $object, $editenable);
2597  print '</td><td class="valuefield">';
2598  if ($action == 'editmode') {
2599  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
2600  } else {
2601  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'none');
2602  }
2603  print '</td></tr>';
2604 
2605  // Multicurrency
2606  if (isModEnabled("multicurrency")) {
2607  // Multicurrency code
2608  print '<tr>';
2609  print '<td>';
2610  $editenable = $usercancreate && $object->statut == Commande::STATUS_DRAFT;
2611  print $form->editfieldkey("Currency", 'multicurrencycode', '', $object, $editenable);
2612  print '</td><td class="valuefield">';
2613  if ($action == 'editmulticurrencycode') {
2614  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'multicurrency_code');
2615  } else {
2616  $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, 'none');
2617  }
2618  print '</td></tr>';
2619 
2620  // Multicurrency rate
2621  if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
2622  print '<tr>';
2623  print '<td>';
2624  $editenable = $usercancreate && $object->multicurrency_code && $object->multicurrency_code != $conf->currency && $object->statut == $object::STATUS_DRAFT;
2625  print $form->editfieldkey("CurrencyRate", 'multicurrencyrate', '', $object, $editenable);
2626  print '</td><td class="valuefield">';
2627  if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
2628  if ($action == 'actualizemulticurrencyrate') {
2629  list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
2630  }
2631  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
2632  } else {
2633  $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
2634  if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
2635  print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
2636  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
2637  print '</div>';
2638  }
2639  }
2640  print '</td></tr>';
2641  }
2642  }
2643 
2644  // TODO Order mode (how we receive order). Not yet implemented
2645  /*
2646  print '<tr><td>';
2647  $editenable = $usercancreate;
2648  print $form->editfieldkey("SourceMode", 'inputmode', '', $object, $editenable);
2649  print '</td><td>';
2650  if ($action == 'editinputmode') {
2651  $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'input_mode_id', 1);
2652  } else {
2653  $form->formInputMode($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->source, 'none');
2654  }
2655  print '</td></tr>';
2656  */
2657 
2658  $tmparray = $object->getTotalWeightVolume();
2659  $totalWeight = $tmparray['weight'];
2660  $totalVolume = $tmparray['volume'];
2661  if ($totalWeight) {
2662  print '<tr><td>'.$langs->trans("CalculatedWeight").'</td>';
2663  print '<td class="valuefield">';
2664  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');
2665  print '</td></tr>';
2666  }
2667  if ($totalVolume) {
2668  print '<tr><td>'.$langs->trans("CalculatedVolume").'</td>';
2669  print '<td class="valuefield">';
2670  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');
2671  print '</td></tr>';
2672  }
2673 
2674  // TODO How record was recorded OrderMode (llx_c_input_method)
2675 
2676  // Incoterms
2677  if (isModEnabled('incoterm')) {
2678  print '<tr><td>';
2679  $editenable = $usercancreate;
2680  print $form->editfieldkey("IncotermLabel", 'incoterm', '', $object, $editenable);
2681  print '</td>';
2682  print '<td class="valuefield">';
2683  if ($action != 'editincoterm') {
2684  print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
2685  } else {
2686  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2687  }
2688  print '</td></tr>';
2689  }
2690 
2691  // Bank Account
2692  if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && isModEnabled("banque")) {
2693  print '<tr><td>';
2694  $editenable = $usercancreate;
2695  print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, $editenable);
2696  print '</td><td class="valuefield">';
2697  if ($action == 'editbankaccount') {
2698  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
2699  } else {
2700  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
2701  }
2702  print '</td>';
2703  print '</tr>';
2704  }
2705 
2706  // Other attributes
2707  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2708 
2709  print '</table>';
2710 
2711  print '</div>';
2712  print '<div class="fichehalfright">';
2713  print '<div class="underbanner clearboth"></div>';
2714 
2715  print '<table class="border tableforfield centpercent">';
2716 
2717  $alert = '';
2718  if (!empty($conf->global->ORDER_MANAGE_MIN_AMOUNT) && $object->total_ht < $object->thirdparty->order_min_amount) {
2719  $alert = ' ' . img_warning($langs->trans('OrderMinAmount') . ': ' . price($object->thirdparty->order_min_amount));
2720  }
2721 
2722  print '<tr>';
2723  print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
2724  print '<td class="nowrap amountcard right">' . price($object->total_ht, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2725  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2726  // Multicurrency Amount HT
2727  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_ht, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2728  }
2729  print '</tr>';
2730 
2731  print '<tr>';
2732  print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
2733  print '<td class="nowrap amountcard right">' . price($object->total_tva, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2734  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2735  // Multicurrency Amount VAT
2736  print '<td class="nowrap amountcard right">' . price($object->multicurrency_total_tva, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2737  }
2738  print '</tr>';
2739 
2740  // Amount Local Taxes
2741  if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
2742  print '<tr>';
2743  print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
2744  print '<td class="nowrap amountcard right">' . price($object->total_localtax1, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2745  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2746  print '<td class="nowrap amountcard right">' . price($object->total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2747  }
2748  print '</tr>';
2749 
2750  print '<tr>';
2751  // Amount Local Taxes
2752  if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
2753  print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
2754  print '<td class="nowrap amountcard right">' . price($object->total_localtax2, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
2755  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2756  print '<td class="nowrap amountcard right">' . price($object->total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
2757  }
2758  print '</tr>';
2759  }
2760  }
2761 
2762  print '<tr>';
2763  print '<td>' . $langs->trans('AmountTTC') . '</td>';
2764  print '<td class="valuefield nowrap right amountcard">' . price($object->total_ttc, 1, '', 1, -1, -1, $conf->currency) . '</td>';
2765  if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
2766  // Multicurrency Amount TTC
2767  print '<td class="valuefield nowrap right amountcard">' . price($object->multicurrency_total_ttc, 1, '', 1, -1, -1, $object->multicurrency_code) . '</td>';
2768  }
2769  print '</tr>'."\n";
2770 
2771  print '</table>';
2772 
2773  // Statut
2774  //print '<tr><td>' . $langs->trans('Status') . '</td><td>' . $object->getLibStatut(4) . '</td></tr>';
2775 
2776  // Margin Infos
2777  if (isModEnabled('margin')) {
2778  $formmargin->displayMarginInfos($object);
2779  }
2780 
2781 
2782  print '</div>';
2783  print '</div>'; // Close fichecenter
2784 
2785  print '<div class="clearboth"></div><br>';
2786 
2787  if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
2788  $blocname = 'contacts';
2789  $title = $langs->trans('ContactsAddresses');
2790  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2791  }
2792 
2793  if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
2794  $blocname = 'notes';
2795  $title = $langs->trans('Notes');
2796  include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
2797  }
2798 
2799  /*
2800  * Lines
2801  */
2802 
2803  // Get object lines
2804  $result = $object->getLinesArray();
2805 
2806  // Add products/services form
2807  //$forceall = 1;
2808  global $inputalsopricewithtax;
2809  $inputalsopricewithtax = 1;
2810 
2811  print '<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">
2812  <input type="hidden" name="token" value="' . newToken().'">
2813  <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
2814  <input type="hidden" name="mode" value="">
2815  <input type="hidden" name="page_y" value="">
2816  <input type="hidden" name="id" value="' . $object->id.'">
2817  <input type="hidden" name="backtopage" value="'.$backtopage.'">
2818  ';
2819 
2820  if (!empty($conf->use_javascript_ajax) && $object->statut == Commande::STATUS_DRAFT) {
2821  include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
2822  }
2823 
2824  print '<div class="div-table-responsive-no-min">';
2825  print '<table id="tablelines" class="noborder noshadow" width="100%">';
2826 
2827  // Show object lines
2828  if (!empty($object->lines)) {
2829  $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
2830  }
2831 
2832  $numlines = count($object->lines);
2833 
2834  /*
2835  * Form to add new line
2836  */
2837  if ($object->statut == Commande::STATUS_DRAFT && $usercancreate && $action != 'selectlines') {
2838  if ($action != 'editline') {
2839  // Add free products/services
2840 
2841  $parameters = array();
2842  // Note that $action and $object may be modified by hook
2843  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action);
2844  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2845  if (empty($reshook))
2846  $object->formAddObjectLine(1, $mysoc, $soc);
2847  }
2848  }
2849  print '</table>';
2850  print '</div>';
2851 
2852  print "</form>\n";
2853 
2854  print dol_get_fiche_end();
2855 
2856  /*
2857  * Buttons for actions
2858  */
2859  if ($action != 'presend' && $action != 'editline') {
2860  print '<div class="tabsAction">';
2861 
2862  $parameters = array();
2863  // Note that $action and $object may be modified by hook
2864  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
2865  if (empty($reshook)) {
2866  // Reopen a closed order
2867  if (($object->statut == Commande::STATUS_CLOSED || $object->statut == Commande::STATUS_CANCELED) && $usercancreate) {
2868  print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&amp;token='.newToken().'&amp;id='.$object->id, '');
2869  }
2870 
2871  // Send
2872  if (empty($user->socid)) {
2873  if ($object->statut > Commande::STATUS_DRAFT || !empty($conf->global->COMMANDE_SENDBYEMAIL_FOR_ALL_STATUS)) {
2874  if ($usercansend) {
2875  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?action=presend&token='.newToken().'&id='.$object->id.'&mode=init#formmailbeforetitle', '');
2876  } else {
2877  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2878  }
2879  }
2880  }
2881 
2882  // Valid
2883  if ($object->statut == Commande::STATUS_DRAFT && ($object->total_ttc >= 0 || !empty($conf->global->ORDER_ENABLE_NEGATIVE)) && $numlines > 0 && $usercanvalidate) {
2884  print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&amp;token='.newToken().'&amp;id='.$object->id, '');
2885  }
2886  // Edit
2887  if ($object->statut == Commande::STATUS_VALIDATED && $usercancreate) {
2888  print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?action=modif&amp;token='.newToken().'&amp;id='.$object->id, '');
2889  }
2890  // Create event
2891  /*if (isModEnabled('agenda') && !empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD))
2892  {
2893  // Add hidden condition because this is not a
2894  // "workflow" action so should appears somewhere else on
2895  // page.
2896  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>';
2897  }*/
2898 
2899  // Create a purchase order
2900  if (!empty($conf->global->WORKFLOW_CAN_CREATE_PURCHASE_ORDER_FROM_SALE_ORDER)) {
2901  if (isModEnabled("supplier_order") && $object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0) {
2902  if ($usercancreatepurchaseorder) {
2903  print dolGetButtonAction('', $langs->trans('AddPurchaseOrder'), 'default', DOL_URL_ROOT.'/fourn/commande/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
2904  }
2905  }
2906  }
2907 
2908  // Create intervention
2909  if (isModEnabled('ficheinter')) {
2910  $langs->load("interventions");
2911 
2912  if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0) {
2913  if ($user->hasRight('ficheinter', 'creer')) {
2914  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, '');
2915  } else {
2916  print dolGetButtonAction($langs->trans('NotAllowed'), $langs->trans('AddIntervention'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2917  }
2918  }
2919  }
2920 
2921  // Create contract
2922  if (isModEnabled('contrat') && ($object->statut == Commande::STATUS_VALIDATED || $object->statut == Commande::STATUS_SHIPMENTONPROCESS || $object->statut == Commande::STATUS_CLOSED)) {
2923  $langs->load("contracts");
2924 
2925  if ($user->hasRight('contrat', 'creer')) {
2926  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, '');
2927  }
2928  }
2929 
2930  // Ship
2931  $numshipping = 0;
2932  if (isModEnabled('expedition')) {
2933  $numshipping = $object->countNbOfShipments();
2934 
2935  if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || !empty($conf->global->STOCK_SUPPORTS_SERVICES))) {
2936  if ((getDolGlobalInt('MAIN_SUBMODULE_EXPEDITION') && $user->hasRight('expedition', 'creer')) || (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') && $user->hasRight('expedition', 'delivery', 'creer'))) {
2937  if ($user->hasRight('expedition', 'creer')) {
2938  print dolGetButtonAction('', $langs->trans('CreateShipment'), 'default', DOL_URL_ROOT.'/expedition/shipment.php?id='.$object->id, '');
2939  } else {
2940  print dolGetButtonAction($langs->trans('NotAllowed'), $langs->trans('CreateShipment'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2941  }
2942  } else {
2943  $langs->load("errors");
2944  print dolGetButtonAction($langs->trans('ErrorModuleSetupNotComplete'), $langs->trans('CreateShipment'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2945  }
2946  }
2947  }
2948 
2949  // Set to shipped
2950  if (($object->statut == Commande::STATUS_VALIDATED || $object->statut == Commande::STATUS_SHIPMENTONPROCESS) && $usercanclose) {
2951  print dolGetButtonAction('', $langs->trans('ClassifyShipped'), 'default', $_SERVER["PHP_SELF"].'?action=shipped&amp;token='.newToken().'&amp;id='.$object->id, '');
2952  }
2953  // Create bill and Classify billed
2954  // Note: Even if module invoice is not enabled, we should be able to use button "Classified billed"
2955  if ($object->statut > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) {
2956  if (isModEnabled('facture') && $user->hasRight('facture', 'creer') && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) {
2957  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, '');
2958  }
2959  if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) {
2960  print dolGetButtonAction('', $langs->trans('ClassifyBilled'), 'default', $_SERVER["PHP_SELF"].'?action=classifybilled&amp;token='.newToken().'&amp;id='.$object->id, '');
2961  }
2962  }
2963  if ($object->statut > Commande::STATUS_DRAFT && $object->billed) {
2964  if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) {
2965  print dolGetButtonAction('', $langs->trans('ClassifyUnBilled'), 'default', $_SERVER["PHP_SELF"].'?action=classifyunbilled&amp;token='.newToken().'&amp;id='.$object->id, '');
2966  }
2967  }
2968  // Clone
2969  if ($usercancreate) {
2970  print dolGetButtonAction('', $langs->trans('ToClone'), 'default', $_SERVER["PHP_SELF"].'?action=clone&amp;token='.newToken().'&amp;id='.$object->id.'&amp;socid='.$object->socid, '');
2971  }
2972 
2973  // Cancel order
2974  if ($object->statut == Commande::STATUS_VALIDATED && !empty($usercancancel)) {
2975  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=cancel&token='.newToken().'">'.$langs->trans("Cancel").'</a>';
2976  }
2977 
2978  // Delete order
2979  if ($usercandelete) {
2980  if ($numshipping == 0) {
2981  print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id, '');
2982  } else {
2983  print dolGetButtonAction($langs->trans('ShippingExist'), $langs->trans('Delete'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
2984  }
2985  }
2986  }
2987  print '</div>';
2988  }
2989 
2990  // Select mail models is same action as presend
2991  if (GETPOST('modelselected')) {
2992  $action = 'presend';
2993  }
2994 
2995  if ($action != 'presend') {
2996  print '<div class="fichecenter"><div class="fichehalfleft">';
2997  print '<a name="builddoc"></a>'; // ancre
2998  // Documents
2999  $objref = dol_sanitizeFileName($object->ref);
3000  $relativepath = $objref.'/'.$objref.'.pdf';
3001  $filedir = $conf->commande->multidir_output[$object->entity].'/'.$objref;
3002  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
3003  $genallowed = $usercanread;
3004  $delallowed = $usercancreate;
3005  print $formfile->showdocuments('commande', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang, '', $object);
3006 
3007 
3008  // Show links to link elements
3009  $linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
3010 
3011  $compatibleImportElementsList = false;
3012  if ($usercancreate
3013  && $object->statut == Commande::STATUS_DRAFT) {
3014  $compatibleImportElementsList = array('commande', 'propal', 'facture'); // import from linked elements
3015  }
3016  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
3017 
3018  // Show online payment link
3019  $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox'));
3020  if (!empty($conf->global->ORDER_HIDE_ONLINE_PAYMENT_ON_ORDER)) {
3021  $useonlinepayment = 0;
3022  }
3023  if ($object->statut != Commande::STATUS_DRAFT && $useonlinepayment) {
3024  print '<br><!-- Link to pay -->';
3025  require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
3026  print showOnlinePaymentUrl('order', $object->ref).'<br>';
3027  }
3028 
3029  print '</div><div class="fichehalfright">';
3030 
3031  $MAXEVENT = 10;
3032 
3033  $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/commande/agenda.php?id='.$object->id);
3034 
3035  // List of actions on element
3036  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
3037  $formactions = new FormActions($db);
3038  $somethingshown = $formactions->showactions($object, 'order', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter); // Show all action for thirdparty
3039 
3040  print '</div></div>';
3041  }
3042 
3043  // Presend form
3044  $modelmail = 'order_send';
3045  $defaulttopic = 'SendOrderRef';
3046  $diroutput = getMultidirOutput($object);
3047  $trackid = 'ord'.$object->id;
3048 
3049  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
3050  }
3051 }
3052 
3053 // End of page
3054 llxFooter();
3055 $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.
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') {
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.