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