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