list.php 84 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058
  1. <?php
  2. /* Copyright (C) 2001-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2019 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
  5. * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
  6. * Copyright (C) 2013-2023 Juanjo Menent <jmenent@2byte.es>
  7. * Copyright (C) 2013-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  8. * Copyright (C) 2013 Jean Heimburger <jean@tiaris.info>
  9. * Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
  10. * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
  11. * Copyright (C) 2013 Adolfo segura <adolfo.segura@gmail.com>
  12. * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
  13. * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
  14. * Copyright (C) 2020-2021 Open-DSI <support@open-dsi.fr>
  15. *
  16. * This program is free software; you can redistribute it and/or modify
  17. * it under the terms of the GNU General Public License as published by
  18. * the Free Software Foundation; either version 3 of the License, or
  19. * (at your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  28. */
  29. /**
  30. * \file htdocs/product/list.php
  31. * \ingroup produit
  32. * \brief Page to list products and services
  33. */
  34. // Load Dolibarr environment
  35. require '../main.inc.php';
  36. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  37. require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
  38. require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
  39. require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
  40. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
  41. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
  42. require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
  43. require_once DOL_DOCUMENT_ROOT.'/workstation/class/workstation.class.php';
  44. if (isModEnabled('categorie')) {
  45. require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  46. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcategory.class.php';
  47. }
  48. // Load translation files required by the page
  49. $langs->loadLangs(array('products', 'stocks', 'suppliers', 'companies', 'margins'));
  50. if (isModEnabled('productbatch')) {
  51. $langs->load("productbatch");
  52. }
  53. // Get parameters
  54. $action = GETPOST('action', 'aZ09');
  55. $massaction = GETPOST('massaction', 'alpha');
  56. $show_files = GETPOST('show_files', 'int');
  57. $confirm = GETPOST('confirm', 'alpha');
  58. $toselect = GETPOST('toselect', 'array');
  59. // Search Criterias
  60. $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
  61. $search_id = GETPOST("search_id", 'alpha');
  62. $search_ref = GETPOST("search_ref", 'alpha');
  63. $search_ref_supplier = GETPOST("search_ref_supplier", 'alpha');
  64. $search_barcode = GETPOST("search_barcode", 'alpha');
  65. $search_label = GETPOST("search_label", 'alpha');
  66. $search_default_workstation = GETPOST("search_default_workstation", 'alpha');
  67. $search_type = GETPOST("search_type", 'int');
  68. $search_vatrate = GETPOST("search_vatrate", 'alpha');
  69. $searchCategoryProductOperator = 0;
  70. if (GETPOSTISSET('formfilteraction')) {
  71. $searchCategoryProductOperator = GETPOSTINT('search_category_product_operator');
  72. } elseif (!empty($conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT)) {
  73. $searchCategoryProductOperator = $conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT;
  74. }
  75. $searchCategoryProductList = GETPOST('search_category_product_list', 'array');
  76. $catid = GETPOST('catid', 'int');
  77. if (!empty($catid) && empty($searchCategoryProductList)) {
  78. $searchCategoryProductList = array($catid);
  79. }
  80. $search_tosell = GETPOST("search_tosell", 'int');
  81. $search_tobuy = GETPOST("search_tobuy", 'int');
  82. $search_country = GETPOST("search_country", 'int');
  83. $search_state = GETPOST("state_id", 'int');
  84. $fourn_id = GETPOST("fourn_id", 'int');
  85. $search_tobatch = GETPOST("search_tobatch", 'int');
  86. $search_accountancy_code_sell = GETPOST("search_accountancy_code_sell", 'alpha');
  87. $search_accountancy_code_sell_intra = GETPOST("search_accountancy_code_sell_intra", 'alpha');
  88. $search_accountancy_code_sell_export = GETPOST("search_accountancy_code_sell_export", 'alpha');
  89. $search_accountancy_code_buy = GETPOST("search_accountancy_code_buy", 'alpha');
  90. $search_accountancy_code_buy_intra = GETPOST("search_accountancy_code_buy_intra", 'alpha');
  91. $search_accountancy_code_buy_export = GETPOST("search_accountancy_code_buy_export", 'alpha');
  92. $search_finished = GETPOST("search_finished", 'int');
  93. $optioncss = GETPOST('optioncss', 'alpha');
  94. $type = GETPOST("type", "int");
  95. //Show/hide child products
  96. if (isModEnabled('variants') && !empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
  97. $show_childproducts = GETPOST('search_show_childproducts');
  98. } else {
  99. $show_childproducts = '';
  100. }
  101. $diroutputmassaction = $conf->product->dir_output.'/temp/massgeneration/'.$user->id;
  102. $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
  103. $sortfield = GETPOST('sortfield', 'aZ09comma');
  104. $sortorder = GETPOST('sortorder', 'aZ09comma');
  105. $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
  106. if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
  107. $page = 0;
  108. } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
  109. $offset = $limit * $page;
  110. $pageprev = $page - 1;
  111. $pagenext = $page + 1;
  112. if (!$sortfield) {
  113. $sortfield = "p.ref";
  114. }
  115. if (!$sortorder) {
  116. $sortorder = "ASC";
  117. }
  118. // Initialize context for list
  119. $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'productservicelist';
  120. if ((string) $type == '1') {
  121. $contextpage = 'servicelist'; if ($search_type == '') {
  122. $search_type = '1';
  123. }
  124. }
  125. if ((string) $type == '0') {
  126. $contextpage = 'productlist'; if ($search_type == '') {
  127. $search_type = '0';
  128. }
  129. }
  130. // Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks
  131. $object = new Product($db);
  132. $hookmanager->initHooks(array('productservicelist'));
  133. $extrafields = new ExtraFields($db);
  134. $form = new Form($db);
  135. $formcompany = new FormCompany($db);
  136. $formproduct = new FormProduct($db);
  137. // fetch optionals attributes and labels
  138. $extrafields->fetch_name_optionals_label($object->table_element);
  139. $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
  140. if (empty($action)) {
  141. $action = 'list';
  142. }
  143. // Get object canvas (By default, this is not defined, so standard usage of dolibarr)
  144. $canvas = GETPOST("canvas");
  145. $objcanvas = null;
  146. if (!empty($canvas)) {
  147. require_once DOL_DOCUMENT_ROOT.'/core/class/canvas.class.php';
  148. $objcanvas = new Canvas($db, $action);
  149. $objcanvas->getCanvas('product', 'list', $canvas);
  150. }
  151. // Define virtualdiffersfromphysical
  152. $virtualdiffersfromphysical = 0;
  153. if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
  154. || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)
  155. || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)
  156. || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION)
  157. || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)
  158. || isModEnabled('mrp')) {
  159. $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
  160. }
  161. // List of fields to search into when doing a "search in all"
  162. $fieldstosearchall = array(
  163. 'p.ref'=>"Ref",
  164. 'p.label'=>"ProductLabel",
  165. 'p.description'=>"Description",
  166. "p.note"=>"Note",
  167. );
  168. // multilang
  169. if (getDolGlobalInt('MAIN_MULTILANGS')) {
  170. $fieldstosearchall['pl.label'] = 'ProductLabelTranslated';
  171. $fieldstosearchall['pl.description'] = 'ProductDescriptionTranslated';
  172. $fieldstosearchall['pl.note'] = 'ProductNoteTranslated';
  173. }
  174. if (isModEnabled('barcode')) {
  175. $fieldstosearchall['p.barcode'] = 'Gencod';
  176. }
  177. // Personalized search criterias. Example: $conf->global->PRODUCT_QUICKSEARCH_ON_FIELDS = 'p.ref=ProductRef;p.label=ProductLabel;p.description=Description;p.note=Note;'
  178. if (!empty($conf->global->PRODUCT_QUICKSEARCH_ON_FIELDS)) {
  179. $fieldstosearchall = dolExplodeIntoArray($conf->global->PRODUCT_QUICKSEARCH_ON_FIELDS);
  180. }
  181. if (empty($conf->global->PRODUIT_MULTIPRICES)) {
  182. $titlesellprice = $langs->trans("SellingPrice");
  183. if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
  184. $titlesellprice = $form->textwithpicto($langs->trans("SellingPrice"), $langs->trans("DefaultPriceRealPriceMayDependOnCustomer"));
  185. }
  186. }
  187. $isInEEC = isInEEC($mysoc);
  188. $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe";
  189. // Definition of array of fields for columns
  190. $arrayfields = array(
  191. 'p.rowid'=>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'noteditable'=>1, 'notnull'=> 1, 'index'=>1, 'position'=>1, 'comment'=>'Id', 'css'=>'left'),
  192. 'p.ref'=>array('label'=>"Ref", 'checked'=>1, 'position'=>10),
  193. //'pfp.ref_fourn'=>array('label'=>$langs->trans("RefSupplier"), 'checked'=>1, 'enabled'=>(!empty($conf->barcode->enabled))),
  194. 'thumbnail'=>array('label'=>'Photo', 'checked'=>0, 'position'=>10),
  195. 'p.label'=>array('label'=>"Label", 'checked'=>1, 'position'=>10),
  196. 'p.fk_product_type'=>array('label'=>"Type", 'checked'=>0, 'enabled'=>(isModEnabled("product") && isModEnabled("service")), 'position'=>11),
  197. 'p.barcode'=>array('label'=>"Gencod", 'checked'=>1, 'enabled'=>(isModEnabled('barcode')), 'position'=>12),
  198. 'p.duration'=>array('label'=>"Duration", 'checked'=>($contextpage != 'productlist'), 'enabled'=>(isModEnabled("service") && (string) $type == '1'), 'position'=>13),
  199. 'p.finished'=>array('label'=>"Nature", 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>19),
  200. 'p.weight'=>array('label'=>'Weight', 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>20),
  201. 'p.weight_units'=>array('label'=>'WeightUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>21),
  202. 'p.length'=>array('label'=>'Length', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>22),
  203. 'p.length_units'=>array('label'=>'LengthUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>23),
  204. 'p.width'=>array('label'=>'Width', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>24),
  205. 'p.width_units'=>array('label'=>'WidthUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>25),
  206. 'p.height'=>array('label'=>'Height', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>26),
  207. 'p.height_units'=>array('label'=>'HeightUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>27),
  208. 'p.surface'=>array('label'=>'Surface', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SURFACE) && $type != '1'), 'position'=>28),
  209. 'p.surface_units'=>array('label'=>'SurfaceUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SURFACE) && $type != '1'), 'position'=>29),
  210. 'p.volume'=>array('label'=>'Volume', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>30),
  211. 'p.volume_units'=>array('label'=>'VolumeUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>31),
  212. 'cu.label'=>array('label'=>"DefaultUnitToShow", 'checked'=>0, 'enabled'=>(isModEnabled("product") && !empty($conf->global->PRODUCT_USE_UNITS)), 'position'=>32),
  213. 'p.fk_default_workstation'=>array('label'=>'DefaultWorkstation', 'checked'=>0, 'enabled'=>isModEnabled('workstation') && $type == 1, 'position'=>33),
  214. 'p.sellprice'=>array('label'=>"SellingPrice", 'checked'=>1, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES), 'position'=>40),
  215. 'p.tva_tx'=>array('label'=>"VATRate", 'checked'=>0, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES), 'position'=>41),
  216. 'p.minbuyprice'=>array('label'=>"BuyingPriceMinShort", 'checked'=>1, 'enabled'=>(!empty($user->rights->fournisseur->lire)), 'position'=>42),
  217. 'p.numbuyprice'=>array('label'=>"BuyingPriceNumShort", 'checked'=>0, 'enabled'=>(!empty($user->rights->fournisseur->lire)), 'position'=>43),
  218. 'p.pmp'=>array('label'=>"PMPValueShort", 'checked'=>0, 'enabled'=>(!empty($user->rights->fournisseur->lire)), 'position'=>44),
  219. 'p.cost_price'=>array('label'=>"CostPrice", 'checked'=>0, 'enabled'=>(!empty($user->rights->fournisseur->lire)), 'position'=>45),
  220. 'p.seuil_stock_alerte'=>array('label'=>"StockLimit", 'checked'=>0, 'enabled'=>(isModEnabled('stock') && $user->rights->stock->lire && ($contextpage != 'servicelist' || !empty($conf->global->STOCK_SUPPORTS_SERVICES))), 'position'=>50),
  221. 'p.desiredstock'=>array('label'=>"DesiredStock", 'checked'=>1, 'enabled'=>(isModEnabled('stock') && $user->rights->stock->lire && ($contextpage != 'servicelist' || !empty($conf->global->STOCK_SUPPORTS_SERVICES))), 'position'=>51),
  222. 'p.stock'=>array('label'=>"PhysicalStock", 'checked'=>1, 'enabled'=>(isModEnabled('stock') && $user->rights->stock->lire && ($contextpage != 'servicelist' || !empty($conf->global->STOCK_SUPPORTS_SERVICES))), 'position'=>52),
  223. 'stock_virtual'=>array('label'=>"VirtualStock", 'checked'=>1, 'enabled'=>(isModEnabled('stock') && $user->rights->stock->lire && ($contextpage != 'servicelist' || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) && $virtualdiffersfromphysical), 'position'=>53),
  224. 'p.tobatch'=>array('label'=>"ManageLotSerial", 'checked'=>0, 'enabled'=>(isModEnabled('productbatch')), 'position'=>60),
  225. 'p.fk_country'=>array('label'=>"Country", 'checked'=>0, 'position'=>100),
  226. 'p.fk_state'=>array('label'=>"State", 'checked'=>0, 'position'=>101),
  227. $alias_product_perentity . '.accountancy_code_sell'=>array('label'=>"ProductAccountancySellCode", 'checked'=>0, 'enabled'=>empty($conf->global->PRODUCT_DISABLE_ACCOUNTING), 'position'=>400),
  228. $alias_product_perentity . '.accountancy_code_sell_intra'=>array('label'=>"ProductAccountancySellIntraCode", 'checked'=>0, 'enabled'=>$isInEEC && empty($conf->global->PRODUCT_DISABLE_ACCOUNTING), 'position'=>401),
  229. $alias_product_perentity . '.accountancy_code_sell_export'=>array('label'=>"ProductAccountancySellExportCode", 'checked'=>0, 'enabled'=>empty($conf->global->PRODUCT_DISABLE_ACCOUNTING), 'position'=>402),
  230. $alias_product_perentity . '.accountancy_code_buy'=>array('label'=>"ProductAccountancyBuyCode", 'checked'=>0, 'enabled'=>empty($conf->global->PRODUCT_DISABLE_ACCOUNTING), 'position'=>403),
  231. $alias_product_perentity . '.accountancy_code_buy_intra'=>array('label'=>"ProductAccountancyBuyIntraCode", 'checked'=>0, 'enabled'=>$isInEEC && empty($conf->global->PRODUCT_DISABLE_ACCOUNTING), 'position'=>404),
  232. $alias_product_perentity . '.accountancy_code_buy_export'=>array('label'=>"ProductAccountancyBuyExportCode", 'checked'=>0, 'enabled'=>empty($conf->global->PRODUCT_DISABLE_ACCOUNTING), 'position'=>405),
  233. 'p.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500),
  234. 'p.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500),
  235. 'p.tosell'=>array('label'=>$langs->transnoentitiesnoconv("Status").' ('.$langs->transnoentitiesnoconv("Sell").')', 'checked'=>1, 'position'=>1000),
  236. 'p.tobuy'=>array('label'=>$langs->transnoentitiesnoconv("Status").' ('.$langs->transnoentitiesnoconv("Buy").')', 'checked'=>1, 'position'=>1000)
  237. );
  238. /*foreach ($object->fields as $key => $val) {
  239. // If $val['visible']==0, then we never show the field
  240. if (!empty($val['visible'])) {
  241. $visible = dol_eval($val['visible'], 1, 1, '1');
  242. $arrayfields['p.'.$key] = array(
  243. 'label'=>$val['label'],
  244. 'checked'=>(($visible < 0) ? 0 : 1),
  245. 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1, 1, '1')),
  246. 'position'=>$val['position']
  247. );
  248. }
  249. }*/
  250. // MultiPrices
  251. if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
  252. for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) {
  253. $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$i;
  254. if (!empty($conf->global->$keyforlabel)) {
  255. $labelp = $i.' - '.$langs->transnoentitiesnoconv($conf->global->$keyforlabel);
  256. } else {
  257. $labelp = $langs->transnoentitiesnoconv("SellingPrice")." ".$i;
  258. }
  259. $arrayfields['p.sellprice'.$i] = array('label'=>$labelp, 'checked'=>($i == 1 ? 1 : 0), 'enabled'=>$conf->global->PRODUIT_MULTIPRICES, 'position'=>floatval('40.'.sprintf('%03s', $i)));
  260. $arraypricelevel[$i] = array($i);
  261. }
  262. }
  263. //var_dump($arraypricelevel);
  264. // Extra fields
  265. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
  266. $object->fields = dol_sort_array($object->fields, 'position');
  267. $arrayfields = dol_sort_array($arrayfields, 'position');
  268. // Security check
  269. if ($search_type == '0') {
  270. $result = restrictedArea($user, 'produit', '', '', '', '', '', 0);
  271. } elseif ($search_type == '1') {
  272. $result = restrictedArea($user, 'service', '', '', '', '', '', 0);
  273. } else {
  274. $result = restrictedArea($user, 'produit|service', '', '', '', '', '', 0);
  275. }
  276. /*
  277. * Actions
  278. */
  279. if (GETPOST('cancel', 'alpha')) {
  280. $action = 'list'; $massaction = '';
  281. }
  282. if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
  283. $massaction = '';
  284. }
  285. $parameters = array();
  286. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  287. if ($reshook < 0) {
  288. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  289. }
  290. $rightskey = 'produit';
  291. if ($type == Product::TYPE_SERVICE) {
  292. $rightskey = 'service';
  293. }
  294. if (empty($reshook)) {
  295. // Selection of new fields
  296. include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
  297. // Purge search criteria
  298. if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
  299. $sall = "";
  300. $search_id = '';
  301. $search_ref = "";
  302. $search_ref_supplier = "";
  303. $search_label = "";
  304. $search_default_workstation = "";
  305. $search_barcode = "";
  306. $searchCategoryProductOperator = 0;
  307. $searchCategoryProductList = array();
  308. $search_tosell = "";
  309. $search_tobuy = "";
  310. $search_tobatch = '';
  311. $search_country = "";
  312. $search_state = "";
  313. $search_vatrate = "";
  314. $search_finished = '';
  315. //$search_type=''; // There is 2 types of list: a list of product and a list of services. No list with both. So when we clear search criteria, we must keep the filter on type.
  316. $show_childproducts = '';
  317. $search_accountancy_code_sell = '';
  318. $search_accountancy_code_sell_intra = '';
  319. $search_accountancy_code_sell_export = '';
  320. $search_accountancy_code_buy = '';
  321. $search_accountancy_code_buy_intra = '';
  322. $search_accountancy_code_buy_export = '';
  323. $search_array_options = array();
  324. }
  325. // Mass actions
  326. $objectclass = 'Product';
  327. if ((string) $search_type == '1') {
  328. $objectlabel = 'Services';
  329. }
  330. if ((string) $search_type == '0') {
  331. $objectlabel = 'Products';
  332. }
  333. $permissiontoread = $user->rights->{$rightskey}->lire;
  334. $permissiontodelete = $user->rights->{$rightskey}->supprimer;
  335. $permissiontoadd = $user->rights->{$rightskey}->creer;
  336. $uploaddir = $conf->product->dir_output;
  337. include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
  338. if (!$error && $massaction == 'switchonsalestatus' && $permissiontoadd) {
  339. $product = new Product($db);
  340. foreach ($toselect as $toselectid) {
  341. $result = $product->fetch($toselectid);
  342. if ($result > 0 && $product->id > 0) {
  343. if ($product->setStatut($product->status ? 0 : 1, null, 'product', 'PRODUCT_MODIFY', 'tosell') < 0) {
  344. setEventMessages($product->error, $product->errors, 'errors');
  345. }
  346. }
  347. }
  348. }
  349. if (!$error && $massaction == 'switchonpurchasestatus' && $permissiontoadd) {
  350. $product = new Product($db);
  351. foreach ($toselect as $toselectid) {
  352. $result = $product->fetch($toselectid);
  353. if ($result > 0 && $product->id > 0) {
  354. if ($product->setStatut($product->status_buy ? 0 : 1, null, 'product', 'PRODUCT_MODIFY', 'tobuy') < 0) {
  355. setEventMessages($product->error, $product->errors, 'errors');
  356. }
  357. }
  358. }
  359. }
  360. }
  361. /*
  362. * View
  363. */
  364. $title = $langs->trans("ProductsAndServices");
  365. if ($search_type != '' && $search_type != '-1') {
  366. if ($search_type == 1) {
  367. $title = $langs->trans("Services");
  368. } else {
  369. $title = $langs->trans("Products");
  370. }
  371. }
  372. $sql = 'SELECT p.rowid, p.ref, p.label, p.fk_product_type, p.barcode, p.price, p.tva_tx, p.price_ttc, p.price_base_type, p.entity,';
  373. $sql .= ' p.fk_product_type, p.duration, p.finished, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
  374. $sql .= ' p.tobatch, ';
  375. if (isModEnabled('workstation')) {
  376. $sql .= ' p.fk_default_workstation, ws.status as status_workstation, ws.ref as ref_workstation, ';
  377. }
  378. if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
  379. $sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export,";
  380. } else {
  381. $sql .= " ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export, ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export,";
  382. }
  383. $sql .= ' p.datec as date_creation, p.tms as date_update, p.pmp, p.stock, p.cost_price,';
  384. $sql .= ' p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units, fk_country, fk_state,';
  385. if (!empty($conf->global->PRODUCT_USE_UNITS)) {
  386. $sql .= ' p.fk_unit, cu.label as cu_label,';
  387. }
  388. $sql .= ' MIN(pfp.unitprice) as bestpurchaseprice';
  389. if (isModEnabled('variants') && (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD) && !$show_childproducts)) {
  390. $sql .= ', pac.rowid as prod_comb_id';
  391. }
  392. // Add fields from extrafields
  393. if (!empty($extrafields->attributes[$object->table_element]['label'])) {
  394. foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
  395. $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
  396. }
  397. }
  398. // Add fields from hooks
  399. $parameters = array();
  400. $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  401. $sql .= $hookmanager->resPrint;
  402. $sqlfields = $sql; // $sql fields to remove for count total
  403. $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
  404. if (isModEnabled('workstation')) {
  405. $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "workstation_workstation ws ON (p.fk_default_workstation = ws.rowid)";
  406. }
  407. if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
  408. $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
  409. }
  410. if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
  411. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_extrafields as ef on (p.rowid = ef.fk_object)";
  412. }
  413. $linktopfp = " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
  414. $sql .= $linktopfp;
  415. // multilang
  416. if (getDolGlobalInt('MAIN_MULTILANGS')) {
  417. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang = '".$db->escape($langs->getDefaultLang())."'";
  418. }
  419. if (isModEnabled('variants') && (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD) && !$show_childproducts)) {
  420. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination pac ON pac.fk_product_child = p.rowid";
  421. }
  422. if (!empty($conf->global->PRODUCT_USE_UNITS)) {
  423. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_units cu ON cu.rowid = p.fk_unit";
  424. }
  425. $sql .= ' WHERE p.entity IN ('.getEntity('product').', 0)';
  426. if ($sall) {
  427. $sql .= ' AND (';
  428. $sql .= natural_search(array_keys($fieldstosearchall), $sall, 0, 1);
  429. // Search also into a supplier reference 'pfp.ref_fourn'="RefSupplier"
  430. $sql .= ' OR EXISTS (SELECT rowid FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp WHERE pfp.fk_product = p.rowid';
  431. $sql .= ' AND ('.natural_search('pfp.ref_fourn', $sall, 0, 1);
  432. if (isModEnabled('barcode')) {
  433. // Search also into a supplier barcode 'pfp.barcode'='GencodBuyPrice';
  434. $sql .= ' OR '.natural_search('pfp.barcode', $sall, 0, 1);
  435. }
  436. $sql .= ')))';
  437. }
  438. // if the type is not 1, we show all products (type = 0,2,3)
  439. if (dol_strlen($search_type) && $search_type != '-1') {
  440. if ($search_type == 1) {
  441. $sql .= " AND p.fk_product_type = 1";
  442. } else {
  443. $sql .= " AND p.fk_product_type <> 1";
  444. }
  445. }
  446. if (isModEnabled('variants') && (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD) && !$show_childproducts)) {
  447. $sql .= " AND pac.rowid IS NULL";
  448. }
  449. if ($search_id) {
  450. $sql .= natural_search('p.rowid', $search_id, 1);
  451. }
  452. if ($search_ref) {
  453. $sql .= natural_search('p.ref', $search_ref);
  454. }
  455. if ($search_label) {
  456. $sql .= natural_search('p.label', $search_label);
  457. }
  458. if ($search_default_workstation) {
  459. $sql .= natural_search('ws.ref', $search_default_workstation);
  460. }
  461. if ($search_barcode) {
  462. $sql .= natural_search('p.barcode', $search_barcode);
  463. }
  464. if (isset($search_tosell) && dol_strlen($search_tosell) > 0 && $search_tosell != -1) {
  465. $sql .= " AND p.tosell = ".((int) $search_tosell);
  466. }
  467. if (isset($search_tobuy) && dol_strlen($search_tobuy) > 0 && $search_tobuy != -1) {
  468. $sql .= " AND p.tobuy = ".((int) $search_tobuy);
  469. }
  470. if (isset($search_tobatch) && dol_strlen($search_tobatch) > 0 && $search_tobatch != -1) {
  471. $sql .= " AND p.tobatch = ".((int) $search_tobatch);
  472. }
  473. if ($search_vatrate) {
  474. $sql .= natural_search('p.tva_tx', $search_vatrate, 1);
  475. }
  476. if (dol_strlen($canvas) > 0) {
  477. $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
  478. }
  479. // Search for tag/category ($searchCategoryProductList is an array of ID)
  480. if (!empty($searchCategoryProductList)) {
  481. $searchCategoryProductSqlList = array();
  482. $listofcategoryid = '';
  483. foreach ($searchCategoryProductList as $searchCategoryProduct) {
  484. if (intval($searchCategoryProduct) == -2) {
  485. $searchCategoryProductSqlList[] = "NOT EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck WHERE p.rowid = ck.fk_product)";
  486. } elseif (intval($searchCategoryProduct) > 0) {
  487. if ($searchCategoryProductOperator == 0) {
  488. $searchCategoryProductSqlList[] = " EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck WHERE p.rowid = ck.fk_product AND ck.fk_categorie = ".((int) $searchCategoryProduct).")";
  489. } else {
  490. $listofcategoryid .= ($listofcategoryid ? ', ' : '') .((int) $searchCategoryProduct);
  491. }
  492. }
  493. }
  494. if ($listofcategoryid) {
  495. $searchCategoryProductSqlList[] = " EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck WHERE p.rowid = ck.fk_product AND ck.fk_categorie IN (".$db->sanitize($listofcategoryid)."))";
  496. }
  497. if ($searchCategoryProductOperator == 1) {
  498. if (!empty($searchCategoryProductSqlList)) {
  499. $sql .= " AND (".implode(' OR ', $searchCategoryProductSqlList).")";
  500. }
  501. } else {
  502. if (!empty($searchCategoryProductSqlList)) {
  503. $sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")";
  504. }
  505. }
  506. }
  507. if ($fourn_id > 0) {
  508. $sql .= " AND pfp.fk_soc = ".((int) $fourn_id);
  509. }
  510. if ($search_country) {
  511. $sql .= " AND p.fk_country = ".((int) $search_country);
  512. }
  513. if ($search_state) {
  514. $sql .= " AND p.fk_state = ".((int) $search_state);
  515. }
  516. if ($search_finished >= 0 && $search_finished !== '') {
  517. $sql .= " AND p.finished = ".((int) $search_finished);
  518. }
  519. if ($search_accountancy_code_sell) {
  520. $sql .= natural_search($alias_product_perentity . '.accountancy_code_sell', $search_accountancy_code_sell);
  521. }
  522. if ($search_accountancy_code_sell_intra) {
  523. $sql .= natural_search($alias_product_perentity . '.accountancy_code_sell_intra', $search_accountancy_code_sell_intra);
  524. }
  525. if ($search_accountancy_code_sell_export) {
  526. $sql .= natural_search($alias_product_perentity . '.accountancy_code_sell_export', $search_accountancy_code_sell_export);
  527. }
  528. if ($search_accountancy_code_buy) {
  529. $sql .= natural_search($alias_product_perentity . '.accountancy_code_buy', $search_accountancy_code_buy);
  530. }
  531. if ($search_accountancy_code_buy_intra) {
  532. $sql .= natural_search($alias_product_perentity . '.accountancy_code_buy_intra', $search_accountancy_code_buy_intra);
  533. }
  534. if ($search_accountancy_code_buy_export) {
  535. $sql .= natural_search($alias_product_perentity . '.accountancy_code_buy_export', $search_accountancy_code_buy_export);
  536. }
  537. // Add where from extra fields
  538. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
  539. // Add where from hooks
  540. $parameters = array();
  541. $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  542. $sql .= $hookmanager->resPrint;
  543. $sql .= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.tva_tx, p.price_ttc, p.price_base_type,";
  544. $sql .= " p.fk_product_type, p.duration, p.finished, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,";
  545. $sql .= ' p.datec, p.tms, p.entity, p.tobatch, p.pmp, p.cost_price, p.stock,';
  546. if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
  547. $sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export,";
  548. } else {
  549. $sql .= " ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export, ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export,";
  550. }
  551. $sql .= ' p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units, p.fk_country, p.fk_state';
  552. if (!empty($conf->global->PRODUCT_USE_UNITS)) {
  553. $sql .= ', p.fk_unit, cu.label';
  554. }
  555. if (isModEnabled('workstation')) {
  556. $sql .= ', p.fk_default_workstation, ws.status, ws.ref ';
  557. }
  558. if (isModEnabled('variants') && (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD) && !$show_childproducts)) {
  559. $sql .= ', pac.rowid';
  560. }
  561. // Add fields from extrafields
  562. if (!empty($extrafields->attributes[$object->table_element]['label'])) {
  563. foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
  564. $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key : '');
  565. }
  566. }
  567. // Add fields from hooks
  568. $parameters = array();
  569. $reshook = $hookmanager->executeHooks('printFieldSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  570. $sql .= $hookmanager->resPrint;
  571. //if (GETPOST("toolowstock")) $sql.= " HAVING SUM(s.reel) < p.seuil_stock_alerte"; // Not used yet
  572. $nbtotalofrecords = '';
  573. if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
  574. /* The fast and low memory method to get and count full list converts the sql into a sql count */
  575. $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
  576. $sqlforcount = preg_replace('/'.preg_quote($linktopfp, '/').'/', '', $sqlforcount);
  577. $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
  578. $resql = $db->query($sqlforcount);
  579. if ($resql) {
  580. $objforcount = $db->fetch_object($resql);
  581. $nbtotalofrecords = $objforcount->nbtotalofrecords;
  582. } else {
  583. dol_print_error($db);
  584. }
  585. if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
  586. $page = 0;
  587. $offset = 0;
  588. }
  589. $db->free($resql);
  590. }
  591. // Complete request and execute it with limit
  592. $sql .= $db->order($sortfield, $sortorder);
  593. if ($limit) {
  594. $sql .= $db->plimit($limit + 1, $offset);
  595. }
  596. $resql = $db->query($sql);
  597. if (!$resql) {
  598. dol_print_error($db);
  599. exit;
  600. }
  601. $num = $db->num_rows($resql);
  602. $arrayofselected = is_array($toselect) ? $toselect : array();
  603. // Direct jump if only one record found
  604. if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall) {
  605. $obj = $db->fetch_object($resql);
  606. $id = $obj->rowid;
  607. header("Location: ".DOL_URL_ROOT.'/product/card.php?id='.$id);
  608. exit;
  609. }
  610. $helpurl = '';
  611. if ($search_type != '') {
  612. if ($search_type == 0) {
  613. $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
  614. } elseif ($search_type == 1) {
  615. $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
  616. }
  617. }
  618. $paramsCat = '';
  619. foreach ($searchCategoryProductList as $searchCategoryProduct) {
  620. $paramsCat .= "&search_category_product_list[]=".urlencode($searchCategoryProduct);
  621. }
  622. //llxHeader('', $title, $helpurl, '', 0, 0, array(), array(), $paramsCat, 'classforhorizontalscrolloftabs');
  623. llxHeader('', $title, $helpurl, '', 0, 0, array(), array(), $paramsCat, '');
  624. // Displays product removal confirmation
  625. if (GETPOST('delprod')) {
  626. setEventMessages($langs->trans("ProductDeleted", GETPOST('delprod')), null, 'mesgs');
  627. }
  628. $param = '';
  629. if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
  630. $param .= '&contextpage='.urlencode($contextpage);
  631. }
  632. if ($limit > 0 && $limit != $conf->liste_limit) {
  633. $param .= '&limit='.urlencode($limit);
  634. }
  635. if ($sall) {
  636. $param .= "&sall=".urlencode($sall);
  637. }
  638. if ($searchCategoryProductOperator == 1) {
  639. $param .= "&search_category_product_operator=".urlencode($searchCategoryProductOperator);
  640. }
  641. foreach ($searchCategoryProductList as $searchCategoryProduct) {
  642. $param .= "&search_category_product_list[]=".urlencode($searchCategoryProduct);
  643. }
  644. if ($search_ref) {
  645. $param = "&search_ref=".urlencode($search_ref);
  646. }
  647. if ($search_ref_supplier) {
  648. $param = "&search_ref_supplier=".urlencode($search_ref_supplier);
  649. }
  650. if ($search_barcode) {
  651. $param .= ($search_barcode ? "&search_barcode=".urlencode($search_barcode) : "");
  652. }
  653. if ($search_label) {
  654. $param .= "&search_label=".urlencode($search_label);
  655. }
  656. if ($search_default_workstation) {
  657. $param .= "&search_default_workstation=".urlencode($search_default_workstation);
  658. }
  659. if ($search_tosell != '') {
  660. $param .= "&search_tosell=".urlencode($search_tosell);
  661. }
  662. if ($search_tobuy != '') {
  663. $param .= "&search_tobuy=".urlencode($search_tobuy);
  664. }
  665. if ($search_tobatch) {
  666. $param = "&search_tobatch=".urlencode($search_tobatch);
  667. }
  668. if ($search_country != '') {
  669. $param .= "&search_country=".urlencode($search_country);
  670. }
  671. if ($search_state != '') {
  672. $param .= "&search_state=".urlencode($search_state);
  673. }
  674. if ($search_vatrate) {
  675. $param = "&search_vatrate=".urlencode($search_vatrate);
  676. }
  677. if ($fourn_id > 0) {
  678. $param .= "&fourn_id=".urlencode($fourn_id);
  679. }
  680. if ($show_childproducts) {
  681. $param .= ($show_childproducts ? "&search_show_childproducts=".urlencode($show_childproducts) : "");
  682. }
  683. if ($type != '') {
  684. $param .= '&type='.urlencode($type);
  685. }
  686. if ($search_type != '') {
  687. $param .= '&search_type='.urlencode($search_type);
  688. }
  689. if ($optioncss != '') {
  690. $param .= '&optioncss='.urlencode($optioncss);
  691. }
  692. if ($search_accountancy_code_sell) {
  693. $param = "&search_accountancy_code_sell=".urlencode($search_accountancy_code_sell);
  694. }
  695. if ($search_accountancy_code_sell_intra) {
  696. $param = "&search_accountancy_code_sell_intra=".urlencode($search_accountancy_code_sell_intra);
  697. }
  698. if ($search_accountancy_code_sell_export) {
  699. $param = "&search_accountancy_code_sell_export=".urlencode($search_accountancy_code_sell_export);
  700. }
  701. if ($search_accountancy_code_buy) {
  702. $param = "&search_accountancy_code_buy=".urlencode($search_accountancy_code_buy);
  703. }
  704. if ($search_accountancy_code_buy_intra) {
  705. $param = "&search_accountancy_code_buy_intra=".urlencode($search_accountancy_code_buy_intra);
  706. }
  707. if ($search_accountancy_code_buy_export) {
  708. $param = "&search_accountancy_code_buy_export=".urlencode($search_accountancy_code_buy_export);
  709. }
  710. if ($search_finished) {
  711. $param = "&search_finished=".urlencode($search_finished);
  712. }
  713. // Add $param from extra fields
  714. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
  715. // List of mass actions available
  716. $arrayofmassactions = array(
  717. 'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
  718. 'edit_extrafields'=>img_picto('', 'edit', 'class="pictofixedwidth"').$langs->trans("ModifyValueExtrafields"),
  719. //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
  720. //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
  721. );
  722. if ($user->rights->{$rightskey}->supprimer) {
  723. $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
  724. }
  725. if ($user->rights->{$rightskey}->creer) {
  726. $arrayofmassactions['switchonsalestatus'] = img_picto('', 'stop-circle', 'class="pictofixedwidth"').$langs->trans("SwitchOnSaleStatus");
  727. $arrayofmassactions['switchonpurchasestatus'] = img_picto('', 'stop-circle', 'class="pictofixedwidth"').$langs->trans("SwitchOnPurchaseStatus");
  728. $arrayofmassactions['preupdateprice'] = img_picto('', 'edit', 'class="pictofixedwidth"').$langs->trans("UpdatePrice");
  729. }
  730. if (isModEnabled('category') && $user->rights->{$rightskey}->creer) {
  731. $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag");
  732. }
  733. if (in_array($massaction, array('presend', 'predelete','preaffecttag', 'edit_extrafields', 'preupdateprice'))) {
  734. $arrayofmassactions = array();
  735. }
  736. $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
  737. $newcardbutton = '';
  738. if ($type === "") {
  739. $perm = ($user->rights->produit->creer || $user->rights->service->creer);
  740. } elseif ($type == Product::TYPE_SERVICE) {
  741. $perm = $user->rights->service->creer;
  742. } elseif ($type == Product::TYPE_PRODUCT) {
  743. $perm = $user->rights->produit->creer;
  744. }
  745. $oldtype = $type;
  746. $params = array();
  747. if ($type === "") {
  748. $params['forcenohideoftext'] = 1;
  749. }
  750. if ($type === "") {
  751. $newcardbutton .= dolGetButtonTitle($langs->trans('NewProduct'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=0', '', $perm, $params);
  752. $type = Product::TYPE_SERVICE;
  753. }
  754. $label = 'NewProduct';
  755. if ($type == Product::TYPE_SERVICE) {
  756. $label = 'NewService';
  757. }
  758. $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type='.$type, '', $perm, $params);
  759. $type = $oldtype;
  760. print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">';
  761. if ($optioncss != '') {
  762. print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
  763. }
  764. print '<input type="hidden" name="token" value="'.newToken().'">';
  765. print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
  766. print '<input type="hidden" name="action" value="list">';
  767. print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
  768. print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
  769. //print '<input type="hidden" name="page" value="'.$page.'">';
  770. print '<input type="hidden" name="type" value="'.$type.'">';
  771. if (empty($arrayfields['p.fk_product_type']['checked'])) {
  772. print '<input type="hidden" name="search_type" value="'.dol_escape_htmltag($search_type).'">';
  773. }
  774. $picto = 'product';
  775. if ($type == 1) {
  776. $picto = 'service';
  777. }
  778. print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
  779. $topicmail = "Information";
  780. $modelmail = "product";
  781. $objecttmp = new Product($db);
  782. $trackid = 'prod'.$object->id;
  783. include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
  784. if (!empty($catid)) {
  785. print "<div id='ways'>";
  786. $c = new Categorie($db);
  787. $ways = $c->print_all_ways(' &gt; ', 'product/list.php');
  788. print " &gt; ".$ways[0]."<br>\n";
  789. print "</div><br>";
  790. }
  791. if ($sall) {
  792. $setupstring = '';
  793. foreach ($fieldstosearchall as $key => $val) {
  794. $fieldstosearchall[$key] = $langs->trans($val);
  795. $setupstring .= $key."=".$val.";";
  796. }
  797. print '<!-- Search done like if PRODUCT_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
  798. print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $sall).join(', ', $fieldstosearchall).'</div>'."\n";
  799. }
  800. // Filter on categories
  801. $moreforfilter = '';
  802. if (isModEnabled('categorie') && $user->hasRight('categorie', 'read')) {
  803. $formcategory = new FormCategory($db);
  804. $moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PRODUCT, $searchCategoryProductList, 'minwidth300', $searchCategoryProductOperator ? $searchCategoryProductOperator : 0);
  805. }
  806. //Show/hide child products. Hidden by default
  807. if (isModEnabled('variants') && !empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
  808. $moreforfilter .= '<div class="divsearchfield">';
  809. $moreforfilter .= '<input type="checkbox" id="search_show_childproducts" name="search_show_childproducts"'.($show_childproducts ? 'checked="checked"' : '').'>';
  810. $moreforfilter .= ' <label for="search_show_childproducts">'.$langs->trans('ShowChildProducts').'</label>';
  811. $moreforfilter .= '</div>';
  812. }
  813. $parameters = array();
  814. $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  815. if (empty($reshook)) {
  816. $moreforfilter .= $hookmanager->resPrint;
  817. } else {
  818. $moreforfilter = $hookmanager->resPrint;
  819. }
  820. if ($moreforfilter) {
  821. print '<div class="liste_titre liste_titre_bydiv centpercent">';
  822. print $moreforfilter;
  823. print '</div>';
  824. }
  825. $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
  826. $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields
  827. if ($massactionbutton) {
  828. $selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
  829. }
  830. print '<div class="div-table-responsive">';
  831. print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
  832. // Lines with input filters
  833. print '<tr class="liste_titre_filter">';
  834. if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
  835. print '<td class="liste_titre center maxwidthsearch">';
  836. $searchpicto = $form->showFilterButtons('left');
  837. print $searchpicto;
  838. print '</td>';
  839. }
  840. if (!empty($arrayfields['p.rowid']['checked'])) {
  841. print '<td class="liste_titre left">';
  842. print '<input class="flat" type="text" name="search_id" size="4" value="'.dol_escape_htmltag($search_id).'">';
  843. print '</td>';
  844. }
  845. if (!empty($arrayfields['p.ref']['checked'])) {
  846. print '<td class="liste_titre left">';
  847. print '<input class="flat" type="text" name="search_ref" size="8" value="'.dol_escape_htmltag($search_ref).'">';
  848. print '</td>';
  849. }
  850. if (!empty($arrayfields['pfp.ref_fourn']['checked'])) {
  851. print '<td class="liste_titre left">';
  852. print '<input class="flat" type="text" name="search_ref_supplier" size="8" value="'.dol_escape_htmltag($search_ref_supplier).'">';
  853. print '</td>';
  854. }
  855. // Thumbnail
  856. if (!empty($arrayfields['thumbnail']['checked'])) {
  857. print '<td class="liste_titre center">';
  858. print '</td>';
  859. }
  860. if (!empty($arrayfields['p.label']['checked'])) {
  861. print '<td class="liste_titre left">';
  862. print '<input class="flat" type="text" name="search_label" size="12" value="'.dol_escape_htmltag($search_label).'">';
  863. print '</td>';
  864. }
  865. // Type
  866. if (!empty($arrayfields['p.fk_product_type']['checked'])) {
  867. print '<td class="liste_titre center">';
  868. $array = array('-1'=>'&nbsp;', '0'=>$langs->trans('Product'), '1'=>$langs->trans('Service'));
  869. print $form->selectarray('search_type', $array, $search_type);
  870. print '</td>';
  871. }
  872. // Barcode
  873. if (!empty($arrayfields['p.barcode']['checked'])) {
  874. print '<td class="liste_titre">';
  875. print '<input class="flat" type="text" name="search_barcode" size="6" value="'.dol_escape_htmltag($search_barcode).'">';
  876. print '</td>';
  877. }
  878. // Duration
  879. if (!empty($arrayfields['p.duration']['checked'])) {
  880. print '<td class="liste_titre">';
  881. print '</td>';
  882. }
  883. // Finished
  884. if (!empty($arrayfields['p.finished']['checked'])) {
  885. print '<td class="liste_titre">';
  886. print $formproduct->selectProductNature('search_finished', $search_finished);
  887. print '</td>';
  888. }
  889. // Weight
  890. if (!empty($arrayfields['p.weight']['checked'])) {
  891. print '<td class="liste_titre">';
  892. print '</td>';
  893. }
  894. // Weight units
  895. if (!empty($arrayfields['p.weight_units']['checked'])) {
  896. print '<td class="liste_titre">';
  897. print '</td>';
  898. }
  899. // Length
  900. if (!empty($arrayfields['p.length']['checked'])) {
  901. print '<td class="liste_titre">';
  902. print '</td>';
  903. }
  904. // Length units
  905. if (!empty($arrayfields['p.length_units']['checked'])) {
  906. print '<td class="liste_titre">';
  907. print '</td>';
  908. }
  909. // Width
  910. if (!empty($arrayfields['p.width']['checked'])) {
  911. print '<td class="liste_titre">';
  912. print '</td>';
  913. }
  914. // Width units
  915. if (!empty($arrayfields['p.width_units']['checked'])) {
  916. print '<td class="liste_titre">';
  917. print '</td>';
  918. }
  919. // Height
  920. if (!empty($arrayfields['p.height']['checked'])) {
  921. print '<td class="liste_titre">';
  922. print '</td>';
  923. }
  924. // Height units
  925. if (!empty($arrayfields['p.height_units']['checked'])) {
  926. print '<td class="liste_titre">';
  927. print '</td>';
  928. }
  929. // Surface
  930. if (!empty($arrayfields['p.surface']['checked'])) {
  931. print '<td class="liste_titre">';
  932. print '</td>';
  933. }
  934. // Surface units
  935. if (!empty($arrayfields['p.surface_units']['checked'])) {
  936. print '<td class="liste_titre">';
  937. print '</td>';
  938. }
  939. // Volume
  940. if (!empty($arrayfields['p.volume']['checked'])) {
  941. print '<td class="liste_titre">';
  942. print '</td>';
  943. }
  944. // Volume units
  945. if (!empty($arrayfields['p.volume_units']['checked'])) {
  946. print '<td class="liste_titre">';
  947. print '</td>';
  948. }
  949. // Unit
  950. if (!empty($arrayfields['cu.label']['checked'])) {
  951. print '<td class="liste_titre">';
  952. print '</td>';
  953. }
  954. // Default workstation
  955. if (!empty($arrayfields['p.fk_default_workstation']['checked'])) {
  956. print '<td class="liste_titre">';
  957. print '<input class="flat" type="text" name="search_default_workstation" size="12" value="'.dol_escape_htmltag($search_default_workstation).'">';
  958. print '</td>';
  959. }
  960. // Sell price
  961. if (!empty($arrayfields['p.sellprice']['checked'])) {
  962. print '<td class="liste_titre right">';
  963. print '</td>';
  964. }
  965. // Multiprice
  966. if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
  967. foreach ($arraypricelevel as $key => $value) {
  968. if (!empty($arrayfields['p.sellprice'.$key]['checked'])) {
  969. print '<td class="liste_titre right">';
  970. print '</td>';
  971. }
  972. }
  973. }
  974. // Minimum buying Price
  975. if (!empty($arrayfields['p.minbuyprice']['checked'])) {
  976. print '<td class="liste_titre">';
  977. print '&nbsp;';
  978. print '</td>';
  979. }
  980. // Number buying Price
  981. if (!empty($arrayfields['p.numbuyprice']['checked'])) {
  982. print '<td class="liste_titre">';
  983. print '&nbsp;';
  984. print '</td>';
  985. }
  986. // Sell price
  987. if (!empty($arrayfields['p.tva_tx']['checked'])) {
  988. print '<td class="liste_titre right">';
  989. print '<input class="right flat maxwidth50" placeholder="%" type="text" name="search_vatrate" size="1" value="'.dol_escape_htmltag($search_vatrate).'">';
  990. print '</td>';
  991. }
  992. // WAP
  993. if (!empty($arrayfields['p.pmp']['checked'])) {
  994. print '<td class="liste_titre">';
  995. print '&nbsp;';
  996. print '</td>';
  997. }
  998. // cost_price
  999. if (!empty($arrayfields['p.cost_price']['checked'])) {
  1000. print '<td class="liste_titre">';
  1001. print '&nbsp;';
  1002. print '</td>';
  1003. }
  1004. // Limit for alert
  1005. if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) {
  1006. print '<td class="liste_titre">';
  1007. print '&nbsp;';
  1008. print '</td>';
  1009. }
  1010. // Desired stock
  1011. if (!empty($arrayfields['p.desiredstock']['checked'])) {
  1012. print '<td class="liste_titre">';
  1013. print '&nbsp;';
  1014. print '</td>';
  1015. }
  1016. // Stock
  1017. if (!empty($arrayfields['p.stock']['checked'])) {
  1018. print '<td class="liste_titre">&nbsp;</td>';
  1019. }
  1020. // Stock
  1021. if (!empty($arrayfields['stock_virtual']['checked'])) {
  1022. print '<td class="liste_titre">&nbsp;</td>';
  1023. }
  1024. // To batch
  1025. if (!empty($arrayfields['p.tobatch']['checked'])) {
  1026. print '<td class="liste_titre center">';
  1027. $statutarray = array(
  1028. '-1' => '',
  1029. '0' => $langs->trans("ProductStatusNotOnBatchShort"),
  1030. '1' => $langs->trans("ProductStatusOnBatchShort"),
  1031. '2' => $langs->trans("ProductStatusOnSerialShort")
  1032. );
  1033. print $form->selectarray('search_tobatch', $statutarray, $search_tobatch);
  1034. print '</td>';
  1035. }
  1036. // Country
  1037. if (!empty($arrayfields['p.fk_country']['checked'])) {
  1038. print '<td class="liste_titre center">';
  1039. print $form->select_country($search_country, 'search_country', '', 0);
  1040. print '</td>';
  1041. }
  1042. // State
  1043. if (!empty($arrayfields['p.fk_state']['checked'])) {
  1044. print '<td class="liste_titre center">';
  1045. print $formcompany->select_state($search_state, $search_country);
  1046. print '</td>';
  1047. }
  1048. // Accountancy code sell
  1049. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) {
  1050. print '<td class="liste_titre"><input class="flat maxwidth75" type="text" name="search_accountancy_code_sell" value="'.dol_escape_htmltag($search_accountancy_code_sell).'"></td>';
  1051. }
  1052. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) {
  1053. print '<td class="liste_titre"><input class="flat maxwidth75" type="text" name="search_accountancy_code_sell_intra" value="'.dol_escape_htmltag($search_accountancy_code_sell_intra).'"></td>';
  1054. }
  1055. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) {
  1056. print '<td class="liste_titre"><input class="flat maxwidth75" type="text" name="search_accountancy_code_sell_export" value="'.dol_escape_htmltag($search_accountancy_code_sell_export).'"></td>';
  1057. }
  1058. // Accountancy code buy
  1059. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) {
  1060. print '<td class="liste_titre"><input class="flat maxwidth75" type="text" name="search_accountancy_code_buy" value="'.dol_escape_htmltag($search_accountancy_code_buy).'"></td>';
  1061. }
  1062. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) {
  1063. print '<td class="liste_titre"><input class="flat maxwidth75" type="text" name="search_accountancy_code_buy_intra" value="'.dol_escape_htmltag($search_accountancy_code_buy_intra).'"></td>';
  1064. }
  1065. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) {
  1066. print '<td class="liste_titre"><input class="flat maxwidth75" type="text" name="search_accountancy_code_buy_export" value="'.dol_escape_htmltag($search_accountancy_code_buy_export).'"></td>';
  1067. }
  1068. // Extra fields
  1069. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
  1070. // Fields from hook
  1071. $parameters = array('arrayfields'=>$arrayfields);
  1072. $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1073. print $hookmanager->resPrint;
  1074. // Date creation
  1075. if (!empty($arrayfields['p.datec']['checked'])) {
  1076. print '<td class="liste_titre">';
  1077. print '</td>';
  1078. }
  1079. // Date modification
  1080. if (!empty($arrayfields['p.tms']['checked'])) {
  1081. print '<td class="liste_titre">';
  1082. print '</td>';
  1083. }
  1084. if (!empty($arrayfields['p.tosell']['checked'])) {
  1085. print '<td class="liste_titre center">';
  1086. print $form->selectarray('search_tosell', array('0'=>$langs->trans('ProductStatusNotOnSellShort'), '1'=>$langs->trans('ProductStatusOnSellShort')), $search_tosell, 1, 0, 0, '', 0, 0, 0, '', 'search_status width100 onrightofpage');
  1087. print '</td >';
  1088. }
  1089. if (!empty($arrayfields['p.tobuy']['checked'])) {
  1090. print '<td class="liste_titre center">';
  1091. print $form->selectarray('search_tobuy', array('0'=>$langs->trans('ProductStatusNotOnBuyShort'), '1'=>$langs->trans('ProductStatusOnBuyShort')), $search_tobuy, 1, 0, 0, '', 0, 0, 0, '', 'search_status width100 onrightofpage');
  1092. print '</td>';
  1093. }
  1094. if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
  1095. print '<td class="liste_titre center maxwidthsearch">';
  1096. $searchpicto = $form->showFilterButtons();
  1097. print $searchpicto;
  1098. print '</td>';
  1099. }
  1100. print '</tr>';
  1101. print '<tr class="liste_titre">';
  1102. if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
  1103. print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
  1104. }
  1105. if (!empty($arrayfields['p.rowid']['checked'])) {
  1106. print_liste_field_titre($arrayfields['p.rowid']['label'], $_SERVER["PHP_SELF"], "p.rowid", "", $param, "", $sortfield, $sortorder);
  1107. }
  1108. if (!empty($arrayfields['p.ref']['checked'])) {
  1109. print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder);
  1110. }
  1111. if (!empty($arrayfields['pfp.ref_fourn']['checked'])) {
  1112. print_liste_field_titre($arrayfields['pfp.ref_fourn']['label'], $_SERVER["PHP_SELF"], "pfp.ref_fourn", "", $param, "", $sortfield, $sortorder);
  1113. }
  1114. if (!empty($arrayfields['thumbnail']['checked'])) {
  1115. print_liste_field_titre($arrayfields['thumbnail']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center ');
  1116. }
  1117. if (!empty($arrayfields['p.label']['checked'])) {
  1118. print_liste_field_titre($arrayfields['p.label']['label'], $_SERVER["PHP_SELF"], "p.label", "", $param, "", $sortfield, $sortorder);
  1119. }
  1120. if (!empty($arrayfields['p.fk_product_type']['checked'])) {
  1121. print_liste_field_titre($arrayfields['p.fk_product_type']['label'], $_SERVER["PHP_SELF"], "p.fk_product_type", "", $param, "", $sortfield, $sortorder, 'center ');
  1122. }
  1123. if (!empty($arrayfields['p.barcode']['checked'])) {
  1124. print_liste_field_titre($arrayfields['p.barcode']['label'], $_SERVER["PHP_SELF"], "p.barcode", "", $param, "", $sortfield, $sortorder);
  1125. }
  1126. if (!empty($arrayfields['p.duration']['checked'])) {
  1127. print_liste_field_titre($arrayfields['p.duration']['label'], $_SERVER["PHP_SELF"], "p.duration", "", $param, '', $sortfield, $sortorder, 'center ');
  1128. }
  1129. if (!empty($arrayfields['p.finished']['checked'])) {
  1130. print_liste_field_titre($arrayfields['p.finished']['label'], $_SERVER["PHP_SELF"], "p.finished", "", $param, '', $sortfield, $sortorder, 'center ');
  1131. }
  1132. if (!empty($arrayfields['p.weight']['checked'])) {
  1133. print_liste_field_titre($arrayfields['p.weight']['label'], $_SERVER['PHP_SELF'], 'p.weight', '', $param, '', $sortfield, $sortorder, 'center ');
  1134. }
  1135. if (!empty($arrayfields['p.weight_units']['checked'])) {
  1136. print_liste_field_titre($arrayfields['p.weight_units']['label'], $_SERVER['PHP_SELF'], 'p.weight_units', '', $param, '', $sortfield, $sortorder, 'center ');
  1137. }
  1138. if (!empty($arrayfields['p.length']['checked'])) {
  1139. print_liste_field_titre($arrayfields['p.length']['label'], $_SERVER['PHP_SELF'], 'p.length', '', $param, '', $sortfield, $sortorder, 'center ');
  1140. }
  1141. if (!empty($arrayfields['p.length_units']['checked'])) {
  1142. print_liste_field_titre($arrayfields['p.length_units']['label'], $_SERVER['PHP_SELF'], 'p.length_units', '', $param, '', $sortfield, $sortorder, 'center ');
  1143. }
  1144. if (!empty($arrayfields['p.width']['checked'])) {
  1145. print_liste_field_titre($arrayfields['p.width']['label'], $_SERVER['PHP_SELF'], 'p.width', '', $param, '', $sortfield, $sortorder, 'center ');
  1146. }
  1147. if (!empty($arrayfields['p.width_units']['checked'])) {
  1148. print_liste_field_titre($arrayfields['p.width_units']['label'], $_SERVER['PHP_SELF'], 'p.width_units', '', $param, '', $sortfield, $sortorder, 'center ');
  1149. }
  1150. if (!empty($arrayfields['p.height']['checked'])) {
  1151. print_liste_field_titre($arrayfields['p.height']['label'], $_SERVER['PHP_SELF'], 'p.height', '', $param, '', $sortfield, $sortorder, 'center ');
  1152. }
  1153. if (!empty($arrayfields['p.height_units']['checked'])) {
  1154. print_liste_field_titre($arrayfields['p.height_units']['label'], $_SERVER['PHP_SELF'], 'p.height_units', '', $param, '', $sortfield, $sortorder, 'center ');
  1155. }
  1156. if (!empty($arrayfields['p.surface']['checked'])) {
  1157. print_liste_field_titre($arrayfields['p.surface']['label'], $_SERVER['PHP_SELF'], "p.surface", '', $param, '', $sortfield, $sortorder, 'center ');
  1158. }
  1159. if (!empty($arrayfields['p.surface_units']['checked'])) {
  1160. print_liste_field_titre($arrayfields['p.surface_units']['label'], $_SERVER['PHP_SELF'], 'p.surface_units', '', $param, '', $sortfield, $sortorder, 'center ');
  1161. }
  1162. if (!empty($arrayfields['p.volume']['checked'])) {
  1163. print_liste_field_titre($arrayfields['p.volume']['label'], $_SERVER['PHP_SELF'], 'p.volume', '', $param, '', $sortfield, $sortorder, 'center ');
  1164. }
  1165. if (!empty($arrayfields['p.volume_units']['checked'])) {
  1166. print_liste_field_titre($arrayfields['p.volume_units']['label'], $_SERVER['PHP_SELF'], 'p.volume_units', '', $param, '', $sortfield, $sortorder, 'center ');
  1167. }
  1168. if (!empty($arrayfields['cu.label']['checked'])) {
  1169. print_liste_field_titre($arrayfields['cu.label']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'center ');
  1170. }
  1171. if (!empty($arrayfields['p.fk_default_workstation']['checked'])) {
  1172. print_liste_field_titre($arrayfields['p.fk_default_workstation']['label'], $_SERVER['PHP_SELF'], 'ws.ref', '', $param, '', $sortfield, $sortorder);
  1173. }
  1174. if (!empty($arrayfields['p.sellprice']['checked'])) {
  1175. print_liste_field_titre($arrayfields['p.sellprice']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
  1176. }
  1177. // Multiprices
  1178. if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
  1179. foreach ($arraypricelevel as $key => $value) {
  1180. if (!empty($arrayfields['p.sellprice'.$key]['checked'])) {
  1181. print_liste_field_titre($arrayfields['p.sellprice'.$key]['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
  1182. }
  1183. }
  1184. }
  1185. if (!empty($arrayfields['p.minbuyprice']['checked'])) {
  1186. print_liste_field_titre($arrayfields['p.minbuyprice']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
  1187. }
  1188. if (!empty($arrayfields['p.numbuyprice']['checked'])) {
  1189. print_liste_field_titre($arrayfields['p.numbuyprice']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
  1190. }
  1191. if (!empty($arrayfields['p.tva_tx']['checked'])) {
  1192. print_liste_field_titre($arrayfields['p.tva_tx']['label'], $_SERVER["PHP_SELF"], 'p.tva_tx', "", $param, '', $sortfield, $sortorder, 'right ');
  1193. }
  1194. if (!empty($arrayfields['p.pmp']['checked'])) {
  1195. print_liste_field_titre($arrayfields['p.pmp']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
  1196. }
  1197. if (!empty($arrayfields['p.cost_price']['checked'])) {
  1198. print_liste_field_titre($arrayfields['p.cost_price']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
  1199. }
  1200. if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) {
  1201. print_liste_field_titre($arrayfields['p.seuil_stock_alerte']['label'], $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", "", $param, '', $sortfield, $sortorder, 'right ');
  1202. }
  1203. if (!empty($arrayfields['p.desiredstock']['checked'])) {
  1204. print_liste_field_titre($arrayfields['p.desiredstock']['label'], $_SERVER["PHP_SELF"], "p.desiredstock", "", $param, '', $sortfield, $sortorder, 'right ');
  1205. }
  1206. if (!empty($arrayfields['p.stock']['checked'])) {
  1207. print_liste_field_titre($arrayfields['p.stock']['label'], $_SERVER["PHP_SELF"], "p.stock", "", $param, '', $sortfield, $sortorder, 'right ');
  1208. }
  1209. if (!empty($arrayfields['stock_virtual']['checked'])) {
  1210. print_liste_field_titre($arrayfields['stock_virtual']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
  1211. }
  1212. if (!empty($arrayfields['p.tobatch']['checked'])) {
  1213. print_liste_field_titre($arrayfields['p.tobatch']['label'], $_SERVER["PHP_SELF"], "p.tobatch", "", $param, '', $sortfield, $sortorder, 'center ');
  1214. }
  1215. if (!empty($arrayfields['p.fk_country']['checked'])) {
  1216. print_liste_field_titre($arrayfields['p.fk_country']['label'], $_SERVER["PHP_SELF"], "p.fk_country", "", $param, '', $sortfield, $sortorder);
  1217. }
  1218. if (!empty($arrayfields['p.fk_state']['checked'])) {
  1219. print_liste_field_titre($arrayfields['p.fk_state']['label'], $_SERVER["PHP_SELF"], "p.fk_state", "", $param, '', $sortfield, $sortorder);
  1220. }
  1221. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) {
  1222. print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_sell", "", $param, '', $sortfield, $sortorder);
  1223. }
  1224. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) {
  1225. print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_sell_intra", "", $param, '', $sortfield, $sortorder);
  1226. }
  1227. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) {
  1228. print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_sell_export", "", $param, '', $sortfield, $sortorder);
  1229. }
  1230. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) {
  1231. print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_buy", "", $param, '', $sortfield, $sortorder);
  1232. }
  1233. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) {
  1234. print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_buy_intra", "", $param, '', $sortfield, $sortorder);
  1235. }
  1236. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) {
  1237. print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_buy_export", "", $param, '', $sortfield, $sortorder);
  1238. }
  1239. // Extra fields
  1240. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
  1241. // Hook fields
  1242. $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
  1243. $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1244. print $hookmanager->resPrint;
  1245. if (!empty($arrayfields['p.datec']['checked'])) {
  1246. print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
  1247. }
  1248. if (!empty($arrayfields['p.tms']['checked'])) {
  1249. print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
  1250. }
  1251. if (!empty($arrayfields['p.tosell']['checked'])) {
  1252. print_liste_field_titre($arrayfields['p.tosell']['label'], $_SERVER["PHP_SELF"], "p.tosell", "", $param, '', $sortfield, $sortorder, 'center ');
  1253. }
  1254. if (!empty($arrayfields['p.tobuy']['checked'])) {
  1255. print_liste_field_titre($arrayfields['p.tobuy']['label'], $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'center ');
  1256. }
  1257. if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
  1258. print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
  1259. }
  1260. print "</tr>\n";
  1261. $product_static = new Product($db);
  1262. $static_ws = new Workstation($db);
  1263. $product_fourn = new ProductFournisseur($db);
  1264. $i = 0;
  1265. $totalarray = array();
  1266. $totalarray['nbfield'] = 0;
  1267. while ($i < min($num, $limit)) {
  1268. $obj = $db->fetch_object($resql);
  1269. // Multilangs
  1270. if (getDolGlobalInt('MAIN_MULTILANGS')) { // If multilang is enabled
  1271. $sql = "SELECT label";
  1272. $sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
  1273. $sql .= " WHERE fk_product = ".((int) $obj->rowid);
  1274. $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
  1275. $sql .= " LIMIT 1";
  1276. $result = $db->query($sql);
  1277. if ($result) {
  1278. $objtp = $db->fetch_object($result);
  1279. if (!empty($objtp->label)) {
  1280. $obj->label = $objtp->label;
  1281. }
  1282. }
  1283. }
  1284. $parameters = array('staticdata' => $obj);
  1285. // Note that $action and $object may have been modified by hook
  1286. // do product_static fetch in hook if wanted or anything else
  1287. $reshook = $hookmanager->executeHooks('loadStaticObject', $parameters, $product_static, $action);
  1288. if (empty($reshook)) {
  1289. $product_static->id = $obj->rowid;
  1290. $product_static->ref = $obj->ref;
  1291. $product_static->ref_fourn = empty($obj->ref_supplier) ? '' : $obj->ref_supplier; // deprecated
  1292. $product_static->ref_supplier = empty($obj->ref_supplier) ? '' : $obj->ref_supplier;
  1293. $product_static->label = $obj->label;
  1294. $product_static->barcode = $obj->barcode;
  1295. $product_static->finished = $obj->finished;
  1296. $product_static->type = $obj->fk_product_type;
  1297. $product_static->status_buy = $obj->tobuy;
  1298. $product_static->status = $obj->tosell;
  1299. $product_static->status_batch = $obj->tobatch;
  1300. $product_static->entity = $obj->entity;
  1301. $product_static->pmp = $obj->pmp;
  1302. $product_static->accountancy_code_sell = $obj->accountancy_code_sell;
  1303. $product_static->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
  1304. $product_static->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
  1305. $product_static->accountancy_code_buy = $obj->accountancy_code_buy;
  1306. $product_static->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
  1307. $product_static->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
  1308. $product_static->length = $obj->length;
  1309. $product_static->length_units = $obj->length_units;
  1310. $product_static->width = $obj->width;
  1311. $product_static->width_units = $obj->width_units;
  1312. $product_static->height = $obj->height;
  1313. $product_static->height_units = $obj->height_units;
  1314. $product_static->weight = $obj->weight;
  1315. $product_static->weight_units = $obj->weight_units;
  1316. $product_static->volume = $obj->volume;
  1317. $product_static->volume_units = $obj->volume_units;
  1318. $product_static->surface = $obj->surface;
  1319. $product_static->surface_units = $obj->surface_units;
  1320. if (!empty($conf->global->PRODUCT_USE_UNITS)) {
  1321. $product_static->fk_unit = $obj->fk_unit;
  1322. }
  1323. // STOCK_DISABLE_OPTIM_LOAD can be set to force load_stock whatever is permissions on stock.
  1324. if ((isModEnabled('stock') && $user->rights->stock->lire && $search_type != 1) || !empty($conf->global->STOCK_DISABLE_OPTIM_LOAD)) { // To optimize call of load_stock
  1325. if ($product_static->type != 1 || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { // Not a service
  1326. $option = 'nobatch';
  1327. if (empty($arrayfields['stock_virtual']['checked'])) {
  1328. $option .= ',novirtual';
  1329. }
  1330. $product_static->load_stock($option); // Load stock_reel + stock_warehouse. This can also call load_virtual_stock()
  1331. }
  1332. }
  1333. }
  1334. $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('product', 'lire');
  1335. if ($product_static->isService()) {
  1336. $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire');
  1337. }
  1338. print '<tr class="oddeven">';
  1339. // Action column
  1340. if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
  1341. print '<td class="nowrap center">';
  1342. if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
  1343. $selected = 0;
  1344. if (in_array($obj->rowid, $arrayofselected)) {
  1345. $selected = 1;
  1346. }
  1347. print '<input id="cb'.$obj->rowid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->rowid.'"'.($selected ? ' checked="checked"' : '').'>';
  1348. }
  1349. print '</td>';
  1350. if (!$i) {
  1351. $totalarray['nbfield']++;
  1352. }
  1353. }
  1354. // Ref
  1355. if (!empty($arrayfields['p.rowid']['checked'])) {
  1356. print '<td class="nowraponall">';
  1357. print $product_static->id;
  1358. print "</td>\n";
  1359. if (!$i) {
  1360. $totalarray['nbfield']++;
  1361. }
  1362. }
  1363. // Ref
  1364. if (!empty($arrayfields['p.ref']['checked'])) {
  1365. print '<td class="tdoverflowmax200">';
  1366. print $product_static->getNomUrl(1);
  1367. print "</td>\n";
  1368. if (!$i) {
  1369. $totalarray['nbfield']++;
  1370. }
  1371. }
  1372. // Ref supplier
  1373. if (!empty($arrayfields['pfp.ref_fourn']['checked'])) {
  1374. print '<td class="tdoverflowmax200">';
  1375. print $product_static->getNomUrl(1);
  1376. print "</td>\n";
  1377. if (!$i) {
  1378. $totalarray['nbfield']++;
  1379. }
  1380. }
  1381. // Thumbnail
  1382. if (!empty($arrayfields['thumbnail']['checked'])) {
  1383. $product_thumbnail_html = '';
  1384. if (!empty($product_static->entity)) {
  1385. $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80);
  1386. if ($product_static->nbphoto > 0) {
  1387. $product_thumbnail_html = $product_thumbnail;
  1388. }
  1389. }
  1390. print '<td class="center">' . $product_thumbnail_html . '</td>';
  1391. if (!$i) {
  1392. $totalarray['nbfield']++;
  1393. }
  1394. }
  1395. // Label
  1396. if (!empty($arrayfields['p.label']['checked'])) {
  1397. print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($product_static->label).'">'.$product_static->label.'</td>';
  1398. if (!$i) {
  1399. $totalarray['nbfield']++;
  1400. }
  1401. }
  1402. // Type
  1403. if (!empty($arrayfields['p.fk_product_type']['checked'])) {
  1404. print '<td class="center">';
  1405. $s = '';
  1406. if ($product_static->type == 0) {
  1407. $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"');
  1408. } else {
  1409. $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"');
  1410. }
  1411. print $s;
  1412. print '</td>';
  1413. if (!$i) {
  1414. $totalarray['nbfield']++;
  1415. }
  1416. }
  1417. // Barcode
  1418. if (!empty($arrayfields['p.barcode']['checked'])) {
  1419. print '<td>'.$product_static->barcode.'</td>';
  1420. if (!$i) {
  1421. $totalarray['nbfield']++;
  1422. }
  1423. }
  1424. // Duration
  1425. if (!empty($arrayfields['p.duration']['checked'])) {
  1426. print '<td class="center nowraponall">';
  1427. if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) {
  1428. $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1);
  1429. $duration_unit = substr($obj->duration, -1);
  1430. if ((float) $duration_value > 1) {
  1431. $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years"));
  1432. } elseif ((float) $duration_value > 0) {
  1433. $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hour"), "d"=>$langs->trans("Day"), "w"=>$langs->trans("Week"), "m"=>$langs->trans("Month"), "y"=>$langs->trans("Year"));
  1434. }
  1435. print $duration_value;
  1436. print ((!empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : '');
  1437. } elseif (!preg_match('/^[a-z]$/i', $obj->duration)) { // If duration is a simple char (like 's' of 'm'), we do not show value
  1438. print $obj->duration;
  1439. }
  1440. print '</td>';
  1441. if (!$i) {
  1442. $totalarray['nbfield']++;
  1443. }
  1444. }
  1445. // Finished
  1446. if (!empty($arrayfields['p.finished']['checked'])) {
  1447. print '<td class="center">';
  1448. print $product_static->getLibFinished();
  1449. print '</td>';
  1450. if (!$i) {
  1451. $totalarray['nbfield']++;
  1452. }
  1453. }
  1454. // Weight
  1455. if (!empty($arrayfields['p.weight']['checked'])) {
  1456. print '<td class="center">';
  1457. print $product_static->weight;
  1458. print '</td>';
  1459. if (!$i) {
  1460. $totalarray['nbfield']++;
  1461. }
  1462. }
  1463. // Weight units
  1464. if (!empty($arrayfields['p.weight_units']['checked'])) {
  1465. print '<td class="center">';
  1466. if ($product_static->weight != '') {
  1467. print measuringUnitString(0, 'weight', $product_static->weight_units);
  1468. }
  1469. print '</td>';
  1470. if (!$i) {
  1471. $totalarray['nbfield']++;
  1472. }
  1473. }
  1474. // Length
  1475. if (!empty($arrayfields['p.length']['checked'])) {
  1476. print '<td class="center">';
  1477. print $product_static->length;
  1478. print '</td>';
  1479. if (!$i) {
  1480. $totalarray['nbfield']++;
  1481. }
  1482. }
  1483. // Length units
  1484. if (!empty($arrayfields['p.length_units']['checked'])) {
  1485. print '<td class="center">';
  1486. if ($product_static->length != '') {
  1487. print measuringUnitString(0, 'size', $product_static->length_units);
  1488. }
  1489. print '</td>';
  1490. if (!$i) {
  1491. $totalarray['nbfield']++;
  1492. }
  1493. }
  1494. // Width
  1495. if (!empty($arrayfields['p.width']['checked'])) {
  1496. print '<td align="center">';
  1497. print $product_static->width;
  1498. print '</td>';
  1499. if (!$i) {
  1500. $totalarray['nbfield']++;
  1501. }
  1502. }
  1503. // Width units
  1504. if (!empty($arrayfields['p.width_units']['checked'])) {
  1505. print '<td class="center">';
  1506. if ($product_static->width != '') {
  1507. print measuringUnitString(0, 'size', $product_static->width_units);
  1508. }
  1509. print '</td>';
  1510. if (!$i) {
  1511. $totalarray['nbfield']++;
  1512. }
  1513. }
  1514. // Height
  1515. if (!empty($arrayfields['p.height']['checked'])) {
  1516. print '<td align="center">';
  1517. print $product_static->height;
  1518. print '</td>';
  1519. if (!$i) {
  1520. $totalarray['nbfield']++;
  1521. }
  1522. }
  1523. // Height units
  1524. if (!empty($arrayfields['p.height_units']['checked'])) {
  1525. print '<td class="center">';
  1526. if ($product_static->height != '') {
  1527. print measuringUnitString(0, 'size', $product_static->height_units);
  1528. }
  1529. print '</td>';
  1530. if (!$i) {
  1531. $totalarray['nbfield']++;
  1532. }
  1533. }
  1534. // Surface
  1535. if (!empty($arrayfields['p.surface']['checked'])) {
  1536. print '<td class="center">';
  1537. print $product_static->surface;
  1538. print '</td>';
  1539. if (!$i) {
  1540. $totalarray['nbfield']++;
  1541. }
  1542. }
  1543. // Surface units
  1544. if (!empty($arrayfields['p.surface_units']['checked'])) {
  1545. print '<td class="center">';
  1546. if ($product_static->surface != '') {
  1547. print measuringUnitString(0, 'surface', $product_static->surface_units);
  1548. }
  1549. print '</td>';
  1550. if (!$i) {
  1551. $totalarray['nbfield']++;
  1552. }
  1553. }
  1554. // Volume
  1555. if (!empty($arrayfields['p.volume']['checked'])) {
  1556. print '<td class="center">';
  1557. print $product_static->volume;
  1558. print '</td>';
  1559. if (!$i) {
  1560. $totalarray['nbfield']++;
  1561. }
  1562. }
  1563. // Volume units
  1564. if (!empty($arrayfields['p.volume_units']['checked'])) {
  1565. print '<td class="center">';
  1566. if ($product_static->volume != '') {
  1567. print measuringUnitString(0, 'volume', $product_static->volume_units);
  1568. }
  1569. print '</td>';
  1570. if (!$i) {
  1571. $totalarray['nbfield']++;
  1572. }
  1573. }
  1574. // Unit
  1575. if (!empty($arrayfields['cu.label']['checked'])) {
  1576. print '<td align="center">';
  1577. if (!empty($obj->cu_label)) {
  1578. print $langs->trans($obj->cu_label);
  1579. }
  1580. print '</td>';
  1581. if (!$i) {
  1582. $totalarray['nbfield']++;
  1583. }
  1584. }
  1585. // Default Workstation
  1586. if (!empty($arrayfields['p.fk_default_workstation']['checked'])) {
  1587. print '<td align="left">';
  1588. if (!empty($obj->fk_default_workstation)) {
  1589. $static_ws->id = $obj->fk_default_workstation;
  1590. $static_ws->ref = $obj->ref_workstation;
  1591. $static_ws->status = $obj->status_workstation;
  1592. print $static_ws->getNomUrl(1);
  1593. }
  1594. print '</td>';
  1595. if (!$i) {
  1596. $totalarray['nbfield']++;
  1597. }
  1598. }
  1599. // Sell price
  1600. if (!empty($arrayfields['p.sellprice']['checked'])) {
  1601. print '<td class="right nowraponall">';
  1602. if ($product_static->status && $usercancreadprice) {
  1603. if ($obj->price_base_type == 'TTC') {
  1604. print '<span class="amount">'.price($obj->price_ttc).' '.$langs->trans("TTC").'</span>';
  1605. } else {
  1606. print '<span class="amount">'.price($obj->price).' '.$langs->trans("HT").'</span>';
  1607. }
  1608. }
  1609. print '</td>';
  1610. if (!$i) {
  1611. $totalarray['nbfield']++;
  1612. }
  1613. }
  1614. // Multiprices
  1615. if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
  1616. if (! isset($productpricescache)) {
  1617. $productpricescache=array();
  1618. }
  1619. if (! isset($productpricescache[$obj->rowid])) {
  1620. $productpricescache[$obj->rowid] = array();
  1621. }
  1622. if ($product_static->status && $usercancreadprice) {
  1623. // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array
  1624. // then reuse the cache array if we need prices for other price levels
  1625. $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type";
  1626. $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p";
  1627. $sqlp .= " WHERE fk_product = ".((int) $obj->rowid);
  1628. $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC";
  1629. $resultp = $db->query($sqlp);
  1630. if ($resultp) {
  1631. $nump = $db->num_rows($resultp);
  1632. $j = 0;
  1633. while ($j < $nump) {
  1634. $objp = $db->fetch_object($resultp);
  1635. if (empty($productpricescache[$obj->rowid][$objp->price_level])) {
  1636. $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price;
  1637. $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc;
  1638. $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type;
  1639. }
  1640. $j++;
  1641. }
  1642. $db->free($resultp);
  1643. } else {
  1644. dol_print_error($db);
  1645. }
  1646. }
  1647. foreach ($arraypricelevel as $key => $value) {
  1648. if (!empty($arrayfields['p.sellprice'.$key]['checked'])) {
  1649. print '<td class="right nowraponall">';
  1650. if (!empty($productpricescache[$obj->rowid])) {
  1651. if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') {
  1652. print '<span class="amount">'.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").'</span>';
  1653. } else {
  1654. print '<span class="amount">'.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").'</span>';
  1655. }
  1656. }
  1657. print '</td>';
  1658. if (!$i) {
  1659. $totalarray['nbfield']++;
  1660. }
  1661. }
  1662. }
  1663. }
  1664. // Better buy price
  1665. if (!empty($arrayfields['p.minbuyprice']['checked'])) {
  1666. print '<td class="right nowraponall">';
  1667. if ($product_static->status_buy && $obj->bestpurchaseprice != '' && $usercancreadprice) {
  1668. if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) {
  1669. if ($product_fourn->product_fourn_price_id > 0) {
  1670. if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) {
  1671. $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1);
  1672. print '<span class="amount">'.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).'</span>';
  1673. } else {
  1674. print '<span class="amount">'.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").'</span>';
  1675. }
  1676. }
  1677. }
  1678. }
  1679. print '</td>';
  1680. if (!$i) {
  1681. $totalarray['nbfield']++;
  1682. }
  1683. }
  1684. // Number of buy prices
  1685. if (!empty($arrayfields['p.numbuyprice']['checked'])) {
  1686. print '<td class="right">';
  1687. if ($product_static->status_buy && $usercancreadprice) {
  1688. if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) {
  1689. $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList);
  1690. print $form->textwithpicto(count($productFournList), $htmltext);
  1691. }
  1692. }
  1693. print '</td>';
  1694. }
  1695. // VAT or Sell Tax Rate
  1696. if (!empty($arrayfields['p.tva_tx']['checked'])) {
  1697. print '<td class="right">';
  1698. print vatrate($obj->tva_tx, true);
  1699. print '</td>';
  1700. if (!$i) {
  1701. $totalarray['nbfield']++;
  1702. }
  1703. }
  1704. // WAP
  1705. if (!empty($arrayfields['p.pmp']['checked'])) {
  1706. print '<td class="nowrap right">';
  1707. if ($usercancreadprice) {
  1708. print '<span class="amount">'.price($product_static->pmp, 1, $langs)."</span>";
  1709. }
  1710. print '</td>';
  1711. }
  1712. // Cost price
  1713. if (!empty($arrayfields['p.cost_price']['checked'])) {
  1714. print '<td class="nowrap right">';
  1715. //print $obj->cost_price;
  1716. if ($usercancreadprice) {
  1717. print '<span class="amount">'.price($obj->cost_price).' '.$langs->trans("HT").'</span>';
  1718. }
  1719. print '</td>';
  1720. }
  1721. // Limit alert
  1722. if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) {
  1723. print '<td class="right">';
  1724. if ($product_static->type != 1) {
  1725. print $obj->seuil_stock_alerte;
  1726. }
  1727. print '</td>';
  1728. if (!$i) {
  1729. $totalarray['nbfield']++;
  1730. }
  1731. }
  1732. // Desired stock
  1733. if (!empty($arrayfields['p.desiredstock']['checked'])) {
  1734. print '<td class="right">';
  1735. if ($product_static->type != 1) {
  1736. print $obj->desiredstock;
  1737. }
  1738. print '</td>';
  1739. if (!$i) {
  1740. $totalarray['nbfield']++;
  1741. }
  1742. }
  1743. // Stock real
  1744. if (!empty($arrayfields['p.stock']['checked'])) {
  1745. print '<td class="right">';
  1746. if ($product_static->type != 1) {
  1747. if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) {
  1748. print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' ';
  1749. }
  1750. if ($usercancreadprice) {
  1751. print price(price2num($product_static->stock_reel, 'MS'), 0, $langs, 1, 0);
  1752. }
  1753. }
  1754. print '</td>';
  1755. if (!$i) {
  1756. $totalarray['nbfield']++;
  1757. }
  1758. }
  1759. // Stock virtual
  1760. if (!empty($arrayfields['stock_virtual']['checked'])) {
  1761. print '<td class="right">';
  1762. if ($product_static->type != 1) {
  1763. if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) {
  1764. print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' ';
  1765. }
  1766. if ($usercancreadprice) {
  1767. print price(price2num($product_static->stock_theorique, 'MS'), 0, $langs, 1, 0);
  1768. }
  1769. }
  1770. print '</td>';
  1771. if (!$i) {
  1772. $totalarray['nbfield']++;
  1773. }
  1774. }
  1775. // Lot/Serial
  1776. if (!empty($arrayfields['p.tobatch']['checked'])) {
  1777. print '<td class="center">';
  1778. print $product_static->getLibStatut(1, 2);
  1779. print '</td>';
  1780. if (!$i) {
  1781. $totalarray['nbfield']++;
  1782. }
  1783. }
  1784. // Country
  1785. if (!empty($arrayfields['p.fk_country']['checked'])) {
  1786. print '<td>'.getCountry($obj->fk_country, 0, $db).'</td>';
  1787. if (!$i) {
  1788. $totalarray['nbfield']++;
  1789. }
  1790. }
  1791. // State
  1792. if (!empty($arrayfields['p.fk_state']['checked'])) {
  1793. print '<td>';
  1794. if (!empty($obj->fk_state)) {
  1795. print getState($obj->fk_state, 0, $db);
  1796. }
  1797. print '</td>';
  1798. if (!$i) {
  1799. $totalarray['nbfield']++;
  1800. }
  1801. }
  1802. // Accountancy code sell
  1803. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) {
  1804. print '<td>'.$product_static->accountancy_code_sell.'</td>';
  1805. if (!$i) {
  1806. $totalarray['nbfield']++;
  1807. }
  1808. }
  1809. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) {
  1810. print '<td>'.$product_static->accountancy_code_sell_intra.'</td>';
  1811. if (!$i) {
  1812. $totalarray['nbfield']++;
  1813. }
  1814. }
  1815. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) {
  1816. print '<td>'.$product_static->accountancy_code_sell_export.'</td>';
  1817. if (!$i) {
  1818. $totalarray['nbfield']++;
  1819. }
  1820. }
  1821. // Accountancy code buy
  1822. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) {
  1823. print '<td>'.$product_static->accountancy_code_buy.'</td>';
  1824. if (!$i) {
  1825. $totalarray['nbfield']++;
  1826. }
  1827. }
  1828. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) {
  1829. print '<td>'.$product_static->accountancy_code_buy_intra.'</td>';
  1830. if (!$i) {
  1831. $totalarray['nbfield']++;
  1832. }
  1833. }
  1834. if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) {
  1835. print '<td>'.$product_static->accountancy_code_buy_export.'</td>';
  1836. if (!$i) {
  1837. $totalarray['nbfield']++;
  1838. }
  1839. }
  1840. // Extra fields
  1841. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
  1842. // Fields from hook
  1843. $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
  1844. $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1845. print $hookmanager->resPrint;
  1846. // Date creation
  1847. if (!empty($arrayfields['p.datec']['checked'])) {
  1848. print '<td class="center nowraponall">';
  1849. print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
  1850. print '</td>';
  1851. if (!$i) {
  1852. $totalarray['nbfield']++;
  1853. }
  1854. }
  1855. // Date modification
  1856. if (!empty($arrayfields['p.tms']['checked'])) {
  1857. print '<td class="center nowraponall">';
  1858. print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser');
  1859. print '</td>';
  1860. if (!$i) {
  1861. $totalarray['nbfield']++;
  1862. }
  1863. }
  1864. // Status (to sell)
  1865. if (!empty($arrayfields['p.tosell']['checked'])) {
  1866. print '<td class="center nowrap">';
  1867. if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
  1868. print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell');
  1869. } else {
  1870. print $product_static->LibStatut($product_static->status, 5, 0);
  1871. }
  1872. print '</td>';
  1873. if (!$i) {
  1874. $totalarray['nbfield']++;
  1875. }
  1876. }
  1877. // Status (to buy)
  1878. if (!empty($arrayfields['p.tobuy']['checked'])) {
  1879. print '<td class="center nowrap">';
  1880. if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
  1881. print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy');
  1882. } else {
  1883. print $product_static->LibStatut($product_static->status_buy, 5, 1);
  1884. }
  1885. print '</td>';
  1886. if (!$i) {
  1887. $totalarray['nbfield']++;
  1888. }
  1889. }
  1890. // Action column
  1891. if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) {
  1892. print '<td class="nowrap center">';
  1893. if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
  1894. $selected = 0;
  1895. if (in_array($obj->rowid, $arrayofselected)) {
  1896. $selected = 1;
  1897. }
  1898. print '<input id="cb'.$obj->rowid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->rowid.'"'.($selected ? ' checked="checked"' : '').'>';
  1899. }
  1900. print '</td>';
  1901. if (!$i) {
  1902. $totalarray['nbfield']++;
  1903. }
  1904. }
  1905. print "</tr>\n";
  1906. $i++;
  1907. }
  1908. $db->free($resql);
  1909. // If no record found
  1910. if ($num == 0) {
  1911. $colspan = 1;
  1912. foreach ($arrayfields as $key => $val) {
  1913. if (!empty($val['checked'])) {
  1914. $colspan++;
  1915. }
  1916. }
  1917. print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
  1918. }
  1919. print "</table>";
  1920. print "</div>";
  1921. print '</form>';
  1922. // End of page
  1923. llxFooter();
  1924. $db->close();