card.php 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929
  1. <?php
  2. /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2015 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-2014 Marcos García <marcosgdf@gmail.com>
  10. * Copyright (C) 2012-2013 Cédric Salvador <csalvador@gpcsolutions.fr>
  11. * Copyright (C) 2011-2016 Alexandre Spangaro <aspangaro.dolibarr@gmail.com>
  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. *
  18. * This program is free software; you can redistribute it and/or modify
  19. * it under the terms of the GNU General Public License as published by
  20. * the Free Software Foundation; either version 3 of the License, or
  21. * (at your option) any later version.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU General Public License
  29. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  30. */
  31. /**
  32. * \file htdocs/product/card.php
  33. * \ingroup product
  34. * \brief Page to show product
  35. */
  36. require '../main.inc.php';
  37. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
  38. require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
  39. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  40. require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
  41. require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
  42. require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php';
  43. require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
  44. require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
  45. require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  46. require_once DOL_DOCUMENT_ROOT.'/core/modules/product/modules_product.php';
  47. if (! empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
  48. if (! empty($conf->facture->enabled)) require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
  49. if (! empty($conf->commande->enabled)) require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
  50. if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
  51. if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/accountancy/class/html.formventilation.class.php';
  52. $langs->load("products");
  53. $langs->load("other");
  54. if (! empty($conf->stock->enabled)) $langs->load("stocks");
  55. if (! empty($conf->facture->enabled)) $langs->load("bills");
  56. if (! empty($conf->productbatch->enabled)) $langs->load("productbatch");
  57. $mesg=''; $error=0; $errors=array();
  58. $refalreadyexists=0;
  59. $id=GETPOST('id', 'int');
  60. $ref=GETPOST('ref', 'alpha');
  61. $type=GETPOST('type','int');
  62. $action=(GETPOST('action','alpha') ? GETPOST('action','alpha') : 'view');
  63. $cancel=GETPOST('cancel');
  64. $confirm=GETPOST('confirm','alpha');
  65. $socid=GETPOST('socid','int');
  66. $duration_value = GETPOST('duration_value');
  67. $duration_unit = GETPOST('duration_unit');
  68. if (! empty($user->societe_id)) $socid=$user->societe_id;
  69. $object = new Product($db);
  70. $extrafields = new ExtraFields($db);
  71. // fetch optionals attributes and labels
  72. $extralabels=$extrafields->fetch_name_optionals_label($object->table_element);
  73. $object = new Product($db);
  74. if ($id > 0 || ! empty($ref))
  75. {
  76. $result = $object->fetch($id, $ref);
  77. 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);
  78. 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);
  79. if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) // For backward compatiblity, we scan also old dirs
  80. {
  81. 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";
  82. 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";
  83. }
  84. }
  85. $modulepart='product';
  86. // Get object canvas (By default, this is not defined, so standard usage of dolibarr)
  87. $canvas = !empty($object->canvas)?$object->canvas:GETPOST("canvas");
  88. $objcanvas=null;
  89. if (! empty($canvas))
  90. {
  91. require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
  92. $objcanvas = new Canvas($db,$action);
  93. $objcanvas->getCanvas('product','card',$canvas);
  94. }
  95. // Security check
  96. $fieldvalue = (! empty($id) ? $id : (! empty($ref) ? $ref : ''));
  97. $fieldtype = (! empty($ref) ? 'ref' : 'rowid');
  98. $result=restrictedArea($user,'produit|service',$fieldvalue,'product&product','','',$fieldtype,$objcanvas);
  99. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  100. $hookmanager->initHooks(array('productcard','globalcard'));
  101. /*
  102. * Actions
  103. */
  104. if ($cancel) $action = '';
  105. $createbarcode=empty($conf->barcode->enabled)?0:1;
  106. if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->creer_advance)) $createbarcode=0;
  107. $parameters=array('id'=>$id, 'ref'=>$ref, 'objcanvas'=>$objcanvas);
  108. $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  109. if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  110. if (empty($reshook))
  111. {
  112. // Type
  113. if ($action == 'setfk_product_type' && $user->rights->produit->creer)
  114. {
  115. $result = $object->setValueFrom('fk_product_type', GETPOST('fk_product_type'));
  116. header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
  117. exit;
  118. }
  119. /*
  120. * Build doc
  121. */
  122. else if ($action == 'builddoc' && $user->rights->produit->creer)
  123. {
  124. // Save last template used to generate document
  125. if (GETPOST('model')) $object->setDocModel($user, GETPOST('model','alpha'));
  126. // Define output language
  127. $outputlangs = $langs;
  128. $newlang='';
  129. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','alpha')) $newlang=GETPOST('lang_id','alpha');
  130. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->thirdparty->default_lang;
  131. if (! empty($newlang))
  132. {
  133. $outputlangs = new Translate("",$conf);
  134. $outputlangs->setDefaultLang($newlang);
  135. }
  136. $result=product_create($db, $object, GETPOST('model','alpha'), $outputlangs);
  137. if ($result <= 0)
  138. {
  139. dol_print_error($db,$result);
  140. exit;
  141. }
  142. }
  143. // Barcode type
  144. if ($action == 'setfk_barcode_type' && $createbarcode)
  145. {
  146. $result = $object->setValueFrom('fk_barcode_type', GETPOST('fk_barcode_type'));
  147. header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
  148. exit;
  149. }
  150. // Barcode value
  151. if ($action == 'setbarcode' && $createbarcode)
  152. {
  153. $result=$object->check_barcode(GETPOST('barcode'),GETPOST('barcode_type_code'));
  154. if ($result >= 0)
  155. {
  156. $result = $object->setValueFrom('barcode', GETPOST('barcode'));
  157. header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
  158. exit;
  159. }
  160. else
  161. {
  162. $langs->load("errors");
  163. if ($result == -1) $errors[] = 'ErrorBadBarCodeSyntax';
  164. else if ($result == -2) $errors[] = 'ErrorBarCodeRequired';
  165. else if ($result == -3) $errors[] = 'ErrorBarCodeAlreadyUsed';
  166. else $errors[] = 'FailedToValidateBarCode';
  167. $error++;
  168. setEventMessages($errors, null, 'errors');
  169. }
  170. }
  171. /*
  172. if ($action == 'setaccountancy_code_buy') {
  173. $result = $object->setAccountancyCode('buy', GETPOST('accountancy_code_buy'));
  174. if ($result < 0) setEventMessages(join(',',$object->errors), null, 'errors');
  175. $action="";
  176. }
  177. if ($action == 'setaccountancy_code_sell')
  178. {
  179. $result = $object->setAccountancyCode('sell', GETPOST('accountancy_code_sell'));
  180. if ($result < 0) setEventMessages(join(',',$object->errors), null, 'errors');
  181. $action="";
  182. }
  183. */
  184. // Add a product or service
  185. if ($action == 'add' && ($user->rights->produit->creer || $user->rights->service->creer))
  186. {
  187. $error=0;
  188. if (! GETPOST('label'))
  189. {
  190. setEventMessages($langs->trans('ErrorFieldRequired',$langs->transnoentities('Label')), null, 'errors');
  191. $action = "create";
  192. $error++;
  193. }
  194. if (empty($ref))
  195. {
  196. setEventMessages($langs->trans('ErrorFieldRequired',$langs->transnoentities('Ref')), null, 'errors');
  197. $action = "create";
  198. $error++;
  199. }
  200. if (! empty($duration_value) && empty($duration_unit))
  201. {
  202. setEventMessages($langs->trans('ErrorFieldRequired',$langs->transnoentities('Unit')), null, 'errors');
  203. $action = "create";
  204. $error++;
  205. }
  206. if (! $error)
  207. {
  208. $units = GETPOST('units', 'int');
  209. $object->ref = $ref;
  210. $object->label = GETPOST('label');
  211. $object->price_base_type = GETPOST('price_base_type');
  212. if ($object->price_base_type == 'TTC')
  213. $object->price_ttc = GETPOST('price');
  214. else
  215. $object->price = GETPOST('price');
  216. if ($object->price_base_type == 'TTC')
  217. $object->price_min_ttc = GETPOST('price_min');
  218. else
  219. $object->price_min = GETPOST('price_min');
  220. $object->tva_tx = str_replace('*','',GETPOST('tva_tx'));
  221. $object->tva_npr = preg_match('/\*/',GETPOST('tva_tx'))?1:0;
  222. // local taxes.
  223. $object->localtax1_tx = get_localtax($object->tva_tx,1);
  224. $object->localtax2_tx = get_localtax($object->tva_tx,2);
  225. $object->type = $type;
  226. $object->status = GETPOST('statut');
  227. $object->status_buy = GETPOST('statut_buy');
  228. $object->status_batch = GETPOST('status_batch');
  229. $object->barcode_type = GETPOST('fk_barcode_type');
  230. $object->barcode = GETPOST('barcode');
  231. // Set barcode_type_xxx from barcode_type id
  232. $stdobject=new GenericObject($db);
  233. $stdobject->element='product';
  234. $stdobject->barcode_type=GETPOST('fk_barcode_type');
  235. $result=$stdobject->fetch_barcode();
  236. if ($result < 0)
  237. {
  238. $error++;
  239. $mesg='Failed to get bar code type information ';
  240. setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors');
  241. }
  242. $object->barcode_type_code = $stdobject->barcode_type_code;
  243. $object->barcode_type_coder = $stdobject->barcode_type_coder;
  244. $object->barcode_type_label = $stdobject->barcode_type_label;
  245. $object->description = dol_htmlcleanlastbr(GETPOST('desc'));
  246. $object->url = GETPOST('url');
  247. $object->note = dol_htmlcleanlastbr(GETPOST('note'));
  248. $object->customcode = GETPOST('customcode');
  249. $object->country_id = GETPOST('country_id');
  250. $object->duration_value = $duration_value;
  251. $object->duration_unit = $duration_unit;
  252. $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte')?GETPOST('seuil_stock_alerte'):0;
  253. $object->desiredstock = GETPOST('desiredstock')?GETPOST('desiredstock'):0;
  254. $object->canvas = GETPOST('canvas');
  255. $object->weight = GETPOST('weight');
  256. $object->weight_units = GETPOST('weight_units');
  257. $object->length = GETPOST('size');
  258. $object->length_units = GETPOST('size_units');
  259. $object->surface = GETPOST('surface');
  260. $object->surface_units = GETPOST('surface_units');
  261. $object->volume = GETPOST('volume');
  262. $object->volume_units = GETPOST('volume_units');
  263. $object->finished = GETPOST('finished');
  264. $object->fk_unit = GETPOST('units');
  265. $accountancy_code_sell = GETPOST('accountancy_code_sell');
  266. $accountancy_code_buy = GETPOST('accountancy_code_buy');
  267. if ($accountancy_code_sell <= 0) { $object->accountancy_code_sell = ''; } else { $object->accountancy_code_sell = $accountancy_code_sell; }
  268. if ($accountancy_code_buy <= 0) { $object->accountancy_code_buy = ''; } else { $object->accountancy_code_buy = $accountancy_code_buy; }
  269. // MultiPrix
  270. if (! empty($conf->global->PRODUIT_MULTIPRICES))
  271. {
  272. for($i=2;$i<=$conf->global->PRODUIT_MULTIPRICES_LIMIT;$i++)
  273. {
  274. if (isset($_POST["price_".$i]))
  275. {
  276. $object->multiprices["$i"] = price2num($_POST["price_".$i],'MU');
  277. $object->multiprices_base_type["$i"] = $_POST["multiprices_base_type_".$i];
  278. }
  279. else
  280. {
  281. $object->multiprices["$i"] = "";
  282. }
  283. }
  284. }
  285. // Fill array 'array_options' with data from add form
  286. $ret = $extrafields->setOptionalsFromPost($extralabels,$object);
  287. if ($ret < 0) $error++;
  288. if (! $error)
  289. {
  290. $id = $object->create($user);
  291. }
  292. if ($id > 0)
  293. {
  294. // Category association
  295. $categories = GETPOST('categories');
  296. $object->setCategories($categories);
  297. header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
  298. exit;
  299. }
  300. else
  301. {
  302. if (count($object->errors)) setEventMessages($object->error, $object->errors, 'errors');
  303. else setEventMessages($langs->trans($object->error), null, 'errors');
  304. $action = "create";
  305. }
  306. }
  307. }
  308. // Update a product or service
  309. if ($action == 'update' && ($user->rights->produit->creer || $user->rights->service->creer))
  310. {
  311. if (GETPOST('cancel'))
  312. {
  313. $action = '';
  314. }
  315. else
  316. {
  317. if ($object->id > 0)
  318. {
  319. $object->oldcopy= clone $object;
  320. $object->ref = $ref;
  321. $object->label = GETPOST('label');
  322. $object->description = dol_htmlcleanlastbr(GETPOST('desc'));
  323. $object->url = GETPOST('url');
  324. $object->note = dol_htmlcleanlastbr(GETPOST('note'));
  325. $object->customcode = GETPOST('customcode');
  326. $object->country_id = GETPOST('country_id');
  327. $object->status = GETPOST('statut');
  328. $object->status_buy = GETPOST('statut_buy');
  329. $object->status_batch = GETPOST('status_batch');
  330. // removed from update view so GETPOST always empty
  331. /*
  332. $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte');
  333. $object->desiredstock = GETPOST('desiredstock');
  334. */
  335. $object->duration_value = GETPOST('duration_value');
  336. $object->duration_unit = GETPOST('duration_unit');
  337. $object->canvas = GETPOST('canvas');
  338. $object->weight = GETPOST('weight');
  339. $object->weight_units = GETPOST('weight_units');
  340. $object->length = GETPOST('size');
  341. $object->length_units = GETPOST('size_units');
  342. $object->surface = GETPOST('surface');
  343. $object->surface_units = GETPOST('surface_units');
  344. $object->volume = GETPOST('volume');
  345. $object->volume_units = GETPOST('volume_units');
  346. $object->finished = GETPOST('finished');
  347. $units = GETPOST('units', 'int');
  348. if ($units > 0) {
  349. $object->fk_unit = $units;
  350. } else {
  351. $object->fk_unit = null;
  352. }
  353. $object->barcode_type = GETPOST('fk_barcode_type');
  354. $object->barcode = GETPOST('barcode');
  355. // Set barcode_type_xxx from barcode_type id
  356. $stdobject=new GenericObject($db);
  357. $stdobject->element='product';
  358. $stdobject->barcode_type=GETPOST('fk_barcode_type');
  359. $result=$stdobject->fetch_barcode();
  360. if ($result < 0)
  361. {
  362. $error++;
  363. $mesg='Failed to get bar code type information ';
  364. setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors');
  365. }
  366. $object->barcode_type_code = $stdobject->barcode_type_code;
  367. $object->barcode_type_coder = $stdobject->barcode_type_coder;
  368. $object->barcode_type_label = $stdobject->barcode_type_label;
  369. $accountancy_code_sell = GETPOST('accountancy_code_sell');
  370. $accountancy_code_buy = GETPOST('accountancy_code_buy');
  371. if ($accountancy_code_sell <= 0) { $object->accountancy_code_sell = ''; } else { $object->accountancy_code_sell = $accountancy_code_sell; }
  372. if ($accountancy_code_buy <= 0) { $object->accountancy_code_buy = ''; } else { $object->accountancy_code_buy = $accountancy_code_buy; }
  373. // Fill array 'array_options' with data from add form
  374. $ret = $extrafields->setOptionalsFromPost($extralabels,$object);
  375. if ($ret < 0) $error++;
  376. if (! $error && $object->check())
  377. {
  378. if ($object->update($object->id, $user) > 0)
  379. {
  380. // Category association
  381. $categories = GETPOST('categories');
  382. $object->setCategories($categories);
  383. $action = 'view';
  384. }
  385. else
  386. {
  387. if (count($object->errors)) setEventMessages($object->error, $object->errors, 'errors');
  388. else setEventMessages($langs->trans($object->error), null, 'errors');
  389. $action = 'edit';
  390. }
  391. }
  392. else
  393. {
  394. if (count($object->errors)) setEventMessages($object->error, $object->errors, 'errors');
  395. else setEventMessages($langs->trans("ErrorProductBadRefOrLabel"), null, 'errors');
  396. $action = 'edit';
  397. }
  398. }
  399. }
  400. }
  401. // Action clone object
  402. if ($action == 'confirm_clone' && $confirm != 'yes') { $action=''; }
  403. if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->produit->creer || $user->rights->service->creer))
  404. {
  405. if (! GETPOST('clone_content') && ! GETPOST('clone_prices') )
  406. {
  407. setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
  408. }
  409. else
  410. {
  411. $db->begin();
  412. $originalId = $id;
  413. if ($object->id > 0)
  414. {
  415. $object->ref = GETPOST('clone_ref');
  416. $object->status = 0;
  417. $object->status_buy = 0;
  418. $object->id = null;
  419. $object->barcode = -1;
  420. if ($object->check())
  421. {
  422. $id = $object->create($user);
  423. if ($id > 0)
  424. {
  425. if (GETPOST('clone_composition'))
  426. {
  427. $result = $object->clone_associations($originalId, $id);
  428. if ($result < 1)
  429. {
  430. $db->rollback();
  431. setEventMessages($langs->trans('ErrorProductClone'), null, 'errors');
  432. header("Location: ".$_SERVER["PHP_SELF"]."?id=".$originalId);
  433. exit;
  434. }
  435. }
  436. // $object->clone_fournisseurs($originalId, $id);
  437. $db->commit();
  438. $db->close();
  439. header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
  440. exit;
  441. }
  442. else
  443. {
  444. $id=$originalId;
  445. if ($object->error == 'ErrorProductAlreadyExists')
  446. {
  447. $db->rollback();
  448. $refalreadyexists++;
  449. $action = "";
  450. $mesg=$langs->trans("ErrorProductAlreadyExists",$object->ref);
  451. $mesg.=' <a href="'.$_SERVER["PHP_SELF"].'?ref='.$object->ref.'">'.$langs->trans("ShowCardHere").'</a>.';
  452. setEventMessages($mesg, null, 'errors');
  453. $object->fetch($id);
  454. }
  455. else
  456. {
  457. $db->rollback();
  458. if (count($object->errors))
  459. {
  460. setEventMessages($object->error, $object->errors, 'errors');
  461. dol_print_error($db,$object->errors);
  462. }
  463. else
  464. {
  465. setEventMessages($langs->trans($object->error), null, 'errors');
  466. dol_print_error($db,$object->error);
  467. }
  468. }
  469. }
  470. }
  471. }
  472. else
  473. {
  474. $db->rollback();
  475. dol_print_error($db,$object->error);
  476. }
  477. }
  478. }
  479. // Delete a product
  480. if ($action == 'confirm_delete' && $confirm != 'yes') { $action=''; }
  481. if ($action == 'confirm_delete' && $confirm == 'yes')
  482. {
  483. if (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->supprimer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->supprimer))
  484. {
  485. $result = $object->delete($object->id);
  486. }
  487. if ($result > 0)
  488. {
  489. header('Location: '.DOL_URL_ROOT.'/product/list.php?type='.$object->type.'&delprod='.urlencode($object->ref));
  490. exit;
  491. }
  492. else
  493. {
  494. setEventMessages($langs->trans($object->error), null, 'errors');
  495. $reload = 0;
  496. $action='';
  497. }
  498. }
  499. // Add product into object
  500. if ($object->id > 0 && $action == 'addin')
  501. {
  502. $thirpdartyid =0 ;
  503. if (GETPOST('propalid') > 0)
  504. {
  505. $propal = new Propal($db);
  506. $result=$propal->fetch(GETPOST('propalid'));
  507. if ($result <= 0)
  508. {
  509. dol_print_error($db,$propal->error);
  510. exit;
  511. }
  512. $thirpdartyid = $propal->socid;
  513. }
  514. elseif (GETPOST('commandeid') > 0)
  515. {
  516. $commande = new Commande($db);
  517. $result=$commande->fetch(GETPOST('commandeid'));
  518. if ($result <= 0)
  519. {
  520. dol_print_error($db,$commande->error);
  521. exit;
  522. }
  523. $thirpdartyid = $commande->socid;
  524. }
  525. elseif (GETPOST('factureid') > 0)
  526. {
  527. $facture = new Facture($db);
  528. $result=$facture->fetch(GETPOST('factureid'));
  529. if ($result <= 0)
  530. {
  531. dol_print_error($db,$facture->error);
  532. exit;
  533. }
  534. $thirpdartyid = $facture->socid;
  535. }
  536. if ( $thirpdartyid > 0) {
  537. $soc = new Societe($db);
  538. $result = $soc->fetch($thirpdartyid);
  539. if ($result <= 0) {
  540. dol_print_error($db, $soc->error);
  541. exit;
  542. }
  543. $desc = $object->description;
  544. $tva_tx = get_default_tva($mysoc, $soc, $object->id);
  545. $tva_npr = get_default_npr($mysoc, $soc, $object->id);
  546. if (empty($tva_tx)) $tva_npr=0;
  547. $localtax1_tx = get_localtax($tva_tx, 1, $soc, $mysoc, $tva_npr);
  548. $localtax2_tx = get_localtax($tva_tx, 2, $soc, $mysoc, $tva_npr);
  549. $pu_ht = $object->price;
  550. $pu_ttc = $object->price_ttc;
  551. $price_base_type = $object->price_base_type;
  552. // If multiprice
  553. if ($conf->global->PRODUIT_MULTIPRICES && $soc->price_level) {
  554. $pu_ht = $object->multiprices[$soc->price_level];
  555. $pu_ttc = $object->multiprices_ttc[$soc->price_level];
  556. $price_base_type = $object->multiprices_base_type[$soc->price_level];
  557. } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
  558. require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
  559. $prodcustprice = new Productcustomerprice($db);
  560. $filter = array('t.fk_product' => $object->id, 't.fk_soc' => $soc->id);
  561. $result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
  562. if ($result) {
  563. if (count($prodcustprice->lines) > 0) {
  564. $pu_ht = price($prodcustprice->lines [0]->price);
  565. $pu_ttc = price($prodcustprice->lines [0]->price_ttc);
  566. $price_base_type = $prodcustprice->lines [0]->price_base_type;
  567. $prod->tva_tx = $prodcustprice->lines [0]->tva_tx;
  568. }
  569. }
  570. }
  571. // On reevalue prix selon taux tva car taux tva transaction peut etre different
  572. // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
  573. if ($tva_tx != $object->tva_tx) {
  574. if ($price_base_type != 'HT') {
  575. $pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
  576. } else {
  577. $pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
  578. }
  579. }
  580. if (GETPOST('propalid') > 0) {
  581. $result = $propal->addline(
  582. $desc,
  583. $pu_ht,
  584. GETPOST('qty'),
  585. $tva_tx,
  586. $localtax1_tx, // localtax1
  587. $localtax2_tx, // localtax2
  588. $object->id,
  589. GETPOST('remise_percent'),
  590. $price_base_type,
  591. $pu_ttc,
  592. 0,
  593. 0,
  594. -1,
  595. 0,
  596. 0,
  597. 0,
  598. 0,
  599. '',
  600. '',
  601. '',
  602. 0,
  603. $object->fk_unit
  604. );
  605. if ($result > 0) {
  606. header("Location: " . DOL_URL_ROOT . "/comm/propal/card.php?id=" . $propal->id);
  607. return;
  608. }
  609. setEventMessages($langs->trans("ErrorUnknown") . ": $result", null, 'errors');
  610. } elseif (GETPOST('commandeid') > 0) {
  611. $result = $commande->addline(
  612. $desc,
  613. $pu_ht,
  614. GETPOST('qty'),
  615. $tva_tx,
  616. $localtax1_tx, // localtax1
  617. $localtax2_tx, // localtax2
  618. $object->id,
  619. GETPOST('remise_percent'),
  620. '',
  621. '',
  622. $price_base_type,
  623. $pu_ttc,
  624. '',
  625. '',
  626. 0,
  627. -1,
  628. 0,
  629. 0,
  630. null,
  631. 0,
  632. '',
  633. 0,
  634. $object->fk_unit
  635. );
  636. if ($result > 0) {
  637. header("Location: " . DOL_URL_ROOT . "/commande/card.php?id=" . $commande->id);
  638. exit;
  639. }
  640. } elseif (GETPOST('factureid') > 0) {
  641. $result = $facture->addline(
  642. $desc,
  643. $pu_ht,
  644. GETPOST('qty'),
  645. $tva_tx,
  646. $localtax1_tx,
  647. $localtax2_tx,
  648. $object->id,
  649. GETPOST('remise_percent'),
  650. '',
  651. '',
  652. '',
  653. '',
  654. '',
  655. $price_base_type,
  656. $pu_ttc,
  657. Facture::TYPE_STANDARD,
  658. -1,
  659. 0,
  660. '',
  661. 0,
  662. 0,
  663. null,
  664. 0,
  665. '',
  666. 0,
  667. 100,
  668. '',
  669. $object->fk_unit
  670. );
  671. if ($result > 0) {
  672. header("Location: " . DOL_URL_ROOT . "/compta/facture.php?facid=" . $facture->id);
  673. exit;
  674. }
  675. }
  676. }
  677. else {
  678. $action="";
  679. setEventMessages($langs->trans("WarningSelectOneDocument"), null, 'warnings');
  680. }
  681. }
  682. }
  683. /*
  684. * View
  685. */
  686. $helpurl='';
  687. if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) $helpurl='EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
  688. if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) $helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
  689. if (isset($_GET['type'])) $title = $langs->trans('CardProduct'.GETPOST('type'));
  690. else $title = $langs->trans('ProductServiceCard');
  691. llxHeader('', $title, $helpurl);
  692. $form = new Form($db);
  693. $formfile = new FormFile($db);
  694. $formproduct = new FormProduct($db);
  695. if (! empty($conf->accounting->enabled)) $formaccountancy = New FormVentilation($db);
  696. if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action))
  697. {
  698. // -----------------------------------------
  699. // When used with CANVAS
  700. // -----------------------------------------
  701. if (empty($object->error) && $id)
  702. {
  703. $object = new Product($db);
  704. $result=$object->fetch($id);
  705. if ($result <= 0) dol_print_error('',$object->error);
  706. }
  707. $objcanvas->assign_values($action, $object->id, $object->ref); // Set value for templates
  708. $objcanvas->display_canvas($action); // Show template
  709. }
  710. else
  711. {
  712. // -----------------------------------------
  713. // When used in standard mode
  714. // -----------------------------------------
  715. if ($action == 'create' && ($user->rights->produit->creer || $user->rights->service->creer))
  716. {
  717. //WYSIWYG Editor
  718. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  719. // Load object modCodeProduct
  720. $module=(! empty($conf->global->PRODUCT_CODEPRODUCT_ADDON)?$conf->global->PRODUCT_CODEPRODUCT_ADDON:'mod_codeproduct_leopard');
  721. if (substr($module, 0, 16) == 'mod_codeproduct_' && substr($module, -3) == 'php')
  722. {
  723. $module = substr($module, 0, dol_strlen($module)-4);
  724. }
  725. $result=dol_include_once('/core/modules/product/'.$module.'.php');
  726. if ($result > 0)
  727. {
  728. $modCodeProduct = new $module();
  729. }
  730. // Load object modBarCodeProduct
  731. if (! empty($conf->barcode->enabled) && ! empty($conf->global->BARCODE_PRODUCT_ADDON_NUM))
  732. {
  733. $module=strtolower($conf->global->BARCODE_PRODUCT_ADDON_NUM);
  734. $dirbarcode=array_merge(array('/core/modules/barcode/'),$conf->modules_parts['barcode']);
  735. foreach ($dirbarcode as $dirroot)
  736. {
  737. $res=dol_include_once($dirroot.$module.'.php');
  738. if ($res) break;
  739. }
  740. if ($res > 0)
  741. {
  742. $modBarCodeProduct =new $module();
  743. }
  744. }
  745. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  746. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  747. print '<input type="hidden" name="action" value="add">';
  748. print '<input type="hidden" name="type" value="'.$type.'">'."\n";
  749. if (! empty($modCodeProduct->code_auto))
  750. print '<input type="hidden" name="code_auto" value="1">';
  751. if (! empty($modBarCodeProduct->code_auto))
  752. print '<input type="hidden" name="barcode_auto" value="1">';
  753. if ($type==1) $title=$langs->trans("NewService");
  754. else $title=$langs->trans("NewProduct");
  755. $linkback="";
  756. print load_fiche_titre($title,$linkback,'title_products.png');
  757. dol_fiche_head('');
  758. print '<table class="border" width="100%">';
  759. print '<tr>';
  760. $tmpcode='';
  761. if (! empty($modCodeProduct->code_auto)) $tmpcode=$modCodeProduct->getNextValue($object,$type);
  762. print '<td class="fieldrequired" width="20%">'.$langs->trans("Ref").'</td><td colspan="3"><input name="ref" size="32" maxlength="128" value="'.dol_escape_htmltag(GETPOST('ref')?GETPOST('ref'):$tmpcode).'">';
  763. if ($refalreadyexists)
  764. {
  765. print $langs->trans("RefAlreadyExists");
  766. }
  767. print '</td></tr>';
  768. // Label
  769. print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td colspan="3"><input name="label" size="40" maxlength="255" value="'.dol_escape_htmltag(GETPOST('label')).'"></td></tr>';
  770. // On sell
  771. print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Sell").')</td><td colspan="3">';
  772. $statutarray=array('1' => $langs->trans("OnSell"), '0' => $langs->trans("NotOnSell"));
  773. print $form->selectarray('statut',$statutarray,GETPOST('statut'));
  774. print '</td></tr>';
  775. // To buy
  776. print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Buy").')</td><td colspan="3">';
  777. $statutarray=array('1' => $langs->trans("ProductStatusOnBuy"), '0' => $langs->trans("ProductStatusNotOnBuy"));
  778. print $form->selectarray('statut_buy',$statutarray,GETPOST('statut_buy'));
  779. print '</td></tr>';
  780. // Batch number management
  781. if (! empty($conf->productbatch->enabled))
  782. {
  783. print '<tr><td>'.$langs->trans("ManageLotSerial").'</td><td colspan="3">';
  784. $statutarray=array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"));
  785. print $form->selectarray('status_batch',$statutarray,GETPOST('status_batch'));
  786. print '</td></tr>';
  787. }
  788. $showbarcode=empty($conf->barcode->enabled)?0:1;
  789. if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode=0;
  790. if ($showbarcode)
  791. {
  792. print '<tr><td>'.$langs->trans('BarcodeType').'</td><td>';
  793. if (isset($_POST['fk_barcode_type']))
  794. {
  795. $fk_barcode_type=GETPOST('fk_barcode_type');
  796. }
  797. else
  798. {
  799. if (empty($fk_barcode_type) && ! empty($conf->global->PRODUIT_DEFAULT_BARCODE_TYPE)) $fk_barcode_type = $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE;
  800. }
  801. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbarcode.class.php';
  802. $formbarcode = new FormBarCode($db);
  803. print $formbarcode->select_barcode_type($fk_barcode_type, 'fk_barcode_type', 1);
  804. print '</td><td>'.$langs->trans("BarcodeValue").'</td><td>';
  805. $tmpcode=isset($_POST['barcode'])?GETPOST('barcode'):$object->barcode;
  806. if (empty($tmpcode) && ! empty($modBarCodeProduct->code_auto)) $tmpcode=$modBarCodeProduct->getNextValue($object,$type);
  807. print '<input size="40" type="text" name="barcode" value="'.dol_escape_htmltag($tmpcode).'">';
  808. print '</td></tr>';
  809. }
  810. // Description (used in invoice, propal...)
  811. print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
  812. $doleditor = new DolEditor('desc', GETPOST('desc'), '', 160, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, '80%');
  813. $doleditor->Create();
  814. print "</td></tr>";
  815. // Public URL
  816. print '<tr><td>'.$langs->trans("PublicUrl").'</td><td colspan="3">';
  817. print '<input type="text" name="url" size="90" value="'.GETPOST('url').'">';
  818. print '</td></tr>';
  819. // Stock min level
  820. if ($type != 1 && ! empty($conf->stock->enabled))
  821. {
  822. print '<tr><td>'.$langs->trans("StockLimit").'</td><td>';
  823. print '<input name="seuil_stock_alerte" size="4" value="'.GETPOST('seuil_stock_alerte').'">';
  824. print '</td>';
  825. // Stock desired level
  826. print '<td>'.$langs->trans("DesiredStock").'</td><td>';
  827. print '<input name="desiredstock" size="4" value="'.GETPOST('desiredstock').'">';
  828. print '</td></tr>';
  829. }
  830. else
  831. {
  832. print '<input name="seuil_stock_alerte" type="hidden" value="0">';
  833. print '<input name="desiredstock" type="hidden" value="0">';
  834. }
  835. // Nature
  836. if ($type != 1)
  837. {
  838. print '<tr><td>'.$langs->trans("Nature").'</td><td colspan="3">';
  839. $statutarray=array('1' => $langs->trans("Finished"), '0' => $langs->trans("RowMaterial"));
  840. print $form->selectarray('finished',$statutarray,GETPOST('finished'),1);
  841. print '</td></tr>';
  842. }
  843. // Duration
  844. if ($type == 1)
  845. {
  846. print '<tr><td>' . $langs->trans("Duration") . '</td><td colspan="3"><input name="duration_value" size="6" maxlength="5" value="' . $duration_value . '"> &nbsp;';
  847. print '<input name="duration_unit" type="radio" value="h">'.$langs->trans("Hour").'&nbsp;';
  848. print '<input name="duration_unit" type="radio" value="d">'.$langs->trans("Day").'&nbsp;';
  849. print '<input name="duration_unit" type="radio" value="w">'.$langs->trans("Week").'&nbsp;';
  850. print '<input name="duration_unit" type="radio" value="m">'.$langs->trans("Month").'&nbsp;';
  851. print '<input name="duration_unit" type="radio" value="y">'.$langs->trans("Year").'&nbsp;';
  852. print '</td></tr>';
  853. }
  854. if ($type != 1) // Le poids et le volume ne concerne que les produits et pas les services
  855. {
  856. // Weight
  857. print '<tr><td>'.$langs->trans("Weight").'</td><td colspan="3">';
  858. print '<input name="weight" size="4" value="'.GETPOST('weight').'">';
  859. print $formproduct->select_measuring_units("weight_units","weight");
  860. print '</td></tr>';
  861. // Length
  862. if (empty($conf->global->PRODUCT_DISABLE_LENGTH))
  863. {
  864. print '<tr><td>'.$langs->trans("Length").'</td><td colspan="3">';
  865. print '<input name="size" size="4" value="'.GETPOST('size').'">';
  866. print $formproduct->select_measuring_units("size_units","size");
  867. print '</td></tr>';
  868. }
  869. if (empty($conf->global->PRODUCT_DISABLE_SURFACE))
  870. {
  871. // Surface
  872. print '<tr><td>'.$langs->trans("Surface").'</td><td colspan="3">';
  873. print '<input name="surface" size="4" value="'.GETPOST('surface').'">';
  874. print $formproduct->select_measuring_units("surface_units","surface");
  875. print '</td></tr>';
  876. }
  877. // Volume
  878. print '<tr><td>'.$langs->trans("Volume").'</td><td colspan="3">';
  879. print '<input name="volume" size="4" value="'.GETPOST('volume').'">';
  880. print $formproduct->select_measuring_units("volume_units","volume");
  881. print '</td></tr>';
  882. }
  883. // Units
  884. if($conf->global->PRODUCT_USE_UNITS)
  885. {
  886. print '<tr><td>'.$langs->trans('DefaultUnitToShow').'</td>';
  887. print '<td colspan="3">';
  888. print $form->selectUnits('','units');
  889. print '</td></tr>';
  890. }
  891. // Custom code
  892. if (empty($conf->global->PRODUCT_DISABLE_CUSTOM_INFO))
  893. {
  894. print '<tr><td>'.$langs->trans("CustomCode").'</td><td><input name="customcode" size="10" value="'.GETPOST('customcode').'"></td>';
  895. // Origin country
  896. print '<td>'.$langs->trans("CountryOrigin").'</td><td>';
  897. print $form->select_country(GETPOST('country_id','int'),'country_id');
  898. if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
  899. print '</td></tr>';
  900. }
  901. // Other attributes
  902. $parameters=array('colspan' => 3);
  903. $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  904. if (empty($reshook) && ! empty($extrafields->attribute_label))
  905. {
  906. print $object->showOptionals($extrafields,'edit',$parameters);
  907. }
  908. // Note (private, no output on invoices, propales...)
  909. print '<tr><td class="tdtop">'.$langs->trans("NoteNotVisibleOnBill").'</td><td colspan="3">';
  910. // 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.
  911. $doleditor = new DolEditor('note', GETPOST('note'), '', 140, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 8, '80%');
  912. $doleditor->Create();
  913. print "</td></tr>";
  914. if($conf->categorie->enabled) {
  915. // Categories
  916. print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
  917. $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', 'parent', 64, 0, 1);
  918. print $form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, '', 0, '100%');
  919. print "</td></tr>";
  920. }
  921. print '</table>';
  922. print '<br>';
  923. if (! empty($conf->global->PRODUIT_MULTIPRICES))
  924. {
  925. // We do no show price array on create when multiprices enabled.
  926. // We must set them on prices tab.
  927. }
  928. else
  929. {
  930. print '<table class="border" width="100%">';
  931. // Price
  932. print '<tr><td>'.$langs->trans("SellingPrice").'</td>';
  933. print '<td><input name="price" size="10" value="'.$object->price.'">';
  934. print $form->selectPriceBaseType($object->price_base_type, "price_base_type");
  935. print '</td></tr>';
  936. // Min price
  937. print '<tr><td>'.$langs->trans("MinPrice").'</td>';
  938. print '<td><input name="price_min" size="10" value="'.$object->price_min.'">';
  939. print '</td></tr>';
  940. // VAT
  941. print '<tr><td width="20%">'.$langs->trans("VATRate").'</td><td>';
  942. print $form->load_tva("tva_tx",-1,$mysoc,'');
  943. print '</td></tr>';
  944. print '</table>';
  945. print '<br>';
  946. }
  947. print '<table class="border" width="100%">';
  948. if (! empty($conf->accounting->enabled))
  949. {
  950. // Accountancy_code_sell
  951. print '<tr><td width="20%">'.$langs->trans("ProductAccountancySellCode").'</td>';
  952. print '<td>';
  953. print $formaccountancy->select_account($object->accountancy_code_sell, 'accountancy_code_sell', 1, '', 0, 1);
  954. print '</td></tr>';
  955. // Accountancy_code_buy
  956. print '<tr><td width="20%">'.$langs->trans("ProductAccountancyBuyCode").'</td>';
  957. print '<td>';
  958. print $formaccountancy->select_account($object->accountancy_code_buy, 'accountancy_code_buy', 1, '', 0, 1);
  959. print '</td></tr>';
  960. }
  961. else // For external software
  962. {
  963. // Accountancy_code_sell
  964. print '<tr><td width="20%">'.$langs->trans("ProductAccountancySellCode").'</td>';
  965. print '<td><input name="accountancy_code_sell" size="16" value="'.$object->accountancy_code_sell.'">';
  966. print '</td></tr>';
  967. // Accountancy_code_buy
  968. print '<tr><td width="20%">'.$langs->trans("ProductAccountancyBuyCode").'</td>';
  969. print '<td><input name="accountancy_code_buy" size="16" value="'.$object->accountancy_code_buy.'">';
  970. print '</td></tr>';
  971. }
  972. print '</table>';
  973. dol_fiche_end();
  974. print '<div class="center"><input type="submit" class="button" value="'.$langs->trans("Create").'"></div>';
  975. print '</form>';
  976. }
  977. /*
  978. * Product card
  979. */
  980. else if ($object->id > 0)
  981. {
  982. // Fiche en mode edition
  983. if ($action == 'edit' && ((($object->type == Product::TYPE_PRODUCT && $user->rights->produit->creer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->creer))))
  984. {
  985. //WYSIWYG Editor
  986. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  987. $type = $langs->trans('Product');
  988. if ($object->isService()) $type = $langs->trans('Service');
  989. //print load_fiche_titre($langs->trans('Modify').' '.$type.' : '.(is_object($object->oldcopy)?$object->oldcopy->ref:$object->ref), "");
  990. // Main official, simple, and not duplicated code
  991. print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="POST">'."\n";
  992. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  993. print '<input type="hidden" name="action" value="update">';
  994. print '<input type="hidden" name="id" value="'.$object->id.'">';
  995. print '<input type="hidden" name="canvas" value="'.$object->canvas.'">';
  996. $head=product_prepare_head($object);
  997. $titre=$langs->trans("CardProduct".$object->type);
  998. $picto=($object->type== Product::TYPE_SERVICE?'service':'product');
  999. dol_fiche_head($head, 'card', $titre, 0, $picto);
  1000. print '<table class="border allwidth">';
  1001. // Ref
  1002. print '<tr><td width="20%" class="fieldrequired">'.$langs->trans("Ref").'</td><td colspan="3"><input name="ref" size="32" maxlength="128" value="'.dol_escape_htmltag($object->ref).'"></td></tr>';
  1003. // Label
  1004. print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td colspan="3"><input name="label" size="40" maxlength="255" value="'.dol_escape_htmltag($object->label).'"></td></tr>';
  1005. // Status To sell
  1006. print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Sell").')</td><td colspan="3">';
  1007. print '<select class="flat" name="statut">';
  1008. if ($object->status)
  1009. {
  1010. print '<option value="1" selected>'.$langs->trans("OnSell").'</option>';
  1011. print '<option value="0">'.$langs->trans("NotOnSell").'</option>';
  1012. }
  1013. else
  1014. {
  1015. print '<option value="1">'.$langs->trans("OnSell").'</option>';
  1016. print '<option value="0" selected>'.$langs->trans("NotOnSell").'</option>';
  1017. }
  1018. print '</select>';
  1019. print '</td></tr>';
  1020. // Status To Buy
  1021. print '<tr><td class="fieldrequired">'.$langs->trans("Status").' ('.$langs->trans("Buy").')</td><td colspan="3">';
  1022. print '<select class="flat" name="statut_buy">';
  1023. if ($object->status_buy)
  1024. {
  1025. print '<option value="1" selected>'.$langs->trans("ProductStatusOnBuy").'</option>';
  1026. print '<option value="0">'.$langs->trans("ProductStatusNotOnBuy").'</option>';
  1027. }
  1028. else
  1029. {
  1030. print '<option value="1">'.$langs->trans("ProductStatusOnBuy").'</option>';
  1031. print '<option value="0" selected>'.$langs->trans("ProductStatusNotOnBuy").'</option>';
  1032. }
  1033. print '</select>';
  1034. print '</td></tr>';
  1035. // Batch number managment
  1036. if ($conf->productbatch->enabled) {
  1037. print '<tr><td>'.$langs->trans("ManageLotSerial").'</td><td colspan="3">';
  1038. $statutarray=array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"));
  1039. print $form->selectarray('status_batch',$statutarray,$object->status_batch);
  1040. print '</td></tr>';
  1041. }
  1042. // Barcode
  1043. $showbarcode=empty($conf->barcode->enabled)?0:1;
  1044. if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode=0;
  1045. if ($showbarcode)
  1046. {
  1047. print '<tr><td>'.$langs->trans('BarcodeType').'</td><td>';
  1048. if (isset($_POST['fk_barcode_type']))
  1049. {
  1050. $fk_barcode_type=GETPOST('fk_barcode_type');
  1051. }
  1052. else
  1053. {
  1054. $fk_barcode_type=$object->barcode_type;
  1055. if (empty($fk_barcode_type) && ! empty($conf->global->PRODUIT_DEFAULT_BARCODE_TYPE)) $fk_barcode_type = $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE;
  1056. }
  1057. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbarcode.class.php';
  1058. $formbarcode = new FormBarCode($db);
  1059. print $formbarcode->select_barcode_type($fk_barcode_type, 'fk_barcode_type', 1);
  1060. print '</td><td>'.$langs->trans("BarcodeValue").'</td><td>';
  1061. $tmpcode=isset($_POST['barcode'])?GETPOST('barcode'):$object->barcode;
  1062. if (empty($tmpcode) && ! empty($modBarCodeProduct->code_auto)) $tmpcode=$modBarCodeProduct->getNextValue($object,$type);
  1063. print '<input size="40" type="text" name="barcode" value="'.dol_escape_htmltag($tmpcode).'">';
  1064. print '</td></tr>';
  1065. }
  1066. // Description (used in invoice, propal...)
  1067. print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
  1068. // 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.
  1069. $doleditor = new DolEditor('desc', $object->description, '', 160, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, 80);
  1070. $doleditor->Create();
  1071. print "</td></tr>";
  1072. print "\n";
  1073. // Public Url
  1074. print '<tr><td>'.$langs->trans("PublicUrl").'</td><td colspan="3">';
  1075. print '<input type="text" name="url" size="80" value="'.$object->url.'">';
  1076. print '</td></tr>';
  1077. // Stock
  1078. /*
  1079. if ($object->isProduct() && ! empty($conf->stock->enabled))
  1080. {
  1081. print "<tr>".'<td>'.$langs->trans("StockLimit").'</td><td>';
  1082. print '<input name="seuil_stock_alerte" size="4" value="'.$object->seuil_stock_alerte.'">';
  1083. print '</td>';
  1084. print '<td>'.$langs->trans("DesiredStock").'</td><td>';
  1085. print '<input name="desiredstock" size="4" value="'.$object->desiredstock.'">';
  1086. print '</td></tr>';
  1087. }
  1088. else
  1089. {
  1090. print '<input name="seuil_stock_alerte" type="hidden" value="'.$object->seuil_stock_alerte.'">';
  1091. print '<input name="desiredstock" type="hidden" value="'.$object->desiredstock.'">';
  1092. }*/
  1093. // Nature
  1094. if($object->type!= Product::TYPE_SERVICE)
  1095. {
  1096. print '<tr><td>'.$langs->trans("Nature").'</td><td colspan="3">';
  1097. $statutarray=array('-1'=>'&nbsp;', '1' => $langs->trans("Finished"), '0' => $langs->trans("RowMaterial"));
  1098. print $form->selectarray('finished',$statutarray,$object->finished);
  1099. print '</td></tr>';
  1100. }
  1101. if ($object->isService())
  1102. {
  1103. // Duration
  1104. print '<tr><td>'.$langs->trans("Duration").'</td><td colspan="3"><input name="duration_value" size="3" maxlength="5" value="'.$object->duration_value.'">';
  1105. print '&nbsp; ';
  1106. print '<input name="duration_unit" type="radio" value="h"'.($object->duration_unit=='h'?' checked':'').'>'.$langs->trans("Hour");
  1107. print '&nbsp; ';
  1108. print '<input name="duration_unit" type="radio" value="d"'.($object->duration_unit=='d'?' checked':'').'>'.$langs->trans("Day");
  1109. print '&nbsp; ';
  1110. print '<input name="duration_unit" type="radio" value="w"'.($object->duration_unit=='w'?' checked':'').'>'.$langs->trans("Week");
  1111. print '&nbsp; ';
  1112. print '<input name="duration_unit" type="radio" value="m"'.($object->duration_unit=='m'?' checked':'').'>'.$langs->trans("Month");
  1113. print '&nbsp; ';
  1114. print '<input name="duration_unit" type="radio" value="y"'.($object->duration_unit=='y'?' checked':'').'>'.$langs->trans("Year");
  1115. print '</td></tr>';
  1116. }
  1117. else
  1118. {
  1119. // Weight
  1120. print '<tr><td>'.$langs->trans("Weight").'</td><td colspan="3">';
  1121. print '<input name="weight" size="5" value="'.$object->weight.'"> ';
  1122. print $formproduct->select_measuring_units("weight_units", "weight", $object->weight_units);
  1123. print '</td></tr>';
  1124. if (empty($conf->global->PRODUCT_DISABLE_LENGTH))
  1125. {
  1126. // Length
  1127. print '<tr><td>'.$langs->trans("Length").'</td><td colspan="3">';
  1128. print '<input name="size" size="5" value="'.$object->length.'"> ';
  1129. print $formproduct->select_measuring_units("size_units", "size", $object->length_units);
  1130. print '</td></tr>';
  1131. }
  1132. if (empty($conf->global->PRODUCT_DISABLE_SURFACE))
  1133. {
  1134. // Surface
  1135. print '<tr><td>'.$langs->trans("Surface").'</td><td colspan="3">';
  1136. print '<input name="surface" size="5" value="'.$object->surface.'"> ';
  1137. print $formproduct->select_measuring_units("surface_units", "surface", $object->surface_units);
  1138. print '</td></tr>';
  1139. }
  1140. // Volume
  1141. print '<tr><td>'.$langs->trans("Volume").'</td><td colspan="3">';
  1142. print '<input name="volume" size="5" value="'.$object->volume.'"> ';
  1143. print $formproduct->select_measuring_units("volume_units", "volume", $object->volume_units);
  1144. print '</td></tr>';
  1145. }
  1146. // Units
  1147. if($conf->global->PRODUCT_USE_UNITS)
  1148. {
  1149. print '<tr><td>'.$langs->trans('DefaultUnitToShow').'</td>';
  1150. print '<td colspan="3">';
  1151. print $form->selectUnits($object->fk_unit, 'units');
  1152. print '</td></tr>';
  1153. }
  1154. // Custom code
  1155. if (! $object->isService() && empty($conf->global->PRODUCT_DISABLE_CUSTOM_INFO))
  1156. {
  1157. print '<tr><td>'.$langs->trans("CustomCode").'</td><td><input name="customcode" size="10" value="'.$object->customcode.'"></td>';
  1158. // Origin country
  1159. print '<td>'.$langs->trans("CountryOrigin").'</td><td>';
  1160. print $form->select_country($object->country_id,'country_id');
  1161. if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
  1162. print '</td></tr>';
  1163. }
  1164. // Other attributes
  1165. $parameters=array('colspan' => ' colspan="2"');
  1166. $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  1167. if (empty($reshook) && ! empty($extrafields->attribute_label))
  1168. {
  1169. print $object->showOptionals($extrafields,'edit');
  1170. }
  1171. // Tags-Categories
  1172. if ($conf->categorie->enabled)
  1173. {
  1174. print '<tr><td class="tdtop">'.$langs->trans("Categories").'</td><td colspan="3">';
  1175. $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', 'parent', 64, 0, 1);
  1176. $c = new Categorie($db);
  1177. $cats = $c->containing($object->id,Categorie::TYPE_PRODUCT);
  1178. foreach($cats as $cat) {
  1179. $arrayselected[] = $cat->id;
  1180. }
  1181. print $form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, '', 0, '100%');
  1182. print "</td></tr>";
  1183. }
  1184. // Note
  1185. print '<tr><td class="tdtop">'.$langs->trans("NoteNotVisibleOnBill").'</td><td colspan="3">';
  1186. $doleditor = new DolEditor('note', $object->note, '', 140, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_PRODUCTDESC, 4, 80);
  1187. $doleditor->Create();
  1188. print "</td></tr>";
  1189. print '</table>';
  1190. print '<br>';
  1191. print '<table class="border" width="100%">';
  1192. if (! empty($conf->accounting->enabled))
  1193. {
  1194. // Accountancy_code_sell
  1195. print '<tr><td width="20%">'.$langs->trans("ProductAccountancySellCode").'</td>';
  1196. print '<td>';
  1197. print $formaccountancy->select_account($object->accountancy_code_sell, 'accountancy_code_sell', 1, '', 1, 1);
  1198. print '</td></tr>';
  1199. // Accountancy_code_buy
  1200. print '<tr><td width="20%">'.$langs->trans("ProductAccountancyBuyCode").'</td>';
  1201. print '<td>';
  1202. print $formaccountancy->select_account($object->accountancy_code_buy, 'accountancy_code_buy', 1, '', 1, 1);
  1203. print '</td></tr>';
  1204. }
  1205. else // For external software
  1206. {
  1207. // Accountancy_code_sell
  1208. print '<tr><td width="20%">'.$langs->trans("ProductAccountancySellCode").'</td>';
  1209. print '<td><input name="accountancy_code_sell" size="16" value="'.$object->accountancy_code_sell.'">';
  1210. print '</td></tr>';
  1211. // Accountancy_code_buy
  1212. print '<tr><td width="20%">'.$langs->trans("ProductAccountancyBuyCode").'</td>';
  1213. print '<td><input name="accountancy_code_buy" size="16" value="'.$object->accountancy_code_buy.'">';
  1214. print '</td></tr>';
  1215. }
  1216. print '</table>';
  1217. dol_fiche_end();
  1218. print '<div class="center">';
  1219. print '<input type="submit" class="button" value="'.$langs->trans("Save").'">';
  1220. print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
  1221. print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
  1222. print '</div>';
  1223. print '</form>';
  1224. }
  1225. // Fiche en mode visu
  1226. else
  1227. {
  1228. $showbarcode=empty($conf->barcode->enabled)?0:1;
  1229. if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode=0;
  1230. $head=product_prepare_head($object);
  1231. $titre=$langs->trans("CardProduct".$object->type);
  1232. $picto=($object->type== Product::TYPE_SERVICE?'service':'product');
  1233. dol_fiche_head($head, 'card', $titre, 0, $picto);
  1234. $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php">'.$langs->trans("BackToList").'</a>';
  1235. dol_banner_tab($object, 'ref', $linkback, ($user->societe_id?0:1), 'ref');
  1236. print '<div class="fichecenter">';
  1237. print '<div class="fichehalfleft">';
  1238. print '<div class="underbanner clearboth"></div>';
  1239. print '<table class="border tableforfield" width="100%">';
  1240. // Type
  1241. if (! empty($conf->produit->enabled) && ! empty($conf->service->enabled))
  1242. {
  1243. // TODO change for compatibility with edit in place
  1244. $typeformat='select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
  1245. print '<tr><td class="titlefield">'.$form->editfieldkey("Type",'fk_product_type',$object->type,$object,$user->rights->produit->creer||$user->rights->service->creer,$typeformat).'</td><td colspan="2">';
  1246. print $form->editfieldval("Type",'fk_product_type',$object->type,$object,$user->rights->produit->creer||$user->rights->service->creer,$typeformat);
  1247. print '</td></tr>';
  1248. }
  1249. if ($showbarcode)
  1250. {
  1251. // Barcode type
  1252. print '<tr><td class="nowrap">';
  1253. print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
  1254. print $langs->trans("BarcodeType");
  1255. print '</td>';
  1256. if (($action != 'editbarcodetype') && ! empty($user->rights->produit->creer) && $createbarcode) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editbarcodetype&amp;id='.$object->id.'">'.img_edit($langs->trans('Edit'),1).'</a></td>';
  1257. print '</tr></table>';
  1258. print '</td><td colspan="2">';
  1259. if ($action == 'editbarcodetype')
  1260. {
  1261. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbarcode.class.php';
  1262. $formbarcode = new FormBarCode($db);
  1263. $formbarcode->form_barcode_type($_SERVER['PHP_SELF'].'?id='.$object->id,$object->barcode_type,'fk_barcode_type');
  1264. }
  1265. else
  1266. {
  1267. $object->fetch_barcode();
  1268. print $object->barcode_type_label?$object->barcode_type_label:($object->barcode?'<div class="warning">'.$langs->trans("SetDefaultBarcodeType").'<div>':'');
  1269. }
  1270. print '</td></tr>'."\n";
  1271. // Barcode value
  1272. print '<tr><td class="nowrap">';
  1273. print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
  1274. print $langs->trans("BarcodeValue");
  1275. print '</td>';
  1276. if (($action != 'editbarcode') && ! empty($user->rights->produit->creer) && $createbarcode) print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editbarcode&amp;id='.$object->id.'">'.img_edit($langs->trans('Edit'),1).'</a></td>';
  1277. print '</tr></table>';
  1278. print '</td><td colspan="2">';
  1279. if ($action == 'editbarcode')
  1280. {
  1281. print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
  1282. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  1283. print '<input type="hidden" name="action" value="setbarcode">';
  1284. print '<input type="hidden" name="barcode_type_code" value="'.$object->barcode_type_code.'">';
  1285. print '<input size="40" type="text" name="barcode" value="'.$object->barcode.'">';
  1286. print '&nbsp;<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
  1287. }
  1288. else
  1289. {
  1290. print $object->barcode;
  1291. }
  1292. print '</td></tr>'."\n";
  1293. }
  1294. // Accountancy sell code
  1295. print '<tr><td class="nowrap">';
  1296. print $langs->trans("ProductAccountancySellCode");
  1297. print '</td><td colspan="2">';
  1298. if (! empty($conf->accounting->enabled)) {
  1299. print length_accountg($object->accountancy_code_sell);
  1300. } else {
  1301. print $object->accountancy_code_sell;
  1302. }
  1303. print '</td></tr>';
  1304. // Accountancy buy code
  1305. print '<tr><td class="nowrap">';
  1306. print $langs->trans("ProductAccountancyBuyCode");
  1307. print '</td><td colspan="2">';
  1308. if (! empty($conf->accounting->enabled)) {
  1309. print length_accountg($object->accountancy_code_buy);
  1310. } else {
  1311. print $object->accountancy_code_buy;
  1312. }
  1313. print '</td></tr>';
  1314. // Status (to sell)
  1315. /*
  1316. print '<tr><td>'.$langs->trans("Status").' ('.$langs->trans("Sell").')</td><td colspan="2">';
  1317. if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
  1318. print ajax_object_onoff($object, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell');
  1319. } else {
  1320. print $object->getLibStatut(2,0);
  1321. }
  1322. print '</td></tr>';
  1323. // Status (to buy)
  1324. print '<tr><td>'.$langs->trans("Status").' ('.$langs->trans("Buy").')</td><td colspan="2">';
  1325. if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
  1326. print ajax_object_onoff($object, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy');
  1327. } else {
  1328. print $object->getLibStatut(2,1);
  1329. }
  1330. print '</td></tr>';
  1331. */
  1332. // Batch number management (to batch)
  1333. if (! empty($conf->productbatch->enabled)) {
  1334. print '<tr><td>'.$langs->trans("ManageLotSerial").'</td><td colspan="2">';
  1335. if (! empty($conf->use_javascript_ajax) && $user->rights->produit->creer && ! empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
  1336. print ajax_object_onoff($object, 'status_batch', 'tobatch', 'ProductStatusOnBatch', 'ProductStatusNotOnBatch');
  1337. } else {
  1338. print $object->getLibStatut(0,2);
  1339. }
  1340. print '</td></tr>';
  1341. }
  1342. // Description
  1343. 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>';
  1344. // Public URL
  1345. print '<tr><td>'.$langs->trans("PublicUrl").'</td><td colspan="2">';
  1346. print dol_print_url($object->url);
  1347. print '</td></tr>';
  1348. print '</table>';
  1349. print '</div>';
  1350. print '<div class="fichehalfright"><div class="ficheaddleft">';
  1351. print '<div class="underbanner clearboth"></div>';
  1352. print '<table class="border tableforfield" width="100%">';
  1353. // Nature
  1354. if($object->type!= Product::TYPE_SERVICE)
  1355. {
  1356. print '<tr><td class="titlefield">'.$langs->trans("Nature").'</td><td colspan="2">';
  1357. print $object->getLibFinished();
  1358. print '</td></tr>';
  1359. }
  1360. if ($object->isService())
  1361. {
  1362. // Duration
  1363. print '<tr><td class="titlefield">'.$langs->trans("Duration").'</td><td colspan="2">'.$object->duration_value.'&nbsp;';
  1364. if ($object->duration_value > 1)
  1365. {
  1366. $dur=array("h"=>$langs->trans("Hours"),"d"=>$langs->trans("Days"),"w"=>$langs->trans("Weeks"),"m"=>$langs->trans("Months"),"y"=>$langs->trans("Years"));
  1367. }
  1368. else if ($object->duration_value > 0)
  1369. {
  1370. $dur=array("h"=>$langs->trans("Hour"),"d"=>$langs->trans("Day"),"w"=>$langs->trans("Week"),"m"=>$langs->trans("Month"),"y"=>$langs->trans("Year"));
  1371. }
  1372. print (! empty($object->duration_unit) && isset($dur[$object->duration_unit]) ? $langs->trans($dur[$object->duration_unit]) : '')."&nbsp;";
  1373. print '</td></tr>';
  1374. }
  1375. else
  1376. {
  1377. // Weight
  1378. print '<tr><td class="titlefield">'.$langs->trans("Weight").'</td><td colspan="2">';
  1379. if ($object->weight != '')
  1380. {
  1381. print $object->weight." ".measuring_units_string($object->weight_units,"weight");
  1382. }
  1383. else
  1384. {
  1385. print '&nbsp;';
  1386. }
  1387. print "</td></tr>\n";
  1388. if (empty($conf->global->PRODUCT_DISABLE_LENGTH))
  1389. {
  1390. // Length
  1391. print '<tr><td>'.$langs->trans("Length").'</td><td colspan="2">';
  1392. if ($object->length != '')
  1393. {
  1394. print $object->length." ".measuring_units_string($object->length_units,"size");
  1395. }
  1396. else
  1397. {
  1398. print '&nbsp;';
  1399. }
  1400. print "</td></tr>\n";
  1401. }
  1402. if (empty($conf->global->PRODUCT_DISABLE_SURFACE))
  1403. {
  1404. // Surface
  1405. print '<tr><td>'.$langs->trans("Surface").'</td><td colspan="2">';
  1406. if ($object->surface != '')
  1407. {
  1408. print $object->surface." ".measuring_units_string($object->surface_units,"surface");
  1409. }
  1410. else
  1411. {
  1412. print '&nbsp;';
  1413. }
  1414. print "</td></tr>\n";
  1415. }
  1416. // Volume
  1417. print '<tr><td>'.$langs->trans("Volume").'</td><td colspan="2">';
  1418. if ($object->volume != '')
  1419. {
  1420. print $object->volume." ".measuring_units_string($object->volume_units,"volume");
  1421. }
  1422. else
  1423. {
  1424. print '&nbsp;';
  1425. }
  1426. print "</td></tr>\n";
  1427. }
  1428. // Unit
  1429. if (! empty($conf->global->PRODUCT_USE_UNITS))
  1430. {
  1431. $unit = $object->getLabelOfUnit();
  1432. print '<tr><td>'.$langs->trans('DefaultUnitToShow').'</td><td>';
  1433. if ($unit !== '') {
  1434. print $langs->trans($unit);
  1435. }
  1436. print '</td></tr>';
  1437. }
  1438. // Custom code
  1439. if (empty($conf->global->PRODUCT_DISABLE_CUSTOM_INFO))
  1440. {
  1441. print '<tr><td>'.$langs->trans("CustomCode").'</td><td colspan="2">'.$object->customcode.'</td>';
  1442. // Origin country code
  1443. print '<tr><td>'.$langs->trans("CountryOrigin").'</td><td colspan="2">'.getCountry($object->country_id,0,$db).'</td>';
  1444. }
  1445. // Other attributes
  1446. $parameters=array('colspan' => ' colspan="'.(2+(($showphoto||$showbarcode)?1:0)).'"');
  1447. $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  1448. if (empty($reshook) && ! empty($extrafields->attribute_label))
  1449. {
  1450. print $object->showOptionals($extrafields);
  1451. }
  1452. // Categories
  1453. if($conf->categorie->enabled) {
  1454. print '<tr><td valign="middle">'.$langs->trans("Categories").'</td><td colspan="3">';
  1455. print $form->showCategories($object->id,'product',1);
  1456. print "</td></tr>";
  1457. }
  1458. // Note
  1459. print '<!-- show Note --> '."\n";
  1460. print '<tr><td class="tdtop">'.$langs->trans("Note").'</td><td colspan="'.(2+(($showphoto||$showbarcode)?1:0)).'">'.(dol_textishtml($object->note)?$object->note:dol_nl2br($object->note,1,true)).'</td></tr>'."\n";
  1461. print '<!-- End show Note --> '."\n";
  1462. print "</table>\n";
  1463. print '</div>';
  1464. print '</div></div>';
  1465. print '<div style="clear:both"></div>';
  1466. dol_fiche_end();
  1467. }
  1468. }
  1469. else if ($action != 'create')
  1470. {
  1471. exit;
  1472. }
  1473. }
  1474. // Load object modCodeProduct
  1475. $module=(! empty($conf->global->PRODUCT_CODEPRODUCT_ADDON)?$conf->global->PRODUCT_CODEPRODUCT_ADDON:'mod_codeproduct_leopard');
  1476. if (substr($module, 0, 16) == 'mod_codeproduct_' && substr($module, -3) == 'php')
  1477. {
  1478. $module = substr($module, 0, dol_strlen($module)-4);
  1479. }
  1480. $result=dol_include_once('/core/modules/product/'.$module.'.php');
  1481. if ($result > 0)
  1482. {
  1483. $modCodeProduct = new $module();
  1484. }
  1485. $tmpcode='';
  1486. if (! empty($modCodeProduct->code_auto)) $tmpcode=$modCodeProduct->getNextValue($object,$object->type);
  1487. // Define confirmation messages
  1488. $formquestionclone=array(
  1489. 'text' => $langs->trans("ConfirmClone"),
  1490. array('type' => 'text', 'name' => 'clone_ref','label' => $langs->trans("NewRefForClone"), 'value' => empty($tmpcode) ? $langs->trans("CopyOf").' '.$object->ref : $tmpcode, 'size'=>24),
  1491. array('type' => 'checkbox', 'name' => 'clone_content','label' => $langs->trans("CloneContentProduct"), 'value' => 1),
  1492. array('type' => 'checkbox', 'name' => 'clone_prices', 'label' => $langs->trans("ClonePricesProduct").' ('.$langs->trans("FeatureNotYetAvailable").')', 'value' => 0, 'disabled' => true),
  1493. array('type' => 'checkbox', 'name' => 'clone_composition', 'label' => $langs->trans('CloneCompositionProduct'), 'value' => 1)
  1494. );
  1495. // Confirm delete product
  1496. if (($action == 'delete' && (empty($conf->use_javascript_ajax) || ! empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js
  1497. || (! empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) // Always output when not jmobile nor js
  1498. {
  1499. print $form->formconfirm("card.php?id=".$object->id,$langs->trans("DeleteProduct"),$langs->trans("ConfirmDeleteProduct"),"confirm_delete",'',0,"action-delete");
  1500. }
  1501. // Clone confirmation
  1502. if (($action == 'clone' && (empty($conf->use_javascript_ajax) || ! empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js
  1503. || (! empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) // Always output when not jmobile nor js
  1504. {
  1505. print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('CloneProduct'),$langs->trans('ConfirmCloneProduct',$object->ref),'confirm_clone',$formquestionclone,'yes','action-clone',250,600);
  1506. }
  1507. /* ************************************************************************** */
  1508. /* */
  1509. /* Barre d'action */
  1510. /* */
  1511. /* ************************************************************************** */
  1512. print "\n".'<div class="tabsAction">'."\n";
  1513. $parameters=array();
  1514. $reshook=$hookmanager->executeHooks('addMoreActionsButtons',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  1515. if (empty($reshook))
  1516. {
  1517. if ($action == '' || $action == 'view')
  1518. {
  1519. if (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->creer ) ||
  1520. ($object->type == Product::TYPE_SERVICE && $user->rights->service->creer))
  1521. {
  1522. if (! isset($object->no_button_edit) || $object->no_button_edit <> 1) print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit&amp;id='.$object->id.'">'.$langs->trans("Modify").'</a></div>';
  1523. if (! isset($object->no_button_copy) || $object->no_button_copy <> 1)
  1524. {
  1525. if (! empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))
  1526. {
  1527. print '<div class="inline-block divButAction"><span id="action-clone" class="butAction">'.$langs->trans('ToClone').'</span></div>'."\n";
  1528. }
  1529. else
  1530. {
  1531. print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=clone&amp;id='.$object->id.'">'.$langs->trans("ToClone").'</a></div>';
  1532. }
  1533. }
  1534. }
  1535. $object_is_used = $object->isObjectUsed($object->id);
  1536. if (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->supprimer)
  1537. || ($object->type == Product::TYPE_SERVICE && $user->rights->service->supprimer))
  1538. {
  1539. if (empty($object_is_used) && (! isset($object->no_button_delete) || $object->no_button_delete <> 1))
  1540. {
  1541. if (! empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))
  1542. {
  1543. print '<div class="inline-block divButAction"><span id="action-delete" class="butActionDelete">'.$langs->trans('Delete').'</span></div>'."\n";
  1544. }
  1545. else
  1546. {
  1547. print '<div class="inline-block divButAction"><a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=delete&amp;id='.$object->id.'">'.$langs->trans("Delete").'</a></div>';
  1548. }
  1549. }
  1550. else
  1551. {
  1552. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("ProductIsUsed").'">'.$langs->trans("Delete").'</a></div>';
  1553. }
  1554. }
  1555. else
  1556. {
  1557. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans("Delete").'</a></div>';
  1558. }
  1559. }
  1560. }
  1561. print "\n</div>\n";
  1562. /*
  1563. * All the "Add to" areas
  1564. */
  1565. if ($object->id && ($action == '' || $action == 'view') && $object->status)
  1566. {
  1567. //Variable used to check if any text is going to be printed
  1568. $html = '';
  1569. //print '<div class="fichecenter"><div class="fichehalfleft">';
  1570. // Propals
  1571. if (! empty($conf->propal->enabled) && $user->rights->propale->creer)
  1572. {
  1573. $propal = new Propal($db);
  1574. $langs->load("propal");
  1575. $var=true;
  1576. $otherprop = $propal->liste_array(2,1,0);
  1577. if (is_array($otherprop) && count($otherprop))
  1578. {
  1579. $var=!$var;
  1580. $html .= '<tr><td style="width: 200px;">';
  1581. $html .= $langs->trans("AddToDraftProposals").'</td><td colspan="2">';
  1582. $html .= $form->selectarray("propalid", $otherprop, 0, 1);
  1583. $html .= '</td></tr>';
  1584. }
  1585. else
  1586. {
  1587. $html .= '<tr><td style="width: 200px;">';
  1588. $html .= $langs->trans("AddToDraftProposals").'</td><td colspan="2">';
  1589. $html .= $langs->trans("NoDraftProposals");
  1590. $html .= '</td></tr>';
  1591. }
  1592. }
  1593. // Commande
  1594. if (! empty($conf->commande->enabled) && $user->rights->commande->creer)
  1595. {
  1596. $commande = new Commande($db);
  1597. $langs->load("orders");
  1598. $var=true;
  1599. $othercom = $commande->liste_array(2, 1, null);
  1600. if (is_array($othercom) && count($othercom))
  1601. {
  1602. $var=!$var;
  1603. $html .= '<tr><td style="width: 200px;">';
  1604. $html .= $langs->trans("AddToDraftOrders").'</td><td colspan="2">';
  1605. $html .= $form->selectarray("commandeid", $othercom, 0, 1);
  1606. $html .= '</td></tr>';
  1607. }
  1608. else
  1609. {
  1610. $html .= '<tr><td style="width: 200px;">';
  1611. $html .= $langs->trans("AddToDraftOrders").'</td><td colspan="2">';
  1612. $html .= $langs->trans("NoDraftOrders");
  1613. $html .= '</td></tr>';
  1614. }
  1615. }
  1616. // Factures
  1617. if (! empty($conf->facture->enabled) && $user->rights->facture->creer)
  1618. {
  1619. $invoice = new Facture($db);
  1620. $langs->load("bills");
  1621. $var=true;
  1622. $otherinvoice = $invoice->liste_array(2, 1, null);
  1623. if (is_array($otherinvoice) && count($otherinvoice))
  1624. {
  1625. $var=!$var;
  1626. $html .= '<tr><td style="width: 200px;">';
  1627. $html .= $langs->trans("AddToDraftInvoices").'</td><td colspan="2">';
  1628. $html .= $form->selectarray("factureid", $otherinvoice, 0, 1);
  1629. $html .= '</td></tr>';
  1630. }
  1631. else
  1632. {
  1633. $html .= '<tr><td style="width: 200px;">';
  1634. $html .= $langs->trans("AddToDraftInvoices").'</td><td colspan="2">';
  1635. $html .= $langs->trans("NoDraftInvoices");
  1636. $html .= '</td></tr>';
  1637. }
  1638. }
  1639. //If any text is going to be printed, then we show the table
  1640. if (!empty($html))
  1641. {
  1642. print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
  1643. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  1644. print '<input type="hidden" name="action" value="addin">';
  1645. print load_fiche_titre($langs->trans("AddToDraft"),'','');
  1646. dol_fiche_head('');
  1647. $html .= '<tr><td class="nowrap">'.$langs->trans("Quantity").' ';
  1648. $html .= '<input type="text" class="flat" name="qty" size="1" value="1"></td><td class="nowrap">'.$langs->trans("ReductionShort").'(%) ';
  1649. $html .= '<input type="text" class="flat" name="remise_percent" size="1" value="0">';
  1650. $html .= '</td></tr>';
  1651. print '<table width="100%" class="border">';
  1652. print $html;
  1653. print '</table>';
  1654. print '<div class="center">';
  1655. print '<input type="submit" class="button" value="'.$langs->trans("Add").'">';
  1656. print '</div>';
  1657. dol_fiche_end();
  1658. print '</form>';
  1659. }
  1660. }
  1661. /*
  1662. * Documents generes
  1663. */
  1664. if ($action == '' || $action == 'view')
  1665. {
  1666. print '<div class="fichecenter"><div class="fichehalfleft">';
  1667. print '<a name="builddoc"></a>'; // ancre
  1668. $filedir=$upload_dir;
  1669. $urlsource=$_SERVER["PHP_SELF"]."?id=".$object->id;
  1670. $genallowed=$user->rights->produit->creer;
  1671. $delallowed=$user->rights->produit->supprimer;
  1672. $var=true;
  1673. $somethingshown=$formfile->show_documents($modulepart,$object->id,$filedir,$urlsource,$genallowed,$delallowed,'',0,0,0,28,0,'',0,'',$object->default_lang);
  1674. print '</div><div class="fichehalfright"><div class="ficheaddleft">';
  1675. print '</div></div></div>';
  1676. }
  1677. llxFooter();
  1678. $db->close();