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