PageRenderTime 68ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/product/fiche.php

https://bitbucket.org/speedealing/speedealing
PHP | 1025 lines | 738 code | 152 blank | 135 comment | 251 complexity | f640e02e8e80be4c4715f563f3a9c90e MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
  5. * Copyright (C) 2005-2013 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-2011 Juanjo Menent <jmenent@2byte.es>
  9. * Copyright (C) 2011-2012 Herve Prot <herve.prot@symeos.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 3 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. */
  24. require '../main.inc.php';
  25. require_once DOL_DOCUMENT_ROOT . '/core/class/canvas.class.php';
  26. require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
  27. require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
  28. require_once DOL_DOCUMENT_ROOT . '/product/lib/product.lib.php';
  29. require_once DOL_DOCUMENT_ROOT . '/societe/lib/societe.lib.php';
  30. if (!empty($conf->propal->enabled))
  31. require_once DOL_DOCUMENT_ROOT . '/propal/class/propal.class.php';
  32. if (!empty($conf->facture->enabled))
  33. require_once DOL_DOCUMENT_ROOT . '/facture/class/facture.class.php';
  34. if (!empty($conf->commande->enabled))
  35. require_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
  36. $langs->load("products");
  37. $langs->load("other");
  38. if (!empty($conf->stock->enabled))
  39. $langs->load("stocks");
  40. if (!empty($conf->facture->enabled))
  41. $langs->load("bills");
  42. $mesg = '';
  43. $error = 0;
  44. $errors = array();
  45. $_error = 0;
  46. $id = GETPOST('id', 'alpha');
  47. $ref = GETPOST('ref', 'alpha');
  48. $type = GETPOST('type', 'alpha');
  49. $action = (GETPOST('action', 'alpha') ? GETPOST('action', 'alpha') : 'view');
  50. $confirm = GETPOST('confirm', 'alpha');
  51. $socid = GETPOST('socid', 'int');
  52. if (!empty($user->societe_id))
  53. $socid = $user->societe_id;
  54. $object = new Product($db);
  55. $extrafields = new ExtraFields($db);
  56. // Get object canvas (By default, this is not defined, so standard usage of dolibarr)
  57. $object->getCanvas($id, $ref);
  58. $canvas = $object->canvas ? $object->canvas : GETPOST("canvas");
  59. $objcanvas = '';
  60. if (!empty($canvas)) {
  61. require_once DOL_DOCUMENT_ROOT . '/core/class/canvas.class.php';
  62. $objcanvas = new Canvas($db, $action);
  63. $objcanvas->getCanvas('product', 'card', $canvas);
  64. }
  65. // Security check
  66. $fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
  67. $fieldtype = (!empty($ref) ? 'ref' : 'rowid');
  68. $result = restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype, $objcanvas);
  69. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  70. $hookmanager->initHooks(array('productcard'));
  71. /*
  72. * Actions
  73. */
  74. $parameters = array('id' => $id, 'ref' => $ref, 'objcanvas' => $objcanvas);
  75. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  76. $error = $hookmanager->error;
  77. $errors = $hookmanager->errors;
  78. if (empty($reshook)) {
  79. // Type
  80. if ($action == 'setfk_product_type' && $user->rights->produit->creer) {
  81. $object->fetch($id);
  82. $result = $object->setValueFrom('fk_product_type', GETPOST('fk_product_type'));
  83. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  84. exit;
  85. }
  86. // Barcode type
  87. if ($action == 'setfk_barcode_type' && $user->rights->barcode->creer) {
  88. $object->fetch($id);
  89. $result = $object->setValueFrom('fk_barcode_type', GETPOST('fk_barcode_type'));
  90. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  91. exit;
  92. }
  93. // Barcode value
  94. if ($action == 'setbarcode' && $user->rights->barcode->creer) {
  95. $object->fetch($id);
  96. //Todo: ajout verification de la validite du code barre en fonction du type
  97. $result = $object->setValueFrom('barcode', GETPOST('barcode'));
  98. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  99. exit;
  100. }
  101. if ($action == 'setaccountancy_code_buy') {
  102. $object->fetch($id, $ref);
  103. $result = $object->setValueFrom('accountancy_code_buy', GETPOST('accountancy_code_buy'));
  104. if ($result < 0) {
  105. $mesg = join(',', $object->errors);
  106. }
  107. $action = "";
  108. }
  109. if ($action == 'setaccountancy_code_sell') {
  110. $object->fetch($id, $ref);
  111. $result = $object->setValueFrom('accountancy_code_sell', GETPOST('accountancy_code_sell'));
  112. if ($result < 0) {
  113. $mesg = join(',', $object->errors);
  114. }
  115. $action = "";
  116. }
  117. // Add a product or service
  118. if ($action == 'add' && ($user->rights->produit->creer || $user->rights->service->creer)) {
  119. $error = 0;
  120. if (!GETPOST('libelle')) {
  121. $mesg = '<div class="error">' . $langs->trans('ErrorFieldRequired', $langs->transnoentities('Label')) . '</div>';
  122. $action = "create";
  123. $error++;
  124. }
  125. if (empty($ref)) {
  126. $mesg = '<div class="error">' . $langs->trans('ErrorFieldRequired', $langs->transnoentities('Ref')) . '</div>';
  127. $action = "create";
  128. $error++;
  129. }
  130. if (!$error) {
  131. $object->ref = $ref;
  132. $object->label = GETPOST('libelle');
  133. $object->type = $type;
  134. $object->Status = GETPOST('statut');
  135. $object->description = dol_htmlcleanlastbr(GETPOST('desc'));
  136. $object->notes = dol_htmlcleanlastbr(GETPOST('note'));
  137. $object->customcode = GETPOST('customcode');
  138. $object->country_id = GETPOST('country_id');
  139. $object->duration_value = GETPOST('duration_value');
  140. $object->duration_unit = GETPOST('duration_unit');
  141. $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte') ? GETPOST('seuil_stock_alerte') : 0;
  142. $object->canvas = GETPOST('canvas');
  143. $object->weight = GETPOST('weight');
  144. $object->weight_units = GETPOST('weight_units');
  145. $object->length = GETPOST('size');
  146. $object->length_units = GETPOST('size_units');
  147. $object->surface = GETPOST('surface');
  148. $object->surface_units = GETPOST('surface_units');
  149. $object->volume = GETPOST('volume');
  150. $object->volume_units = GETPOST('volume_units');
  151. $object->finished = GETPOST('finished');
  152. $object->hidden = GETPOST('hidden') == 'yes' ? 1 : 0;
  153. // ADD BASE Price
  154. $obj = new stdClass();
  155. $obj->tms = dol_now();
  156. $obj->price_base_type = GETPOST('price_base_type');
  157. if ($obj->price_base_type == 'TTC')
  158. $obj->price_ttc = floatval(GETPOST('price'));
  159. else
  160. $obj->pu_ht = floatval(GETPOST('price'));
  161. if ($obj->price_base_type == 'TTC')
  162. $obj->price_min_ttc = floatval(GETPOST('price_min'));
  163. else
  164. $obj->price_min = floatval(GETPOST('price_min'));
  165. $obj->tva_tx = floatval(str_replace('*', '', GETPOST('tva_tx')));
  166. $obj->tva_npr = preg_match('/\*/', GETPOST('tva_tx')) ? 1 : 0;
  167. // local taxes.
  168. $obj->localtax1_tx = get_localtax($obj->tva_tx, 1);
  169. $obj->localtax2_tx = get_localtax($obj->tva_tx, 2);
  170. $object->updatePrice($obj);
  171. /* // MultiPrix
  172. if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
  173. for ($i = 2; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) {
  174. if (isset($_POST["price_" . $i])) {
  175. $object->multiprices["$i"] = price2num($_POST["price_" . $i], 'MU');
  176. $object->multiprices_base_type["$i"] = $_POST["multiprices_base_type_" . $i];
  177. } else {
  178. $object->multiprices["$i"] = "";
  179. }
  180. }
  181. } */
  182. // Get extra fields
  183. foreach ($_POST as $key => $value) {
  184. if (preg_match("/^options_/", $key)) {
  185. $object->array_options[$key] = $_POST[$key];
  186. }
  187. }
  188. $id = $object->create($user);
  189. if ($id < 0) {
  190. $mesg = '<div class="error">' . $langs->trans($object->error) . '</div>';
  191. $action = "create";
  192. } else {
  193. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $id);
  194. exit;
  195. }
  196. }
  197. }
  198. // Update a product or service
  199. if ($action == 'update' && ($user->rights->produit->creer || $user->rights->service->creer)) {
  200. if (GETPOST('cancel')) {
  201. $action = '';
  202. } else {
  203. if ($object->fetch($id)) {
  204. $object->oldcopy = dol_clone($object);
  205. $object->ref = $ref;
  206. $object->label = GETPOST('libelle');
  207. $object->description = dol_htmlcleanlastbr(GETPOST('desc'));
  208. $object->notes = dol_htmlcleanlastbr(GETPOST('note'));
  209. $object->customcode = GETPOST('customcode');
  210. $object->country_id = GETPOST('country_id');
  211. $object->Status = GETPOST('statut');
  212. $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte');
  213. $object->duration_value = GETPOST('duration_value');
  214. $object->duration_unit = GETPOST('duration_unit');
  215. $object->canvas = GETPOST('canvas');
  216. $object->weight = GETPOST('weight');
  217. $object->weight_units = GETPOST('weight_units');
  218. $object->length = GETPOST('size');
  219. $object->length_units = GETPOST('size_units');
  220. $object->surface = GETPOST('surface');
  221. $object->surface_units = GETPOST('surface_units');
  222. $object->volume = GETPOST('volume');
  223. $object->volume_units = GETPOST('volume_units');
  224. $object->finished = GETPOST('finished');
  225. $object->hidden = GETPOST('hidden') == 'yes' ? 1 : 0;
  226. // Get extra fields
  227. foreach ($_POST as $key => $value) {
  228. if (preg_match("/^options_/", $key)) {
  229. $object->array_options[$key] = $_POST[$key];
  230. }
  231. }
  232. if ($object->check()) {
  233. if ($object->update($object->id, $user) > 0) {
  234. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  235. exit;
  236. } else {
  237. $action = 'edit';
  238. $mesg = $object->error;
  239. }
  240. } else {
  241. $action = 'edit';
  242. $mesg = $langs->trans("ErrorProductBadRefOrLabel");
  243. }
  244. }
  245. }
  246. }
  247. // Action clone object
  248. if ($action == 'confirm_clone' && $confirm != 'yes') {
  249. $action = '';
  250. }
  251. if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->produit->creer || $user->rights->service->creer)) {
  252. if (!GETPOST('clone_content') && !GETPOST('clone_prices')) {
  253. $mesg = '<div class="error">' . $langs->trans("NoCloneOptionsSpecified") . '</div>';
  254. } else {
  255. $db->begin();
  256. $originalId = $id;
  257. if ($object->fetch($id, $ref) > 0) {
  258. $object->ref = GETPOST('clone_ref');
  259. $object->Status = "DISABLE";
  260. $object->finished = "FINISHED";
  261. unset($object->id);
  262. if ($object->check()) {
  263. $id = $object->create($user);
  264. if ($id > 0) {
  265. // $object->clone_fournisseurs($originalId, $id);
  266. header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
  267. exit;
  268. } else {
  269. $id = $originalId;
  270. if ($object->error == 'ErrorProductAlreadyExists') {
  271. $_error++;
  272. $action = "";
  273. $mesg = '<div class="error">' . $langs->trans("ErrorProductAlreadyExists", $object->ref);
  274. $mesg.=' <a href="' . $_SERVER["PHP_SELF"] . '?ref=' . $object->ref . '">' . $langs->trans("ShowCardHere") . '</a>.';
  275. $mesg.='</div>';
  276. //dol_print_error($object->db);
  277. } else {
  278. $mesg = $object->error;
  279. dol_print_error($db, $object->error);
  280. }
  281. }
  282. }
  283. } else {
  284. dol_print_error($db, $object->error);
  285. }
  286. }
  287. }
  288. // Delete a product
  289. if ($action == 'confirm_delete' && $confirm != 'yes') {
  290. $action = '';
  291. }
  292. if ($action == 'confirm_delete' && $confirm == 'yes') {
  293. $object = new Product($db);
  294. $object->load($id);
  295. if (($object->type == "PRODUCT" && $user->rights->produit->supprimer) || ($object->type == "SERVICE" && $user->rights->service->supprimer)) {
  296. $result = $object->delete();
  297. }
  298. if ($result > 0) {
  299. header('Location: ' . DOL_URL_ROOT . '/product/list.php?delprod=' . urlencode($object->ref));
  300. exit;
  301. } else {
  302. $mesg = $object->error;
  303. $reload = 0;
  304. $action = '';
  305. }
  306. }
  307. }
  308. if (GETPOST("cancel") == $langs->trans("Cancel")) {
  309. $action = '';
  310. header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
  311. exit;
  312. }
  313. /*
  314. * View
  315. */
  316. $helpurl = '';
  317. if (GETPOST("type") == 'PRODUCT')
  318. $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
  319. if (GETPOST("type") == 'SERVICE')
  320. $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
  321. if (isset($_GET['type']))
  322. $title = $langs->trans('CardProduct' . GETPOST('type'));
  323. else
  324. $title = $langs->trans('ProductServiceCard');
  325. llxHeader('', $title, $helpurl);
  326. $form = new Form($db);
  327. $formproduct = new FormProduct($db);
  328. if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
  329. // -----------------------------------------
  330. // When used with CANVAS
  331. // -----------------------------------------
  332. if (empty($object->error) && ($id || $ref)) {
  333. $object = new Product($db);
  334. $object->fetch($id, $ref);
  335. }
  336. $objcanvas->assign_values($action, $object->id, $ref); // Set value for templates
  337. $objcanvas->display_canvas($action); // Show template
  338. } else {
  339. // -----------------------------------------
  340. // When used in standard mode
  341. // -----------------------------------------
  342. if ($action == 'create' && ($user->rights->produit->creer || $user->rights->service->creer)) {
  343. //WYSIWYG Editor
  344. require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  345. // Load object modCodeProduct
  346. $module = (!empty($conf->global->PRODUCT_CODEPRODUCT_ADDON) ? $conf->global->PRODUCT_CODEPRODUCT_ADDON : 'mod_codeproduct_leopard');
  347. if (substr($module, 0, 16) == 'mod_codeproduct_' && substr($module, -3) == 'php') {
  348. $module = substr($module, 0, dol_strlen($module) - 4);
  349. }
  350. dol_include_once('/core/modules/product/' . $module . '.php');
  351. $modCodeProduct = new $module;
  352. print '<form action="' . $_SERVER['PHP_SELF'] . '" method="post">';
  353. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
  354. print '<input type="hidden" name="action" value="add">';
  355. print '<input type="hidden" name="type" value="' . $type . '">' . "\n";
  356. if (!empty($modCodeProduct->code_auto))
  357. print '<input type="hidden" name="code_auto" value="1">';
  358. if ($type == "SERVICE")
  359. $title = $langs->trans("NewService");
  360. else
  361. $title = $langs->trans("NewProduct");
  362. print_fiche_titre($title);
  363. print '<div class="with-padding">';
  364. print '<div class="columns">';
  365. print column_start();
  366. dol_htmloutput_mesg($mesg);
  367. print '<table class="border" width="100%">';
  368. print '<tr>';
  369. $tmpcode = GETPOST("ref");
  370. if (!empty($modCodeProduct->code_auto))
  371. $tmpcode = $modCodeProduct->getNextValue($object, $type);
  372. print '<td class="fieldrequired" width="20%">' . $langs->trans("Ref") . '</td><td><input name="ref" size="40" maxlength="32" value="' . $tmpcode . '">';
  373. if ($_error) {
  374. print $langs->trans("RefAlreadyExists");
  375. }
  376. print '</td></tr>';
  377. // Label
  378. print '<tr><td class="fieldrequired">' . $langs->trans("Label") . '</td><td><input name="libelle" size="40" value="' . GETPOST('libelle') . '"></td></tr>';
  379. // On sell
  380. print '<tr><td class="fieldrequired">' . $langs->trans("Status") . '</td><td>';
  381. print $object->select_fk_extrafields('Status', 'statut');
  382. print '</td></tr>';
  383. // Stock min level
  384. if ($type != "SERVICE" && !empty($conf->stock->enabled)) {
  385. print '<tr><td>' . $langs->trans("StockLimit") . '</td><td>';
  386. print '<input name="seuil_stock_alerte" size="4" value="' . GETPOST('seuil_stock_alerte') . '">';
  387. print '</td></tr>';
  388. } else {
  389. print '<input name="seuil_stock_alerte" type="hidden" value="0">';
  390. }
  391. // Description (used in invoice, propal...)
  392. print '<tr><td valign="top">' . $langs->trans("Description") . '</td><td>';
  393. $doleditor = new DolEditor('desc', GETPOST('desc'), '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, 90);
  394. $doleditor->Create();
  395. print "</td></tr>";
  396. // Nature
  397. if ($type != "SERVICE") {
  398. print '<tr><td>' . $langs->trans("Nature") . '</td><td>';
  399. print $object->select_fk_extrafields('finished', 'finished');
  400. print '</td></tr>';
  401. }
  402. // Duration
  403. if ($type == "SERVICE") {
  404. print '<tr><td>' . $langs->trans("Duration") . '</td><td><input name="duration_value" size="6" maxlength="5" value="' . GETPOST('duration_value') . '"> &nbsp;';
  405. print '<input name="duration_unit" type="radio" value="h">' . $langs->trans("Hour") . '&nbsp;';
  406. print '<input name="duration_unit" type="radio" value="d">' . $langs->trans("Day") . '&nbsp;';
  407. print '<input name="duration_unit" type="radio" value="w">' . $langs->trans("Week") . '&nbsp;';
  408. print '<input name="duration_unit" type="radio" value="m">' . $langs->trans("Month") . '&nbsp;';
  409. print '<input name="duration_unit" type="radio" value="y">' . $langs->trans("Year") . '&nbsp;';
  410. print '</td></tr>';
  411. }
  412. if ($type != "SERVICE") { // Le poids et le volume ne concerne que les produits et pas les services
  413. // Weight
  414. print '<tr><td>' . $langs->trans("Weight") . '</td><td>';
  415. print '<input name="weight" size="4" value="' . GETPOST('weight') . '">';
  416. print $object->select_fk_extrafields("weight_units", "weight_units");
  417. print '</td></tr>';
  418. // Length
  419. print '<tr><td>' . $langs->trans("Length") . '</td><td>';
  420. print '<input name="size" size="4" value="' . GETPOST('size') . '">';
  421. print $object->select_fk_extrafields("size_units", "size_units");
  422. print '</td></tr>';
  423. // Surface
  424. print '<tr><td>' . $langs->trans("Surface") . '</td><td>';
  425. print '<input name="surface" size="4" value="' . GETPOST('surface') . '">';
  426. print $object->select_fk_extrafields("surface_units", "surface_units");
  427. print '</td></tr>';
  428. // Volume
  429. print '<tr><td>' . $langs->trans("Volume") . '</td><td>';
  430. print '<input name="volume" size="4" value="' . GETPOST('volume') . '">';
  431. print $object->select_fk_extrafields("volume_units", "volume_units");
  432. print '</td></tr>';
  433. // Customs code
  434. print '<tr><td>' . $langs->trans("CustomCode") . '</td><td><input name="customcode" size="10" value="' . GETPOST('customcode') . '"></td></tr>';
  435. }
  436. // Origin country
  437. print '<tr><td>' . $langs->trans("CountryOrigin") . '</td><td>';
  438. print $object->select_fk_extrafields("country_id", "country_id");
  439. if ($user->admin)
  440. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"), 1);
  441. print '</td></tr>';
  442. // Other attributes
  443. $parameters = array('colspan' => ' colspan="2"');
  444. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  445. if (empty($reshook) && !empty($extrafields->attribute_label)) {
  446. foreach ($extrafields->attribute_label as $key => $label) {
  447. $value = (GETPOST('options_' . $key) ? GETPOST('options_' . $key) : $object->array_options["options_" . $key]);
  448. print '<tr><td>' . $label . '</td><td colspan="3">';
  449. print $extrafields->showInputField($key, $value);
  450. print '</td></tr>' . "\n";
  451. }
  452. }
  453. // Note (private, no output on invoices, propales...)
  454. print '<tr><td valign="top">' . $langs->trans("NoteNotVisibleOnBill") . '</td><td>';
  455. // 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.
  456. $doleditor = new DolEditor('note', GETPOST('note'), '', 180, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 8, 70);
  457. $doleditor->Create();
  458. print "</td></tr>";
  459. print '</table>';
  460. print '<br>';
  461. print '<table class="border" width="100%">';
  462. // PRIX
  463. print '<tr><td>' . $langs->trans("SellingPrice") . '</td>';
  464. print '<td><input name="price" size="10" value="' . $object->price[0]->price . '">';
  465. print $object->select_fk_extrafields("price_base_type", "price_base_type", $object->price[0]->price_base_type);
  466. print '</td></tr>';
  467. // MIN PRICE
  468. print '<tr><td>' . $langs->trans("MinPrice") . '</td>';
  469. print '<td><input name="price_min" size="10" value="' . $object->price[0]->price_min . '">';
  470. print '</td></tr>';
  471. // VAT
  472. print '<tr><td width="20%">' . $langs->trans("VATRate") . '</td><td>';
  473. print $object->select_fk_extrafields("tva_tx", "tva_tx", '', false);
  474. print '</td></tr>';
  475. print '</table>';
  476. print '<br>';
  477. print '<center><input type="submit" class="button" value="' . $langs->trans("Create") . '"></center>';
  478. print '</form>';
  479. print column_end();
  480. print '</div></div>';
  481. }
  482. /**
  483. * Product card
  484. */ else if ($id) {
  485. $res = $object->fetch($id);
  486. if ($res < 0) {
  487. dol_print_error($db, $object->error);
  488. exit;
  489. }
  490. // Fiche en mode edition
  491. if ($action == 'edit' && ($user->rights->produit->creer || $user->rights->service->creer)) {
  492. //WYSIWYG Editor
  493. require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  494. $type = $langs->trans('Product');
  495. if ($object->isservice())
  496. $type = $langs->trans('Service');
  497. print_fiche_titre($langs->trans('Modify') . ' ' . $type . ' : ' . $object->ref);
  498. print '<div class="with-padding">';
  499. print '<div class="columns">';
  500. print column_start();
  501. dol_htmloutput_errors($mesg);
  502. // Main official, simple, and not duplicated code
  503. print '<form action="' . $_SERVER['PHP_SELF'] . '" method="POST">' . "\n";
  504. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
  505. print '<input type="hidden" name="action" value="update">';
  506. print '<input type="hidden" name="id" value="' . $object->id . '">';
  507. print '<input type="hidden" name="canvas" value="' . $object->canvas . '">';
  508. print '<table class="border allwidth">';
  509. // Ref
  510. print '<tr><td width="15%" class="fieldrequired">' . $langs->trans("Ref") . '</td><td colspan="2"><input name="ref" size="40" maxlength="32" value="' . (GETPOST("ref") ? GETPOST("ref") : $object->ref) . '"></td></tr>';
  511. // Label
  512. print '<tr><td class="fieldrequired">' . $langs->trans("Label") . '</td><td colspan="2"><input name="libelle" size="40" value="' . $object->label . '"></td></tr>';
  513. // Status
  514. print '<tr><td class="fieldrequired">' . $langs->trans("Status") . '</td><td colspan="2">';
  515. print $object->select_fk_extrafields('Status', 'statut');
  516. print '</td></tr>';
  517. // Description (used in invoice, propal...)
  518. print '<tr><td valign="top">' . $langs->trans("Description") . '</td><td colspan="2">';
  519. // 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.
  520. $doleditor = new DolEditor('desc', $object->description, '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, 90);
  521. $doleditor->Create();
  522. print "</td></tr>";
  523. print "\n";
  524. // Nature
  525. if ($object->type != "SERVICE") {
  526. print '<tr><td>' . $langs->trans("Nature") . '</td><td colspan="2">';
  527. print $object->select_fk_extrafields('finished', 'finished');
  528. print '</td></tr>';
  529. }
  530. if ($object->isproduct() && !empty($conf->stock->enabled)) {
  531. print "<tr>" . '<td>' . $langs->trans("StockLimit") . '</td><td colspan="2">';
  532. print '<input name="seuil_stock_alerte" size="4" value="' . $object->seuil_stock_alerte . '">';
  533. print '</td></tr>';
  534. } else {
  535. print '<input name="seuil_stock_alerte" type="hidden" value="' . $object->seuil_stock_alerte . '">';
  536. }
  537. if ($object->isservice()) {
  538. // Duration
  539. print '<tr><td>' . $langs->trans("Duration") . '</td><td colspan="2"><input name="duration_value" size="3" maxlength="5" value="' . $object->duration_value . '">';
  540. print '&nbsp; ';
  541. print '<input name="duration_unit" type="radio" value="h"' . ($object->duration_unit == 'h' ? ' checked' : '') . '>' . $langs->trans("Hour");
  542. print '&nbsp; ';
  543. print '<input name="duration_unit" type="radio" value="d"' . ($object->duration_unit == 'd' ? ' checked' : '') . '>' . $langs->trans("Day");
  544. print '&nbsp; ';
  545. print '<input name="duration_unit" type="radio" value="w"' . ($object->duration_unit == 'w' ? ' checked' : '') . '>' . $langs->trans("Week");
  546. print '&nbsp; ';
  547. print '<input name="duration_unit" type="radio" value="m"' . ($object->duration_unit == 'm' ? ' checked' : '') . '>' . $langs->trans("Month");
  548. print '&nbsp; ';
  549. print '<input name="duration_unit" type="radio" value="y"' . ($object->duration_unit == 'y' ? ' checked' : '') . '>' . $langs->trans("Year");
  550. print '</td></tr>';
  551. } else {
  552. // Weight
  553. print '<tr><td>' . $langs->trans("Weight") . '</td><td colspan="2">';
  554. print '<input name="weight" size="5" value="' . $object->weight . '"> ';
  555. print $object->select_fk_extrafields("weight_units", "weight_units");
  556. print '</td></tr>';
  557. // Length
  558. print '<tr><td>' . $langs->trans("Length") . '</td><td colspan="2">';
  559. print '<input name="size" size="5" value="' . $object->length . '"> ';
  560. print $object->select_fk_extrafields("size_units", "size_units");
  561. print '</td></tr>';
  562. // Surface
  563. print '<tr><td>' . $langs->trans("Surface") . '</td><td colspan="2">';
  564. print '<input name="surface" size="5" value="' . $object->surface . '"> ';
  565. print $object->select_fk_extrafields("surface_units", "surface_units");
  566. print '</td></tr>';
  567. // Volume
  568. print '<tr><td>' . $langs->trans("Volume") . '</td><td colspan="2">';
  569. print '<input name="volume" size="5" value="' . $object->volume . '"> ';
  570. print $object->select_fk_extrafields("volume_units", "volume_units");
  571. print '</td></tr>';
  572. // Customs code
  573. print '<tr><td>' . $langs->trans("CustomCode") . '</td><td colspan="2"><input name="customcode" size="10" value="' . $object->customcode . '"></td></tr>';
  574. }
  575. // Origin country
  576. print '<tr><td>' . $langs->trans("CountryOrigin") . '</td><td colspan="2">';
  577. print $object->select_fk_extrafields('country_id', 'country_id');
  578. //print $form->select_country($object->country_id, 'country_id');
  579. if ($user->admin)
  580. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"), 1);
  581. print '</td></tr>';
  582. //Tag list
  583. print '<tr><td>' . $langs->trans("Categories") . '</td><td colspan="3">';
  584. print '<ul id="array_tag_handler"></ul>';
  585. ?>
  586. <script>
  587. $(document).ready(function() {
  588. $("#array_tag_handler").tagHandler({
  589. getData: {id: '<?php echo $object->id; ?>', class: '<?php echo get_class($object); ?>'},
  590. getURL: '<?php echo DOL_URL_ROOT . '/core/ajax/loadtaghandler.php'; ?>',
  591. updateData: {id: '<?php echo $object->id; ?>', class: '<?php echo get_class($object); ?>'},
  592. updateURL: '<?php echo DOL_URL_ROOT . '/core/ajax/savetaghandler.php'; ?>',
  593. autocomplete: true,
  594. autoUpdate: true
  595. });
  596. });
  597. </script>
  598. <?php
  599. print "</td></tr>";
  600. // Other attributes
  601. $parameters = array('colspan' => ' colspan="2"');
  602. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  603. if (empty($reshook) && !empty($extrafields->attribute_label)) {
  604. foreach ($extrafields->attribute_label as $key => $label) {
  605. $value = (isset($_POST["options_" . $key]) ? $_POST["options_" . $key] : $object->array_options["options_" . $key]);
  606. print '<tr><td>' . $label . '</td><td colspan="3">';
  607. print $extrafields->showInputField($key, $value);
  608. print '</td></tr>' . "\n";
  609. }
  610. }
  611. // Note
  612. print '<tr><td valign="top">' . $langs->trans("NoteNotVisibleOnBill") . '</td><td colspan="2">';
  613. $doleditor = new DolEditor('note', $object->note, '', 200, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 8, 70);
  614. $doleditor->Create();
  615. print "</td></tr>";
  616. print '</table>';
  617. print '<br>';
  618. print '<center><input type="submit" class="button" value="' . $langs->trans("Save") . '"> &nbsp; &nbsp; ';
  619. print '<input type="submit" class="button" name="cancel" value="' . $langs->trans("Cancel") . '"></center>';
  620. print '</form>';
  621. print column_end();
  622. print '</div><div>';
  623. } else {
  624. // Fiche en mode visu
  625. dol_htmloutput_mesg($mesg);
  626. $head = product_prepare_head($object, $user);
  627. $title = $langs->trans("CardProduct" . $object->type);
  628. $picto = ($object->type == "SERVICE" ? 'service' : 'product');
  629. print_fiche_titre($title);
  630. print '<div class="with-padding">';
  631. print '<div class="columns">';
  632. print column_start();
  633. dol_fiche_head($head, 'card', $title, 0, $picto);
  634. $showphoto = $object->is_photo_available($conf->product->multidir_output[$object->entity]);
  635. $showbarcode = (!empty($conf->barcode->enabled) && $user->rights->barcode->lire);
  636. // En mode visu
  637. print '<table class="border" width="100%"><tr>';
  638. // Ref
  639. print '<td width="15%">' . $langs->trans("Ref") . '</td><td colspan="' . (2 + (($showphoto || $showbarcode) ? 1 : 0)) . '">';
  640. print $form->showrefnav($object, 'ref', '', 1, 'ref');
  641. print '</td>';
  642. print '</tr>';
  643. //Name
  644. print '<tr><td>' . $langs->trans("Name") . '</td><td colspan="2">' . $object->ref . '</td>';
  645. // Label
  646. print '<tr><td>' . $form->editfieldkey("Label", 'label', $object->label, $object, $user->rights->produit->creer || $user->rights->service->creer, 'string') . '</td><td colspan="2">';
  647. print $form->editfieldval("Label", 'label', $object->label, $object, $user->rights->produit->creer || $user->rights->service->creer, 'string');
  648. print '</td>';
  649. $nblignes = 8;
  650. if (!empty($conf->produit->enabled) && !empty($conf->service->enabled))
  651. $nblignes++;
  652. if ($showbarcode)
  653. $nblignes+=2;
  654. if ($object->type != "SERVICE")
  655. $nblignes++;
  656. if ($object->isservice())
  657. $nblignes++;
  658. else
  659. $nblignes+=4;
  660. // Photo
  661. if ($showphoto || $showbarcode) {
  662. print '<td valign="middle" align="center" width="25%" rowspan="' . $nblignes . '">';
  663. if ($showphoto)
  664. print $object->show_photos($conf->product->multidir_output[$object->entity], 1, 1, 0, 0, 0, 80);
  665. if ($showphoto && $showbarcode)
  666. print '<br><br>';
  667. if ($showbarcode)
  668. print $form->showbarcode($object);
  669. print '</td>';
  670. }
  671. print '</tr>';
  672. // Type
  673. if (!empty($conf->produit->enabled) && !empty($conf->service->enabled)) {
  674. print '<tr><td>' . $form->editfieldkey("Type", 'type', $object->type, $object, $user->rights->produit->creer || $user->rights->service->creer, "select") . '</td><td colspan="2">';
  675. print $form->editfieldval("Type", 'type', $object->type, $object, $user->rights->produit->creer || $user->rights->service->creer, "select");
  676. print '</td></tr>';
  677. }
  678. if ($showbarcode) {
  679. // Barcode type
  680. print '<tr><td nowrap>';
  681. print '<table width="100%" class="nobordernopadding"><tr><td nowrap>';
  682. print $langs->trans("BarcodeType");
  683. print '<td>';
  684. if (($action != 'editbarcodetype') && $user->rights->barcode->creer)
  685. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editbarcodetype&amp;id=' . $object->id . '">' . img_edit($langs->trans('Edit'), 1) . '</a></td>';
  686. print '</tr></table>';
  687. print '</td><td colspan="2">';
  688. if ($action == 'editbarcodetype') {
  689. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formbarcode.class.php';
  690. $formbarcode = new FormBarCode($db);
  691. $formbarcode->form_barcode_type($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->barcode_type, 'fk_barcode_type');
  692. } else {
  693. $object->fetch_barcode();
  694. print $object->barcode_type_label ? $object->barcode_type_label : ($object->barcode ? '<div class="warning">' . $langs->trans("SetDefaultBarcodeType") . '<div>' : '');
  695. }
  696. print '</td></tr>' . "\n";
  697. // Barcode value
  698. print '<tr><td nowrap>';
  699. print '<table width="100%" class="nobordernopadding"><tr><td nowrap>';
  700. print $langs->trans("BarcodeValue");
  701. print '<td>';
  702. if (($action != 'editbarcode') && $user->rights->barcode->creer)
  703. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editbarcode&amp;id=' . $object->id . '">' . img_edit($langs->trans('Edit'), 1) . '</a></td>';
  704. print '</tr></table>';
  705. print '</td><td colspan="2">';
  706. if ($action == 'editbarcode') {
  707. print '<form method="post" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '">';
  708. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
  709. print '<input type="hidden" name="action" value="setbarcode">';
  710. print '<input size="40" type="text" name="barcode" value="' . $object->barcode . '">';
  711. print '&nbsp;<input type="submit" class="button" value="' . $langs->trans("Modify") . '">';
  712. } else {
  713. print $object->barcode;
  714. }
  715. print '</td></tr>' . "\n";
  716. }
  717. // Accountancy sell code
  718. print '<tr><td>' . $form->editfieldkey("ProductAccountancySellCode", 'accountancy_code_sell', $object->accountancy_code_sell, $object, $user->rights->produit->creer || $user->rights->service->creer, 'string') . '</td><td colspan="2">';
  719. print $form->editfieldval("ProductAccountancySellCode", 'accountancy_code_sell', $object->accountancy_code_sell, $object, $user->rights->produit->creer || $user->rights->service->creer, 'string');
  720. print '</td></tr>';
  721. // Accountancy buy code
  722. print '<tr><td>' . $form->editfieldkey("ProductAccountancyBuyCode", 'accountancy_code_buy', $object->accountancy_code_buy, $object, $user->rights->produit->creer || $user->rights->service->creer, 'string') . '</td><td colspan="2">';
  723. print $form->editfieldval("ProductAccountancyBuyCode", 'accountancy_code_buy', $object->accountancy_code_buy, $object, $user->rights->produit->creer || $user->rights->service->creer, 'string');
  724. print '</td></tr>';
  725. // Status
  726. print '<tr><td>' . $form->editfieldkey("Status", 'Status', $object->Status, $object, $user->rights->produit->creer || $user->rights->service->creer, "select") . '</td><td colspan="2">';
  727. print $form->editfieldval("Status", 'Status', $object->Status, $object, $user->rights->produit->creer || $user->rights->service->creer, "select");
  728. print '</td></tr>';
  729. // Description
  730. print '<tr><td valign="top">' . $langs->trans("Description") . '</td><td colspan="2">' . (dol_textishtml($object->description) ? $object->description : dol_nl2br($object->description, 1, true)) . '</td></tr>';
  731. // Nature
  732. if ($object->type != "SERVICE") {
  733. print '<tr><td>' . $langs->trans("Nature") . '</td><td colspan="2">';
  734. print $object->print_fk_extrafields("finished");
  735. print '</td></tr>';
  736. }
  737. if ($object->isservice()) {
  738. // Duration
  739. print '<tr><td>' . $langs->trans("Duration") . '</td><td colspan="2">' . $object->duration_value . '&nbsp;';
  740. if ($object->duration_value > 1) {
  741. $dur = array("h" => $langs->trans("Hours"), "d" => $langs->trans("Days"), "w" => $langs->trans("Weeks"), "m" => $langs->trans("Months"), "y" => $langs->trans("Years"));
  742. } else if ($object->duration_value > 0) {
  743. $dur = array("h" => $langs->trans("Hour"), "d" => $langs->trans("Day"), "w" => $langs->trans("Week"), "m" => $langs->trans("Month"), "y" => $langs->trans("Year"));
  744. }
  745. print (!empty($object->duration_unit) && isset($dur[$object->duration_unit]) ? $langs->trans($dur[$object->duration_unit]) : '') . "&nbsp;";
  746. print '</td></tr>';
  747. } else {
  748. // Weight
  749. print '<tr><td>' . $langs->trans("Weight") . '</td><td colspan="2">';
  750. if ($object->weight != '') {
  751. print $object->weight . " " . $object->print_fk_extrafields("weight_units");
  752. } else {
  753. print '&nbsp;';
  754. }
  755. print "</td></tr>\n";
  756. // Length
  757. print '<tr><td>' . $langs->trans("Length") . '</td><td colspan="2">';
  758. if ($object->length != '') {
  759. print $object->length . " " . $object->print_fk_extrafields("length_units");
  760. } else {
  761. print '&nbsp;';
  762. }
  763. print "</td></tr>\n";
  764. // Surface
  765. print '<tr><td>' . $langs->trans("Surface") . '</td><td colspan="2">';
  766. if ($object->surface != '') {
  767. print $object->surface . " " . $object->print_fk_extrafields("surface_units");
  768. } else {
  769. print '&nbsp;';
  770. }
  771. print "</td></tr>\n";
  772. // Volume
  773. print '<tr><td>' . $langs->trans("Volume") . '</td><td colspan="2">';
  774. if ($object->volume != '') {
  775. print $object->volume . " " . $object->print_fk_extrafields("volume_units");
  776. } else {
  777. print '&nbsp;';
  778. }
  779. print "</td></tr>\n";
  780. }
  781. // Customs code
  782. print '<tr><td>' . $langs->trans("CustomCode") . '</td><td colspan="2">' . $object->customcode . '</td>';
  783. // Origin country code
  784. print '<tr><td>' . $langs->trans("CountryOrigin") . '</td><td colspan="2">';
  785. if ($object->country_id) {
  786. $img = picto_from_langcode($object->country_id);
  787. print ($img ? $img . ' ' : '') . $object->print_fk_extrafields("country_id");
  788. }
  789. print '</td>';
  790. //Tag list
  791. print '<tr><td>' . $form->editfieldkey("Categories", 'Tag', $object->Tag, $object, $user->rights->produit->creer || $user->rights->service->creer, "tag") . '</td><td colspan="2">';
  792. print $form->editfieldval("Categories", 'Tag', $object->Tag, $object, $user->rights->produit->creer || $user->rights->service->creer, "tag");
  793. print "</td></tr>";
  794. // Other attributes
  795. $parameters = array('colspan' => ' colspan="' . (2 + (($showphoto || $showbarcode) ? 1 : 0)) . '"');
  796. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  797. if (empty($reshook) && !empty($extrafields->attribute_label)) {
  798. foreach ($extrafields->attribute_label as $key => $label) {
  799. $value = (isset($_POST["options_" . $key]) ? $_POST["options_" . $key] : $object->array_options["options_" . $key]);
  800. print '<tr><td>' . $label . '</td><td colspan="3">';
  801. print $extrafields->showOutputField($key, $value);
  802. print '</td></tr>' . "\n";
  803. }
  804. }
  805. print "</table>\n";
  806. dol_fiche_end();
  807. /* * ************************************************************************* */
  808. /* */
  809. /* Barre d'action */
  810. /* */
  811. /* * ************************************************************************* */
  812. print "\n" . '<div class="tabsAction">' . "\n";
  813. if ($action == '' || $action == 'view') {
  814. if ($user->rights->produit->creer || $user->rights->service->creer) {
  815. if (!isset($object->no_button_edit) || $object->no_button_edit <> 1)
  816. print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?action=edit&amp;id=' . $object->id . '">' . $langs->trans("Modify") . '</a>';
  817. if (!isset($object->no_button_copy) || $object->no_button_copy <> 1) {
  818. if (!empty($conf->use_javascript_ajax)) {
  819. print '<span id="action-clone" class="butAction">' . $langs->trans('ToClone') . '</span>' . "\n";
  820. print $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('CloneProduct'), $langs->trans('ConfirmCloneProduct', $object->ref), 'confirm_clone', $formquestionclone, 'yes', 'action-clone', 230, 600);
  821. } else {
  822. print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?action=clone&amp;id=' . $object->id . '">' . $langs->trans("ToClone") . '</a>';
  823. }
  824. }
  825. }
  826. $object_is_used = $object->isObjectUsed($object->id);
  827. if (($object->type == "PRODUCT" && $user->rights->produit->supprimer) || ($object->type == "SERVICE" && $user->rights->service->supprimer)) {
  828. if (empty($object_is_used) && (!isset($object->no_button_delete) || $object->no_button_delete <> 1)) {
  829. if (!empty($conf->use_javascript_ajax)) {
  830. print '<span id="action-delete" class="butActionDelete">' . $langs->trans('Delete') . '</span>' . "\n";
  831. print $form->formconfirm($_SERVER["PHP_SELF"] . "?id=" . $object->id, $langs->trans("DeleteProduct"), $langs->trans("ConfirmDeleteProduct"), "confirm_delete", '', 0, "action-delete");
  832. } else {
  833. print '<a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?action=delete&amp;id=' . $object->id . '">' . $langs->trans("Delete") . '</a>';
  834. }
  835. } else {
  836. print '<a class="butActionRefused" href="#" title="' . $langs->trans("ProductIsUsed") . '">' . $langs->trans("Delete") . '</a>';
  837. }
  838. } else {
  839. print '<a class="butActionRefused" href="#" title="' . $langs->trans("NotEnoughPermissions") . '">' . $langs->trans("Delete") . '</a>';
  840. }
  841. }
  842. print "</div>";
  843. print column_end();
  844. print column_start("six");
  845. print $object->show_notes();
  846. print column_end();
  847. print column_start("twelve");
  848. print $object->show_price(10, $object->id);
  849. print column_end();
  850. print '</div></div>';
  851. }
  852. } else if ($action != 'create') {
  853. header("Location: index.php");
  854. exit;
  855. }
  856. }
  857. // Define confirmation messages
  858. $formquestionclone = array(
  859. 'text' => $langs->trans("ConfirmClone"),
  860. array('type' => 'text', 'name' => 'clone_ref', 'label' => $langs->trans("NewRefForClone"), 'value' => $langs->trans("CopyOf") . ' ' . $object->ref, 'size' => 24),
  861. array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneContentProduct"), 'value' => 1),
  862. array('type' => 'checkbox', 'name' => 'clone_prices', 'label' => $langs->trans("ClonePricesProduct") . ' (' . $langs->trans("FeatureNotYetAvailable") . ')', 'value' => 0, 'disabled' => true)
  863. );
  864. // Confirm delete product
  865. if ($action == 'delete' && empty($conf->use_javascript_ajax)) {
  866. print $form->formconfirm("fiche.php?id=" . $object->id, $langs->trans("DeleteProduct"), $langs->trans("ConfirmDeleteProduct"), "confirm_delete", '', 0, "action-delete");
  867. }
  868. // Clone confirmation
  869. if ($action == 'clone' && empty($conf->use_javascript_ajax)) {
  870. print $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('CloneProduct'), $langs->trans('ConfirmCloneProduct', $object->ref), 'confirm_clone', $formquestionclone, 'yes', 'action-clone', 230, 600);
  871. }
  872. llxFooter();
  873. ?>