dolibarr 19.0.3
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$sql .= ' WHERE p.entity IN ('.getEntity('product').')';
497if ($sall) {
498 // Clean $fieldstosearchall
499 $newfieldstosearchall = $fieldstosearchall;
500 unset($newfieldstosearchall['pfp.ref_fourn']);
501 unset($newfieldstosearchall['pfp.barcode']);
502
503 $sql .= ' AND (';
504 $sql .= natural_search(array_keys($newfieldstosearchall), $sall, 0, 1);
505 // Search also into a supplier reference 'pfp.ref_fourn'="RefSupplier"
506 $sql .= ' OR EXISTS (SELECT rowid FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp WHERE pfp.fk_product = p.rowid';
507 $sql .= ' AND ('.natural_search('pfp.ref_fourn', $sall, 0, 1);
508 if (isModEnabled('barcode')) {
509 // Search also into a supplier barcode 'pfp.barcode'='GencodBuyPrice';
510 $sql .= ' OR '.natural_search('pfp.barcode', $sall, 0, 1);
511 }
512 $sql .= ')))';
513}
514// if the type is not 1, we show all products (type = 0,2,3)
515if (dol_strlen($search_type) && $search_type != '-1') {
516 if ($search_type == 1) {
517 $sql .= " AND p.fk_product_type = 1";
518 } else {
519 $sql .= " AND p.fk_product_type <> 1";
520 }
521}
522
523if (isModEnabled('variants') && !$show_childproducts) {
524 $sql .= " AND pac.rowid IS NULL";
525}
526
527if ($search_id) {
528 $sql .= natural_search('p.rowid', $search_id, 1);
529}
530if ($search_ref) {
531 $sql .= natural_search('p.ref', $search_ref);
532}
533if ($search_label) {
534 $sql .= natural_search('p.label', $search_label);
535}
536if ($search_default_workstation) {
537 $sql .= natural_search('ws.ref', $search_default_workstation);
538}
539if ($search_barcode) {
540 $sql .= natural_search('p.barcode', $search_barcode);
541}
542if (isset($search_tosell) && dol_strlen($search_tosell) > 0 && $search_tosell != -1) {
543 $sql .= " AND p.tosell = ".((int) $search_tosell);
544}
545if (isset($search_tobuy) && dol_strlen($search_tobuy) > 0 && $search_tobuy != -1) {
546 $sql .= " AND p.tobuy = ".((int) $search_tobuy);
547}
548if (isset($search_tobatch) && dol_strlen($search_tobatch) > 0 && $search_tobatch != -1) {
549 $sql .= " AND p.tobatch = ".((int) $search_tobatch);
550}
551if ($search_vatrate) {
552 $sql .= natural_search('p.tva_tx', $search_vatrate, 1);
553}
554if (dol_strlen($canvas) > 0) {
555 $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
556}
557// Search for tag/category ($searchCategoryProductList is an array of ID)
558if (!empty($searchCategoryProductList)) {
559 $searchCategoryProductSqlList = array();
560 $listofcategoryid = '';
561 foreach ($searchCategoryProductList as $searchCategoryProduct) {
562 if (intval($searchCategoryProduct) == -2) {
563 $searchCategoryProductSqlList[] = "NOT EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck WHERE p.rowid = ck.fk_product)";
564 } elseif (intval($searchCategoryProduct) > 0) {
565 if ($searchCategoryProductOperator == 0) {
566 $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).")";
567 } else {
568 $listofcategoryid .= ($listofcategoryid ? ', ' : '') .((int) $searchCategoryProduct);
569 }
570 }
571 }
572 if ($listofcategoryid) {
573 $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)."))";
574 }
575 if ($searchCategoryProductOperator == 1) {
576 if (!empty($searchCategoryProductSqlList)) {
577 $sql .= " AND (".implode(' OR ', $searchCategoryProductSqlList).")";
578 }
579 } else {
580 if (!empty($searchCategoryProductSqlList)) {
581 $sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")";
582 }
583 }
584}
585if ($fourn_id > 0) {
586 $sql .= " AND pfp.fk_soc = ".((int) $fourn_id);
587}
588if ($search_country) {
589 $sql .= " AND p.fk_country = ".((int) $search_country);
590}
591if ($search_state) {
592 $sql .= " AND p.fk_state = ".((int) $search_state);
593}
594if ($search_finished >= 0 && $search_finished !== '') {
595 $sql .= " AND p.finished = ".((int) $search_finished);
596}
597if ($search_accountancy_code_sell) {
598 $sql .= natural_search($alias_product_perentity . '.accountancy_code_sell', clean_account($search_accountancy_code_sell));
599}
600if ($search_accountancy_code_sell_intra) {
601 $sql .= natural_search($alias_product_perentity . '.accountancy_code_sell_intra', clean_account($search_accountancy_code_sell_intra));
602}
603if ($search_accountancy_code_sell_export) {
604 $sql .= natural_search($alias_product_perentity . '.accountancy_code_sell_export', clean_account($search_accountancy_code_sell_export));
605}
606if ($search_accountancy_code_buy) {
607 $sql .= natural_search($alias_product_perentity . '.accountancy_code_buy', clean_account($search_accountancy_code_buy));
608}
609if ($search_accountancy_code_buy_intra) {
610 $sql .= natural_search($alias_product_perentity . '.accountancy_code_buy_intra', clean_account($search_accountancy_code_buy_intra));
611}
612if ($search_accountancy_code_buy_export) {
613 $sql .= natural_search($alias_product_perentity . '.accountancy_code_buy_export', clean_account($search_accountancy_code_buy_export));
614}
615if (getDolGlobalString('PRODUCT_USE_UNITS') && $search_units) {
616 $sql .= natural_search('cu.rowid', $search_units);
617}
618// Add where from extra fields
619include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
620// Add where from hooks
621$parameters = array();
622$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
623$sql .= $hookmanager->resPrint;
624$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,";
625$sql .= " p.fk_product_type, p.duration, p.finished, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,";
626$sql .= ' p.datec, p.tms, p.entity, p.tobatch, p.pmp, p.cost_price, p.stock,';
627if (!getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
628 $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,";
629} else {
630 $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,";
631}
632$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';
633if (getDolGlobalString('PRODUCT_USE_UNITS')) {
634 $sql .= ', p.fk_unit, cu.label';
635}
636if (isModEnabled('workstation')) {
637 $sql .= ', p.fk_default_workstation, ws.status, ws.ref';
638}
639if (isModEnabled('variants')) {
640 $sql .= ', pac.rowid';
641 $sql .= ', pac.fk_product_parent';
642}
643// Add fields from extrafields
644if (!empty($extrafields->attributes[$object->table_element]['label'])) {
645 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
646 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key : '');
647 }
648}
649// Add groupby from hooks
650$parameters = array();
651$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
652$sql .= $hookmanager->resPrint;
653//if (GETPOST("toolowstock")) $sql.= " HAVING SUM(s.reel) < p.seuil_stock_alerte"; // Not used yet
654
655$nbtotalofrecords = '';
656if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
657 /* The fast and low memory method to get and count full list converts the sql into a sql count */
658 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
659 $sqlforcount = preg_replace('/'.preg_quote($linktopfp, '/').'/', '', $sqlforcount);
660 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
661
662 $resql = $db->query($sqlforcount);
663 if ($resql) {
664 $objforcount = $db->fetch_object($resql);
665 $nbtotalofrecords = $objforcount->nbtotalofrecords;
666 } else {
667 dol_print_error($db);
668 }
669
670 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
671 $page = 0;
672 $offset = 0;
673 }
674 $db->free($resql);
675}
676
677// Complete request and execute it with limit
678$sql .= $db->order($sortfield, $sortorder);
679if ($limit) {
680 $sql .= $db->plimit($limit + 1, $offset);
681}
682
683$resql = $db->query($sql);
684if (!$resql) {
685 dol_print_error($db);
686 exit;
687}
688
689$num = $db->num_rows($resql);
690
691
692// Direct jump if only one record found
693if ($num == 1 && getDolGlobalString('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $sall) {
694 $obj = $db->fetch_object($resql);
695 $id = $obj->rowid;
696 header("Location: ".DOL_URL_ROOT.'/product/card.php?id='.$id);
697 exit;
698}
699
700
701// Output page
702// --------------------------------------------------------------------
703
704$helpurl = '';
705if ($search_type != '') {
706 if ($search_type == 0) {
707 $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
708 } elseif ($search_type == 1) {
709 $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
710 }
711}
712
713$paramsCat = '';
714foreach ($searchCategoryProductList as $searchCategoryProduct) {
715 $paramsCat .= "&search_category_product_list[]=".urlencode($searchCategoryProduct);
716}
717
718//llxHeader('', $title, $helpurl, '', 0, 0, array(), array(), $paramsCat, 'classforhorizontalscrolloftabs');
719llxHeader('', $title, $helpurl, '', 0, 0, array(), array(), $paramsCat, '');
720
721$arrayofselected = is_array($toselect) ? $toselect : array();
722
723// Displays product removal confirmation
724if (GETPOST('delprod')) {
725 setEventMessages($langs->trans("ProductDeleted", GETPOST('delprod')), null, 'mesgs');
726}
727
728$param = '';
729if (!empty($mode)) {
730 $param .= '&mode='.urlencode($mode);
731}
732if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
733 $param .= '&contextpage='.urlencode($contextpage);
734}
735if ($limit > 0 && $limit != $conf->liste_limit) {
736 $param .= '&limit='.((int) $limit);
737}
738if ($optioncss != '') {
739 $param .= '&optioncss='.urlencode($optioncss);
740}
741if ($sall) {
742 $param .= "&sall=".urlencode($sall);
743}
744if ($searchCategoryProductOperator == 1) {
745 $param .= "&search_category_product_operator=".urlencode($searchCategoryProductOperator);
746}
747foreach ($searchCategoryProductList as $searchCategoryProduct) {
748 $param .= "&search_category_product_list[]=".urlencode($searchCategoryProduct);
749}
750if ($search_ref) {
751 $param .= "&search_ref=".urlencode($search_ref);
752}
753if ($search_ref_supplier) {
754 $param .= "&search_ref_supplier=".urlencode($search_ref_supplier);
755}
756if ($search_barcode) {
757 $param .= ($search_barcode ? "&search_barcode=".urlencode($search_barcode) : "");
758}
759if ($search_label) {
760 $param .= "&search_label=".urlencode($search_label);
761}
762if ($search_default_workstation) {
763 $param .= "&search_default_workstation=".urlencode($search_default_workstation);
764}
765if ($search_tosell != '') {
766 $param .= "&search_tosell=".urlencode($search_tosell);
767}
768if ($search_tobuy != '') {
769 $param .= "&search_tobuy=".urlencode($search_tobuy);
770}
771if ($search_tobatch) {
772 $param .= "&search_tobatch=".urlencode($search_tobatch);
773}
774if ($search_country != '') {
775 $param .= "&search_country=".urlencode($search_country);
776}
777if ($search_state != '') {
778 $param .= "&search_state=".urlencode($search_state);
779}
780if ($search_vatrate) {
781 $param .= "&search_vatrate=".urlencode($search_vatrate);
782}
783if ($fourn_id > 0) {
784 $param .= "&fourn_id=".urlencode($fourn_id);
785}
786if ($show_childproducts) {
787 $param .= ($show_childproducts ? "&search_show_childproducts=".urlencode($show_childproducts) : "");
788}
789if ($type != '') {
790 $param .= '&type='.urlencode($type);
791}
792if ($search_type != '') {
793 $param .= '&search_type='.urlencode($search_type);
794}
795if ($search_accountancy_code_sell) {
796 $param .= "&search_accountancy_code_sell=".urlencode($search_accountancy_code_sell);
797}
798if ($search_accountancy_code_sell_intra) {
799 $param .= "&search_accountancy_code_sell_intra=".urlencode($search_accountancy_code_sell_intra);
800}
801if ($search_accountancy_code_sell_export) {
802 $param .= "&search_accountancy_code_sell_export=".urlencode($search_accountancy_code_sell_export);
803}
804if ($search_accountancy_code_buy) {
805 $param .= "&search_accountancy_code_buy=".urlencode($search_accountancy_code_buy);
806}
807if ($search_accountancy_code_buy_intra) {
808 $param .= "&search_accountancy_code_buy_intra=".urlencode($search_accountancy_code_buy_intra);
809}
810if ($search_accountancy_code_buy_export) {
811 $param .= "&search_accountancy_code_buy_export=".urlencode($search_accountancy_code_buy_export);
812}
813if ($search_finished) {
814 $param .= "&search_finished=".urlencode($search_finished);
815}
816// Add $param from extra fields
817include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
818
819// Add $param from hooks
820$parameters = array('param' => &$param);
821$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
822$param .= $hookmanager->resPrint;
823
824// List of mass actions available
825$arrayofmassactions = array(
826 'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
827 'edit_extrafields'=>img_picto('', 'edit', 'class="pictofixedwidth"').$langs->trans("ModifyValueExtrafields"),
828 //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
829 //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
830);
831if ($user->hasRight($rightskey, 'creer')) {
832 $arrayofmassactions['preupdateprice'] = img_picto('', 'edit', 'class="pictofixedwidth"').$langs->trans("UpdatePrice");
833 $arrayofmassactions['switchonsalestatus'] = img_picto('', 'stop-circle', 'class="pictofixedwidth"').$langs->trans("SwitchOnSaleStatus");
834 $arrayofmassactions['switchonpurchasestatus'] = img_picto('', 'stop-circle', 'class="pictofixedwidth"').$langs->trans("SwitchOnPurchaseStatus");
835}
836if (isModEnabled('category') && $user->hasRight($rightskey, 'creer')) {
837 $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag");
838}
839if (in_array($massaction, array('presend', 'predelete','preaffecttag', 'edit_extrafields', 'preupdateprice'))) {
840 $arrayofmassactions = array();
841}
842if ($user->hasRight($rightskey, 'supprimer')) {
843 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
844}
845$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
846
847$newcardbutton = '';
848$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'));
849$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'));
850
851if ($type === "") {
852 $perm = ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'));
853} elseif ($type == Product::TYPE_SERVICE) {
854 $perm = $user->hasRight('service', 'creer');
855} elseif ($type == Product::TYPE_PRODUCT) {
856 $perm = $user->hasRight('produit', 'creer');
857}
858 $oldtype = $type;
859 $params = array();
860if ($type === "") {
861 $params['forcenohideoftext'] = 1;
862}
863$newcardbutton .= dolGetButtonTitleSeparator();
864if ((isModEnabled('product') && $type === "") || $type == Product::TYPE_PRODUCT) {
865 $label = 'NewProduct';
866 $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=0', '', $perm, $params);
867}
868if ((isModEnabled('service') && $type === "") || $type == Product::TYPE_SERVICE) {
869 $label = 'NewService';
870 $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=1', '', $perm, $params);
871}
872
873print '<form id="searchFormList" action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire">';
874if ($optioncss != '') {
875 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
876}
877print '<input type="hidden" name="token" value="'.newToken().'">';
878print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
879print '<input type="hidden" name="action" value="list">';
880print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
881print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
882//print '<input type="hidden" name="page" value="'.$page.'">';
883print '<input type="hidden" name="type" value="'.$type.'">';
884print '<input type="hidden" name="page_y" value="">';
885print '<input type="hidden" name="mode" value="'.$mode.'">';
886
887if (empty($arrayfields['p.fk_product_type']['checked'])) {
888 print '<input type="hidden" name="search_type" value="'.dol_escape_htmltag($search_type).'">';
889}
890
891$picto = 'product';
892if ($type == 1) {
893 $picto = 'service';
894}
895
896print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
897
898$topicmail = "Information";
899$modelmail = "product";
900$objecttmp = new Product($db);
901$trackid = 'prod'.$object->id;
902include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
903
904if (!empty($catid)) {
905 print "<div id='ways'>";
906 $c = new Categorie($db);
907 $ways = $c->print_all_ways(' &gt; ', 'product/list.php');
908 print " &gt; ".$ways[0]."<br>\n";
909 print "</div><br>";
910}
911
912if ($sall) {
913 $setupstring = '';
914 foreach ($fieldstosearchall as $key => $val) {
915 $fieldstosearchall[$key] = $langs->trans($val);
916 $setupstring .= $key."=".$val.";";
917 }
918 print '<!-- Search done like if PRODUCT_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
919 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $sall).join(', ', $fieldstosearchall).'</div>'."\n";
920}
921
922// Filter on categories
923$moreforfilter = '';
924if (isModEnabled('categorie') && $user->hasRight('categorie', 'read')) {
925 $formcategory = new FormCategory($db);
926 $moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PRODUCT, $searchCategoryProductList, 'minwidth300', $searchCategoryProductOperator ? $searchCategoryProductOperator : 0);
927}
928
929// Show/hide child variant products
930if (isModEnabled('variants')) {
931 $moreforfilter .= '<div class="divsearchfield">';
932 $moreforfilter .= '<input type="checkbox" id="search_show_childproducts" name="search_show_childproducts"'.($show_childproducts ? 'checked="checked"' : '').'>';
933 $moreforfilter .= ' <label for="search_show_childproducts">'.$langs->trans('ShowChildProducts').'</label>';
934 $moreforfilter .= '</div>';
935}
936
937$parameters = array();
938$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
939if (empty($reshook)) {
940 $moreforfilter .= $hookmanager->resPrint;
941} else {
942 $moreforfilter = $hookmanager->resPrint;
943}
944
945if (!empty($moreforfilter)) {
946 print '<div class="liste_titre liste_titre_bydiv centpercent">';
947 print $moreforfilter;
948 print '</div>';
949}
950
951$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
952$selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields
953$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
954
955print '<div class="div-table-responsive">';
956print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
957
958// Fields title search
959// --------------------------------------------------------------------
960print '<tr class="liste_titre_filter">';
961// Action column
962if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
963 print '<td class="liste_titre center maxwidthsearch">';
964 $searchpicto = $form->showFilterButtons('left');
965 print $searchpicto;
966 print '</td>';
967}
968if (!empty($arrayfields['p.rowid']['checked'])) {
969 print '<td class="liste_titre left">';
970 print '<input class="flat" type="text" name="search_id" size="4" value="'.dol_escape_htmltag($search_id).'">';
971 print '</td>';
972}
973if (!empty($arrayfields['p.ref']['checked'])) {
974 print '<td class="liste_titre left">';
975 print '<input class="flat" type="text" name="search_ref" size="8" value="'.dol_escape_htmltag($search_ref).'">';
976 print '</td>';
977}
978if (!empty($arrayfields['pfp.ref_fourn']['checked'])) {
979 print '<td class="liste_titre left">';
980 print '<input class="flat" type="text" name="search_ref_supplier" size="8" value="'.dol_escape_htmltag($search_ref_supplier).'">';
981 print '</td>';
982}
983// Thumbnail
984if (!empty($arrayfields['thumbnail']['checked'])) {
985 print '<td class="liste_titre center">';
986 print '</td>';
987}
988if (!empty($arrayfields['p.label']['checked'])) {
989 print '<td class="liste_titre left">';
990 print '<input class="flat" type="text" name="search_label" size="12" value="'.dol_escape_htmltag($search_label).'">';
991 print '</td>';
992}
993// Type
994if (!empty($arrayfields['p.fk_product_type']['checked'])) {
995 print '<td class="liste_titre center">';
996 $array = array('-1'=>'&nbsp;', '0'=>$langs->trans('Product'), '1'=>$langs->trans('Service'));
997 print $form->selectarray('search_type', $array, $search_type);
998 print '</td>';
999}
1000// Description
1001if (!empty($arrayfields['p.description']['checked'])) {
1002 print '<td class="liste_titre left">';
1003 print '</td>';
1004}
1005// Barcode
1006if (!empty($arrayfields['p.barcode']['checked'])) {
1007 print '<td class="liste_titre">';
1008 print '<input class="flat" type="text" name="search_barcode" size="6" value="'.dol_escape_htmltag($search_barcode).'">';
1009 print '</td>';
1010}
1011// Duration
1012if (!empty($arrayfields['p.duration']['checked'])) {
1013 print '<td class="liste_titre">';
1014 print '</td>';
1015}
1016// Parent
1017if (!empty($arrayfields['pac.fk_product_parent']['checked'])) {
1018 print '<td class="liste_titre">';
1019 print '</td>';
1020}
1021// Finished
1022if (!empty($arrayfields['p.finished']['checked'])) {
1023 print '<td class="liste_titre">';
1024 print $formproduct->selectProductNature('search_finished', $search_finished);
1025 print '</td>';
1026}
1027// Weight
1028if (!empty($arrayfields['p.weight']['checked'])) {
1029 print '<td class="liste_titre">';
1030 print '</td>';
1031}
1032// Weight units
1033if (!empty($arrayfields['p.weight_units']['checked'])) {
1034 print '<td class="liste_titre">';
1035 print '</td>';
1036}
1037// Length
1038if (!empty($arrayfields['p.length']['checked'])) {
1039 print '<td class="liste_titre">';
1040 print '</td>';
1041}
1042// Length units
1043if (!empty($arrayfields['p.length_units']['checked'])) {
1044 print '<td class="liste_titre">';
1045 print '</td>';
1046}
1047// Width
1048if (!empty($arrayfields['p.width']['checked'])) {
1049 print '<td class="liste_titre">';
1050 print '</td>';
1051}
1052// Width units
1053if (!empty($arrayfields['p.width_units']['checked'])) {
1054 print '<td class="liste_titre">';
1055 print '</td>';
1056}
1057// Height
1058if (!empty($arrayfields['p.height']['checked'])) {
1059 print '<td class="liste_titre">';
1060 print '</td>';
1061}
1062// Height units
1063if (!empty($arrayfields['p.height_units']['checked'])) {
1064 print '<td class="liste_titre">';
1065 print '</td>';
1066}
1067// Surface
1068if (!empty($arrayfields['p.surface']['checked'])) {
1069 print '<td class="liste_titre">';
1070 print '</td>';
1071}
1072// Surface units
1073if (!empty($arrayfields['p.surface_units']['checked'])) {
1074 print '<td class="liste_titre">';
1075 print '</td>';
1076}
1077// Volume
1078if (!empty($arrayfields['p.volume']['checked'])) {
1079 print '<td class="liste_titre">';
1080 print '</td>';
1081}
1082// Volume units
1083if (!empty($arrayfields['p.volume_units']['checked'])) {
1084 print '<td class="liste_titre">';
1085 print '</td>';
1086}
1087
1088// Unit
1089if (!empty($arrayfields['cu.label']['checked'])) {
1090 print '<td class="liste_titre">';
1091 print $form->selectUnits($search_units, 'search_units', 1);
1092 print '</td>';
1093}
1094
1095// Default workstation
1096if (!empty($arrayfields['p.fk_default_workstation']['checked'])) {
1097 print '<td class="liste_titre">';
1098 print '<input class="flat width75" type="text" name="search_default_workstation" value="'.dol_escape_htmltag($search_default_workstation).'">';
1099 print '</td>';
1100}
1101
1102// Sell price
1103if (!empty($arrayfields['p.sellprice']['checked'])) {
1104 print '<td class="liste_titre right">';
1105 print '</td>';
1106}
1107
1108// Multiprice
1109if (getDolGlobalString('PRODUIT_MULTIPRICES')) {
1110 foreach ($arraypricelevel as $key => $value) {
1111 if (!empty($arrayfields['p.sellprice'.$key]['checked'])) {
1112 print '<td class="liste_titre right">';
1113 print '</td>';
1114 }
1115 }
1116}
1117
1118// Minimum buying Price
1119if (!empty($arrayfields['p.minbuyprice']['checked'])) {
1120 print '<td class="liste_titre">';
1121 print '&nbsp;';
1122 print '</td>';
1123}
1124// Number buying Price
1125if (!empty($arrayfields['p.numbuyprice']['checked'])) {
1126 print '<td class="liste_titre">';
1127 print '&nbsp;';
1128 print '</td>';
1129}
1130// VAT or Sell Tax Rate
1131if (!empty($arrayfields['p.tva_tx']['checked'])) {
1132 print '<td class="liste_titre right">';
1133 print '<input class="right flat maxwidth50" placeholder="%" type="text" name="search_vatrate" size="1" value="'.dol_escape_htmltag($search_vatrate).'">';
1134 print '</td>';
1135}
1136// WAP
1137if (!empty($arrayfields['p.pmp']['checked'])) {
1138 print '<td class="liste_titre">';
1139 print '&nbsp;';
1140 print '</td>';
1141}
1142// cost_price
1143if (!empty($arrayfields['p.cost_price']['checked'])) {
1144 print '<td class="liste_titre">';
1145 print '&nbsp;';
1146 print '</td>';
1147}
1148// Limit for alert
1149if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) {
1150 print '<td class="liste_titre">';
1151 print '&nbsp;';
1152 print '</td>';
1153}
1154// Desired stock
1155if (!empty($arrayfields['p.desiredstock']['checked'])) {
1156 print '<td class="liste_titre">';
1157 print '&nbsp;';
1158 print '</td>';
1159}
1160// Stock
1161if (!empty($arrayfields['p.stock']['checked'])) {
1162 print '<td class="liste_titre">&nbsp;</td>';
1163}
1164// Stock
1165if (!empty($arrayfields['stock_virtual']['checked'])) {
1166 print '<td class="liste_titre">&nbsp;</td>';
1167}
1168// To batch
1169if (!empty($arrayfields['p.tobatch']['checked'])) {
1170 print '<td class="liste_titre center">';
1171 $statutarray = array(
1172 '-1' => '',
1173 '0' => $langs->trans("ProductStatusNotOnBatchShort"),
1174 '1' => $langs->trans("ProductStatusOnBatchShort"),
1175 '2' => $langs->trans("ProductStatusOnSerialShort")
1176 );
1177 print $form->selectarray('search_tobatch', $statutarray, $search_tobatch);
1178 print '</td>';
1179}
1180// Country
1181if (!empty($arrayfields['p.fk_country']['checked'])) {
1182 print '<td class="liste_titre center">';
1183 print $form->select_country($search_country, 'search_country', '', 0);
1184 print '</td>';
1185}
1186// State
1187if (!empty($arrayfields['p.fk_state']['checked'])) {
1188 print '<td class="liste_titre center">';
1189 print $formcompany->select_state($search_state, $search_country);
1190 print '</td>';
1191}
1192// Accountancy code sell
1193if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) {
1194 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>';
1195}
1196if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) {
1197 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>';
1198}
1199if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) {
1200 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>';
1201}
1202// Accountancy code buy
1203if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) {
1204 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>';
1205}
1206if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) {
1207 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>';
1208}
1209if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) {
1210 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>';
1211}
1212// Extra fields
1213include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1214// Fields from hook
1215$parameters = array('arrayfields'=>$arrayfields);
1216$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1217print $hookmanager->resPrint;
1218// Date creation
1219if (!empty($arrayfields['p.datec']['checked'])) {
1220 print '<td class="liste_titre">';
1221 print '</td>';
1222}
1223// Date modification
1224if (!empty($arrayfields['p.tms']['checked'])) {
1225 print '<td class="liste_titre">';
1226 print '</td>';
1227}
1228if (!empty($arrayfields['p.tosell']['checked'])) {
1229 print '<td class="liste_titre center parentonrightofpage">';
1230 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');
1231 print '</td>';
1232}
1233if (!empty($arrayfields['p.tobuy']['checked'])) {
1234 print '<td class="liste_titre center parentonrightofpage">';
1235 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');
1236 print '</td>';
1237}
1238// Action column
1239if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1240 print '<td class="liste_titre center maxwidthsearch">';
1241 $searchpicto = $form->showFilterButtons();
1242 print $searchpicto;
1243 print '</td>';
1244}
1245print '</tr>'."\n";
1246
1247$totalarray = array();
1248$totalarray['nbfield'] = 0;
1249
1250// Fields title label
1251// --------------------------------------------------------------------
1252print '<tr class="liste_titre">';
1253// Action column
1254if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1255 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1256 $totalarray['nbfield']++;
1257}
1258if (!empty($arrayfields['p.rowid']['checked'])) {
1259 print_liste_field_titre($arrayfields['p.rowid']['label'], $_SERVER["PHP_SELF"], "p.rowid", "", $param, "", $sortfield, $sortorder);
1260 $totalarray['nbfield']++;
1261}
1262if (!empty($arrayfields['p.ref']['checked'])) {
1263 print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder);
1264 $totalarray['nbfield']++;
1265}
1266if (!empty($arrayfields['pfp.ref_fourn']['checked'])) {
1267 print_liste_field_titre($arrayfields['pfp.ref_fourn']['label'], $_SERVER["PHP_SELF"], "pfp.ref_fourn", "", $param, "", $sortfield, $sortorder);
1268 $totalarray['nbfield']++;
1269}
1270if (!empty($arrayfields['thumbnail']['checked'])) {
1271 print_liste_field_titre($arrayfields['thumbnail']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center ');
1272 $totalarray['nbfield']++;
1273}
1274if (!empty($arrayfields['p.label']['checked'])) {
1275 print_liste_field_titre($arrayfields['p.label']['label'], $_SERVER["PHP_SELF"], "p.label", "", $param, "", $sortfield, $sortorder);
1276 $totalarray['nbfield']++;
1277}
1278if (!empty($arrayfields['p.fk_product_type']['checked'])) {
1279 print_liste_field_titre($arrayfields['p.fk_product_type']['label'], $_SERVER["PHP_SELF"], "p.fk_product_type", "", $param, "", $sortfield, $sortorder, 'center ');
1280 $totalarray['nbfield']++;
1281}
1282if (!empty($arrayfields['p.description']['checked'])) {
1283 print_liste_field_titre($arrayfields['p.description']['label'], $_SERVER["PHP_SELF"], "p.description", "", $param, "", $sortfield, $sortorder);
1284 $totalarray['nbfield']++;
1285}
1286if (!empty($arrayfields['p.barcode']['checked'])) {
1287 print_liste_field_titre($arrayfields['p.barcode']['label'], $_SERVER["PHP_SELF"], "p.barcode", "", $param, "", $sortfield, $sortorder);
1288 $totalarray['nbfield']++;
1289}
1290if (!empty($arrayfields['p.duration']['checked'])) {
1291 print_liste_field_titre($arrayfields['p.duration']['label'], $_SERVER["PHP_SELF"], "p.duration", "", $param, '', $sortfield, $sortorder, 'center ');
1292 $totalarray['nbfield']++;
1293}
1294if (!empty($arrayfields['pac.fk_product_parent']['checked'])) {
1295 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']);
1296}
1297if (!empty($arrayfields['p.finished']['checked'])) {
1298 print_liste_field_titre($arrayfields['p.finished']['label'], $_SERVER["PHP_SELF"], "p.finished", "", $param, '', $sortfield, $sortorder, 'center ');
1299 $totalarray['nbfield']++;
1300}
1301
1302if (!empty($arrayfields['p.weight']['checked'])) {
1303 print_liste_field_titre($arrayfields['p.weight']['label'], $_SERVER['PHP_SELF'], 'p.weight', '', $param, '', $sortfield, $sortorder, 'center ');
1304 $totalarray['nbfield']++;
1305}
1306if (!empty($arrayfields['p.weight_units']['checked'])) {
1307 print_liste_field_titre($arrayfields['p.weight_units']['label'], $_SERVER['PHP_SELF'], 'p.weight_units', '', $param, '', $sortfield, $sortorder, 'center ');
1308 $totalarray['nbfield']++;
1309}
1310if (!empty($arrayfields['p.length']['checked'])) {
1311 print_liste_field_titre($arrayfields['p.length']['label'], $_SERVER['PHP_SELF'], 'p.length', '', $param, '', $sortfield, $sortorder, 'center ');
1312 $totalarray['nbfield']++;
1313}
1314if (!empty($arrayfields['p.length_units']['checked'])) {
1315 print_liste_field_titre($arrayfields['p.length_units']['label'], $_SERVER['PHP_SELF'], 'p.length_units', '', $param, '', $sortfield, $sortorder, 'center ');
1316 $totalarray['nbfield']++;
1317}
1318if (!empty($arrayfields['p.width']['checked'])) {
1319 print_liste_field_titre($arrayfields['p.width']['label'], $_SERVER['PHP_SELF'], 'p.width', '', $param, '', $sortfield, $sortorder, 'center ');
1320 $totalarray['nbfield']++;
1321}
1322if (!empty($arrayfields['p.width_units']['checked'])) {
1323 print_liste_field_titre($arrayfields['p.width_units']['label'], $_SERVER['PHP_SELF'], 'p.width_units', '', $param, '', $sortfield, $sortorder, 'center ');
1324 $totalarray['nbfield']++;
1325}
1326if (!empty($arrayfields['p.height']['checked'])) {
1327 print_liste_field_titre($arrayfields['p.height']['label'], $_SERVER['PHP_SELF'], 'p.height', '', $param, '', $sortfield, $sortorder, 'center ');
1328 $totalarray['nbfield']++;
1329}
1330if (!empty($arrayfields['p.height_units']['checked'])) {
1331 print_liste_field_titre($arrayfields['p.height_units']['label'], $_SERVER['PHP_SELF'], 'p.height_units', '', $param, '', $sortfield, $sortorder, 'center ');
1332 $totalarray['nbfield']++;
1333}
1334if (!empty($arrayfields['p.surface']['checked'])) {
1335 print_liste_field_titre($arrayfields['p.surface']['label'], $_SERVER['PHP_SELF'], "p.surface", '', $param, '', $sortfield, $sortorder, 'center ');
1336 $totalarray['nbfield']++;
1337}
1338if (!empty($arrayfields['p.surface_units']['checked'])) {
1339 print_liste_field_titre($arrayfields['p.surface_units']['label'], $_SERVER['PHP_SELF'], 'p.surface_units', '', $param, '', $sortfield, $sortorder, 'center ');
1340 $totalarray['nbfield']++;
1341}
1342if (!empty($arrayfields['p.volume']['checked'])) {
1343 print_liste_field_titre($arrayfields['p.volume']['label'], $_SERVER['PHP_SELF'], 'p.volume', '', $param, '', $sortfield, $sortorder, 'center ');
1344 $totalarray['nbfield']++;
1345}
1346if (!empty($arrayfields['p.volume_units']['checked'])) {
1347 print_liste_field_titre($arrayfields['p.volume_units']['label'], $_SERVER['PHP_SELF'], 'p.volume_units', '', $param, '', $sortfield, $sortorder, 'center ');
1348 $totalarray['nbfield']++;
1349}
1350if (!empty($arrayfields['cu.label']['checked'])) {
1351 print_liste_field_titre($arrayfields['cu.label']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'center ');
1352 $totalarray['nbfield']++;
1353}
1354if (!empty($arrayfields['p.fk_default_workstation']['checked'])) {
1355 print_liste_field_titre($arrayfields['p.fk_default_workstation']['label'], $_SERVER['PHP_SELF'], 'ws.ref', '', $param, '', $sortfield, $sortorder);
1356 $totalarray['nbfield']++;
1357}
1358if (!empty($arrayfields['p.sellprice']['checked'])) {
1359 print_liste_field_titre($arrayfields['p.sellprice']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1360 $totalarray['nbfield']++;
1361}
1362
1363// Multiprices
1364if (getDolGlobalString('PRODUIT_MULTIPRICES')) {
1365 foreach ($arraypricelevel as $key => $value) {
1366 if (!empty($arrayfields['p.sellprice'.$key]['checked'])) {
1367 print_liste_field_titre($arrayfields['p.sellprice'.$key]['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1368 $totalarray['nbfield']++;
1369 }
1370 }
1371}
1372
1373if (!empty($arrayfields['p.minbuyprice']['checked'])) {
1374 print_liste_field_titre($arrayfields['p.minbuyprice']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1375 $totalarray['nbfield']++;
1376}
1377if (!empty($arrayfields['p.numbuyprice']['checked'])) {
1378 print_liste_field_titre($arrayfields['p.numbuyprice']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1379 $totalarray['nbfield']++;
1380}
1381if (!empty($arrayfields['p.tva_tx']['checked'])) {
1382 print_liste_field_titre($arrayfields['p.tva_tx']['label'], $_SERVER["PHP_SELF"], 'p.tva_tx', "", $param, '', $sortfield, $sortorder, 'right ');
1383 $totalarray['nbfield']++;
1384}
1385if (!empty($arrayfields['p.pmp']['checked'])) {
1386 print_liste_field_titre($arrayfields['p.pmp']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1387 $totalarray['nbfield']++;
1388}
1389if (!empty($arrayfields['p.cost_price']['checked'])) {
1390 print_liste_field_titre($arrayfields['p.cost_price']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1391 $totalarray['nbfield']++;
1392}
1393if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) {
1394 print_liste_field_titre($arrayfields['p.seuil_stock_alerte']['label'], $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", "", $param, '', $sortfield, $sortorder, 'right ');
1395 $totalarray['nbfield']++;
1396}
1397if (!empty($arrayfields['p.desiredstock']['checked'])) {
1398 print_liste_field_titre($arrayfields['p.desiredstock']['label'], $_SERVER["PHP_SELF"], "p.desiredstock", "", $param, '', $sortfield, $sortorder, 'right ');
1399 $totalarray['nbfield']++;
1400}
1401if (!empty($arrayfields['p.stock']['checked'])) {
1402 print_liste_field_titre($arrayfields['p.stock']['label'], $_SERVER["PHP_SELF"], "p.stock", "", $param, '', $sortfield, $sortorder, 'right ');
1403 $totalarray['nbfield']++;
1404}
1405if (!empty($arrayfields['stock_virtual']['checked'])) {
1406 print_liste_field_titre($arrayfields['stock_virtual']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
1407 $totalarray['nbfield']++;
1408}
1409if (!empty($arrayfields['p.tobatch']['checked'])) {
1410 print_liste_field_titre($arrayfields['p.tobatch']['label'], $_SERVER["PHP_SELF"], "p.tobatch", "", $param, '', $sortfield, $sortorder, 'center ');
1411 $totalarray['nbfield']++;
1412}
1413if (!empty($arrayfields['p.fk_country']['checked'])) {
1414 print_liste_field_titre($arrayfields['p.fk_country']['label'], $_SERVER["PHP_SELF"], "p.fk_country", "", $param, '', $sortfield, $sortorder);
1415 $totalarray['nbfield']++;
1416}
1417if (!empty($arrayfields['p.fk_state']['checked'])) {
1418 print_liste_field_titre($arrayfields['p.fk_state']['label'], $_SERVER["PHP_SELF"], "p.fk_state", "", $param, '', $sortfield, $sortorder);
1419 $totalarray['nbfield']++;
1420}
1421if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) {
1422 print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_sell", "", $param, '', $sortfield, $sortorder);
1423 $totalarray['nbfield']++;
1424}
1425if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) {
1426 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);
1427 $totalarray['nbfield']++;
1428}
1429if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) {
1430 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);
1431 $totalarray['nbfield']++;
1432}
1433if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) {
1434 print_liste_field_titre($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['label'], $_SERVER["PHP_SELF"], $alias_product_perentity . ".accountancy_code_buy", "", $param, '', $sortfield, $sortorder);
1435 $totalarray['nbfield']++;
1436}
1437if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) {
1438 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);
1439 $totalarray['nbfield']++;
1440}
1441if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) {
1442 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);
1443 $totalarray['nbfield']++;
1444}
1445// Extra fields
1446include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1447// Hook fields
1448$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray);
1449$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1450print $hookmanager->resPrint;
1451if (!empty($arrayfields['p.datec']['checked'])) {
1452 print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1453 $totalarray['nbfield']++;
1454}
1455if (!empty($arrayfields['p.tms']['checked'])) {
1456 print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1457 $totalarray['nbfield']++;
1458}
1459if (!empty($arrayfields['p.tosell']['checked'])) {
1460 print_liste_field_titre($arrayfields['p.tosell']['label'], $_SERVER["PHP_SELF"], "p.tosell", "", $param, '', $sortfield, $sortorder, 'center ');
1461 $totalarray['nbfield']++;
1462}
1463if (!empty($arrayfields['p.tobuy']['checked'])) {
1464 print_liste_field_titre($arrayfields['p.tobuy']['label'], $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'center ');
1465 $totalarray['nbfield']++;
1466}
1467// Action column
1468if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1469 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1470 $totalarray['nbfield']++;
1471}
1472print '</tr>'."\n";
1473
1474
1475// Loop on record
1476// --------------------------------------------------------------------
1477$i = 0;
1478$savnbfield = $totalarray['nbfield'];
1479$totalarray = array();
1480$totalarray['nbfield'] = 0;
1481$imaxinloop = ($limit ? min($num, $limit) : $num);
1482while ($i < $imaxinloop) {
1483 $obj = $db->fetch_object($resql);
1484 if (empty($obj)) {
1485 break; // Should not happen
1486 }
1487
1488 // Multilangs
1489 if (getDolGlobalInt('MAIN_MULTILANGS')) { // If multilang is enabled
1490 $sql = "SELECT label";
1491 $sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
1492 $sql .= " WHERE fk_product = ".((int) $obj->rowid);
1493 $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
1494 $sql .= " LIMIT 1";
1495
1496 $result = $db->query($sql);
1497 if ($result) {
1498 $objtp = $db->fetch_object($result);
1499 if (!empty($objtp->label)) {
1500 $obj->label = $objtp->label;
1501 }
1502 }
1503 }
1504
1505 $parameters = array('staticdata' => $obj);
1506 // Note that $action and $object may have been modified by hook
1507 // do product_static fetch in hook if wanted or anything else
1508 $reshook = $hookmanager->executeHooks('loadStaticObject', $parameters, $product_static, $action);
1509 if (empty($reshook)) {
1510 $product_static->id = $obj->rowid;
1511 $product_static->ref = $obj->ref;
1512 $product_static->description = $obj->description;
1513 $product_static->ref_fourn = empty($obj->ref_supplier) ? '' : $obj->ref_supplier; // deprecated
1514 $product_static->ref_supplier = empty($obj->ref_supplier) ? '' : $obj->ref_supplier;
1515 $product_static->label = $obj->label;
1516 $product_static->barcode = $obj->barcode;
1517 $product_static->finished = $obj->finished;
1518 $product_static->type = $obj->fk_product_type;
1519 $product_static->status_buy = $obj->tobuy;
1520 $product_static->status = $obj->tosell;
1521 $product_static->status_batch = $obj->tobatch;
1522 $product_static->entity = $obj->entity;
1523 $product_static->pmp = $obj->pmp;
1524 $product_static->accountancy_code_sell = $obj->accountancy_code_sell;
1525 $product_static->accountancy_code_sell_export = $obj->accountancy_code_sell_export;
1526 $product_static->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra;
1527 $product_static->accountancy_code_buy = $obj->accountancy_code_buy;
1528 $product_static->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra;
1529 $product_static->accountancy_code_buy_export = $obj->accountancy_code_buy_export;
1530 $product_static->length = $obj->length;
1531 $product_static->length_units = $obj->length_units;
1532 $product_static->width = $obj->width;
1533 $product_static->width_units = $obj->width_units;
1534 $product_static->height = $obj->height;
1535 $product_static->height_units = $obj->height_units;
1536 $product_static->weight = $obj->weight;
1537 $product_static->weight_units = $obj->weight_units;
1538 $product_static->volume = $obj->volume;
1539 $product_static->volume_units = $obj->volume_units;
1540 $product_static->surface = $obj->surface;
1541 $product_static->surface_units = $obj->surface_units;
1542 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
1543 $product_static->fk_unit = $obj->fk_unit;
1544 }
1545
1546 // STOCK_DISABLE_OPTIM_LOAD can be set to force load_stock whatever is permissions on stock.
1547 if ((isModEnabled('stock') && $user->hasRight('stock', 'lire') && $search_type != 1) || getDolGlobalString('STOCK_DISABLE_OPTIM_LOAD')) { // To optimize call of load_stock
1548 if ($product_static->type != 1 || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) { // Not a service
1549 $option = 'nobatch';
1550 if (empty($arrayfields['stock_virtual']['checked'])) {
1551 $option .= ',novirtual';
1552 }
1553 $product_static->load_stock($option); // Load stock_reel + stock_warehouse. This can also call load_virtual_stock()
1554 }
1555 }
1556 }
1557
1558 $product_static->price = $obj->price;
1559
1560 $object = $product_static;
1561
1562 $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS') ? $user->hasRight('product', 'product_advance', 'read_prices') : $user->hasRight('product', 'lire');
1563 if ($product_static->isService()) {
1564 $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS') ? $user->hasRight('service', 'service_advance', 'read_prices') : $user->hasRight('service', 'lire');
1565 }
1566
1567 if ($mode == 'kanban') {
1568 if ($i == 0) {
1569 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
1570 print '<div class="box-flex-container kanban">';
1571 }
1572
1573 // Output Kanban
1574 $selected = -1;
1575 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1576 $selected = 0;
1577 if (in_array($object->id, $arrayofselected)) {
1578 $selected = 1;
1579 }
1580 }
1581 print $object->getKanbanView('', array('selected' => $selected));
1582 if ($i == ($imaxinloop - 1)) {
1583 print '</div>';
1584 print '</td></tr>';
1585 }
1586 } else {
1587 // Show line of result
1588 $j = 0;
1589 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
1590
1591 // Action column
1592 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1593 print '<td class="nowrap center">';
1594 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1595 $selected = 0;
1596 if (in_array($object->id, $arrayofselected)) {
1597 $selected = 1;
1598 }
1599 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->rowid.'"'.($selected ? ' checked="checked"' : '').'>';
1600 }
1601 print '</td>';
1602 if (!$i) {
1603 $totalarray['nbfield']++;
1604 }
1605 }
1606 // Rowid
1607 if (!empty($arrayfields['p.rowid']['checked'])) {
1608 print '<td class="nowraponall">';
1609 print $product_static->id;
1610 print "</td>\n";
1611 if (!$i) {
1612 $totalarray['nbfield']++;
1613 }
1614 }
1615
1616 // Ref
1617 if (!empty($arrayfields['p.ref']['checked'])) {
1618 print '<td class="tdoverflowmax250">';
1619 print $product_static->getNomUrl(1);
1620 print "</td>\n";
1621 if (!$i) {
1622 $totalarray['nbfield']++;
1623 }
1624 }
1625
1626 // Ref supplier
1627 if (!empty($arrayfields['pfp.ref_fourn']['checked'])) {
1628 print '<td class="tdoverflowmax200">';
1629 print $product_static->getNomUrl(1);
1630 print "</td>\n";
1631 if (!$i) {
1632 $totalarray['nbfield']++;
1633 }
1634 }
1635
1636 // Thumbnail
1637 if (!empty($arrayfields['thumbnail']['checked'])) {
1638 $product_thumbnail_html = '';
1639 if (!empty($product_static->entity)) {
1640 $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80);
1641 if ($product_static->nbphoto > 0) {
1642 $product_thumbnail_html = $product_thumbnail;
1643 }
1644 }
1645
1646 print '<td class="center">' . $product_thumbnail_html . '</td>';
1647 if (!$i) {
1648 $totalarray['nbfield']++;
1649 }
1650 }
1651
1652 // Label
1653 if (!empty($arrayfields['p.label']['checked'])) {
1654 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($product_static->label).'">'.$product_static->label.'</td>';
1655 if (!$i) {
1656 $totalarray['nbfield']++;
1657 }
1658 }
1659
1660 // Type
1661 if (!empty($arrayfields['p.fk_product_type']['checked'])) {
1662 print '<td class="center">';
1663 $s = '';
1664 if ($product_static->type == 0) {
1665 $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"');
1666 } else {
1667 $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"');
1668 }
1669 print $s;
1670 print '</td>';
1671 if (!$i) {
1672 $totalarray['nbfield']++;
1673 }
1674 }
1675
1676 // Description
1677 if (!empty($arrayfields['p.description']['checked'])) {
1678 print '<td class="left">';
1679 // Since description can be very large (several pages of HTML-
1680 // code) we limit to the first two rows
1681 print dolGetFirstLineofText($product_static->description, 2);
1682 print '</td>';
1683 if (!$i) {
1684 $totalarray['nbfield']++;
1685 }
1686 }
1687
1688 // Barcode
1689 if (!empty($arrayfields['p.barcode']['checked'])) {
1690 print '<td>'.$product_static->barcode.'</td>';
1691 if (!$i) {
1692 $totalarray['nbfield']++;
1693 }
1694 }
1695
1696 // Duration
1697 if (!empty($arrayfields['p.duration']['checked'])) {
1698 print '<td class="center nowraponall">';
1699
1700 if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) {
1701 $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1);
1702 $duration_unit = substr($obj->duration, -1);
1703
1704 if ((float) $duration_value > 1) {
1705 $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"));
1706 } elseif ((float) $duration_value > 0) {
1707 $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"));
1708 }
1709 print $duration_value;
1710 print((!empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : '');
1711 } elseif (!preg_match('/^[a-z]$/i', $obj->duration)) { // If duration is a simple char (like 's' of 'm'), we do not show value
1712 print $obj->duration;
1713 }
1714
1715 print '</td>';
1716 if (!$i) {
1717 $totalarray['nbfield']++;
1718 }
1719 }
1720
1721 if (!empty($arrayfields['pac.fk_product_parent']['checked'])) {
1722 print '<td class="nowraponall">';
1723 if ($obj->fk_product_parent > 0) {
1724 if (!empty($conf->cache['product'][$obj->fk_product_parent])) {
1725 $product_parent_static = $conf->cache['product'][$obj->fk_product_parent];
1726 } else {
1727 $product_parent_static= new Product($db);
1728 $product_parent_static->fetch($obj->fk_product_parent);
1729 $conf->cache['product'][$obj->fk_product_parent] = $product_parent_static;
1730 }
1731 print $product_parent_static->getNomUrl(1);
1732 }
1733 print '</td>';
1734 if (!$i) {
1735 $totalarray['nbfield']++;
1736 }
1737 }
1738 // Finished
1739 if (!empty($arrayfields['p.finished']['checked'])) {
1740 print '<td class="center">';
1741 print $product_static->getLibFinished();
1742 print '</td>';
1743 if (!$i) {
1744 $totalarray['nbfield']++;
1745 }
1746 }
1747 // Weight
1748 if (!empty($arrayfields['p.weight']['checked'])) {
1749 print '<td class="center">';
1750 print $product_static->weight;
1751 print '</td>';
1752 if (!$i) {
1753 $totalarray['nbfield']++;
1754 }
1755 }
1756 // Weight units
1757 if (!empty($arrayfields['p.weight_units']['checked'])) {
1758 print '<td class="center">';
1759 if ($product_static->weight != '') {
1760 print measuringUnitString(0, 'weight', $product_static->weight_units);
1761 }
1762 print '</td>';
1763 if (!$i) {
1764 $totalarray['nbfield']++;
1765 }
1766 }
1767 // Length
1768 if (!empty($arrayfields['p.length']['checked'])) {
1769 print '<td class="center">';
1770 print $product_static->length;
1771 print '</td>';
1772 if (!$i) {
1773 $totalarray['nbfield']++;
1774 }
1775 }
1776 // Length units
1777 if (!empty($arrayfields['p.length_units']['checked'])) {
1778 print '<td class="center">';
1779 if ($product_static->length != '') {
1780 print measuringUnitString(0, 'size', $product_static->length_units);
1781 }
1782 print '</td>';
1783 if (!$i) {
1784 $totalarray['nbfield']++;
1785 }
1786 }
1787 // Width
1788 if (!empty($arrayfields['p.width']['checked'])) {
1789 print '<td align="center">';
1790 print $product_static->width;
1791 print '</td>';
1792 if (!$i) {
1793 $totalarray['nbfield']++;
1794 }
1795 }
1796 // Width units
1797 if (!empty($arrayfields['p.width_units']['checked'])) {
1798 print '<td class="center">';
1799 if ($product_static->width != '') {
1800 print measuringUnitString(0, 'size', $product_static->width_units);
1801 }
1802 print '</td>';
1803 if (!$i) {
1804 $totalarray['nbfield']++;
1805 }
1806 }
1807 // Height
1808 if (!empty($arrayfields['p.height']['checked'])) {
1809 print '<td align="center">';
1810 print $product_static->height;
1811 print '</td>';
1812 if (!$i) {
1813 $totalarray['nbfield']++;
1814 }
1815 }
1816 // Height units
1817 if (!empty($arrayfields['p.height_units']['checked'])) {
1818 print '<td class="center">';
1819 if ($product_static->height != '') {
1820 print measuringUnitString(0, 'size', $product_static->height_units);
1821 }
1822 print '</td>';
1823 if (!$i) {
1824 $totalarray['nbfield']++;
1825 }
1826 }
1827 // Surface
1828 if (!empty($arrayfields['p.surface']['checked'])) {
1829 print '<td class="center">';
1830 print $product_static->surface;
1831 print '</td>';
1832 if (!$i) {
1833 $totalarray['nbfield']++;
1834 }
1835 }
1836 // Surface units
1837 if (!empty($arrayfields['p.surface_units']['checked'])) {
1838 print '<td class="center">';
1839 if ($product_static->surface != '') {
1840 print measuringUnitString(0, 'surface', $product_static->surface_units);
1841 }
1842 print '</td>';
1843 if (!$i) {
1844 $totalarray['nbfield']++;
1845 }
1846 }
1847 // Volume
1848 if (!empty($arrayfields['p.volume']['checked'])) {
1849 print '<td class="center">';
1850 print $product_static->volume;
1851 print '</td>';
1852 if (!$i) {
1853 $totalarray['nbfield']++;
1854 }
1855 }
1856 // Volume units
1857 if (!empty($arrayfields['p.volume_units']['checked'])) {
1858 print '<td class="center">';
1859 if ($product_static->volume != '') {
1860 print measuringUnitString(0, 'volume', $product_static->volume_units);
1861 }
1862 print '</td>';
1863 if (!$i) {
1864 $totalarray['nbfield']++;
1865 }
1866 }
1867 // Unit
1868 if (!empty($arrayfields['cu.label']['checked'])) {
1869 print '<td align="center">';
1870 if (!empty($obj->cu_label)) {
1871 print $langs->trans($obj->cu_label);
1872 }
1873 print '</td>';
1874 if (!$i) {
1875 $totalarray['nbfield']++;
1876 }
1877 }
1878
1879 // Default Workstation
1880 if (!empty($arrayfields['p.fk_default_workstation']['checked'])) {
1881 print '<td align="left">';
1882 if (isModEnabled('workstation') && !empty($obj->fk_default_workstation)) {
1883 $workstation_static->id = $obj->fk_default_workstation;
1884 $workstation_static->ref = $obj->ref_workstation;
1885 $workstation_static->status = $obj->status_workstation;
1886
1887 print $workstation_static->getNomUrl(1);
1888 }
1889 print '</td>';
1890 if (!$i) {
1891 $totalarray['nbfield']++;
1892 }
1893 }
1894
1895 // Sell price
1896 if (!empty($arrayfields['p.sellprice']['checked'])) {
1897 print '<td class="right nowraponall">';
1898 if ($product_static->status && $usercancreadprice) {
1899 if ($obj->price_base_type == 'TTC') {
1900 print '<span class="amount">'.price($obj->price_ttc).' '.$langs->trans("TTC").'</span>';
1901 } else {
1902 print '<span class="amount">'.price($obj->price).' '.$langs->trans("HT").'</span>';
1903 }
1904 }
1905 print '</td>';
1906 if (!$i) {
1907 $totalarray['nbfield']++;
1908 }
1909 }
1910
1911 // Multiprices
1912 if (getDolGlobalString('PRODUIT_MULTIPRICES')) {
1913 if (! isset($productpricescache)) {
1914 $productpricescache=array();
1915 }
1916 if (! isset($productpricescache[$obj->rowid])) {
1917 $productpricescache[$obj->rowid] = array();
1918 }
1919
1920 if ($product_static->status && $usercancreadprice) {
1921 // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array
1922 // then reuse the cache array if we need prices for other price levels
1923 $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type";
1924 $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p";
1925 $sqlp .= " WHERE fk_product = ".((int) $obj->rowid);
1926 $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC";
1927 $resultp = $db->query($sqlp);
1928 if ($resultp) {
1929 $nump = $db->num_rows($resultp);
1930 $j = 0;
1931 while ($j < $nump) {
1932 $objp = $db->fetch_object($resultp);
1933
1934 if (empty($productpricescache[$obj->rowid][$objp->price_level])) {
1935 $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price;
1936 $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc;
1937 $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type;
1938 }
1939
1940 $j++;
1941 }
1942
1943 $db->free($resultp);
1944 } else {
1945 dol_print_error($db);
1946 }
1947 }
1948
1949 foreach ($arraypricelevel as $key => $value) {
1950 if (!empty($arrayfields['p.sellprice'.$key]['checked'])) {
1951 print '<td class="right nowraponall">';
1952 if (!empty($productpricescache[$obj->rowid]) && isset($productpricescache[$obj->rowid][$key]['price_base_type'])) {
1953 if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') {
1954 print '<span class="amount">'.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").'</span>';
1955 } else {
1956 print '<span class="amount">'.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").'</span>';
1957 }
1958 }
1959 print '</td>';
1960 if (!$i) {
1961 $totalarray['nbfield']++;
1962 }
1963 }
1964 }
1965 }
1966
1967 // Better buy price
1968 if (!empty($arrayfields['p.minbuyprice']['checked'])) {
1969 print '<td class="right nowraponall">';
1970 if ($product_static->status_buy && $obj->bestpurchaseprice != '' && $usercancreadprice) {
1971 if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) {
1972 if ($product_fourn->product_fourn_price_id > 0) {
1973 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'))) {
1974 $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1);
1975 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>';
1976 } else {
1977 print '<span class="amount">'.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").'</span>';
1978 }
1979 }
1980 }
1981 }
1982 print '</td>';
1983 if (!$i) {
1984 $totalarray['nbfield']++;
1985 }
1986 }
1987
1988 // Number of buy prices
1989 if (!empty($arrayfields['p.numbuyprice']['checked'])) {
1990 print '<td class="right">';
1991 if ($product_static->status_buy && $usercancreadprice) {
1992 if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) {
1993 $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList);
1994 print $form->textwithpicto(count($productFournList), $htmltext);
1995 }
1996 }
1997 print '</td>';
1998 }
1999
2000 // VAT or Sell Tax Rate
2001 if (!empty($arrayfields['p.tva_tx']['checked'])) {
2002 print '<td class="right">';
2003 print vatrate($obj->tva_tx, true);
2004 print '</td>';
2005 if (!$i) {
2006 $totalarray['nbfield']++;
2007 }
2008 }
2009
2010 // WAP
2011 if (!empty($arrayfields['p.pmp']['checked'])) {
2012 print '<td class="nowrap right">';
2013 if ($usercancreadprice) {
2014 print '<span class="amount">'.price($product_static->pmp, 1, $langs)."</span>";
2015 }
2016 print '</td>';
2017 }
2018 // Cost price
2019 if (!empty($arrayfields['p.cost_price']['checked'])) {
2020 print '<td class="nowrap right">';
2021 //print $obj->cost_price;
2022 if ($usercancreadprice) {
2023 print '<span class="amount">'.price($obj->cost_price).' '.$langs->trans("HT").'</span>';
2024 }
2025 print '</td>';
2026 }
2027
2028 // Limit alert
2029 if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) {
2030 print '<td class="right">';
2031 if ($product_static->type != 1) {
2032 print $obj->seuil_stock_alerte;
2033 }
2034 print '</td>';
2035 if (!$i) {
2036 $totalarray['nbfield']++;
2037 }
2038 }
2039 // Desired stock
2040 if (!empty($arrayfields['p.desiredstock']['checked'])) {
2041 print '<td class="right">';
2042 if ($product_static->type != 1) {
2043 print $obj->desiredstock;
2044 }
2045 print '</td>';
2046 if (!$i) {
2047 $totalarray['nbfield']++;
2048 }
2049 }
2050 // Stock real
2051 if (!empty($arrayfields['p.stock']['checked'])) {
2052 print '<td class="right">';
2053 if ($product_static->type != 1) {
2054 if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) {
2055 print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' ';
2056 }
2057 if ($usercancreadprice) {
2058 if ($product_static->stock_reel < 0) {
2059 print '<span class="warning">';
2060 }
2061 print price(price2num($product_static->stock_reel, 'MS'), 0, $langs, 1, 0);
2062 if ($product_static->stock_reel < 0) {
2063 print '</span>';
2064 }
2065 }
2066 }
2067 print '</td>';
2068 if (!$i) {
2069 $totalarray['nbfield']++;
2070 }
2071 }
2072 // Stock virtual
2073 if (!empty($arrayfields['stock_virtual']['checked'])) {
2074 print '<td class="right">';
2075 if ($product_static->type != 1) {
2076 if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) {
2077 print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' ';
2078 }
2079 if ($usercancreadprice) {
2080 if ($product_static->stock_theorique < 0) {
2081 print '<span class="warning">';
2082 }
2083 print price(price2num($product_static->stock_theorique, 'MS'), 0, $langs, 1, 0);
2084 if ($product_static->stock_theorique < 0) {
2085 print '</span>';
2086 }
2087 }
2088 }
2089 print '</td>';
2090 if (!$i) {
2091 $totalarray['nbfield']++;
2092 }
2093 }
2094 // Lot/Serial
2095 if (!empty($arrayfields['p.tobatch']['checked'])) {
2096 print '<td class="center">';
2097 print $product_static->getLibStatut(1, 2);
2098 print '</td>';
2099 if (!$i) {
2100 $totalarray['nbfield']++;
2101 }
2102 }
2103 // Country
2104 if (!empty($arrayfields['p.fk_country']['checked'])) {
2105 print '<td>'.getCountry($obj->fk_country, 0, $db).'</td>';
2106 if (!$i) {
2107 $totalarray['nbfield']++;
2108 }
2109 }
2110 // State
2111 if (!empty($arrayfields['p.fk_state']['checked'])) {
2112 print '<td>';
2113 if (!empty($obj->fk_state)) {
2114 print getState($obj->fk_state, 0, $db);
2115 }
2116 print '</td>';
2117 if (!$i) {
2118 $totalarray['nbfield']++;
2119 }
2120 }
2121 // Accountancy code sell
2122 if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) {
2123 print '<td>'.length_accountg($product_static->accountancy_code_sell).'</td>';
2124 if (!$i) {
2125 $totalarray['nbfield']++;
2126 }
2127 }
2128 if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) {
2129 print '<td>'.length_accountg($product_static->accountancy_code_sell_intra).'</td>';
2130 if (!$i) {
2131 $totalarray['nbfield']++;
2132 }
2133 }
2134 if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) {
2135 print '<td>'.length_accountg($product_static->accountancy_code_sell_export).'</td>';
2136 if (!$i) {
2137 $totalarray['nbfield']++;
2138 }
2139 }
2140 // Accountancy code buy
2141 if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) {
2142 print '<td>'.length_accountg($product_static->accountancy_code_buy).'</td>';
2143 if (!$i) {
2144 $totalarray['nbfield']++;
2145 }
2146 }
2147 if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) {
2148 print '<td>'.length_accountg($product_static->accountancy_code_buy_intra).'</td>';
2149 if (!$i) {
2150 $totalarray['nbfield']++;
2151 }
2152 }
2153 if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) {
2154 print '<td>'.length_accountg($product_static->accountancy_code_buy_export).'</td>';
2155 if (!$i) {
2156 $totalarray['nbfield']++;
2157 }
2158 }
2159 // Extra fields
2160 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2161 // Fields from hook
2162 $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
2163 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2164 print $hookmanager->resPrint;
2165 // Date creation
2166 if (!empty($arrayfields['p.datec']['checked'])) {
2167 print '<td class="center nowraponall">';
2168 print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
2169 print '</td>';
2170 if (!$i) {
2171 $totalarray['nbfield']++;
2172 }
2173 }
2174 // Date modification
2175 if (!empty($arrayfields['p.tms']['checked'])) {
2176 print '<td class="center nowraponall">';
2177 print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser');
2178 print '</td>';
2179 if (!$i) {
2180 $totalarray['nbfield']++;
2181 }
2182 }
2183
2184 // Status (to sell)
2185 if (!empty($arrayfields['p.tosell']['checked'])) {
2186 print '<td class="center nowrap">';
2187 if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && getDolGlobalString('MAIN_DIRECT_STATUS_UPDATE')) {
2188 print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell');
2189 } else {
2190 print $product_static->LibStatut($product_static->status, 5, 0);
2191 }
2192 print '</td>';
2193 if (!$i) {
2194 $totalarray['nbfield']++;
2195 }
2196 }
2197 // Status (to buy)
2198 if (!empty($arrayfields['p.tobuy']['checked'])) {
2199 print '<td class="center nowrap">';
2200 if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && getDolGlobalString('MAIN_DIRECT_STATUS_UPDATE')) {
2201 print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy');
2202 } else {
2203 print $product_static->LibStatut($product_static->status_buy, 5, 1);
2204 }
2205 print '</td>';
2206 if (!$i) {
2207 $totalarray['nbfield']++;
2208 }
2209 }
2210
2211 // Action column
2212 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2213 print '<td class="nowrap center">';
2214 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
2215 $selected = 0;
2216 if (in_array($object->id, $arrayofselected)) {
2217 $selected = 1;
2218 }
2219 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->rowid.'"'.($selected ? ' checked="checked"' : '').'>';
2220 }
2221 print '</td>';
2222 if (!$i) {
2223 $totalarray['nbfield']++;
2224 }
2225 }
2226
2227 print '</tr>'."\n";
2228 }
2229
2230 $i++;
2231}
2232
2233// If no record found
2234if ($num == 0) {
2235 $colspan = 1;
2236 foreach ($arrayfields as $key => $val) {
2237 if (!empty($val['checked'])) {
2238 $colspan++;
2239 }
2240 }
2241 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
2242}
2243
2244$db->free($resql);
2245
2246print '</table>'."\n";
2247print '</div>'."\n";
2248
2249print '</form>'."\n";
2250
2251// End of page
2252llxFooter();
2253$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.