dolibarr 20.0.2
bom_list.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
25// Load Dolibarr environment
26require '../main.inc.php';
27require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
28require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
29require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
30require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
31require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
32
33// Load translation files required by the page
34$langs->loadLangs(array('mrp', 'other'));
35
36// Get Parameters
37$id = GETPOSTINT('id');
38$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
39$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
40$show_files = GETPOSTINT('show_files'); // Show files area generated by bulk actions ?
41$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
42$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
43$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
44$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bomlist'; // To manage different context of search
45$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
46$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
47$mode = GETPOST('mode', 'aZ'); // mode view (kanban or common)
48
49
50// Load variable for pagination
51$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
52$sortfield = GETPOST('sortfield', 'aZ09comma');
53$sortorder = GETPOST('sortorder', 'aZ09comma');
54$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page');
55if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
56 // If $page is not defined, or '' or -1 or if we click on clear filters
57 $page = 0;
58}
59$offset = $limit * $page;
60$pageprev = $page - 1;
61$pagenext = $page + 1;
62//if (! $sortfield) $sortfield="p.date_fin";
63//if (! $sortorder) $sortorder="DESC";
64
65// Initialize technical objects
66$object = new BOM($db);
67$extrafields = new ExtraFields($db);
68$diroutputmassaction = $conf->bom->dir_output.'/temp/massgeneration/'.$user->id;
69$hookmanager->initHooks(array('bomlist')); // Note that conf->hooks_modules contains array
70
71// Fetch optionals attributes and labels
72$extrafields->fetch_name_optionals_label($object->table_element);
73
74$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
75
76// Default sort order (if not yet defined by previous GETPOST)
77if (!$sortfield) {
78 reset($object->fields); // Reset is required to avoid key() to return null.
79 $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition.
80}
81if (!$sortorder) {
82 $sortorder = "ASC";
83}
84
85// Initialize array of search criteria
86$search_all = trim(GETPOST('search_all', 'alphanohtml'));
87$search = array();
88foreach ($object->fields as $key => $val) {
89 if (GETPOST('search_'.$key, 'alpha') !== '') {
90 $search[$key] = GETPOST('search_'.$key, 'alpha');
91 }
92 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
93 $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOSTINT('search_'.$key.'_dtstartmonth'), GETPOSTINT('search_'.$key.'_dtstartday'), GETPOSTINT('search_'.$key.'_dtstartyear'));
94 $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOSTINT('search_'.$key.'_dtendmonth'), GETPOSTINT('search_'.$key.'_dtendday'), GETPOSTINT('search_'.$key.'_dtendyear'));
95 }
96}
97
98$fieldstosearchall = array();
99// List of fields to search into when doing a "search in all"
100foreach ($object->fields as $key => $val) {
101 if (!empty($val['searchall'])) {
102 $fieldstosearchall['t.'.$key] = $val['label'];
103 }
104}
105
106// Definition of array of fields for columns
107$arrayfields = array();
108foreach ($object->fields as $key => $val) {
109 // If $val['visible']==0, then we never show the field
110 if (!empty($val['visible'])) {
111 $visible = (int) dol_eval($val['visible'], 1);
112 $arrayfields['t.'.$key] = array(
113 'label' => $val['label'],
114 'checked' => (($visible < 0) ? 0 : 1),
115 'enabled' => (abs($visible) != 3 && (bool) dol_eval($val['enabled'], 1)),
116 'position' => $val['position'],
117 'help' => isset($val['help']) ? $val['help'] : ''
118 );
119 }
120}
121// Extra fields
122include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
123
124$object->fields = dol_sort_array($object->fields, 'position');
125$arrayfields = dol_sort_array($arrayfields, 'position');
126
127$permissiontoread = $user->hasRight('bom', 'read');
128$permissiontoadd = $user->hasRight('bom', 'write');
129$permissiontodelete = $user->hasRight('bom', 'delete');
130
131// Security check
132if ($user->socid > 0) {
133 // Protection if external user
135}
136$result = restrictedArea($user, 'bom');
137
138
139/*
140 * Actions
141 */
142
143if (GETPOST('cancel', 'alpha')) {
144 $action = 'list';
145 $massaction = '';
146}
147if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
148 $massaction = '';
149}
150
151$parameters = array();
152$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
153if ($reshook < 0) {
154 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
155}
156
157if (empty($reshook)) {
158 // Selection of new fields
159 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
160
161 // Purge search criteria
162 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
163 foreach ($object->fields as $key => $val) {
164 $search[$key] = '';
165 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
166 $search[$key.'_dtstart'] = '';
167 $search[$key.'_dtend'] = '';
168 }
169 }
170 $toselect = array();
171 $search_array_options = array();
172 }
173 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
174 || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
175 $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
176 }
177
178 // Mass actions
179 $objectclass = 'BOM';
180 $objectlabel = 'BillOfMaterials';
181 $permissiontoread = $user->hasRight('bom', 'read');
182 $permissiontodelete = $user->hasRight('bom', 'delete');
183 $uploaddir = $conf->bom->dir_output;
184 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
185
186
187 // Validate records
188 if (!$error && $massaction == 'disable' && $permissiontoadd) {
189 $objecttmp = new $objectclass($db);
190
191 if (!$error) {
192 $db->begin();
193
194 $nbok = 0;
195 foreach ($toselect as $toselectid) {
196 $result = $objecttmp->fetch($toselectid);
197 if ($result > 0) {
198 if ($objecttmp->status != $objecttmp::STATUS_VALIDATED) {
199 $langs->load("errors");
200 setEventMessages($langs->trans("ErrorObjectMustHaveStatusActiveToBeDisabled", $objecttmp->ref), null, 'errors');
201 $error++;
202 break;
203 }
204
205 // Can be 'cancel()' or 'close()'
206 $result = $objecttmp->cancel($user);
207 if ($result < 0) {
208 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
209 $error++;
210 break;
211 } else {
212 $nbok++;
213 }
214 } else {
215 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
216 $error++;
217 break;
218 }
219 }
220
221 if (!$error) {
222 setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
223 $db->commit();
224 } else {
225 $db->rollback();
226 }
227 //var_dump($listofobjectthirdparties);exit;
228 }
229 }
230
231 // Validate records
232 if (!$error && $massaction == 'enable' && $permissiontoadd) {
233 $objecttmp = new $objectclass($db);
234
235 if (!$error) {
236 $db->begin();
237
238 $nbok = 0;
239 foreach ($toselect as $toselectid) {
240 $result = $objecttmp->fetch($toselectid);
241 if ($result > 0) {
242 if ($objecttmp->status != $objecttmp::STATUS_DRAFT && $objecttmp->status != $objecttmp::STATUS_CANCELED) {
243 $langs->load("errors");
244 setEventMessages($langs->trans("ErrorObjectMustHaveStatusDraftOrDisabledToBeActivated", $objecttmp->ref), null, 'errors');
245 $error++;
246 break;
247 }
248
249 // Can be 'cancel()' or 'close()'
250 $result = $objecttmp->validate($user);
251 if ($result < 0) {
252 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
253 $error++;
254 break;
255 } else {
256 $nbok++;
257 }
258 } else {
259 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
260 $error++;
261 break;
262 }
263 }
264
265 if (!$error) {
266 setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
267 $db->commit();
268 } else {
269 $db->rollback();
270 }
271 //var_dump($listofobjectthirdparties);exit;
272 }
273 }
274}
275
276
277/*
278 * View
279 */
280
281$form = new Form($db);
282
283$now = dol_now();
284
285$title = $langs->trans('ListOfBOMs');
286$help_url = 'EN:Module_BOM';
287$morejs = array();
288$morecss = array();
289
290
291// Build and execute select
292// --------------------------------------------------------------------
293$sql = 'SELECT ';
294$sql .= $object->getFieldList('t');
295// Add fields from extrafields
296if (!empty($extrafields->attributes[$object->table_element]['label'])) {
297 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
298 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
299 }
300}
301// Add fields from hooks
302$parameters = array();
303$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
304$sql .= $hookmanager->resPrint;
305$sql = preg_replace('/,\s*$/', '', $sql);
306
307$sqlfields = $sql; // $sql fields to remove for count total
308
309$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t";
310if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
311 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
312}
313// Add table from hooks
314$parameters = array();
315$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
316$sql .= $hookmanager->resPrint;
317if ($object->ismultientitymanaged == 1) {
318 $sql .= " WHERE t.entity IN (".getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
319} else {
320 $sql .= " WHERE 1 = 1";
321}
322foreach ($search as $key => $val) {
323 if (array_key_exists($key, $object->fields)) {
324 if ($key == 'status' && $search[$key] == -1) {
325 continue;
326 }
327 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
328 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
329 if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
330 $search[$key] = '';
331 }
332 $mode_search = 2;
333 }
334 if ($search[$key] != '') {
335 $sql .= natural_search("t.".$db->sanitize($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
336 }
337 } else {
338 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
339 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
340 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
341 if (preg_match('/_dtstart$/', $key)) {
342 $sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
343 }
344 if (preg_match('/_dtend$/', $key)) {
345 $sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
346 }
347 }
348 }
349 }
350}
351
352if ($search_all) {
353 $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
354}
355//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear);
356// Add where from extra fields
357include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
358// Add where from hooks
359$parameters = array();
360$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
361$sql .= $hookmanager->resPrint;
362
363/* If a group by is required
364$sql.= " GROUP BY ";
365foreach($object->fields as $key => $val) {
366 $sql .= "t.".$db->escape($key).", ";
367}
368// Add fields from extrafields
369if (!empty($extrafields->attributes[$object->table_element]['label'])) {
370 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
371 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
372 }
373}
374// Add groupby from hooks
375$parameters=array();
376$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
377$sql.=$hookmanager->resPrint;
378$sql=preg_replace('/,\s*$/','', $sql);
379*/
380
381// Count total nb of records
382$nbtotalofrecords = '';
383if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
384 /* The fast and low memory method to get and count full list converts the sql into a sql count */
385 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
386 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
387 $resql = $db->query($sqlforcount);
388 if ($resql) {
389 $objforcount = $db->fetch_object($resql);
390 $nbtotalofrecords = $objforcount->nbtotalofrecords;
391 } else {
392 dol_print_error($db);
393 }
394
395 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
396 $page = 0;
397 $offset = 0;
398 }
399 $db->free($resql);
400}
401
402// Complete request and execute it with limit
403$sql .= $db->order($sortfield, $sortorder);
404if ($limit) {
405 $sql .= $db->plimit($limit + 1, $offset);
406}
407
408$resql = $db->query($sql);
409if (!$resql) {
410 dol_print_error($db);
411 exit;
412}
413
414$num = $db->num_rows($resql);
415
416// Direct jump if only one record found
417if ($num == 1 && getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) {
418 $obj = $db->fetch_object($resql);
419 $id = $obj->rowid;
420 header("Location: ".DOL_URL_ROOT.'/bom/bom_card.php?id='.((int) $id));
421 exit;
422}
423
424
425// Output page
426// --------------------------------------------------------------------
427
428llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'mod-bom page-list bodyforlist');
429
430$arrayofselected = is_array($toselect) ? $toselect : array();
431
432$param = '';
433if (!empty($mode)) {
434 $param .= '&mode='.urlencode($mode);
435}
436if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
437 $param .= '&contextpage='.urlencode($contextpage);
438}
439if ($limit > 0 && $limit != $conf->liste_limit) {
440 $param .= '&limit='.((int) $limit);
441}
442if ($optioncss != '') {
443 $param .= '&optioncss='.urlencode($optioncss);
444}
445foreach ($search as $key => $val) {
446 if (is_array($search[$key])) {
447 foreach ($search[$key] as $skey) {
448 if ($skey != '') {
449 $param .= '&search_'.$key.'[]='.urlencode($skey);
450 }
451 }
452 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
453 $param .= '&search_'.$key.'month='.(GETPOSTINT('search_'.$key.'month'));
454 $param .= '&search_'.$key.'day='.(GETPOSTINT('search_'.$key.'day'));
455 $param .= '&search_'.$key.'year='.(GETPOSTINT('search_'.$key.'year'));
456 } elseif ($search[$key] != '') {
457 $param .= '&search_'.$key.'='.urlencode($search[$key]);
458 }
459}
460// Add $param from extra fields
461include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
462// Add $param from hooks
463$parameters = array('param' => &$param);
464$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
465$param .= $hookmanager->resPrint;
466
467// List of mass actions available
468$arrayofmassactions = array(
469 //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
470 'enable' => img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Enable"),
471 'disable' => img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Disable"),
472);
473if (!empty($permissiontodelete)) {
474 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
475}
476if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
477 $arrayofmassactions = array();
478}
479$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
480
481print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
482if ($optioncss != '') {
483 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
484}
485print '<input type="hidden" name="token" value="'.newToken().'">';
486print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
487print '<input type="hidden" name="action" value="list">';
488print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
489print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
490print '<input type="hidden" name="page" value="'.$page.'">';
491print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
492print '<input type="hidden" name="page_y" value="">';
493print '<input type="hidden" name="mode" value="'.$mode.'">';
494
495$newcardbutton = '';
496$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'));
497$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'));
498$newcardbutton .= dolGetButtonTitleSeparator();
499$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/bom/bom_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $user->hasRight('bom', 'write'));
500
501print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
502
503// Add code for pre mass action (confirmation or email presend form)
504$topicmail = "SendBillOfMaterialsRef";
505$modelmail = "bom";
506$objecttmp = new BOM($db);
507$trackid = 'bom'.$object->id;
508include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
509
510if ($search_all) {
511 $setupstring = '';
512 foreach ($fieldstosearchall as $key => $val) {
513 $fieldstosearchall[$key] = $langs->trans($val);
514 $setupstring .= $key."=".$val.";";
515 }
516 print '<!-- Search done like if BOM_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
517 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>'."\n";
518}
519
520$moreforfilter = '';
521/*$moreforfilter.='<div class="divsearchfield">';
522$moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
523$moreforfilter.= '</div>';*/
524
525$parameters = array();
526$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
527if (empty($reshook)) {
528 $moreforfilter .= $hookmanager->resPrint;
529} else {
530 $moreforfilter = $hookmanager->resPrint;
531}
532
533if (!empty($moreforfilter)) {
534 print '<div class="liste_titre liste_titre_bydiv centpercent">';
535 print $moreforfilter;
536 print '</div>';
537}
538
539$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
540$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields with user setup
541$selectedfields = ($mode != 'kanban' ? $htmlofselectarray : '');
542$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
543
544print '<div class="div-table-responsive">';
545print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
546
547
548// Fields title search
549// --------------------------------------------------------------------
550print '<tr class="liste_titre_filter">';
551
552// Action column
553if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
554 print '<td class="liste_titre center maxwidthsearch">';
555 $searchpicto = $form->showFilterButtons('left');
556 print $searchpicto;
557 print '</td>';
558}
559
560foreach ($object->fields as $key => $val) {
561 $searchkey = empty($search[$key]) ? '' : $search[$key];
562 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
563 if ($key == 'status') {
564 $cssforfield .= ($cssforfield ? ' ' : '').'center';
565 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
566 $cssforfield .= ($cssforfield ? ' ' : '').'center';
567 } elseif (in_array($val['type'], array('timestamp'))) {
568 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
569 } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('id', 'rowid', 'ref', 'status')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
570 $cssforfield .= ($cssforfield ? ' ' : '').'right';
571 }
572 if (!empty($arrayfields['t.'.$key]['checked'])) {
573 print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').($key == 'status' ? ' parentonrightofpage' : '').'">';
574 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
575 print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), 1, 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1);
576 } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) {
577 print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1);
578 } elseif (!preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
579 print '<input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
580 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
581 print '<div class="nowrap">';
582 print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
583 print '</div>';
584 print '<div class="nowrap">';
585 print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
586 print '</div>';
587 } elseif ($key == 'lang') {
588 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
589 $formadmin = new FormAdmin($db);
590 print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth100imp maxwidth125', 2);
591 } else {
592 print '<input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
593 }
594 print '</td>';
595 }
596}
597// Extra fields
598include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
599
600// Fields from hook
601$parameters = array('arrayfields' => $arrayfields);
602$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
603print $hookmanager->resPrint;
604// Action column
605if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
606 print '<td class="liste_titre center maxwidthsearch">';
607 $searchpicto = $form->showFilterButtons();
608 print $searchpicto;
609 print '</td>';
610}
611print '</tr>'."\n";
612
613$totalarray = array();
614$totalarray['nbfield'] = 0;
615
616// Fields title label
617// --------------------------------------------------------------------
618print '<tr class="liste_titre">';
619// Action column
620if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
621 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
622 $totalarray['nbfield']++;
623}
624foreach ($object->fields as $key => $val) {
625 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
626 if ($key == 'status') {
627 $cssforfield .= ($cssforfield ? ' ' : '').'center';
628 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
629 $cssforfield .= ($cssforfield ? ' ' : '').'center';
630 } elseif (in_array($val['type'], array('timestamp'))) {
631 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
632 } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('id', 'rowid', 'ref', 'status')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
633 $cssforfield .= ($cssforfield ? ' ' : '').'right';
634 }
635 $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label
636 if (!empty($arrayfields['t.'.$key]['checked'])) {
637 print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''), 0, (empty($val['helplist']) ? '' : $val['helplist']))."\n";
638 $totalarray['nbfield']++;
639 }
640}
641// Extra fields
642include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
643// Hook fields
644$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
645$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
646print $hookmanager->resPrint;
647// Action column
648if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
649 print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
650 $totalarray['nbfield']++;
651}
652print '</tr>'."\n";
653
654
655// Detect if we need a fetch on each output line
656$needToFetchEachLine = 0;
657if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) {
658 foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) {
659 if (!is_null($val) && preg_match('/\$object/', $val)) {
660 $needToFetchEachLine++; // There is at least one compute field that use $object
661 }
662 }
663}
664
665
666// Loop on record
667// --------------------------------------------------------------------
668$i = 0;
669$savnbfield = $totalarray['nbfield'];
670$totalarray = array();
671$totalarray['nbfield'] = 0;
672$imaxinloop = ($limit ? min($num, $limit) : $num);
673while ($i < $imaxinloop) {
674 $obj = $db->fetch_object($resql);
675 if (empty($obj)) {
676 break; // Should not happen
677 }
678
679 // Store properties in $object
680 $object->setVarsFromFetchObj($obj);
681
682 // mode view kanban
683 if ($mode == 'kanban') {
684 if ($i == 0) {
685 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
686 print '<div class="box-flex-container kanban">';
687 }
688
689 // TODO Use a cache for product
690 if (!empty($obj->fk_product)) {
691 $prod = new Product($db);
692 $prod->fetch($obj->fk_product);
693 } else {
694 $prod = null;
695 }
696
697 // Output Kanban
698 $selected = -1;
699 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
700 $selected = 0;
701 if (in_array($object->id, $arrayofselected)) {
702 $selected = 1;
703 }
704 }
705 print $object->getKanbanView('', array('prod' => $prod, 'selected' => $selected));
706 if ($i == ($imaxinloop - 1)) {
707 print '</div>';
708 print '</td></tr>';
709 }
710 } else {
711 // Show line of result
712 $j = 0;
713 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
714 // Action column
715 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
716 print '<td class="nowrap center">';
717 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
718 $selected = 0;
719 if (in_array($object->id, $arrayofselected)) {
720 $selected = 1;
721 }
722 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
723 }
724 print '</td>';
725 if (!$i) {
726 $totalarray['nbfield']++;
727 }
728 }
729 foreach ($object->fields as $key => $val) {
730 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
731 if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
732 $cssforfield .= ($cssforfield ? ' ' : '').'center';
733 } elseif ($key == 'status') {
734 $cssforfield .= ($cssforfield ? ' ' : '').'center';
735 }
736
737 if (in_array($val['type'], array('timestamp'))) {
738 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
739 } elseif ($key == 'ref') {
740 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
741 }
742
743 if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('id', 'rowid', 'ref', 'status')) && empty($val['arrayofkeyval'])) {
744 $cssforfield .= ($cssforfield ? ' ' : '').'right';
745 }
746
747 if (!empty($arrayfields['t.'.$key]['checked'])) {
748 print '<td'.($cssforfield ? ' class="'.$cssforfield.(preg_match('/tdoverflow/', $cssforfield) ? ' classfortooltip' : '').'"' : '');
749 if (preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key)) {
750 print ' title="'.dol_escape_htmltag($object->$key).'"';
751 }
752 print '>';
753 if ($key == 'status') {
754 print $object->getLibStatut(5);
755 } elseif ($key == 'rowid') {
756 print $object->showOutputField($val, $key, $object->id, '');
757 } else {
758 print $object->showOutputField($val, $key, $object->$key, '');
759 }
760 print '</td>';
761 if (!$i) {
762 $totalarray['nbfield']++;
763 }
764 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
765 if (!$i) {
766 $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
767 }
768 if (!isset($totalarray['val'])) {
769 $totalarray['val'] = array();
770 }
771 if (!isset($totalarray['val']['t.'.$key])) {
772 $totalarray['val']['t.'.$key] = 0;
773 }
774 $totalarray['val']['t.'.$key] += $object->$key;
775 }
776 }
777 }
778 // Extra fields
779 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
780 // Fields from hook
781 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
782 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
783 print $hookmanager->resPrint;
784 // Action column
785 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
786 print '<td class="nowrap center">';
787 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
788 $selected = 0;
789 if (in_array($object->id, $arrayofselected)) {
790 $selected = 1;
791 }
792 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
793 }
794 print '</td>';
795 if (!$i) {
796 $totalarray['nbfield']++;
797 }
798 }
799
800 print '</tr>'."\n";
801 }
802
803 $i++;
804}
805
806// Show total line
807include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
808
809
810// If no record found
811if ($num == 0) {
812 $colspan = 1;
813 foreach ($arrayfields as $key => $val) {
814 if (!empty($val['checked'])) {
815 $colspan++;
816 }
817 }
818 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
819}
820
821
822$db->free($resql);
823
824$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
825$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
826print $hookmanager->resPrint;
827
828print '</table>'."\n";
829print '</div>'."\n";
830
831print '</form>'."\n";
832
833
834if (in_array('builddoc', array_keys($arrayofmassactions)) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
835 $hidegeneratedfilelistifempty = 1;
836 if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
837 $hidegeneratedfilelistifempty = 0;
838 }
839
840 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
841 $formfile = new FormFile($db);
842
843 // Show list of available documents
844 $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
845 $urlsource .= str_replace('&amp;', '&', $param);
846
847 $filedir = $diroutputmassaction;
848 $genallowed = $permissiontoread;
849 $delallowed = $permissiontoadd;
850
851 print $formfile->showdocuments('massfilesarea_bom', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
852}
853
854// End of page
855llxFooter();
856$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class for BOM.
Definition bom.class.php:45
Class to manage standard extra fields.
Class to generate html code for admin pages.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class to manage products or services.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
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_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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...
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
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 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...
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.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.