dolibarr  13.0.2
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
5  * Copyright (C) 2005-2015 Regis Houssin <regis.houssin@capnetworks.com>
6  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
7  * Copyright (C) 2006 Auguria SARL <info@auguria.org>
8  * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
9  * Copyright (C) 2013-2016 Marcos García <marcosgdf@gmail.com>
10  * Copyright (C) 2012-2013 Cédric Salvador <csalvador@gpcsolutions.fr>
11  * Copyright (C) 2011-2020 Alexandre Spangaro <aspangaro@open-dsi.fr>
12  * Copyright (C) 2014 Cédric Gross <c.gross@kreiz-it.fr>
13  * Copyright (C) 2014-2015 Ferran Marcet <fmarcet@2byte.es>
14  * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
15  * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
16  * Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
17  * Copyright (C) 2016 Meziane Sof <virtualsof@yahoo.fr>
18  * Copyright (C) 2017 Josep Lluís Amador <joseplluis@lliuretic.cat>
19  * Copyright (C) 2019-2021 Frédéric France <frederic.france@netlogic.fr>
20  * Copyright (C) 2019-2020 Thibault FOUCART <support@ptibogxiv.net>
21  * Copyright (C) 2020 Pierre Ardoin <mapiolca@me.com>
22  *
23  * This program is free software; you can redistribute it and/or modify
24  * it under the terms of the GNU General Public License as published by
25  * the Free Software Foundation; either version 3 of the License, or
26  * (at your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31  * GNU General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program. If not, see <https://www.gnu.org/licenses/>.
35  */
36 
43 require '../main.inc.php';
44 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
45 require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
46 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
47 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
48 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
49 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
50 require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php';
51 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
52 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
53 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
54 require_once DOL_DOCUMENT_ROOT.'/core/modules/product/modules_product.class.php';
55 
56 if (!empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
57 if (!empty($conf->facture->enabled)) require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
58 if (!empty($conf->commande->enabled)) require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
59 if (!empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
60 if (!empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
61 if (!empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
62 
63 // Load translation files required by the page
64 $langs->loadLangs(array('products', 'other'));
65 if (!empty($conf->stock->enabled)) $langs->load("stocks");
66 if (!empty($conf->facture->enabled)) $langs->load("bills");
67 if (!empty($conf->productbatch->enabled)) $langs->load("productbatch");
68 
69 $mesg = ''; $error = 0; $errors = array();
70 
71 $refalreadyexists = 0;
72 
73 $id = GETPOST('id', 'int');
74 $ref = GETPOST('ref', 'alpha');
75 $type = (GETPOST('type', 'int') !== '') ? GETPOST('type', 'int') : Product::TYPE_PRODUCT;
76 $action = (GETPOST('action', 'alpha') ? GETPOST('action', 'alpha') : 'view');
77 $cancel = GETPOST('cancel', 'alpha');
78 $backtopage = GETPOST('backtopage', 'alpha');
79 $confirm = GETPOST('confirm', 'alpha');
80 $socid = GETPOST('socid', 'int');
81 $duration_value = GETPOST('duration_value', 'int');
82 $duration_unit = GETPOST('duration_unit', 'alpha');
83 
84 $accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha');
85 $accountancy_code_sell_intra = GETPOST('accountancy_code_sell_intra', 'alpha');
86 $accountancy_code_sell_export = GETPOST('accountancy_code_sell_export', 'alpha');
87 $accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha');
88 $accountancy_code_buy_intra = GETPOST('accountancy_code_buy_intra', 'alpha');
89 $accountancy_code_buy_export = GETPOST('accountancy_code_buy_export', 'alpha');
90 
91 // by default 'alphanohtml' (better security); hidden conf MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML allows basic html
92 $label_security_check = empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML) ? 'alphanohtml' : 'restricthtml';
93 
94 if (!empty($user->socid)) $socid = $user->socid;
95 
96 $object = new Product($db);
97 $object->type = $type; // so test later to fill $usercancxxx is correct
98 $extrafields = new ExtraFields($db);
99 
100 // fetch optionals attributes and labels
101 $extrafields->fetch_name_optionals_label($object->table_element);
102 
103 if ($id > 0 || !empty($ref))
104 {
105  $result = $object->fetch($id, $ref);
106 
107  if (!empty($conf->product->enabled)) $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref);
108  elseif (!empty($conf->service->enabled)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref);
109 
110  if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) // For backward compatiblity, we scan also old dirs
111  {
112  if (!empty($conf->product->enabled)) $upload_dirold = $conf->product->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos";
113  else $upload_dirold = $conf->service->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos";
114  }
115 }
116 
117 $modulepart = 'product';
118 
119 // Get object canvas (By default, this is not defined, so standard usage of dolibarr)
120 $canvas = !empty($object->canvas) ? $object->canvas : GETPOST("canvas");
121 $objcanvas = null;
122 if (!empty($canvas))
123 {
124  require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
125  $objcanvas = new Canvas($db, $action);
126  $objcanvas->getCanvas('product', 'card', $canvas);
127 }
128 
129 // Security check
130 $fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
131 $fieldtype = (!empty($id) ? 'rowid' : 'ref');
132 $result = restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
133 
134 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
135 $hookmanager->initHooks(array('productcard', 'globalcard'));
136 
137 
138 
139 /*
140  * Actions
141  */
142 
143 if ($cancel) $action = '';
144 
145 $usercanread = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->lire) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->lire));
146 $usercancreate = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->creer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->creer));
147 $usercandelete = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->supprimer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->supprimer));
148 $createbarcode = empty($conf->barcode->enabled) ? 0 : 1;
149 if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->creer_advance)) $createbarcode = 0;
150 
151 $parameters = array('id'=>$id, 'ref'=>$ref, 'objcanvas'=>$objcanvas);
152 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
153 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
154 
155 if (empty($reshook))
156 {
157  // Type
158  if ($action == 'setfk_product_type' && $usercancreate)
159  {
160  $result = $object->setValueFrom('fk_product_type', GETPOST('fk_product_type'), '', null, 'text', '', $user, 'PRODUCT_MODIFY');
161  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
162  exit;
163  }
164 
165  // Actions to build doc
166  $upload_dir = $conf->product->dir_output;
167  $permissiontoadd = $usercancreate;
168  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
169 
170  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
171 
172  // Barcode type
173  if ($action == 'setfk_barcode_type' && $createbarcode)
174  {
175  $result = $object->setValueFrom('fk_barcode_type', GETPOST('fk_barcode_type'), '', null, 'text', '', $user, 'PRODUCT_MODIFY');
176  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
177  exit;
178  }
179 
180  // Barcode value
181  if ($action == 'setbarcode' && $createbarcode)
182  {
183  $result = $object->check_barcode(GETPOST('barcode'), GETPOST('barcode_type_code'));
184 
185  if ($result >= 0)
186  {
187  $result = $object->setValueFrom('barcode', GETPOST('barcode'), '', null, 'text', '', $user, 'PRODUCT_MODIFY');
188  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
189  exit;
190  } else {
191  $langs->load("errors");
192  if ($result == -1) $errors[] = 'ErrorBadBarCodeSyntax';
193  elseif ($result == -2) $errors[] = 'ErrorBarCodeRequired';
194  elseif ($result == -3) $errors[] = 'ErrorBarCodeAlreadyUsed';
195  else $errors[] = 'FailedToValidateBarCode';
196 
197  $error++;
198  setEventMessages($errors, null, 'errors');
199  }
200  }
201 
202  // Add a product or service
203  if ($action == 'add' && $usercancreate)
204  {
205  $error = 0;
206 
207  if (!GETPOST('label', $label_security_check))
208  {
209  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Label')), null, 'errors');
210  $action = "create";
211  $error++;
212  }
213  if (empty($ref))
214  {
215  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Ref')), null, 'errors');
216  $action = "create";
217  $error++;
218  }
219  if (!empty($duration_value) && empty($duration_unit))
220  {
221  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Unit')), null, 'errors');
222  $action = "create";
223  $error++;
224  }
225 
226  if (!$error)
227  {
228  $units = GETPOST('units', 'int');
229 
230  $object->ref = $ref;
231  $object->label = GETPOST('label', $label_security_check);
232  $object->price_base_type = GETPOST('price_base_type', 'aZ09');
233 
234  if ($object->price_base_type == 'TTC')
235  $object->price_ttc = GETPOST('price');
236  else $object->price = GETPOST('price');
237  if ($object->price_base_type == 'TTC')
238  $object->price_min_ttc = GETPOST('price_min');
239  else $object->price_min = GETPOST('price_min');
240 
241  $tva_tx_txt = GETPOST('tva_tx', 'alpha'); // tva_tx can be '8.5' or '8.5*' or '8.5 (XXX)' or '8.5* (XXX)'
242 
243  // We must define tva_tx, npr and local taxes
244  $vatratecode = '';
245  $tva_tx = preg_replace('/[^0-9\.].*$/', '', $tva_tx_txt); // keep remove all after the numbers and dot
246  $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0;
247  $localtax1 = 0; $localtax2 = 0; $localtax1_type = '0'; $localtax2_type = '0';
248  // If value contains the unique code of vat line (new recommanded method), we use it to find npr and local taxes
249  $reg = array();
250  if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg))
251  {
252  // We look into database using code (we can't use get_localtax() because it depends on buyer that is not known). Same in update price.
253  $vatratecode = $reg[1];
254  // Get record from code
255  $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
256  $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
257  $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
258  $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
259  $sql .= " AND t.code = '".$db->escape($vatratecode)."'";
260  $resql = $db->query($sql);
261  if ($resql)
262  {
263  $obj = $db->fetch_object($resql);
264  $npr = $obj->recuperableonly;
265  $localtax1 = $obj->localtax1;
266  $localtax2 = $obj->localtax2;
267  $localtax1_type = $obj->localtax1_type;
268  $localtax2_type = $obj->localtax2_type;
269  }
270  }
271 
272  $object->default_vat_code = $vatratecode;
273  $object->tva_tx = $tva_tx;
274  $object->tva_npr = $npr;
275  $object->localtax1_tx = $localtax1;
276  $object->localtax2_tx = $localtax2;
277  $object->localtax1_type = $localtax1_type;
278  $object->localtax2_type = $localtax2_type;
279 
280  $object->type = $type;
281  $object->status = GETPOST('statut');
282  $object->status_buy = GETPOST('statut_buy');
283  $object->status_batch = GETPOST('status_batch');
284 
285  $object->barcode_type = GETPOST('fk_barcode_type');
286  $object->barcode = GETPOST('barcode');
287  // Set barcode_type_xxx from barcode_type id
288  $stdobject = new GenericObject($db);
289  $stdobject->element = 'product';
290  $stdobject->barcode_type = GETPOST('fk_barcode_type');
291  $result = $stdobject->fetch_barcode();
292  if ($result < 0)
293  {
294  $error++;
295  $mesg = 'Failed to get bar code type information ';
296  setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors');
297  }
298  $object->barcode_type_code = $stdobject->barcode_type_code;
299  $object->barcode_type_coder = $stdobject->barcode_type_coder;
300  $object->barcode_type_label = $stdobject->barcode_type_label;
301 
302  $object->description = dol_htmlcleanlastbr(GETPOST('desc', 'restricthtml'));
303  $object->url = GETPOST('url');
304  $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private', 'restricthtml'));
305  $object->note = $object->note_private; // deprecated
306  $object->customcode = GETPOST('customcode', 'alphanohtml');
307  $object->country_id = GETPOST('country_id', 'int');
308  $object->state_id = GETPOST('state_id', 'int');
309  $object->duration_value = $duration_value;
310  $object->duration_unit = $duration_unit;
311  $object->fk_default_warehouse = GETPOST('fk_default_warehouse');
312  $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte') ?GETPOST('seuil_stock_alerte') : 0;
313  $object->desiredstock = GETPOST('desiredstock') ?GETPOST('desiredstock') : 0;
314  $object->canvas = GETPOST('canvas');
315  $object->net_measure = GETPOST('net_measure');
316  $object->net_measure_units = GETPOST('net_measure_units'); // This is not the fk_unit but the power of unit
317  $object->weight = GETPOST('weight');
318  $object->weight_units = GETPOST('weight_units'); // This is not the fk_unit but the power of unit
319  $object->length = GETPOST('size');
320  $object->length_units = GETPOST('size_units'); // This is not the fk_unit but the power of unit
321  $object->width = GETPOST('sizewidth');
322  $object->height = GETPOST('sizeheight');
323  $object->surface = GETPOST('surface');
324  $object->surface_units = GETPOST('surface_units'); // This is not the fk_unit but the power of unit
325  $object->volume = GETPOST('volume');
326  $object->volume_units = GETPOST('volume_units'); // This is not the fk_unit but the power of unit
327  $finished = GETPOST('finished', 'int');
328  if ($finished > 0) {
329  $object->finished = $finished;
330  } else {
331  $object->finished = null;
332  }
333 
334  $units = GETPOST('units', 'int');
335  if ($units > 0) {
336  $object->fk_unit = $units;
337  } else {
338  $object->fk_unit = null;
339  }
340 
341  $accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha');
342  $accountancy_code_sell_intra = GETPOST('accountancy_code_sell_intra', 'alpha');
343  $accountancy_code_sell_export = GETPOST('accountancy_code_sell_export', 'alpha');
344  $accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha');
345  $accountancy_code_buy_intra = GETPOST('accountancy_code_buy_intra', 'alpha');
346  $accountancy_code_buy_export = GETPOST('accountancy_code_buy_export', 'alpha');
347 
348  if ($accountancy_code_sell <= 0) { $object->accountancy_code_sell = ''; } else { $object->accountancy_code_sell = $accountancy_code_sell; }
349  if ($accountancy_code_sell_intra <= 0) { $object->accountancy_code_sell_intra = ''; } else { $object->accountancy_code_sell_intra = $accountancy_code_sell_intra; }
350  if ($accountancy_code_sell_export <= 0) { $object->accountancy_code_sell_export = ''; } else { $object->accountancy_code_sell_export = $accountancy_code_sell_export; }
351  if ($accountancy_code_buy <= 0) { $object->accountancy_code_buy = ''; } else { $object->accountancy_code_buy = $accountancy_code_buy; }
352  if ($accountancy_code_buy_intra <= 0) { $object->accountancy_code_buy_intra = ''; } else { $object->accountancy_code_buy_intra = $accountancy_code_buy_intra; }
353  if ($accountancy_code_buy_export <= 0) { $object->accountancy_code_buy_export = ''; } else { $object->accountancy_code_buy_export = $accountancy_code_buy_export; }
354 
355  // MultiPrix
356  if (!empty($conf->global->PRODUIT_MULTIPRICES))
357  {
358  for ($i = 2; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++)
359  {
360  if (GETPOSTISSET("price_".$i))
361  {
362  $object->multiprices["$i"] = price2num($_POST["price_".$i], 'MU');
363  $object->multiprices_base_type["$i"] = $_POST["multiprices_base_type_".$i];
364  } else {
365  $object->multiprices["$i"] = "";
366  }
367  }
368  }
369 
370  // Fill array 'array_options' with data from add form
371  $ret = $extrafields->setOptionalsFromPost(null, $object);
372  if ($ret < 0) $error++;
373 
374  if (!$error)
375  {
376  $id = $object->create($user);
377  }
378 
379  if ($id > 0)
380  {
381  // Category association
382  $categories = GETPOST('categories', 'array');
383  $object->setCategories($categories);
384 
385  if (!empty($backtopage))
386  {
387  $backtopage = preg_replace('/--IDFORBACKTOPAGE--/', $object->id, $backtopage); // New method to autoselect project after a New on another form object creation
388  if (preg_match('/\?/', $backtopage)) $backtopage .= '&socid='.$object->id; // Old method
389  header("Location: ".$backtopage);
390  exit;
391  } else {
392  header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
393  exit;
394  }
395  } else {
396  if (count($object->errors)) setEventMessages($object->error, $object->errors, 'errors');
397  else setEventMessages($langs->trans($object->error), null, 'errors');
398  $action = "create";
399  }
400  }
401  }
402 
403  // Update a product or service
404  if ($action == 'update' && $usercancreate)
405  {
406  if (GETPOST('cancel', 'alpha'))
407  {
408  $action = '';
409  } else {
410  if ($object->id > 0)
411  {
412  $object->oldcopy = clone $object;
413 
414  $object->ref = $ref;
415  $object->label = GETPOST('label', $label_security_check);
416  $object->description = dol_htmlcleanlastbr(GETPOST('desc', 'restricthtml'));
417  $object->url = GETPOST('url');
418  if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB))
419  {
420  $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private', 'restricthtml'));
421  $object->note = $object->note_private;
422  }
423  $object->customcode = GETPOST('customcode', 'alpha');
424  $object->country_id = GETPOST('country_id', 'int');
425  $object->state_id = GETPOST('state_id', 'int');
426  $object->status = GETPOST('statut', 'int');
427  $object->status_buy = GETPOST('statut_buy', 'int');
428  $object->status_batch = GETPOST('status_batch', 'aZ09');
429  // removed from update view so GETPOST always empty
430  $object->fk_default_warehouse = GETPOST('fk_default_warehouse');
431  /*
432  $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte');
433  $object->desiredstock = GETPOST('desiredstock');
434  */
435  $object->duration_value = GETPOST('duration_value', 'int');
436  $object->duration_unit = GETPOST('duration_unit', 'alpha');
437 
438  $object->canvas = GETPOST('canvas');
439  $object->net_measure = GETPOST('net_measure');
440  $object->net_measure_units = GETPOST('net_measure_units'); // This is not the fk_unit but the power of unit
441  $object->weight = GETPOST('weight');
442  $object->weight_units = GETPOST('weight_units'); // This is not the fk_unit but the power of unit
443  $object->length = GETPOST('size');
444  $object->length_units = GETPOST('size_units'); // This is not the fk_unit but the power of unit
445  $object->width = GETPOST('sizewidth');
446  $object->height = GETPOST('sizeheight');
447 
448  $object->surface = GETPOST('surface');
449  $object->surface_units = GETPOST('surface_units'); // This is not the fk_unit but the power of unit
450  $object->volume = GETPOST('volume');
451  $object->volume_units = GETPOST('volume_units'); // This is not the fk_unit but the power of unit
452 
453  $finished = GETPOST('finished', 'int');
454  if ($finished >= 0) {
455  $object->finished = $finished;
456  } else {
457  $object->finished = null;
458  }
459 
460  $units = GETPOST('units', 'int');
461  if ($units > 0) {
462  $object->fk_unit = $units;
463  } else {
464  $object->fk_unit = null;
465  }
466 
467  $object->barcode_type = GETPOST('fk_barcode_type');
468  $object->barcode = GETPOST('barcode');
469  // Set barcode_type_xxx from barcode_type id
470  $stdobject = new GenericObject($db);
471  $stdobject->element = 'product';
472  $stdobject->barcode_type = GETPOST('fk_barcode_type');
473  $result = $stdobject->fetch_barcode();
474  if ($result < 0)
475  {
476  $error++;
477  $mesg = 'Failed to get bar code type information ';
478  setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors');
479  }
480  $object->barcode_type_code = $stdobject->barcode_type_code;
481  $object->barcode_type_coder = $stdobject->barcode_type_coder;
482  $object->barcode_type_label = $stdobject->barcode_type_label;
483 
484  $accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha');
485  $accountancy_code_sell_intra = GETPOST('accountancy_code_sell_intra', 'alpha');
486  $accountancy_code_sell_export = GETPOST('accountancy_code_sell_export', 'alpha');
487  $accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha');
488  $accountancy_code_buy_intra = GETPOST('accountancy_code_buy_intra', 'alpha');
489  $accountancy_code_buy_export = GETPOST('accountancy_code_buy_export', 'alpha');
490 
491  if ($accountancy_code_sell <= 0) { $object->accountancy_code_sell = ''; } else { $object->accountancy_code_sell = $accountancy_code_sell; }
492  if ($accountancy_code_sell_intra <= 0) { $object->accountancy_code_sell_intra = ''; } else { $object->accountancy_code_sell_intra = $accountancy_code_sell_intra; }
493  if ($accountancy_code_sell_export <= 0) { $object->accountancy_code_sell_export = ''; } else { $object->accountancy_code_sell_export = $accountancy_code_sell_export; }
494  if ($accountancy_code_buy <= 0) { $object->accountancy_code_buy = ''; } else { $object->accountancy_code_buy = $accountancy_code_buy; }
495  if ($accountancy_code_buy_intra <= 0) { $object->accountancy_code_buy_intra = ''; } else { $object->accountancy_code_buy_intra = $accountancy_code_buy_intra; }
496  if ($accountancy_code_buy_export <= 0) { $object->accountancy_code_buy_export = ''; } else { $object->accountancy_code_buy_export = $accountancy_code_buy_export; }
497 
498  // Fill array 'array_options' with data from add form
499  $ret = $extrafields->setOptionalsFromPost(null, $object);
500  if ($ret < 0) $error++;
501 
502  if (!$error && $object->check())
503  {
504  if ($object->update($object->id, $user) > 0)
505  {
506  // Category association
507  $categories = GETPOST('categories', 'array');
508  $object->setCategories($categories);
509 
510  $action = 'view';
511  } else {
512  if (count($object->errors)) setEventMessages($object->error, $object->errors, 'errors');
513  else setEventMessages($langs->trans($object->error), null, 'errors');
514  $action = 'edit';
515  }
516  } else {
517  if (count($object->errors)) setEventMessages($object->error, $object->errors, 'errors');
518  else setEventMessages($langs->trans("ErrorProductBadRefOrLabel"), null, 'errors');
519  $action = 'edit';
520  }
521  }
522  }
523  }
524 
525  // Action clone object
526  if ($action == 'confirm_clone' && $confirm != 'yes') { $action = ''; }
527  if ($action == 'confirm_clone' && $confirm == 'yes' && $usercancreate)
528  {
529  if (!GETPOST('clone_content') && !GETPOST('clone_prices'))
530  {
531  setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
532  } else {
533  $db->begin();
534 
535  $originalId = $id;
536  if ($object->id > 0)
537  {
538  $object->ref = GETPOST('clone_ref', 'alphanohtml');
539  $object->status = 0;
540  $object->status_buy = 0;
541  $object->id = null;
542  $object->barcode = -1;
543 
544  if ($object->check())
545  {
546  $object->context['createfromclone'] = 'createfromclone';
547  $id = $object->create($user);
548  if ($id > 0)
549  {
550  if (GETPOST('clone_composition'))
551  {
552  $result = $object->clone_associations($originalId, $id);
553 
554  if ($result < 1)
555  {
556  $db->rollback();
557  setEventMessages($langs->trans('ErrorProductClone'), null, 'errors');
558  header("Location: ".$_SERVER["PHP_SELF"]."?id=".$originalId);
559  exit;
560  }
561  }
562 
563  if (GETPOST('clone_categories'))
564  {
565  $result = $object->cloneCategories($originalId, $id);
566 
567  if ($result < 1)
568  {
569  $db->rollback();
570  setEventMessages($langs->trans('ErrorProductClone'), null, 'errors');
571  header("Location: ".$_SERVER["PHP_SELF"]."?id=".$originalId);
572  exit;
573  }
574  }
575 
576  if (GETPOST('clone_prices')) {
577  $result = $object->clone_price($originalId, $id);
578 
579  if ($result < 1) {
580  $db->rollback();
581  setEventMessages($langs->trans('ErrorProductClone'), null, 'errors');
582  header('Location: '.$_SERVER['PHP_SELF'].'?id='.$originalId);
583  exit();
584  }
585  }
586 
587  // $object->clone_fournisseurs($originalId, $id);
588 
589  $db->commit();
590  $db->close();
591 
592  header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
593  exit;
594  } else {
595  $id = $originalId;
596 
597  if ($object->error == 'ErrorProductAlreadyExists')
598  {
599  $db->rollback();
600 
601  $refalreadyexists++;
602  $action = "";
603 
604  $mesg = $langs->trans("ErrorProductAlreadyExists", $object->ref);
605  $mesg .= ' <a href="'.$_SERVER["PHP_SELF"].'?ref='.$object->ref.'">'.$langs->trans("ShowCardHere").'</a>.';
606  setEventMessages($mesg, null, 'errors');
607  $object->fetch($id);
608  } else {
609  $db->rollback();
610  if (count($object->errors))
611  {
612  setEventMessages($object->error, $object->errors, 'errors');
613  dol_print_error($db, $object->errors);
614  } else {
615  setEventMessages($langs->trans($object->error), null, 'errors');
616  dol_print_error($db, $object->error);
617  }
618  }
619  }
620 
621  unset($object->context['createfromclone']);
622  }
623  } else {
624  $db->rollback();
625  dol_print_error($db, $object->error);
626  }
627  }
628  }
629 
630  // Delete a product
631  if ($action == 'confirm_delete' && $confirm != 'yes') { $action = ''; }
632  if ($action == 'confirm_delete' && $confirm == 'yes' && $usercandelete)
633  {
634  $result = $object->delete($user);
635 
636  if ($result > 0)
637  {
638  header('Location: '.DOL_URL_ROOT.'/product/list.php?type='.$object->type.'&delprod='.urlencode($object->ref));
639  exit;
640  } else {
641  setEventMessages($langs->trans($object->error), null, 'errors');
642  $reload = 0;
643  $action = '';
644  }
645  }
646 
647 
648  // Add product into object
649  if ($object->id > 0 && $action == 'addin')
650  {
651  $thirpdartyid = 0;
652  if (GETPOST('propalid') > 0)
653  {
654  $propal = new Propal($db);
655  $result = $propal->fetch(GETPOST('propalid'));
656  if ($result <= 0)
657  {
658  dol_print_error($db, $propal->error);
659  exit;
660  }
661  $thirpdartyid = $propal->socid;
662  } elseif (GETPOST('commandeid') > 0)
663  {
664  $commande = new Commande($db);
665  $result = $commande->fetch(GETPOST('commandeid'));
666  if ($result <= 0)
667  {
668  dol_print_error($db, $commande->error);
669  exit;
670  }
671  $thirpdartyid = $commande->socid;
672  } elseif (GETPOST('factureid') > 0)
673  {
674  $facture = new Facture($db);
675  $result = $facture->fetch(GETPOST('factureid'));
676  if ($result <= 0)
677  {
678  dol_print_error($db, $facture->error);
679  exit;
680  }
681  $thirpdartyid = $facture->socid;
682  }
683 
684  if ($thirpdartyid > 0) {
685  $soc = new Societe($db);
686  $result = $soc->fetch($thirpdartyid);
687  if ($result <= 0) {
688  dol_print_error($db, $soc->error);
689  exit;
690  }
691 
692  $desc = $object->description;
693 
694  $tva_tx = get_default_tva($mysoc, $soc, $object->id);
695  $tva_npr = get_default_npr($mysoc, $soc, $object->id);
696  if (empty($tva_tx)) $tva_npr = 0;
697  $localtax1_tx = get_localtax($tva_tx, 1, $soc, $mysoc, $tva_npr);
698  $localtax2_tx = get_localtax($tva_tx, 2, $soc, $mysoc, $tva_npr);
699 
700  $pu_ht = $object->price;
701  $pu_ttc = $object->price_ttc;
702  $price_base_type = $object->price_base_type;
703 
704  // If multiprice
705  if ($conf->global->PRODUIT_MULTIPRICES && $soc->price_level) {
706  $pu_ht = $object->multiprices[$soc->price_level];
707  $pu_ttc = $object->multiprices_ttc[$soc->price_level];
708  $price_base_type = $object->multiprices_base_type[$soc->price_level];
709  } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
710  require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php';
711 
712  $prodcustprice = new Productcustomerprice($db);
713 
714  $filter = array('t.fk_product' => $object->id, 't.fk_soc' => $soc->id);
715 
716  $result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
717  if ($result) {
718  if (count($prodcustprice->lines) > 0) {
719  $pu_ht = price($prodcustprice->lines [0]->price);
720  $pu_ttc = price($prodcustprice->lines [0]->price_ttc);
721  $price_base_type = $prodcustprice->lines [0]->price_base_type;
722  $tva_tx = $prodcustprice->lines [0]->tva_tx;
723  }
724  }
725  }
726 
727  $tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
728  $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
729 
730  // On reevalue prix selon taux tva car taux tva transaction peut etre different
731  // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
732  if ($tmpvat != $tmpprodvat) {
733  if ($price_base_type != 'HT') {
734  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
735  } else {
736  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
737  }
738  }
739 
740  if (GETPOST('propalid') > 0) {
741  // Define cost price for margin calculation
742  $buyprice = 0;
743  if (($result = $propal->defineBuyPrice($pu_ht, GETPOST('remise_percent'), $object->id)) < 0)
744  {
745  dol_syslog($langs->trans('FailedToGetCostPrice'));
746  setEventMessages($langs->trans('FailedToGetCostPrice'), null, 'errors');
747  } else {
748  $buyprice = $result;
749  }
750 
751  $result = $propal->addline(
752  $desc,
753  $pu_ht,
754  GETPOST('qty'),
755  $tva_tx,
756  $localtax1_tx, // localtax1
757  $localtax2_tx, // localtax2
758  $object->id,
759  GETPOST('remise_percent'),
760  $price_base_type,
761  $pu_ttc,
762  0,
763  0,
764  -1,
765  0,
766  0,
767  0,
768  $buyprice,
769  '',
770  '',
771  '',
772  0,
773  $object->fk_unit
774  );
775  if ($result > 0) {
776  header("Location: ".DOL_URL_ROOT."/comm/propal/card.php?id=".$propal->id);
777  return;
778  }
779 
780  setEventMessages($langs->trans("ErrorUnknown").": $result", null, 'errors');
781  } elseif (GETPOST('commandeid') > 0) {
782  // Define cost price for margin calculation
783  $buyprice = 0;
784  if (($result = $commande->defineBuyPrice($pu_ht, GETPOST('remise_percent'), $object->id)) < 0)
785  {
786  dol_syslog($langs->trans('FailedToGetCostPrice'));
787  setEventMessages($langs->trans('FailedToGetCostPrice'), null, 'errors');
788  } else {
789  $buyprice = $result;
790  }
791 
792  $result = $commande->addline(
793  $desc,
794  $pu_ht,
795  GETPOST('qty'),
796  $tva_tx,
797  $localtax1_tx, // localtax1
798  $localtax2_tx, // localtax2
799  $object->id,
800  GETPOST('remise_percent'),
801  '',
802  '',
803  $price_base_type,
804  $pu_ttc,
805  '',
806  '',
807  0,
808  -1,
809  0,
810  0,
811  null,
812  $buyprice,
813  '',
814  0,
815  $object->fk_unit
816  );
817 
818  if ($result > 0) {
819  header("Location: ".DOL_URL_ROOT."/commande/card.php?id=".$commande->id);
820  exit;
821  }
822  } elseif (GETPOST('factureid') > 0) {
823  // Define cost price for margin calculation
824  $buyprice = 0;
825  if (($result = $facture->defineBuyPrice($pu_ht, GETPOST('remise_percent'), $object->id)) < 0)
826  {
827  dol_syslog($langs->trans('FailedToGetCostPrice'));
828  setEventMessages($langs->trans('FailedToGetCostPrice'), null, 'errors');
829  } else {
830  $buyprice = $result;
831  }
832 
833  $result = $facture->addline(
834  $desc,
835  $pu_ht,
836  GETPOST('qty'),
837  $tva_tx,
838  $localtax1_tx,
839  $localtax2_tx,
840  $object->id,
841  GETPOST('remise_percent'),
842  '',
843  '',
844  '',
845  '',
846  '',
847  $price_base_type,
848  $pu_ttc,
850  -1,
851  0,
852  '',
853  0,
854  0,
855  null,
856  $buyprice,
857  '',
858  0,
859  100,
860  '',
861  $object->fk_unit
862  );
863 
864  if ($result > 0) {
865  header("Location: ".DOL_URL_ROOT."/compta/facture/card.php?facid=".$facture->id);
866  exit;
867  }
868  }
869  } else {
870  $action = "";
871  setEventMessages($langs->trans("WarningSelectOneDocument"), null, 'warnings');
872  }
873  }
874 }
875 
876 
877 
878 /*
879  * View
880  */
881 
882 $title = $langs->trans('ProductServiceCard');
883 $helpurl = '';
884 $shortlabel = dol_trunc($object->label, 16);
885 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT))
886 {
887  $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Card');
888  $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
889 }
890 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE))
891 {
892  $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Card');
893  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
894 }
895 
896 llxHeader('', $title, $helpurl);
897 
898 $form = new Form($db);
899 $formfile = new FormFile($db);
900 $formproduct = new FormProduct($db);
901 $formcompany = new FormCompany($db);
902 if (!empty($conf->accounting->enabled)) $formaccounting = new FormAccounting($db);
903 
904 // Load object modBarCodeProduct
905 $res = 0;
906 if (!empty($conf->barcode->enabled) && !empty($conf->global->BARCODE_PRODUCT_ADDON_NUM))
907 {
908  $module = strtolower($conf->global->BARCODE_PRODUCT_ADDON_NUM);
909  $dirbarcode = array_merge(array('/core/modules/barcode/'), $conf->modules_parts['barcode']);
910  foreach ($dirbarcode as $dirroot)
911  {
912  $res = dol_include_once($dirroot.$module.'.php');
913  if ($res) break;
914  }
915  if ($res > 0)
916  {
917  $modBarCodeProduct = new $module();
918  }
919 }
920 
921 
922 if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
923  // -----------------------------------------
924  // When used with CANVAS
925  // -----------------------------------------
926  if (empty($object->error) && $id)
927  {
928  $object = new Product($db);
929  $result = $object->fetch($id);
930  if ($result <= 0) dol_print_error('', $object->error);
931  }
932  $objcanvas->assign_values($action, $object->id, $object->ref); // Set value for templates
933  $objcanvas->display_canvas($action); // Show template
934 } else {
935  // -----------------------------------------
936  // When used in standard mode
937  // -----------------------------------------
938  if ($action == 'create' && $usercancreate) {
939  //WYSIWYG Editor
940  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
941 
942  print '<script type="text/javascript">';
943  print '$(document).ready(function () {
944  $("#selectcountry_id").change(function() {
945  document.formprod.action.value="create";
946  document.formprod.submit();
947  });
948  });';
949  print '</script>'."\n";
950 
951  // Load object modCodeProduct
952  $module = (!empty($conf->global->PRODUCT_CODEPRODUCT_ADDON) ? $conf->global->PRODUCT_CODEPRODUCT_ADDON : 'mod_codeproduct_leopard');
953  if (substr($module, 0, 16) == 'mod_codeproduct_' && substr($module, -3) == 'php')
954  {
955  $module = substr($module, 0, dol_strlen($module) - 4);
956  }
957  $result = dol_include_once('/core/modules/product/'.$module.'.php');
958  if ($result > 0)
959  {
960  $modCodeProduct = new $module();
961  }
962 
963  dol_set_focus('input[name="ref"]');
964 
965  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formprod">';
966  print '<input type="hidden" name="token" value="'.newToken().'">';
967  print '<input type="hidden" name="action" value="add">';
968  print '<input type="hidden" name="type" value="'.$type.'">'."\n";
969  if (!empty($modCodeProduct->code_auto))
970  print '<input type="hidden" name="code_auto" value="1">';
971  if (!empty($modBarCodeProduct->code_auto))
972  print '<input type="hidden" name="barcode_auto" value="1">';
973  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
974 
975  if ($type == 1) {
976  $picto = 'service';
977  $title = $langs->trans("NewService");
978  } else {
979  $picto = 'product';
980  $title = $langs->trans("NewProduct");
981  }
982  $linkback = "";
983  print load_fiche_titre($title, $linkback, $picto);
984 
985  // We set country_id, country_code and country for the selected country
986  $object->country_id = GETPOSTISSET('country_id') ? GETPOST('country_id', 'int') : null;
987  if ($object->country_id > 0)
988  {
989  $tmparray = getCountry($object->country_id, 'all');
990  $object->country_code = $tmparray['code'];
991  $object->country = $tmparray['label'];
992  }
993 
995 
996  print '<table class="border centpercent">';
997 
998  print '<tr>';
999  $tmpcode = '';
1000  if (!empty($modCodeProduct->code_auto)) $tmpcode = $modCodeProduct->getNextValue($object, $type);
1001  print '<td class="titlefieldcreate fieldrequired">'.$langs->trans("Ref").'</td><td colspan="3"><input id="ref" name="ref" class="maxwidth200" maxlength="128" value="'.dol_escape_htmltag(GETPOSTISSET('ref') ? GETPOST('ref', 'alphanohtml') : $tmpcode).'">';
1002  if ($refalreadyexists)
1003  {
1004  print $langs->trans("RefAlreadyExists");
1005  }
1006  print '</td></tr>';
1007 
1008  // Label
1009  print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td colspan="3"><input name="label" class="minwidth300 maxwidth400onsmartphone" maxlength="255" value="'.dol_escape_htmltag(GETPOST('label', $label_security_check)).'"></td></tr>';
1010 
1011  // On sell
1012  print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Sell").')</td><td colspan="3">';
1013  $statutarray = array('1' => $langs->trans("OnSell"), '0' => $langs->trans("NotOnSell"));
1014  print $form->selectarray('statut', $statutarray, GETPOST('statut'));
1015  print '</td></tr>';
1016 
1017  // To buy
1018  print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Buy").')</td><td colspan="3">';
1019  $statutarray = array('1' => $langs->trans("ProductStatusOnBuy"), '0' => $langs->trans("ProductStatusNotOnBuy"));
1020  print $form->selectarray('statut_buy', $statutarray, GETPOST('statut_buy'));
1021  print '</td></tr>';
1022 
1023  // Batch number management
1024  if (!empty($conf->productbatch->enabled))
1025  {
1026  print '<tr><td>'.$langs->trans("ManageLotSerial").'</td><td colspan="3">';
1027  $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"));
1028  print $form->selectarray('status_batch', $statutarray, GETPOST('status_batch'));
1029  print '</td></tr>';
1030  }
1031 
1032  $showbarcode = empty($conf->barcode->enabled) ? 0 : 1;
1033  if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode = 0;
1034 
1035  if ($showbarcode)
1036  {
1037  print '<tr><td>'.$langs->trans('BarcodeType').'</td><td>';
1038  if (GETPOSTISSET('fk_barcode_type')) {
1039  $fk_barcode_type = GETPOST('fk_barcode_type');
1040  } else {
1041  if (empty($fk_barcode_type) && !empty($conf->global->PRODUIT_DEFAULT_BARCODE_TYPE)) $fk_barcode_type = $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE;
1042  }
1043  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbarcode.class.php';
1044  $formbarcode = new FormBarCode($db);
1045  print $formbarcode->selectBarcodeType($fk_barcode_type, 'fk_barcode_type', 1);
1046  print '</td>';
1047  if ($conf->browser->layout == 'phone') print '</tr><tr>';
1048  print '<td>'.$langs->trans("BarcodeValue").'</td><td>';
1049  $tmpcode = GETPOSTISSET('barcode') ? GETPOST('barcode') : $object->barcode;
1050  if (empty($tmpcode) && !empty($modBarCodeProduct->code_auto)) $tmpcode = $modBarCodeProduct->getNextValue($object, $type);
1051  print '<input class="maxwidth100" type="text" name="barcode" value="'.dol_escape_htmltag($tmpcode).'">';
1052  print '</td></tr>';
1053  }
1054 
1055  // Description (used in invoice, propal...)
1056  print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
1057 
1058  $doleditor = new DolEditor('desc', GETPOST('desc', 'restricthtml'), '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '90%');
1059  $doleditor->Create();
1060 
1061  print "</td></tr>";
1062 
1063  // Public URL
1064  print '<tr><td>'.$langs->trans("PublicUrl").'</td><td colspan="3">';
1065  print '<input type="text" name="url" class="quatrevingtpercent" value="'.GETPOST('url').'">';
1066  print '</td></tr>';
1067 
1068  if ($type != 1 && !empty($conf->stock->enabled))
1069  {
1070  // Default warehouse
1071  print '<tr><td>'.$langs->trans("DefaultWarehouse").'</td><td>';
1072  print $formproduct->selectWarehouses(GETPOST('fk_default_warehouse'), 'fk_default_warehouse', 'warehouseopen', 1);
1073  print ' <a href="'.DOL_URL_ROOT.'/product/stock/card.php?action=create&amp;backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$object->id.'&action=edit').'">';
1074  print '<span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddWarehouse").'"></span>';
1075  print '</a>';
1076  print '</td>';
1077  print '</tr>';
1078 
1079  // Stock min level
1080  print '<tr><td>'.$form->textwithpicto($langs->trans("StockLimit"), $langs->trans("StockLimitDesc"), 1).'</td><td>';
1081  print '<input name="seuil_stock_alerte" class="maxwidth50" value="'.GETPOST('seuil_stock_alerte').'">';
1082  print '</td>';
1083  if ($conf->browser->layout == 'phone') print '</tr><tr>';
1084  // Stock desired level
1085  print '<td>'.$form->textwithpicto($langs->trans("DesiredStock"), $langs->trans("DesiredStockDesc"), 1).'</td><td>';
1086  print '<input name="desiredstock" class="maxwidth50" value="'.GETPOST('desiredstock').'">';
1087  print '</td></tr>';
1088  } else {
1089  print '<input name="seuil_stock_alerte" type="hidden" value="0">';
1090  print '<input name="desiredstock" type="hidden" value="0">';
1091  }
1092 
1093  // Duration
1094  if ($type == 1)
1095  {
1096  print '<tr><td>'.$langs->trans("Duration").'</td><td colspan="3">';
1097  print '<input name="duration_value" size="4" value="'.GETPOST('duration_value', 'int').'">';
1098  print $formproduct->selectMeasuringUnits("duration_unit", "time", GETPOST('duration_value', 'alpha'), 0, 1);
1099  print '</td></tr>';
1100  }
1101 
1102  if ($type != 1) // Nature, Weight and volume only applies to products and not to services
1103  {
1104  // Nature
1105  print '<tr><td>'.$form->textwithpicto($langs->trans("NatureOfProductShort"), $langs->trans("NatureOfProductDesc")).'</td><td colspan="3">';
1106  $statutarray = array('1' => $langs->trans("Finished"), '0' => $langs->trans("RowMaterial"));
1107  print $form->selectarray('finished', $statutarray, GETPOST('finished', 'alpha'), 1);
1108  print '</td></tr>';
1109 
1110  // Brut Weight
1111  print '<tr><td>'.$langs->trans("Weight").'</td><td colspan="3">';
1112  print '<input name="weight" size="4" value="'.GETPOST('weight').'">';
1113  print $formproduct->selectMeasuringUnits("weight_units", "weight", GETPOSTISSET('weight_units') ?GETPOST('weight_units', 'alpha') : (empty($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? 0 : $conf->global->MAIN_WEIGHT_DEFAULT_UNIT), 0, 2);
1114  print '</td></tr>';
1115 
1116  // Brut Length
1117  if (empty($conf->global->PRODUCT_DISABLE_SIZE))
1118  {
1119  print '<tr><td>'.$langs->trans("Length").' x '.$langs->trans("Width").' x '.$langs->trans("Height").'</td><td colspan="3">';
1120  print '<input name="size" class="width50" value="'.GETPOST('size').'"> x ';
1121  print '<input name="sizewidth" class="width50" value="'.GETPOST('sizewidth').'"> x ';
1122  print '<input name="sizeheight" class="width50" value="'.GETPOST('sizeheight').'">';
1123  print $formproduct->selectMeasuringUnits("size_units", "size", GETPOSTISSET('size_units') ?GETPOST('size_units', 'alpha') : '0', 0, 2);
1124  print '</td></tr>';
1125  }
1126  if (empty($conf->global->PRODUCT_DISABLE_SURFACE))
1127  {
1128  // Brut Surface
1129  print '<tr><td>'.$langs->trans("Surface").'</td><td colspan="3">';
1130  print '<input name="surface" size="4" value="'.GETPOST('surface').'">';
1131  print $formproduct->selectMeasuringUnits("surface_units", "surface", GETPOSTISSET('surface_units') ?GETPOST('surface_units', 'alpha') : '0', 0, 2);
1132  print '</td></tr>';
1133  }
1134  if (empty($conf->global->PRODUCT_DISABLE_VOLUME))
1135  {
1136  // Brut Volume
1137  print '<tr><td>'.$langs->trans("Volume").'</td><td colspan="3">';
1138  print '<input name="volume" size="4" value="'.GETPOST('volume').'">';
1139  print $formproduct->selectMeasuringUnits("volume_units", "volume", GETPOSTISSET('volume_units') ?GETPOST('volume_units', 'alpha') : '0', 0, 2);
1140  print '</td></tr>';
1141  }
1142 
1143  if (!empty($conf->global->PRODUCT_ADD_NET_MEASURE))
1144  {
1145  // Net Measure
1146  print '<tr><td>'.$langs->trans("NetMeasure").'</td><td colspan="3">';
1147  print '<input name="net_measure" size="4" value="'.GETPOST('net_measure').'">';
1148  print $formproduct->selectMeasuringUnits("net_measure_units", '', GETPOSTISSET('net_measure_units') ?GETPOST('net_measure_units', 'alpha') : (empty($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? 0 : $conf->global->MAIN_WEIGHT_DEFAULT_UNIT), 0, 0);
1149  print '</td></tr>';
1150  }
1151  }
1152 
1153  // Units
1154  if (!empty($conf->global->PRODUCT_USE_UNITS))
1155  {
1156  print '<tr><td>'.$langs->trans('DefaultUnitToShow').'</td>';
1157  print '<td colspan="3">';
1158  print $form->selectUnits(empty($line->fk_unit) ? $conf->global->PRODUCT_USE_UNITS : $line->fk_unit, 'units');
1159  print '</td></tr>';
1160  }
1161 
1162  // Custom code
1163  if (empty($conf->global->PRODUCT_DISABLE_CUSTOM_INFO) && empty($type))
1164  {
1165  print '<tr><td>'.$langs->trans("CustomCode").'</td><td><input name="customcode" class="maxwidth100onsmartphone" value="'.GETPOST('customcode').'"></td></tr>';
1166 
1167  // Origin country
1168  print '<td>'.$langs->trans("CountryOrigin").'</td>';
1169  print '<td>';
1170  print img_picto('', 'globe-americas', 'class="paddingrightonly"');
1171  print $form->select_country((GETPOSTISSET('country_id') ? GETPOST('country_id') : $object->country_id), 'country_id', '', 0, 'minwidth300 widthcentpercentminusx');
1172  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1173  print '</td>';
1174 
1175  // State
1176  if (empty($conf->global->PRODUCT_DISABLE_STATE))
1177  {
1178  if ($conf->browser->layout == 'phone') print '</tr><tr>';
1179  if (!empty($conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT) && ($conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT == 1 || $conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT == 2))
1180  {
1181  print '<td>'.$form->editfieldkey('RegionStateOrigin', 'state_id', '', $object, 0).'</td><td colspan="3">';
1182  } else {
1183  print '<td>'.$form->editfieldkey('StateOrigin', 'state_id', '', $object, 0).'</td><td colspan="3">';
1184  }
1185 
1186  print $formcompany->select_state($object->state_id, $object->country_code);
1187  print '</tr>';
1188  }
1189 
1190  print '</tr>';
1191  }
1192 
1193  // Other attributes
1194  $parameters = array('colspan' => 3, 'cols' => '3');
1195  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1196  print $hookmanager->resPrint;
1197  if (empty($reshook))
1198  {
1199  print $object->showOptionals($extrafields, 'edit', $parameters);
1200  }
1201 
1202  // Note (private, no output on invoices, propales...)
1203  //if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB)) available in create mode
1204  //{
1205  print '<tr><td class="tdtop">'.$langs->trans("NoteNotVisibleOnBill").'</td><td colspan="3">';
1206 
1207  // We use dolibarr_details as type of DolEditor here, because we must not accept images as description is included into PDF and not accepted by TCPDF.
1208  $doleditor = new DolEditor('note_private', GETPOST('note_private', 'restricthtml'), '', 140, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_8, '90%');
1209  $doleditor->Create();
1210 
1211  print "</td></tr>";
1212  //}
1213 
1214  if ($conf->categorie->enabled) {
1215  // Categories
1216  print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
1217  $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', 'parent', 64, 0, 1);
1218  print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
1219  print "</td></tr>";
1220  }
1221 
1222  print '</table>';
1223 
1224  print '<hr>';
1225 
1226  if (!empty($conf->global->PRODUIT_MULTIPRICES))
1227  {
1228  // We do no show price array on create when multiprices enabled.
1229  // We must set them on prices tab.
1230  print '<table class="border centpercent">';
1231  // VAT
1232  print '<tr><td class="titlefieldcreate">'.$langs->trans("VATRate").'</td><td>';
1233  $defaultva = get_default_tva($mysoc, $mysoc);
1234  print $form->load_tva("tva_tx", $defaultva, $mysoc, $mysoc, 0, 0, '', false, 1);
1235  print '</td></tr>';
1236  print '</table>';
1237 
1238  print '<br>';
1239  } else {
1240  print '<table class="border centpercent">';
1241 
1242  // Price
1243  print '<tr><td class="titlefieldcreate">'.$langs->trans("SellingPrice").'</td>';
1244  print '<td><input name="price" class="maxwidth50" value="'.$object->price.'">';
1245  print $form->selectPriceBaseType($conf->global->PRODUCT_PRICE_BASE_TYPE, "price_base_type");
1246  print '</td></tr>';
1247 
1248  // Min price
1249  print '<tr><td>'.$langs->trans("MinPrice").'</td>';
1250  print '<td><input name="price_min" class="maxwidth50" value="'.$object->price_min.'">';
1251  print '</td></tr>';
1252 
1253  // VAT
1254  print '<tr><td>'.$langs->trans("VATRate").'</td><td>';
1255  $defaultva = get_default_tva($mysoc, $mysoc);
1256  print $form->load_tva("tva_tx", $defaultva, $mysoc, $mysoc, 0, 0, '', false, 1);
1257  print '</td></tr>';
1258 
1259  print '</table>';
1260 
1261  print '<br>';
1262  }
1263 
1264  // Accountancy codes
1265  print '<table class="border centpercent">';
1266 
1267  if (!empty($conf->accounting->enabled))
1268  {
1269  // Accountancy_code_sell
1270  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellCode").'</td>';
1271  print '<td>';
1272  if ($type == 0) {
1273  $accountancy_code_sell = (GETPOSTISSET('accountancy_code_sell') ? GETPOST('accountancy_code_sell', 'alpha') : $conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT);
1274  } else {
1275  $accountancy_code_sell = (GETPOSTISSET('accountancy_code_sell') ? GETPOST('accountancy_code_sell', 'alpha') : $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT);
1276  }
1277  print $formaccounting->select_account($accountancy_code_sell, 'accountancy_code_sell', 1, null, 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1);
1278  print '</td></tr>';
1279 
1280  // Accountancy_code_sell_intra
1281  if ($mysoc->isInEEC())
1282  {
1283  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellIntraCode").'</td>';
1284  print '<td>';
1285  if ($type == 0) {
1286  $accountancy_code_sell_intra = (GETPOSTISSET('accountancy_code_sell_intra') ? GETPOST('accountancy_code_sell_intra', 'alpha') : $conf->global->ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT);
1287  } else {
1288  $accountancy_code_sell_intra = (GETPOSTISSET('accountancy_code_sell_intra') ? GETPOST('accountancy_code_sell_intra', 'alpha') : $conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT);
1289  }
1290  print $formaccounting->select_account($accountancy_code_sell_intra, 'accountancy_code_sell_intra', 1, null, 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1);
1291  print '</td></tr>';
1292  }
1293 
1294  // Accountancy_code_sell_export
1295  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellExportCode").'</td>';
1296  print '<td>';
1297  if ($type == 0)
1298  {
1299  $accountancy_code_sell_export = (GETPOST('accountancy_code_sell_export') ? GETPOST('accountancy_code_sell_export', 'alpha') : $conf->global->ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT);
1300  } else {
1301  $accountancy_code_sell_export = (GETPOST('accountancy_code_sell_export') ? GETPOST('accountancy_code_sell_export', 'alpha') : $conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT);
1302  }
1303  print $formaccounting->select_account($accountancy_code_sell_export, 'accountancy_code_sell_export', 1, null, 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1);
1304  print '</td></tr>';
1305 
1306  // Accountancy_code_buy
1307  print '<tr><td>'.$langs->trans("ProductAccountancyBuyCode").'</td>';
1308  print '<td>';
1309  if ($type == 0) {
1310  $accountancy_code_buy = (GETPOST('accountancy_code_buy', 'alpha') ? (GETPOST('accountancy_code_buy', 'alpha')) : $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT);
1311  } else {
1312  $accountancy_code_buy = (GETPOST('accountancy_code_buy', 'alpha') ? (GETPOST('accountancy_code_buy', 'alpha')) : $conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT);
1313  }
1314  print $formaccounting->select_account($accountancy_code_buy, 'accountancy_code_buy', 1, null, 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1);
1315  print '</td></tr>';
1316 
1317  // Accountancy_code_buy_intra
1318  if ($mysoc->isInEEC())
1319  {
1320  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyIntraCode").'</td>';
1321  print '<td>';
1322  if ($type == 0) {
1323  $accountancy_code_buy_intra = (GETPOSTISSET('accountancy_code_buy_intra') ? GETPOST('accountancy_code_buy_intra', 'alpha') : $conf->global->ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT);
1324  } else {
1325  $accountancy_code_buy_intra = (GETPOSTISSET('accountancy_code_buy_intra') ? GETPOST('accountancy_code_buy_intra', 'alpha') : $conf->global->ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT);
1326  }
1327  print $formaccounting->select_account($accountancy_code_buy_intra, 'accountancy_code_buy_intra', 1, null, 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1);
1328  print '</td></tr>';
1329  }
1330 
1331  // Accountancy_code_buy_export
1332  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyExportCode").'</td>';
1333  print '<td>';
1334  if ($type == 0)
1335  {
1336  $accountancy_code_buy_export = (GETPOST('accountancy_code_buy_export') ? GETPOST('accountancy_code_buy_export', 'alpha') : $conf->global->ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT);
1337  } else {
1338  $accountancy_code_buy_export = (GETPOST('accountancy_code_buy_export') ? GETPOST('accountancy_code_buy_export', 'alpha') : $conf->global->ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT);
1339  }
1340  print $formaccounting->select_account($accountancy_code_buy_export, 'accountancy_code_buy_export', 1, null, 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1);
1341  print '</td></tr>';
1342  } else // For external software
1343  {
1344  if (!empty($accountancy_code_sell)) { $object->accountancy_code_sell = $accountancy_code_sell; }
1345  if (!empty($accountancy_code_sell_intra)) { $object->accountancy_code_sell_intra = $accountancy_code_sell_intra; }
1346  if (!empty($accountancy_code_sell_export)) { $object->accountancy_code_sell_export = $accountancy_code_sell_export; }
1347  if (!empty($accountancy_code_buy)) { $object->accountancy_code_buy = $accountancy_code_buy; }
1348  if (!empty($accountancy_code_buy_intra)) { $object->accountancy_code_buy_intra = $accountancy_code_buy_intra; }
1349  if (!empty($accountancy_code_buy_export)) { $object->accountancy_code_buy_export = $accountancy_code_buy_export; }
1350 
1351  // Accountancy_code_sell
1352  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellCode").'</td>';
1353  print '<td class="maxwidthonsmartphone"><input class="minwidth100" name="accountancy_code_sell" value="'.$object->accountancy_code_sell.'">';
1354  print '</td></tr>';
1355 
1356  // Accountancy_code_sell_intra
1357  if ($mysoc->isInEEC())
1358  {
1359  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellIntraCode").'</td>';
1360  print '<td class="maxwidthonsmartphone"><input class="minwidth100" name="accountancy_code_sell_intra" value="'.$object->accountancy_code_sell_intra.'">';
1361  print '</td></tr>';
1362  }
1363 
1364  // Accountancy_code_sell_export
1365  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellExportCode").'</td>';
1366  print '<td class="maxwidthonsmartphone"><input class="minwidth100" name="accountancy_code_sell_export" value="'.$object->accountancy_code_sell_export.'">';
1367  print '</td></tr>';
1368 
1369  // Accountancy_code_buy
1370  print '<tr><td>'.$langs->trans("ProductAccountancyBuyCode").'</td>';
1371  print '<td class="maxwidthonsmartphone"><input class="minwidth100" name="accountancy_code_buy" value="'.$object->accountancy_code_buy.'">';
1372  print '</td></tr>';
1373 
1374  // Accountancy_code_buy_intra
1375  if ($mysoc->isInEEC())
1376  {
1377  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyIntraCode").'</td>';
1378  print '<td class="maxwidthonsmartphone"><input class="minwidth100" name="accountancy_code_buy_intra" value="'.$object->accountancy_code_buy_intra.'">';
1379  print '</td></tr>';
1380  }
1381 
1382  // Accountancy_code_buy_export
1383  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyExportCode").'</td>';
1384  print '<td class="maxwidthonsmartphone"><input class="minwidth100" name="accountancy_code_buy_export" value="'.$object->accountancy_code_buy_export.'">';
1385  print '</td></tr>';
1386  }
1387  print '</table>';
1388 
1389  print dol_get_fiche_end();
1390 
1391  print '<div class="center">';
1392  print '<input type="submit" class="button" value="'.$langs->trans("Create").'">';
1393  print ' &nbsp; &nbsp; ';
1394  print '<input type="button" class="button button-cancel" value="'.$langs->trans("Cancel").'" onClick="javascript:history.go(-1)">';
1395  print '</div>';
1396 
1397  print '</form>';
1398  } elseif ($object->id > 0) {
1399  /*
1400  * Product card
1401  */
1402  // Fiche en mode edition
1403  if ($action == 'edit' && $usercancreate)
1404  {
1405  //WYSIWYG Editor
1406  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1407 
1408  print '<script type="text/javascript">';
1409  print '$(document).ready(function () {
1410  $("#selectcountry_id").change(function () {
1411  document.formprod.action.value="edit";
1412  document.formprod.submit();
1413  });
1414  });';
1415  print '</script>'."\n";
1416 
1417  // We set country_id, country_code and country for the selected country
1418  $object->country_id = GETPOST('country_id') ? GETPOST('country_id') : $object->country_id;
1419  if ($object->country_id)
1420  {
1421  $tmparray = getCountry($object->country_id, 'all');
1422  $object->country_code = $tmparray['code'];
1423  $object->country = $tmparray['label'];
1424  }
1425 
1426 
1427  $type = $langs->trans('Product');
1428  if ($object->isService()) $type = $langs->trans('Service');
1429  //print load_fiche_titre($langs->trans('Modify').' '.$type.' : '.(is_object($object->oldcopy)?$object->oldcopy->ref:$object->ref), "");
1430 
1431  // Main official, simple, and not duplicated code
1432  print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="POST" name="formprod">'."\n";
1433  print '<input type="hidden" name="token" value="'.newToken().'">';
1434  print '<input type="hidden" name="action" value="update">';
1435  print '<input type="hidden" name="id" value="'.$object->id.'">';
1436  print '<input type="hidden" name="canvas" value="'.$object->canvas.'">';
1437 
1438  $head = product_prepare_head($object);
1439  $titre = $langs->trans("CardProduct".$object->type);
1440  $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
1441  print dol_get_fiche_head($head, 'card', $titre, 0, $picto);
1442 
1443 
1444  print '<table class="border allwidth">';
1445 
1446  // Ref
1447  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Ref").'</td><td colspan="3"><input name="ref" class="maxwidth200" maxlength="128" value="'.dol_escape_htmltag($object->ref).'"></td></tr>';
1448 
1449  // Label
1450  print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td colspan="3"><input name="label" class="minwidth300 maxwidth400onsmartphone" maxlength="255" value="'.dol_escape_htmltag($object->label).'"></td></tr>';
1451 
1452  // Status To sell
1453  print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Sell").')</td><td colspan="3">';
1454  print '<select class="flat" name="statut">';
1455  if ($object->status)
1456  {
1457  print '<option value="1" selected>'.$langs->trans("OnSell").'</option>';
1458  print '<option value="0">'.$langs->trans("NotOnSell").'</option>';
1459  } else {
1460  print '<option value="1">'.$langs->trans("OnSell").'</option>';
1461  print '<option value="0" selected>'.$langs->trans("NotOnSell").'</option>';
1462  }
1463  print '</select>';
1464  print '</td></tr>';
1465 
1466  // Status To Buy
1467  print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Buy").')</td><td colspan="3">';
1468  print '<select class="flat" name="statut_buy">';
1469  if ($object->status_buy)
1470  {
1471  print '<option value="1" selected>'.$langs->trans("ProductStatusOnBuy").'</option>';
1472  print '<option value="0">'.$langs->trans("ProductStatusNotOnBuy").'</option>';
1473  } else {
1474  print '<option value="1">'.$langs->trans("ProductStatusOnBuy").'</option>';
1475  print '<option value="0" selected>'.$langs->trans("ProductStatusNotOnBuy").'</option>';
1476  }
1477  print '</select>';
1478  print '</td></tr>';
1479 
1480  // Batch number managment
1481  if ($conf->productbatch->enabled)
1482  {
1483  if ($object->isProduct() || !empty($conf->global->STOCK_SUPPORTS_SERVICES))
1484  {
1485  print '<tr><td>'.$langs->trans("ManageLotSerial").'</td><td colspan="3">';
1486  $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"));
1487  print $form->selectarray('status_batch', $statutarray, $object->status_batch);
1488  print '</td></tr>';
1489  }
1490  }
1491 
1492  // Barcode
1493  $showbarcode = empty($conf->barcode->enabled) ? 0 : 1;
1494  if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode = 0;
1495 
1496  if ($showbarcode)
1497  {
1498  print '<tr><td>'.$langs->trans('BarcodeType').'</td><td>';
1499  if (GETPOSTISSET('fk_barcode_type')) {
1500  $fk_barcode_type = GETPOST('fk_barcode_type');
1501  } else {
1502  $fk_barcode_type = $object->barcode_type;
1503  if (empty($fk_barcode_type) && !empty($conf->global->PRODUIT_DEFAULT_BARCODE_TYPE)) $fk_barcode_type = $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE;
1504  }
1505  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbarcode.class.php';
1506  $formbarcode = new FormBarCode($db);
1507  print $formbarcode->selectBarcodeType($fk_barcode_type, 'fk_barcode_type', 1);
1508  print '</td><td>'.$langs->trans("BarcodeValue").'</td><td>';
1509  $tmpcode = GETPOSTISSET('barcode') ? GETPOST('barcode') : $object->barcode;
1510  if (empty($tmpcode) && !empty($modBarCodeProduct->code_auto)) $tmpcode = $modBarCodeProduct->getNextValue($object, $type);
1511  print '<input size="40" class="maxwidthonsmartphone" type="text" name="barcode" value="'.dol_escape_htmltag($tmpcode).'">';
1512  print '</td></tr>';
1513  }
1514 
1515  // Description (used in invoice, propal...)
1516  print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
1517 
1518  // We use dolibarr_details as type of DolEditor here, because we must not accept images as description is included into PDF and not accepted by TCPDF.
1519  $doleditor = new DolEditor('desc', $object->description, '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '90%');
1520  $doleditor->Create();
1521 
1522  print "</td></tr>";
1523  print "\n";
1524 
1525  // Public Url
1526  print '<tr><td>'.$langs->trans("PublicUrl").'</td><td colspan="3">';
1527  print '<input type="text" name="url" class="quatrevingtpercent" value="'.$object->url.'">';
1528  print '</td></tr>';
1529 
1530  // Stock
1531  if ($object->isProduct() && !empty($conf->stock->enabled))
1532  {
1533  // Default warehouse
1534  print '<tr><td>'.$langs->trans("DefaultWarehouse").'</td><td>';
1535  print $formproduct->selectWarehouses($object->fk_default_warehouse, 'fk_default_warehouse', 'warehouseopen', 1);
1536  print ' <a href="'.DOL_URL_ROOT.'/product/stock/card.php?action=create&amp;backtopage='.urlencode($_SERVER['PHP_SELF'].'?action=create&type='.GETPOST('type', 'int')).'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddWarehouse").'"></span></a>';
1537  print '</td>';
1538  /*
1539  print "<tr>".'<td>'.$langs->trans("StockLimit").'</td><td>';
1540  print '<input name="seuil_stock_alerte" size="4" value="'.$object->seuil_stock_alerte.'">';
1541  print '</td>';
1542 
1543  print '<td>'.$langs->trans("DesiredStock").'</td><td>';
1544  print '<input name="desiredstock" size="4" value="'.$object->desiredstock.'">';
1545  print '</td></tr>';
1546  */
1547  }
1548  /*
1549  else
1550  {
1551  print '<input name="seuil_stock_alerte" type="hidden" value="'.$object->seuil_stock_alerte.'">';
1552  print '<input name="desiredstock" type="hidden" value="'.$object->desiredstock.'">';
1553  }*/
1554 
1555  if ($object->isService())
1556  {
1557  // Duration
1558  print '<tr><td>'.$langs->trans("Duration").'</td><td colspan="3">';
1559  print '<input name="duration_value" size="5" value="'.$object->duration_value.'"> ';
1560  print $formproduct->selectMeasuringUnits("duration_unit", "time", $object->duration_unit, 0, 1);
1561  print '</td></tr>';
1562  } else {
1563  // Nature
1564  print '<tr><td>'.$form->textwithpicto($langs->trans("NatureOfProductShort"), $langs->trans("NatureOfProductDesc")).'</td><td colspan="3">';
1565  print $formproduct->selectProductNature('finished', $object->finished);
1566  print '</td></tr>';
1567 
1568  // Brut Weight
1569  print '<tr><td>'.$langs->trans("Weight").'</td><td colspan="3">';
1570  print '<input name="weight" size="5" value="'.$object->weight.'"> ';
1571  print $formproduct->selectMeasuringUnits("weight_units", "weight", $object->weight_units, 0, 2);
1572  print '</td></tr>';
1573 
1574  if (empty($conf->global->PRODUCT_DISABLE_SIZE))
1575  {
1576  // Brut Length
1577  print '<tr><td>'.$langs->trans("Length").' x '.$langs->trans("Width").' x '.$langs->trans("Height").'</td><td colspan="3">';
1578  print '<input name="size" size="5" value="'.$object->length.'">x';
1579  print '<input name="sizewidth" size="5" value="'.$object->width.'">x';
1580  print '<input name="sizeheight" size="5" value="'.$object->height.'"> ';
1581  print $formproduct->selectMeasuringUnits("size_units", "size", $object->length_units, 0, 2);
1582  print '</td></tr>';
1583  }
1584  if (empty($conf->global->PRODUCT_DISABLE_SURFACE))
1585  {
1586  // Brut Surface
1587  print '<tr><td>'.$langs->trans("Surface").'</td><td colspan="3">';
1588  print '<input name="surface" size="5" value="'.$object->surface.'"> ';
1589  print $formproduct->selectMeasuringUnits("surface_units", "surface", $object->surface_units, 0, 2);
1590  print '</td></tr>';
1591  }
1592  if (empty($conf->global->PRODUCT_DISABLE_VOLUME))
1593  {
1594  // Brut Volume
1595  print '<tr><td>'.$langs->trans("Volume").'</td><td colspan="3">';
1596  print '<input name="volume" size="5" value="'.$object->volume.'"> ';
1597  print $formproduct->selectMeasuringUnits("volume_units", "volume", $object->volume_units, 0, 2);
1598  print '</td></tr>';
1599  }
1600 
1601  if (!empty($conf->global->PRODUCT_ADD_NET_MEASURE))
1602  {
1603  // Net Measure
1604  print '<tr><td>'.$langs->trans("NetMeasure").'</td><td colspan="3">';
1605  print '<input name="net_measure" size="5" value="'.$object->net_measure.'"> ';
1606  print $formproduct->selectMeasuringUnits("net_measure_units", "", $object->net_measure_units, 0, 0);
1607  print '</td></tr>';
1608  }
1609  }
1610  // Units
1611  if (!empty($conf->global->PRODUCT_USE_UNITS))
1612  {
1613  print '<tr><td>'.$langs->trans('DefaultUnitToShow').'</td>';
1614  print '<td colspan="3">';
1615  print $form->selectUnits($object->fk_unit, 'units');
1616  print '</td></tr>';
1617  }
1618 
1619  // Custom code
1620  if (!$object->isService() && empty($conf->global->PRODUCT_DISABLE_CUSTOM_INFO))
1621  {
1622  print '<tr><td>'.$langs->trans("CustomCode").'</td><td><input name="customcode" class="maxwidth100onsmartphone" value="'.$object->customcode.'"></td></tr>';
1623  // Origin country
1624  print '<td>'.$langs->trans("CountryOrigin").'</td>';
1625  print '<td>';
1626  print img_picto('', 'globe-americas', 'class="paddingrightonly"');
1627  print $form->select_country($object->country_id, 'country_id', '', 0, 'minwidth100 maxwidthonsmartphone');
1628  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1629  print '</td>';
1630  // State
1631  if (empty($conf->global->PRODUCT_DISABLE_STATE))
1632  {
1633  if ($conf->browser->layout == 'phone') print '</tr><tr>';
1634  if (!empty($conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT) && ($conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT == 1 || $conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT == 2))
1635  {
1636  print '<td>'.$form->editfieldkey('RegionStateOrigin', 'state_id', '', $object, 0).'</td><td colspan="3">';
1637  } else {
1638  print '<td>'.$form->editfieldkey('StateOrigin', 'state_id', '', $object, 0).'</td><td colspan="3">';
1639  }
1640 
1641  print $formcompany->select_state($object->state_id, $object->country_code);
1642  print '</td>';
1643  }
1644  print '</tr>';
1645  }
1646 
1647  // Other attributes
1648  $parameters = array('colspan' => ' colspan="3"', 'cols' => 3);
1649  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1650  print $hookmanager->resPrint;
1651  if (empty($reshook))
1652  {
1653  print $object->showOptionals($extrafields, 'edit', $parameters);
1654  }
1655 
1656  // Tags-Categories
1657  if ($conf->categorie->enabled)
1658  {
1659  print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
1660  $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', 'parent', 64, 0, 1);
1661  $c = new Categorie($db);
1662  $cats = $c->containing($object->id, Categorie::TYPE_PRODUCT);
1663  $arrayselected = array();
1664  if (is_array($cats)) {
1665  foreach ($cats as $cat) {
1666  $arrayselected[] = $cat->id;
1667  }
1668  }
1669  print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
1670  print "</td></tr>";
1671  }
1672 
1673  // Note private
1674  if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB))
1675  {
1676  print '<tr><td class="tdtop">'.$langs->trans("NoteNotVisibleOnBill").'</td><td colspan="3">';
1677 
1678  $doleditor = new DolEditor('note_private', $object->note_private, '', 140, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, ROWS_4, '90%');
1679  $doleditor->Create();
1680 
1681  print "</td></tr>";
1682  }
1683 
1684  print '</table>';
1685 
1686  print '<br>';
1687 
1688  print '<table class="border centpercent">';
1689 
1690  if (!empty($conf->accounting->enabled))
1691  {
1692  // Accountancy_code_sell
1693  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellCode").'</td>';
1694  print '<td>';
1695  print $formaccounting->select_account($object->accountancy_code_sell, 'accountancy_code_sell', 1, '', 1, 1);
1696  print '</td></tr>';
1697 
1698  // Accountancy_code_sell_intra
1699  if ($mysoc->isInEEC())
1700  {
1701  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellIntraCode").'</td>';
1702  print '<td>';
1703  print $formaccounting->select_account($object->accountancy_code_sell_intra, 'accountancy_code_sell_intra', 1, '', 1, 1);
1704  print '</td></tr>';
1705  }
1706 
1707  // Accountancy_code_sell_export
1708  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellExportCode").'</td>';
1709  print '<td>';
1710  print $formaccounting->select_account($object->accountancy_code_sell_export, 'accountancy_code_sell_export', 1, '', 1, 1);
1711  print '</td></tr>';
1712 
1713  // Accountancy_code_buy
1714  print '<tr><td>'.$langs->trans("ProductAccountancyBuyCode").'</td>';
1715  print '<td>';
1716  print $formaccounting->select_account($object->accountancy_code_buy, 'accountancy_code_buy', 1, '', 1, 1);
1717  print '</td></tr>';
1718 
1719  // Accountancy_code_buy_intra
1720  if ($mysoc->isInEEC())
1721  {
1722  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyIntraCode").'</td>';
1723  print '<td>';
1724  print $formaccounting->select_account($object->accountancy_code_buy_intra, 'accountancy_code_buy_intra', 1, '', 1, 1);
1725  print '</td></tr>';
1726  }
1727 
1728  // Accountancy_code_buy_export
1729  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyExportCode").'</td>';
1730  print '<td>';
1731  print $formaccounting->select_account($object->accountancy_code_buy_export, 'accountancy_code_buy_export', 1, '', 1, 1);
1732  print '</td></tr>';
1733  } else {
1734  // For external software
1735  // Accountancy_code_sell
1736  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellCode").'</td>';
1737  print '<td><input name="accountancy_code_sell" class="maxwidth200" value="'.$object->accountancy_code_sell.'">';
1738  print '</td></tr>';
1739 
1740  // Accountancy_code_sell_intra
1741  if ($mysoc->isInEEC())
1742  {
1743  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellIntraCode").'</td>';
1744  print '<td><input name="accountancy_code_sell_intra" class="maxwidth200" value="'.$object->accountancy_code_sell_intra.'">';
1745  print '</td></tr>';
1746  }
1747 
1748  // Accountancy_code_sell_export
1749  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancySellExportCode").'</td>';
1750  print '<td><input name="accountancy_code_sell_export" class="maxwidth200" value="'.$object->accountancy_code_sell_export.'">';
1751  print '</td></tr>';
1752 
1753  // Accountancy_code_buy
1754  print '<tr><td>'.$langs->trans("ProductAccountancyBuyCode").'</td>';
1755  print '<td><input name="accountancy_code_buy" class="maxwidth200" value="'.$object->accountancy_code_buy.'">';
1756  print '</td></tr>';
1757 
1758  // Accountancy_code_buy_intra
1759  if ($mysoc->isInEEC())
1760  {
1761  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyIntraCode").'</td>';
1762  print '<td><input name="accountancy_code_buy_intra" class="maxwidth200" value="'.$object->accountancy_code_buy_intra.'">';
1763  print '</td></tr>';
1764  }
1765 
1766  // Accountancy_code_buy_export
1767  print '<tr><td class="titlefieldcreate">'.$langs->trans("ProductAccountancyBuyExportCode").'</td>';
1768  print '<td><input name="accountancy_code_buy_export" class="maxwidth200" value="'.$object->accountancy_code_buy_export.'">';
1769  print '</td></tr>';
1770  }
1771  print '</table>';
1772 
1773  print dol_get_fiche_end();
1774 
1775  print '<div class="center">';
1776  print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
1777  print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
1778  print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1779  print '</div>';
1780 
1781  print '</form>';
1782  } else {
1783  // Fiche en mode visu
1784  $showbarcode = empty($conf->barcode->enabled) ? 0 : 1;
1785  if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode = 0;
1786 
1787  $head = product_prepare_head($object);
1788  $titre = $langs->trans("CardProduct".$object->type);
1789  $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
1790 
1791  print dol_get_fiche_head($head, 'card', $titre, -1, $picto);
1792 
1793  $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1&type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
1794  $object->next_prev_filter = " fk_product_type = ".$object->type;
1795 
1796  $shownav = 1;
1797  if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) $shownav = 0;
1798 
1799  dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
1800 
1801 
1802  print '<div class="fichecenter">';
1803  print '<div class="fichehalfleft">';
1804 
1805  print '<div class="underbanner clearboth"></div>';
1806  print '<table class="border tableforfield" width="100%">';
1807 
1808  // Type
1809  if (!empty($conf->product->enabled) && !empty($conf->service->enabled))
1810  {
1811  // TODO change for compatibility with edit in place
1812  $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
1813  print '<tr><td class="titlefield">';
1814  print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type');
1815  print '</td><td colspan="2">';
1816  print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat);
1817  print '</td></tr>';
1818  }
1819 
1820  if ($showbarcode)
1821  {
1822  // Barcode type
1823  print '<tr><td class="nowrap">';
1824  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1825  print $langs->trans("BarcodeType");
1826  print '</td>';
1827  if (($action != 'editbarcodetype') && $usercancreate && $createbarcode) print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editbarcodetype&amp;id='.$object->id.'">'.img_edit($langs->trans('Edit'), 1).'</a></td>';
1828  print '</tr></table>';
1829  print '</td><td colspan="2">';
1830  if ($action == 'editbarcodetype' || $action == 'editbarcode')
1831  {
1832  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbarcode.class.php';
1833  $formbarcode = new FormBarCode($db);
1834  }
1835  if ($action == 'editbarcodetype')
1836  {
1837  print $formbarcode->formBarcodeType($_SERVER['PHP_SELF'].'?id='.$object->id, $object->barcode_type, 'fk_barcode_type');
1838  } else {
1839  $object->fetch_barcode();
1840  print $object->barcode_type_label ? $object->barcode_type_label : ($object->barcode ? '<div class="warning">'.$langs->trans("SetDefaultBarcodeType").'<div>' : '');
1841  }
1842  print '</td></tr>'."\n";
1843 
1844  // Barcode value
1845  print '<tr><td class="nowrap">';
1846  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1847  print $langs->trans("BarcodeValue");
1848  print '</td>';
1849  if (($action != 'editbarcode') && $usercancreate && $createbarcode) print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editbarcode&amp;id='.$object->id.'">'.img_edit($langs->trans('Edit'), 1).'</a></td>';
1850  print '</tr></table>';
1851  print '</td><td colspan="2">';
1852  if ($action == 'editbarcode')
1853  {
1854  $tmpcode = GETPOSTISSET('barcode') ? GETPOST('barcode') : $object->barcode;
1855  if (empty($tmpcode) && !empty($modBarCodeProduct->code_auto)) $tmpcode = $modBarCodeProduct->getNextValue($object, $type);
1856 
1857  print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
1858  print '<input type="hidden" name="token" value="'.newToken().'">';
1859  print '<input type="hidden" name="action" value="setbarcode">';
1860  print '<input type="hidden" name="barcode_type_code" value="'.$object->barcode_type_code.'">';
1861  print '<input size="40" class="maxwidthonsmartphone" type="text" name="barcode" value="'.$tmpcode.'">';
1862  print '&nbsp;<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
1863  print '</form>';
1864  } else {
1865  print $object->barcode;
1866  }
1867  print '</td></tr>'."\n";
1868  }
1869 
1870  // Accountancy sell code
1871  print '<tr><td class="nowrap">';
1872  print $langs->trans("ProductAccountancySellCode");
1873  print '</td><td colspan="2">';
1874  if (!empty($conf->accounting->enabled))
1875  {
1876  if (!empty($object->accountancy_code_sell))
1877  {
1878  $accountingaccount = new AccountingAccount($db);
1879  $accountingaccount->fetch('', $object->accountancy_code_sell, 1);
1880 
1881  print $accountingaccount->getNomUrl(0, 1, 1, '', 1);
1882  }
1883  } else {
1884  print $object->accountancy_code_sell;
1885  }
1886  print '</td></tr>';
1887 
1888  // Accountancy sell code intra-community
1889  if ($mysoc->isInEEC())
1890  {
1891  print '<tr><td class="nowrap">';
1892  print $langs->trans("ProductAccountancySellIntraCode");
1893  print '</td><td colspan="2">';
1894  if (!empty($conf->accounting->enabled))
1895  {
1896  if (!empty($object->accountancy_code_sell_intra))
1897  {
1898  $accountingaccount2 = new AccountingAccount($db);
1899  $accountingaccount2->fetch('', $object->accountancy_code_sell_intra, 1);
1900 
1901  print $accountingaccount2->getNomUrl(0, 1, 1, '', 1);
1902  }
1903  } else {
1904  print $object->accountancy_code_sell_intra;
1905  }
1906  print '</td></tr>';
1907  }
1908 
1909  // Accountancy sell code export
1910  print '<tr><td class="nowrap">';
1911  print $langs->trans("ProductAccountancySellExportCode");
1912  print '</td><td colspan="2">';
1913  if (!empty($conf->accounting->enabled))
1914  {
1915  if (!empty($object->accountancy_code_sell_export))
1916  {
1917  $accountingaccount3 = new AccountingAccount($db);
1918  $accountingaccount3->fetch('', $object->accountancy_code_sell_export, 1);
1919 
1920  print $accountingaccount3->getNomUrl(0, 1, 1, '', 1);
1921  }
1922  } else {
1923  print $object->accountancy_code_sell_export;
1924  }
1925  print '</td></tr>';
1926 
1927  // Accountancy buy code
1928  print '<tr><td class="nowrap">';
1929  print $langs->trans("ProductAccountancyBuyCode");
1930  print '</td><td colspan="2">';
1931  if (!empty($conf->accounting->enabled))
1932  {
1933  if (!empty($object->accountancy_code_buy))
1934  {
1935  $accountingaccount4 = new AccountingAccount($db);
1936  $accountingaccount4->fetch('', $object->accountancy_code_buy, 1);
1937 
1938  print $accountingaccount4->getNomUrl(0, 1, 1, '', 1);
1939  }
1940  } else {
1941  print $object->accountancy_code_buy;
1942  }
1943  print '</td></tr>';
1944 
1945  // Accountancy buy code intra-community
1946  if ($mysoc->isInEEC())
1947  {
1948  print '<tr><td class="nowrap">';
1949  print $langs->trans("ProductAccountancyBuyIntraCode");
1950  print '</td><td colspan="2">';
1951  if (!empty($conf->accounting->enabled))
1952  {
1953  if (!empty($object->accountancy_code_buy_intra))
1954  {
1955  $accountingaccount5 = new AccountingAccount($db);
1956  $accountingaccount5->fetch('', $object->accountancy_code_buy_intra, 1);
1957 
1958  print $accountingaccount5->getNomUrl(0, 1, 1, '', 1);
1959  }
1960  } else {
1961  print $object->accountancy_code_buy_intra;
1962  }
1963  print '</td></tr>';
1964  }
1965 
1966  // Accountancy buy code export
1967  print '<tr><td class="nowrap">';
1968  print $langs->trans("ProductAccountancyBuyExportCode");
1969  print '</td><td colspan="2">';
1970  if (!empty($conf->accounting->enabled))
1971  {
1972  if (!empty($object->accountancy_code_buy_export))
1973  {
1974  $accountingaccount6 = new AccountingAccount($db);
1975  $accountingaccount6->fetch('', $object->accountancy_code_buy_export, 1);
1976 
1977  print $accountingaccount6->getNomUrl(0, 1, 1, '', 1);
1978  }
1979  } else {
1980  print $object->accountancy_code_buy_export;
1981  }
1982  print '</td></tr>';
1983 
1984  // Batch number management (to batch)
1985  if (!empty($conf->productbatch->enabled))
1986  {
1987  if ($object->isProduct() || !empty($conf->global->STOCK_SUPPORTS_SERVICES))
1988  {
1989  print '<tr><td>'.$langs->trans("ManageLotSerial").'</td><td colspan="2">';
1990  if (!empty($conf->use_javascript_ajax) && $usercancreate && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
1991  print ajax_object_onoff($object, 'status_batch', 'tobatch', 'ProductStatusOnBatch', 'ProductStatusNotOnBatch');
1992  } else {
1993  print $object->getLibStatut(0, 2);
1994  }
1995  print '</td></tr>';
1996  }
1997  }
1998 
1999  // Description
2000  print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="2">'.(dol_textishtml($object->description) ? $object->description : dol_nl2br($object->description, 1, true)).'</td></tr>';
2001 
2002  // Public URL
2003  print '<tr><td>'.$langs->trans("PublicUrl").'</td><td colspan="2">';
2004  print dol_print_url($object->url);
2005  print '</td></tr>';
2006 
2007  // Default warehouse
2008  if ($object->isProduct() && !empty($conf->stock->enabled))
2009  {
2010  $warehouse = new Entrepot($db);
2011  $warehouse->fetch($object->fk_default_warehouse);
2012 
2013  print '<tr><td>'.$langs->trans("DefaultWarehouse").'</td><td>';
2014  print (!empty($warehouse->id) ? $warehouse->getNomUrl(1) : '');
2015  print '</td>';
2016  }
2017 
2018  // Parent product.
2019  if (!empty($conf->variants->enabled) && ($object->isProduct() || $object->isService())) {
2020  $combination = new ProductCombination($db);
2021 
2022  if ($combination->fetchByFkProductChild($object->id) > 0) {
2023  $prodstatic = new Product($db);
2024  $prodstatic->fetch($combination->fk_product_parent);
2025 
2026  // Parent product
2027  print '<tr><td>'.$langs->trans("ParentProduct").'</td><td colspan="2">';
2028  print $prodstatic->getNomUrl(1);
2029  print '</td></tr>';
2030  }
2031  }
2032 
2033  print '</table>';
2034  print '</div>';
2035  print '<div class="fichehalfright"><div class="ficheaddleft">';
2036 
2037  print '<div class="underbanner clearboth"></div>';
2038  print '<table class="border tableforfield" width="100%">';
2039 
2040  if ($object->isService())
2041  {
2042  // Duration
2043  print '<tr><td class="titlefield">'.$langs->trans("Duration").'</td><td colspan="2">'.$object->duration_value.'&nbsp;';
2044  if ($object->duration_value > 1)
2045  {
2046  $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years"));
2047  } elseif ($object->duration_value > 0)
2048  {
2049  $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hour"), "d"=>$langs->trans("Day"), "w"=>$langs->trans("Week"), "m"=>$langs->trans("Month"), "y"=>$langs->trans("Year"));
2050  }
2051  print (!empty($object->duration_unit) && isset($dur[$object->duration_unit]) ? $langs->trans($dur[$object->duration_unit]) : '')."&nbsp;";
2052 
2053  print '</td></tr>';
2054  } else {
2055  // Nature
2056  print '<tr><td class="titlefield">'.$form->textwithpicto($langs->trans("NatureOfProductShort"), $langs->trans("NatureOfProductDesc")).'</td><td colspan="2">';
2057  print $object->getLibFinished();
2058  print '</td></tr>';
2059 
2060  // Brut Weight
2061  print '<tr><td class="titlefield">'.$langs->trans("Weight").'</td><td colspan="2">';
2062  if ($object->weight != '')
2063  {
2064  print $object->weight." ".measuringUnitString(0, "weight", $object->weight_units);
2065  } else {
2066  print '&nbsp;';
2067  }
2068  print "</td></tr>\n";
2069 
2070  if (empty($conf->global->PRODUCT_DISABLE_SIZE))
2071  {
2072  // Brut Length
2073  print '<tr><td>'.$langs->trans("Length").' x '.$langs->trans("Width").' x '.$langs->trans("Height").'</td><td colspan="2">';
2074  if ($object->length != '' || $object->width != '' || $object->height != '')
2075  {
2076  print $object->length;
2077  if ($object->width) print " x ".$object->width;
2078  if ($object->height) print " x ".$object->height;
2079  print ' '.measuringUnitString(0, "size", $object->length_units);
2080  } else {
2081  print '&nbsp;';
2082  }
2083  print "</td></tr>\n";
2084  }
2085  if (empty($conf->global->PRODUCT_DISABLE_SURFACE))
2086  {
2087  // Brut Surface
2088  print '<tr><td>'.$langs->trans("Surface").'</td><td colspan="2">';
2089  if ($object->surface != '')
2090  {
2091  print $object->surface." ".measuringUnitString(0, "surface", $object->surface_units);
2092  } else {
2093  print '&nbsp;';
2094  }
2095  print "</td></tr>\n";
2096  }
2097  if (empty($conf->global->PRODUCT_DISABLE_VOLUME))
2098  {
2099  // Brut Volume
2100  print '<tr><td>'.$langs->trans("Volume").'</td><td colspan="2">';
2101  if ($object->volume != '')
2102  {
2103  print $object->volume." ".measuringUnitString(0, "volume", $object->volume_units);
2104  } else {
2105  print '&nbsp;';
2106  }
2107  print "</td></tr>\n";
2108  }
2109 
2110  if (!empty($conf->global->PRODUCT_ADD_NET_MEASURE))
2111  {
2112  // Net Measure
2113  print '<tr><td class="titlefield">'.$langs->trans("NetMeasure").'</td><td colspan="2">';
2114  if ($object->net_measure != '')
2115  {
2116  print $object->net_measure." ".measuringUnitString($object->net_measure_units);
2117  } else {
2118  print '&nbsp;';
2119  }
2120  }
2121  }
2122 
2123  // Unit
2124  if (!empty($conf->global->PRODUCT_USE_UNITS))
2125  {
2126  $unit = $object->getLabelOfUnit();
2127 
2128  print '<tr><td>'.$langs->trans('DefaultUnitToShow').'</td><td>';
2129  if ($unit !== '') {
2130  print $langs->trans($unit);
2131  }
2132  print '</td></tr>';
2133  }
2134 
2135  // Custom code
2136  if (!$object->isService() && empty($conf->global->PRODUCT_DISABLE_CUSTOM_INFO))
2137  {
2138  print '<tr><td>'.$langs->trans("CustomCode").'</td><td colspan="2">'.$object->customcode.'</td>';
2139 
2140  // Origin country code
2141  print '<tr><td>'.$langs->trans("Origin").'</td><td colspan="2">'.getCountry($object->country_id, 0, $db);
2142  if (!empty($object->state_id)) print ' - '.getState($object->state_id, 0, $db);
2143  print '</td>';
2144  }
2145 
2146  // Other attributes
2147  $parameters = array('colspan' => ' colspan="'.(2 + (($showphoto || $showbarcode) ? 1 : 0)).'"', 'cols' => (2 + (($showphoto || $showbarcode) ? 1 : 0)));
2148  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2149 
2150  // Categories
2151  if ($conf->categorie->enabled) {
2152  print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td colspan="3">';
2153  print $form->showCategories($object->id, Categorie::TYPE_PRODUCT, 1);
2154  print "</td></tr>";
2155  }
2156 
2157  // Note private
2158  if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB))
2159  {
2160  print '<!-- show Note --> '."\n";
2161  print '<tr><td class="tdtop">'.$langs->trans("NotePrivate").'</td><td colspan="'.(2 + (($showphoto || $showbarcode) ? 1 : 0)).'">'.(dol_textishtml($object->note_private) ? $object->note_private : dol_nl2br($object->note_private, 1, true)).'</td></tr>'."\n";
2162  print '<!-- End show Note --> '."\n";
2163  }
2164 
2165  print "</table>\n";
2166  print '</div>';
2167 
2168  print '</div></div>';
2169  print '<div style="clear:both"></div>';
2170 
2171  print dol_get_fiche_end();
2172  }
2173  } elseif ($action != 'create')
2174  {
2175  exit;
2176  }
2177 }
2178 
2179 // Load object modCodeProduct
2180 $module = (!empty($conf->global->PRODUCT_CODEPRODUCT_ADDON) ? $conf->global->PRODUCT_CODEPRODUCT_ADDON : 'mod_codeproduct_leopard');
2181 if (substr($module, 0, 16) == 'mod_codeproduct_' && substr($module, -3) == 'php')
2182 {
2183  $module = substr($module, 0, dol_strlen($module) - 4);
2184 }
2185 $result = dol_include_once('/core/modules/product/'.$module.'.php');
2186 if ($result > 0)
2187 {
2188  $modCodeProduct = new $module();
2189 }
2190 
2191 $tmpcode = '';
2192 if (!empty($modCodeProduct->code_auto)) $tmpcode = $modCodeProduct->getNextValue($object, $object->type);
2193 
2194 $formconfirm = '';
2195 
2196 // Confirm delete product
2197 if (($action == 'delete' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js
2198  || (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) // Always output when not jmobile nor js
2199 {
2200  $formconfirm = $form->formconfirm("card.php?id=".$object->id, $langs->trans("DeleteProduct"), $langs->trans("ConfirmDeleteProduct"), "confirm_delete", '', 0, "action-delete");
2201 }
2202 
2203 // Clone confirmation
2204 if (($action == 'clone' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js
2205  || (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) // Always output when not jmobile nor js
2206 {
2207  // Define confirmation messages
2208  $formquestionclone = array(
2209  'text' => $langs->trans("ConfirmClone"),
2210  array('type' => 'text', 'name' => 'clone_ref', 'label' => $langs->trans("NewRefForClone"), 'value' => empty($tmpcode) ? $langs->trans("CopyOf").' '.$object->ref : $tmpcode, 'size'=>24),
2211  array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneContentProduct"), 'value' => 1),
2212  array('type' => 'checkbox', 'name' => 'clone_categories', 'label' => $langs->trans("CloneCategoriesProduct"), 'value' => 1),
2213  );
2214  if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
2215  $formquestionclone[] = array('type' => 'checkbox', 'name' => 'clone_prices', 'label' => $langs->trans("ClonePricesProduct").' ('.$langs->trans("CustomerPrices").')', 'value' => 0);
2216  }
2217  if (!empty($conf->global->PRODUIT_SOUSPRODUITS))
2218  {
2219  $formquestionclone[] = array('type' => 'checkbox', 'name' => 'clone_composition', 'label' => $langs->trans('CloneCompositionProduct'), 'value' => 1);
2220  }
2221 
2222  $formconfirm .= $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneProduct', $object->ref), 'confirm_clone', $formquestionclone, 'yes', 'action-clone', 350, 600);
2223 }
2224 
2225 // Call Hook formConfirm
2226 $parameters = array('formConfirm' => $formconfirm, 'object' => $object);
2227 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2228 if (empty($reshook)) $formconfirm .= $hookmanager->resPrint;
2229 elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint;
2230 
2231 // Print form confirm
2232 print $formconfirm;
2233 
2234 /* ************************************************************************** */
2235 /* */
2236 /* Barre d'action */
2237 /* */
2238 /* ************************************************************************** */
2239 if ($action != 'create' && $action != 'edit')
2240 {
2241  print "\n".'<div class="tabsAction">'."\n";
2242 
2243  $parameters = array();
2244  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2245  if (empty($reshook))
2246  {
2247  if ($usercancreate)
2248  {
2249  if (!isset($object->no_button_edit) || $object->no_button_edit <> 1) print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit&amp;id='.$object->id.'">'.$langs->trans("Modify").'</a>';
2250 
2251  if (!isset($object->no_button_copy) || $object->no_button_copy <> 1)
2252  {
2253  if (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))
2254  {
2255  print '<span id="action-clone" class="butAction">'.$langs->trans('ToClone').'</span>'."\n";
2256  } else {
2257  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=clone&amp;id='.$object->id.'">'.$langs->trans("ToClone").'</a>';
2258  }
2259  }
2260  }
2261  $object_is_used = $object->isObjectUsed($object->id);
2262 
2263  if ($usercandelete)
2264  {
2265  if (empty($object_is_used) && (!isset($object->no_button_delete) || $object->no_button_delete <> 1))
2266  {
2267  if (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))
2268  {
2269  print '<span id="action-delete" class="butActionDelete">'.$langs->trans('Delete').'</span>'."\n";
2270  } else {
2271  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=delete&amp;token='.newToken().'&amp;id='.$object->id.'">'.$langs->trans("Delete").'</a>';
2272  }
2273  } else {
2274  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("ProductIsUsed").'">'.$langs->trans("Delete").'</a>';
2275  }
2276  } else {
2277  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans("Delete").'</a>';
2278  }
2279  }
2280 
2281  print "\n</div>\n";
2282 }
2283 
2284 /*
2285  * All the "Add to" areas
2286  */
2287 
2288 if (!empty($conf->global->PRODUCT_ADD_FORM_ADD_TO) && $object->id && ($action == '' || $action == 'view') && $object->status)
2289 {
2290  //Variable used to check if any text is going to be printed
2291  $html = '';
2292  //print '<div class="fichecenter"><div class="fichehalfleft">';
2293 
2294  // Propals
2295  if (!empty($conf->propal->enabled) && $user->rights->propale->creer)
2296  {
2297  $propal = new Propal($db);
2298 
2299  $langs->load("propal");
2300 
2301  $otherprop = $propal->liste_array(2, 1, 0);
2302 
2303  if (is_array($otherprop) && count($otherprop))
2304  {
2305  $html .= '<tr><td style="width: 200px;">';
2306  $html .= $langs->trans("AddToDraftProposals").'</td><td>';
2307  $html .= $form->selectarray("propalid", $otherprop, 0, 1);
2308  $html .= '</td></tr>';
2309  } else {
2310  $html .= '<tr><td style="width: 200px;">';
2311  $html .= $langs->trans("AddToDraftProposals").'</td><td>';
2312  $html .= $langs->trans("NoDraftProposals");
2313  $html .= '</td></tr>';
2314  }
2315  }
2316 
2317  // Commande
2318  if (!empty($conf->commande->enabled) && $user->rights->commande->creer)
2319  {
2320  $commande = new Commande($db);
2321 
2322  $langs->load("orders");
2323 
2324  $othercom = $commande->liste_array(2, 1, null);
2325  if (is_array($othercom) && count($othercom))
2326  {
2327  $html .= '<tr><td style="width: 200px;">';
2328  $html .= $langs->trans("AddToDraftOrders").'</td><td>';
2329  $html .= $form->selectarray("commandeid", $othercom, 0, 1);
2330  $html .= '</td></tr>';
2331  } else {
2332  $html .= '<tr><td style="width: 200px;">';
2333  $html .= $langs->trans("AddToDraftOrders").'</td><td>';
2334  $html .= $langs->trans("NoDraftOrders");
2335  $html .= '</td></tr>';
2336  }
2337  }
2338 
2339  // Factures
2340  if (!empty($conf->facture->enabled) && $user->rights->facture->creer)
2341  {
2342  $invoice = new Facture($db);
2343 
2344  $langs->load("bills");
2345 
2346  $otherinvoice = $invoice->liste_array(2, 1, null);
2347  if (is_array($otherinvoice) && count($otherinvoice))
2348  {
2349  $html .= '<tr><td style="width: 200px;">';
2350  $html .= $langs->trans("AddToDraftInvoices").'</td><td>';
2351  $html .= $form->selectarray("factureid", $otherinvoice, 0, 1);
2352  $html .= '</td></tr>';
2353  } else {
2354  $html .= '<tr><td style="width: 200px;">';
2355  $html .= $langs->trans("AddToDraftInvoices").'</td><td>';
2356  $html .= $langs->trans("NoDraftInvoices");
2357  $html .= '</td></tr>';
2358  }
2359  }
2360 
2361  //If any text is going to be printed, then we show the table
2362  if (!empty($html))
2363  {
2364  print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
2365  print '<input type="hidden" name="token" value="'.newToken().'">';
2366  print '<input type="hidden" name="action" value="addin">';
2367 
2368  print load_fiche_titre($langs->trans("AddToDraft"), '', '');
2369 
2370  print dol_get_fiche_head('');
2371 
2372  $html .= '<tr><td class="nowrap">'.$langs->trans("Quantity").' ';
2373  $html .= '<input type="text" class="flat" name="qty" size="1" value="1"></td>';
2374  $html .= '<td class="nowrap">'.$langs->trans("ReductionShort").'(%) ';
2375  $html .= '<input type="text" class="flat" name="remise_percent" size="1" value="0">';
2376  $html .= '</td></tr>';
2377 
2378  print '<table width="100%" class="border">';
2379  print $html;
2380  print '</table>';
2381 
2382  print '<div class="center">';
2383  print '<input type="submit" class="button" value="'.$langs->trans("Add").'">';
2384  print '</div>';
2385 
2386  print dol_get_fiche_end();
2387 
2388  print '</form>';
2389  }
2390 }
2391 
2392 
2393 /*
2394  * Documents generes
2395  */
2396 
2397 if ($action != 'create' && $action != 'edit' && $action != 'delete')
2398 {
2399  print '<div class="fichecenter"><div class="fichehalfleft">';
2400  print '<a name="builddoc"></a>'; // ancre
2401 
2402  // Documents
2403  $objectref = dol_sanitizeFileName($object->ref);
2404  $relativepath = $comref.'/'.$objectref.'.pdf';
2405  if (!empty($conf->product->multidir_output[$object->entity])) {
2406  $filedir = $conf->product->multidir_output[$object->entity].'/'.$objectref; //Check repertories of current entities
2407  } else {
2408  $filedir = $conf->product->dir_output.'/'.$objectref;
2409  }
2410  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2411  $genallowed = $usercanread;
2412  $delallowed = $usercancreate;
2413 
2414  print $formfile->showdocuments($modulepart, $object->ref, $filedir, $urlsource, $genallowed, $delallowed, '', 0, 0, 0, 28, 0, '', 0, '', $object->default_lang, '', $object);
2415  $somethingshown = $formfile->numoffiles;
2416 
2417  print '</div><div class="fichehalfright"><div class="ficheaddleft">';
2418 
2419  $MAXEVENT = 10;
2420 
2421  $morehtmlright = '<a href="'.DOL_URL_ROOT.'/product/agenda.php?id='.$object->id.'">';
2422  $morehtmlright .= $langs->trans("SeeAll");
2423  $morehtmlright .= '</a>';
2424 
2425  // List of actions on element
2426  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2427  $formactions = new FormActions($db);
2428  $somethingshown = $formactions->showactions($object, 'product', 0, 1, '', $MAXEVENT, '', $morehtmlright); // Show all action for product
2429 
2430  print '</div></div></div>';
2431 }
2432 
2433 // End of page
2434 llxFooter();
2435 $db->close();
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
File of class to manage predefined price products or services by customer.
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
img_edit($titlealt= 'default', $float=0, $other= '')
Show logo editer/modifier fiche.
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.
const TYPE_STANDARD
Standard invoice.
Class to manage building of HTML components.
dol_print_url($url, $target= '_blank', $max=32, $withpicto=0)
Show Url link.
Class to manage canvas.
Class to manage products or services.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
const TYPE_SERVICE
Service.
const TYPE_PRODUCT
Regular product.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Fonction qui renvoie si tva doit etre tva percue recuperable.
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate, from a $thirdparty_buyer to a $thirdparty_seller Note: This function applies same rules than get_default_tva.
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...
Class with static methods for building HTML components related to products Only components common to ...
llxHeader()
Empty header.
Definition: wrapper.php:45
Class to build HTML component for third parties management Only common components are here...
Class to manage standard extra fields.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
Class to manage generation of HTML components Only common components must be here.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage categories.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
Class to manage customers orders.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart= '')
Return a path to have a the directory according to object where files are stored. ...
if(!GETPOST('transkey', 'alphanohtml')&&!GETPOST('transphrase', 'alphanohtml')) else
View.
Definition: notice.php:44
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
Class to manage barcode HTML.
dol_sanitizeFileName($str, $newstr= '_', $unaccent=1)
Clean a string to use it as a file name.
Class ProductCombination Used to represent a product combination.
Class to offer components to list and upload files.
print $_SERVER["PHP_SELF"]
Edit parameters.
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
print
Draft customers invoices.
Definition: index.php:89
Class to manage generation of HTML components for accounting management.
Class of a generic business object.
ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input=array())
On/off button to change status of an object This is called when MAIN_DIRECT_STATUS_UPDATE is set and ...
Definition: ajax.lib.php:573
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) Si ...
newToken()
Return the value of token currently saved into session with name &#39;newtoken&#39;.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Class to manage a WYSIWYG editor.
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;...&#39; if string larger than length.
Class to manage accounting accounts.
Class to manage invoices.
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.
llxFooter()
Empty footer.
Definition: wrapper.php:59
if(!defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN'
Draft customers invoices.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin= '1', $morecss= '', $textfordropdown= '')
Show information for admin users or standard users.
dol_set_focus($selector)
Set focus onto field with selector (similar behaviour of &#39;autofocus&#39; HTML5 tag)
getCountry($searchkey, $withcode= '', $dbtouse=0, $outputlangs= '', $entconv=1, $searchlabel= '')
Return country label, code or id from an id, code or label.
product_prepare_head($object)
Prepare array with list of tabs.
Definition: product.lib.php:35
Class to manage proposals.
measuringUnitString($unit, $measuring_style= '', $scale= '', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
Class to manage warehouses.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $keepmoretags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
dol_textishtml($msg, $option=0)
Return if a text is a html content.