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