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