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