product.lib.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <?php
  2. /* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  4. * Copyright (C) 2009-2010 Regis Houssin <regis.houssin@capnetworks.com>
  5. * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  6. * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. * or see http://www.gnu.org/
  21. */
  22. /**
  23. * \file htdocs/core/lib/product.lib.php
  24. * \brief Ensemble de fonctions de base pour le module produit et service
  25. * \ingroup product
  26. */
  27. /**
  28. * Prepare array with list of tabs
  29. *
  30. * @param Product $object Object related to tabs
  31. * @return array Array of tabs to show
  32. */
  33. function product_prepare_head($object)
  34. {
  35. global $db, $langs, $conf, $user;
  36. $langs->load("products");
  37. $h = 0;
  38. $head = array();
  39. $head[$h][0] = DOL_URL_ROOT."/product/card.php?id=".$object->id;
  40. $head[$h][1] = $langs->trans("Card");
  41. $head[$h][2] = 'card';
  42. $h++;
  43. if (! empty($object->status))
  44. {
  45. $head[$h][0] = DOL_URL_ROOT."/product/price.php?id=".$object->id;
  46. $head[$h][1] = $langs->trans("SellingPrices");
  47. $head[$h][2] = 'price';
  48. $h++;
  49. }
  50. if (! empty($object->status_buy) || (! empty($conf->margin->enabled) && ! empty($object->status))) // If margin is on and product on sell, we may need the cost price even if product os not on purchase
  51. {
  52. if ((! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->lire)
  53. || (! empty($conf->margin->enabled) && $user->rights->margin->liretous)
  54. )
  55. {
  56. $head[$h][0] = DOL_URL_ROOT."/product/fournisseurs.php?id=".$object->id;
  57. $head[$h][1] = $langs->trans("BuyingPrices");
  58. $head[$h][2] = 'suppliers';
  59. $h++;
  60. }
  61. }
  62. // Multilangs
  63. if (! empty($conf->global->MAIN_MULTILANGS))
  64. {
  65. $head[$h][0] = DOL_URL_ROOT."/product/traduction.php?id=".$object->id;
  66. $head[$h][1] = $langs->trans("Translation");
  67. $head[$h][2] = 'translation';
  68. $h++;
  69. }
  70. // Sub products
  71. if (! empty($conf->global->PRODUIT_SOUSPRODUITS))
  72. {
  73. $head[$h][0] = DOL_URL_ROOT."/product/composition/card.php?id=".$object->id;
  74. $head[$h][1] = $langs->trans('AssociatedProducts');
  75. $head[$h][2] = 'subproduct';
  76. $h++;
  77. }
  78. $head[$h][0] = DOL_URL_ROOT."/product/stats/card.php?id=".$object->id;
  79. $head[$h][1] = $langs->trans('Statistics');
  80. $head[$h][2] = 'stats';
  81. $h++;
  82. $head[$h][0] = DOL_URL_ROOT."/product/stats/facture.php?showmessage=1&id=".$object->id;
  83. $head[$h][1] = $langs->trans('Referers');
  84. $head[$h][2] = 'referers';
  85. $h++;
  86. if (!empty($conf->variants->enabled) && $object->isProduct()) {
  87. global $db;
  88. require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
  89. $prodcomb = new ProductCombination($db);
  90. if ($prodcomb->fetchByFkProductChild($object->id) == -1)
  91. {
  92. $head[$h][0] = DOL_URL_ROOT."/variants/combinations.php?id=".$object->id;
  93. $head[$h][1] = $langs->trans('ProductCombinations');
  94. $head[$h][2] = 'combinations';
  95. $nbVariant = $prodcomb->countNbOfCombinationForFkProductParent($object->id);
  96. if ($nbVariant > 0) $head[$h][1].= ' <span class="badge">'.$nbVariant.'</span>';
  97. }
  98. $h++;
  99. }
  100. if ($object->isProduct() || ($object->isService() && ! empty($conf->global->STOCK_SUPPORTS_SERVICES))) // If physical product we can stock (or service with option)
  101. {
  102. if (! empty($conf->stock->enabled) && $user->rights->stock->lire)
  103. {
  104. $head[$h][0] = DOL_URL_ROOT."/product/stock/product.php?id=".$object->id;
  105. $head[$h][1] = $langs->trans("Stock");
  106. $head[$h][2] = 'stock';
  107. $h++;
  108. }
  109. }
  110. // Show more tabs from modules
  111. // Entries must be declared in modules descriptor with line
  112. // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
  113. // $this->tabs = array('entity:-tabname); to remove a tab
  114. complete_head_from_modules($conf,$langs,$object,$head,$h,'product');
  115. // Notes
  116. if (empty($conf->global->MAIN_DISABLE_NOTES_TAB))
  117. {
  118. $nbNote = 0;
  119. if(!empty($object->note_private)) $nbNote++;
  120. if(!empty($object->note_public)) $nbNote++;
  121. $head[$h][0] = DOL_URL_ROOT.'/product/note.php?id='.$object->id;
  122. $head[$h][1] = $langs->trans('Notes');
  123. if ($nbNote > 0) $head[$h][1].= ' <span class="badge">'.$nbNote.'</span>';
  124. $head[$h][2] = 'note';
  125. $h++;
  126. }
  127. // Attachments
  128. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  129. require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
  130. if (! empty($conf->product->enabled) && ($object->type==Product::TYPE_PRODUCT)) $upload_dir = $conf->product->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
  131. if (! empty($conf->service->enabled) && ($object->type==Product::TYPE_SERVICE)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
  132. $nbFiles = count(dol_dir_list($upload_dir,'files',0,'','(\.meta|_preview.*\.png)$'));
  133. if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) {
  134. if (! empty($conf->product->enabled) && ($object->type==Product::TYPE_PRODUCT)) $upload_dir = $conf->produit->multidir_output[$object->entity].'/'.get_exdir($object->id,2,0,0,$object,'product').$object->id.'/photos';
  135. if (! empty($conf->service->enabled) && ($object->type==Product::TYPE_SERVICE)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir($object->id,2,0,0,$object,'product').$object->id.'/photos';
  136. $nbFiles += count(dol_dir_list($upload_dir,'files',0,'','(\.meta|_preview.*\.png)$'));
  137. }
  138. $nbLinks=Link::count($db, $object->element, $object->id);
  139. $head[$h][0] = DOL_URL_ROOT.'/product/document.php?id='.$object->id;
  140. $head[$h][1] = $langs->trans('Documents');
  141. if (($nbFiles+$nbLinks) > 0) $head[$h][1].= ' <span class="badge">'.($nbFiles+$nbLinks).'</span>';
  142. $head[$h][2] = 'documents';
  143. $h++;
  144. complete_head_from_modules($conf,$langs,$object,$head,$h,'product', 'remove');
  145. // Log
  146. $head[$h][0] = DOL_URL_ROOT.'/product/info.php?id='.$object->id;
  147. $head[$h][1] = $langs->trans("Info");
  148. $head[$h][2] = 'info';
  149. $h++;
  150. return $head;
  151. }
  152. /**
  153. * Prepare array with list of tabs
  154. *
  155. * @param ProductLot $object Object related to tabs
  156. * @return array Array of tabs to show
  157. */
  158. function productlot_prepare_head($object)
  159. {
  160. global $db, $langs, $conf, $user;
  161. $langs->load("products");
  162. $langs->load("productbatch");
  163. $h = 0;
  164. $head = array();
  165. $head[$h][0] = DOL_URL_ROOT."/product/stock/productlot_card.php?id=".$object->id;
  166. $head[$h][1] = $langs->trans("Card");
  167. $head[$h][2] = 'card';
  168. $h++;
  169. // Show more tabs from modules
  170. // Entries must be declared in modules descriptor with line
  171. // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
  172. // $this->tabs = array('entity:-tabname); to remove a tab
  173. complete_head_from_modules($conf,$langs,$object,$head,$h,'productlot');
  174. complete_head_from_modules($conf,$langs,$object,$head,$h,'productlot', 'remove');
  175. // Log
  176. /*
  177. $head[$h][0] = DOL_URL_ROOT.'/product/info.php?id='.$object->id;
  178. $head[$h][1] = $langs->trans("Info");
  179. $head[$h][2] = 'info';
  180. $h++;
  181. */
  182. return $head;
  183. }
  184. /**
  185. * Return array head with list of tabs to view object informations.
  186. *
  187. * @return array head array with tabs
  188. */
  189. function product_admin_prepare_head()
  190. {
  191. global $langs, $conf, $user;
  192. $h = 0;
  193. $head = array();
  194. $head[$h][0] = DOL_URL_ROOT."/product/admin/product.php";
  195. $head[$h][1] = $langs->trans('Parameters');
  196. $head[$h][2] = 'general';
  197. $h++;
  198. if (!empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($conf->global->PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL))
  199. {
  200. $head[$h] = array(
  201. 0 => DOL_URL_ROOT."/product/admin/price_rules.php",
  202. 1 => $langs->trans('MultipriceRules'),
  203. 2 => 'generator'
  204. );
  205. $h++;
  206. }
  207. // Show more tabs from modules
  208. // Entries must be declared in modules descriptor with line
  209. // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
  210. // $this->tabs = array('entity:-tabname); to remove a tab
  211. complete_head_from_modules($conf,$langs,null,$head,$h,'product_admin');
  212. $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_extrafields.php';
  213. $head[$h][1] = $langs->trans("ExtraFields");
  214. $head[$h][2] = 'attributes';
  215. $h++;
  216. complete_head_from_modules($conf,$langs,null,$head,$h,'product_admin','remove');
  217. return $head;
  218. }
  219. /**
  220. * Return array head with list of tabs to view object informations.
  221. *
  222. * @return array head array with tabs
  223. */
  224. function product_lot_admin_prepare_head()
  225. {
  226. global $langs, $conf, $user;
  227. $h = 0;
  228. $head = array();
  229. // Show more tabs from modules
  230. // Entries must be declared in modules descriptor with line
  231. // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
  232. // $this->tabs = array('entity:-tabname); to remove a tab
  233. complete_head_from_modules($conf,$langs,null,$head,$h,'product_lot_admin');
  234. $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_lot_extrafields.php';
  235. $head[$h][1] = $langs->trans("ExtraFields");
  236. $head[$h][2] = 'attributes';
  237. $h++;
  238. complete_head_from_modules($conf,$langs,null,$head,$h,'product_lot_admin','remove');
  239. return $head;
  240. }
  241. /**
  242. * Show stats for company
  243. *
  244. * @param Product $product Product object
  245. * @param int $socid Thirdparty id
  246. * @return integer NB of lines shown into array
  247. */
  248. function show_stats_for_company($product,$socid)
  249. {
  250. global $conf,$langs,$user,$db;
  251. $nblines = 0;
  252. print '<tr>';
  253. print '<td align="left" width="25%" valign="top">'.$langs->trans("Referers").'</td>';
  254. print '<td align="right" width="25%">'.$langs->trans("NbOfThirdParties").'</td>';
  255. print '<td align="right" width="25%">'.$langs->trans("NbOfObjectReferers").'</td>';
  256. print '<td align="right" width="25%">'.$langs->trans("TotalQuantity").'</td>';
  257. print '</tr>';
  258. // Propals
  259. if (! empty($conf->propal->enabled) && $user->rights->propale->lire)
  260. {
  261. $nblines++;
  262. $ret=$product->load_stats_propale($socid);
  263. if ($ret < 0) dol_print_error($db);
  264. $langs->load("propal");
  265. print '<tr><td>';
  266. print '<a href="propal.php?id='.$product->id.'">'.img_object('','propal').' '.$langs->trans("Proposals").'</a>';
  267. print '</td><td align="right">';
  268. print $product->stats_propale['customers'];
  269. print '</td><td align="right">';
  270. print $product->stats_propale['nb'];
  271. print '</td><td align="right">';
  272. print $product->stats_propale['qty'];
  273. print '</td>';
  274. print '</tr>';
  275. }
  276. // Commandes clients
  277. if (! empty($conf->commande->enabled) && $user->rights->commande->lire)
  278. {
  279. $nblines++;
  280. $ret=$product->load_stats_commande($socid);
  281. if ($ret < 0) dol_print_error($db);
  282. $langs->load("orders");
  283. print '<tr><td>';
  284. print '<a href="commande.php?id='.$product->id.'">'.img_object('','order').' '.$langs->trans("CustomersOrders").'</a>';
  285. print '</td><td align="right">';
  286. print $product->stats_commande['customers'];
  287. print '</td><td align="right">';
  288. print $product->stats_commande['nb'];
  289. print '</td><td align="right">';
  290. print $product->stats_commande['qty'];
  291. print '</td>';
  292. print '</tr>';
  293. }
  294. // Commandes fournisseurs
  295. if (! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->commande->lire)
  296. {
  297. $nblines++;
  298. $ret=$product->load_stats_commande_fournisseur($socid);
  299. if ($ret < 0) dol_print_error($db);
  300. $langs->load("orders");
  301. print '<tr><td>';
  302. print '<a href="commande_fournisseur.php?id='.$product->id.'">'.img_object('','order').' '.$langs->trans("SuppliersOrders").'</a>';
  303. print '</td><td align="right">';
  304. print $product->stats_commande_fournisseur['suppliers'];
  305. print '</td><td align="right">';
  306. print $product->stats_commande_fournisseur['nb'];
  307. print '</td><td align="right">';
  308. print $product->stats_commande_fournisseur['qty'];
  309. print '</td>';
  310. print '</tr>';
  311. }
  312. // Contrats
  313. if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire)
  314. {
  315. $nblines++;
  316. $ret=$product->load_stats_contrat($socid);
  317. if ($ret < 0) dol_print_error($db);
  318. $langs->load("contracts");
  319. print '<tr><td>';
  320. print '<a href="contrat.php?id='.$product->id.'">'.img_object('','contract').' '.$langs->trans("Contracts").'</a>';
  321. print '</td><td align="right">';
  322. print $product->stats_contrat['customers'];
  323. print '</td><td align="right">';
  324. print $product->stats_contrat['nb'];
  325. print '</td><td align="right">';
  326. print $product->stats_contrat['qty'];
  327. print '</td>';
  328. print '</tr>';
  329. }
  330. // Factures clients
  331. if (! empty($conf->facture->enabled) && $user->rights->facture->lire)
  332. {
  333. $nblines++;
  334. $ret=$product->load_stats_facture($socid);
  335. if ($ret < 0) dol_print_error($db);
  336. $langs->load("bills");
  337. print '<tr><td>';
  338. print '<a href="facture.php?id='.$product->id.'">'.img_object('','bill').' '.$langs->trans("CustomersInvoices").'</a>';
  339. print '</td><td align="right">';
  340. print $product->stats_facture['customers'];
  341. print '</td><td align="right">';
  342. print $product->stats_facture['nb'];
  343. print '</td><td align="right">';
  344. print $product->stats_facture['qty'];
  345. print '</td>';
  346. print '</tr>';
  347. }
  348. // Factures fournisseurs
  349. if (! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire)
  350. {
  351. $nblines++;
  352. $ret=$product->load_stats_facture_fournisseur($socid);
  353. if ($ret < 0) dol_print_error($db);
  354. $langs->load("bills");
  355. print '<tr><td>';
  356. print '<a href="facture_fournisseur.php?id='.$product->id.'">'.img_object('','bill').' '.$langs->trans("SuppliersInvoices").'</a>';
  357. print '</td><td align="right">';
  358. print $product->stats_facture_fournisseur['suppliers'];
  359. print '</td><td align="right">';
  360. print $product->stats_facture_fournisseur['nb'];
  361. print '</td><td align="right">';
  362. print $product->stats_facture_fournisseur['qty'];
  363. print '</td>';
  364. print '</tr>';
  365. }
  366. return $nblines++;
  367. }
  368. /**
  369. * Return translation label of a unit key
  370. *
  371. * @param int $unit Unit key (-3,0,3,98,99...)
  372. * @param string $measuring_style Style of unit: weight, volume,...
  373. * @return string Unit string
  374. * @see formproduct->load_measuring_units
  375. */
  376. function measuring_units_string($unit,$measuring_style='')
  377. {
  378. global $langs;
  379. $measuring_units=array();
  380. if ($measuring_style == 'weight')
  381. {
  382. $measuring_units[3] = $langs->transnoentitiesnoconv("WeightUnitton");
  383. $measuring_units[0] = $langs->transnoentitiesnoconv("WeightUnitkg");
  384. $measuring_units[-3] = $langs->transnoentitiesnoconv("WeightUnitg");
  385. $measuring_units[-6] = $langs->transnoentitiesnoconv("WeightUnitmg");
  386. $measuring_units[99] = $langs->transnoentitiesnoconv("WeightUnitpound");
  387. }
  388. else if ($measuring_style == 'size')
  389. {
  390. $measuring_units[0] = $langs->transnoentitiesnoconv("SizeUnitm");
  391. $measuring_units[-1] = $langs->transnoentitiesnoconv("SizeUnitdm");
  392. $measuring_units[-2] = $langs->transnoentitiesnoconv("SizeUnitcm");
  393. $measuring_units[-3] = $langs->transnoentitiesnoconv("SizeUnitmm");
  394. $measuring_units[98] = $langs->transnoentitiesnoconv("SizeUnitfoot");
  395. $measuring_units[99] = $langs->transnoentitiesnoconv("SizeUnitinch");
  396. }
  397. else if ($measuring_style == 'surface')
  398. {
  399. $measuring_units[0] = $langs->transnoentitiesnoconv("SurfaceUnitm2");
  400. $measuring_units[-2] = $langs->transnoentitiesnoconv("SurfaceUnitdm2");
  401. $measuring_units[-4] = $langs->transnoentitiesnoconv("SurfaceUnitcm2");
  402. $measuring_units[-6] = $langs->transnoentitiesnoconv("SurfaceUnitmm2");
  403. $measuring_units[98] = $langs->transnoentitiesnoconv("SurfaceUnitfoot2");
  404. $measuring_units[99] = $langs->transnoentitiesnoconv("SurfaceUnitinch2");
  405. }
  406. else if ($measuring_style == 'volume')
  407. {
  408. $measuring_units[0] = $langs->transnoentitiesnoconv("VolumeUnitm3");
  409. $measuring_units[-3] = $langs->transnoentitiesnoconv("VolumeUnitdm3");
  410. $measuring_units[-6] = $langs->transnoentitiesnoconv("VolumeUnitcm3");
  411. $measuring_units[-9] = $langs->transnoentitiesnoconv("VolumeUnitmm3");
  412. $measuring_units[88] = $langs->transnoentitiesnoconv("VolumeUnitfoot3");
  413. $measuring_units[89] = $langs->transnoentitiesnoconv("VolumeUnitinch3");
  414. $measuring_units[97] = $langs->transnoentitiesnoconv("VolumeUnitounce");
  415. $measuring_units[98] = $langs->transnoentitiesnoconv("VolumeUnitlitre");
  416. $measuring_units[99] = $langs->transnoentitiesnoconv("VolumeUnitgallon");
  417. }
  418. return $measuring_units[$unit];
  419. }