dolibarr 24.0.0-beta
log_viewer.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2026 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2026 Nick Fragoulis
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
25require '../../main.inc.php';
34require_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php';
35require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
36require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
37
38// Load translations
39$langs->loadLangs(array("admin", "other"));
40
41// Parameters
42$action = GETPOST('action', 'aZ09');
43$massaction = GETPOST('massaction', 'alpha');
44$confirm = GETPOST('confirm', 'alpha');
45$toselect = GETPOST('toselect', 'array');
46$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'ailoglist';
47$optioncss = GETPOST('optioncss', 'alpha');
48$mode = GETPOST('mode', 'alpha');
49
50// Search parameters for all columns
51$search_date_start = dol_mktime(0, 0, 0, GETPOSTINT('search_date_startmonth'), GETPOSTINT('search_date_startday'), GETPOSTINT('search_date_startyear'));
52$search_date_end = dol_mktime(23, 59, 59, GETPOSTINT('search_date_endmonth'), GETPOSTINT('search_date_endday'), GETPOSTINT('search_date_endyear'));
53$search_user = GETPOST('search_user', 'alpha');
54$search_query = GETPOST('search_query', 'alpha');
55$search_tool = GETPOST('search_tool', 'alpha');
56$search_provider = GETPOST('search_provider', 'alpha');
57$search_time_min = GETPOST('search_time_min', 'alpha');
58$search_time_max = GETPOST('search_time_max', 'alpha');
59$search_status = GETPOST('search_status', 'alpha');
60
61// Pagination parameters
62$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
63$sortfield = GETPOST('sortfield', 'aZ09comma');
64$sortorder = GETPOST('sortorder', 'aZ09comma');
65$page = GETPOSTINT("page");
66if (empty($page) || $page == -1) {
67 $page = 0;
68}
69$offset = $limit * $page;
70if (!$sortfield) $sortfield = "l.date_request";
71if (!$sortorder) $sortorder = "DESC";
72
73// Initialize array of search criteria
74$search_array = array(
75 'search_date_start' => $search_date_start,
76 'search_date_end' => $search_date_end,
77 'search_user' => $search_user,
78 'search_query' => $search_query,
79 'search_tool' => $search_tool,
80 'search_provider' => $search_provider,
81 'search_time_min' => $search_time_min,
82 'search_time_max' => $search_time_max,
83 'search_status' => $search_status
84);
85
86// Access Control
87if (!$user->admin) {
89}
90if (!isModEnabled('ai')) {
91 accessforbidden('Module AI not activated.');
92}
93
94
95/*
96 * Actions
97 */
98
99$error = '';
100if ($action == 'purge' && $confirm == 'yes') {
101 $db->begin();
102
103 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "ai_request_log";
104 $sql .= " WHERE entity IN (" . getEntity('airequestlog') . ")";
105
106 $resql = $db->query($sql);
107
108 if ($resql) {
109 $nbDeleted = $db->affected_rows($resql);
110 $db->commit();
111 setEventMessages($langs->trans("LogsCleared") . " (" . $nbDeleted . ")", null, 'mesgs');
112 } else {
113 $db->rollback();
114 setEventMessages($db->lasterror(), null, 'errors');
115 }
116
117 header('Location: ' . $_SERVER["PHP_SELF"]);
118 exit;
119}
120
121// Purge selection
122if ($massaction == 'purge' && !empty($toselect) && is_array($toselect)) {
123 $db->begin();
124
125 foreach ($toselect as $id) {
126 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "ai_request_log";
127 $sql .= " WHERE rowid = " . ((int) $id);
128 $sql .= " AND entity IN (" . getEntity('airequestlog') . ")";
129
130 $resql = $db->query($sql);
131 if (!$resql) {
132 $error++;
133 $db->rollback();
134 setEventMessages($db->lasterror(), null, 'errors');
135 break;
136 }
137 }
138
139 if (!$error) {
140 $db->commit();
141 setEventMessages($langs->trans("SelectedLogsDeleted"), null, 'mesgs');
142 } else {
143 $db->rollback();
144 }
145
146 $action = 'list';
147 $massaction = '';
148}
149
150// Clear filter action
151if (GETPOST('button_removefilter', 'alpha') || GETPOST('button_removefilter_x', 'alpha')) {
152 $search_date_start = '';
153 $search_date_end = '';
154 $search_user = '';
155 $search_query = '';
156 $search_tool = '';
157 $search_provider = '';
158 $search_time_min = '';
159 $search_time_max = '';
160 $search_status = '';
161 // Reset page
162 $page = 0;
163}
164
165
166/*
167 * View
168 */
169
170// Initialize array of search criteria for the view
171$param = '';
172if ($contextpage != $_SERVER["PHP_SELF"]) {
173 $param .= '&contextpage='.urlencode($contextpage);
174}
175if ($limit > 0 && $limit != $conf->liste_limit) {
176 $param .= '&limit='.((int) $limit);
177}
178foreach ($search_array as $key => $val) {
179 if (!empty($val) || $val === '0') {
180 $param .= '&' . urlencode($key) . '=' . urlencode($val);
181 }
182}
183
184llxHeader('', $langs->trans("AIRequestLogs"), '');
185
186
187// Build WHERE clause
188$where = array();
189
190$where[] = "l.entity IN (" . getEntity('airequestlog') . ")";
191
192if ($search_date_start) {
193 $where[] = "l.date_request >= '" . $db->escape(date('Y-m-d H:i:s', $search_date_start)) . "'";
194}
195if ($search_date_end) {
196 $where[] = "l.date_request <= '" . $db->escape(date('Y-m-d H:i:s', $search_date_end)) . "'";
197}
198if ($search_user) {
199 $where[] = "u.login LIKE '%" . $db->escape($search_user) . "%'";
200}
201if ($search_query) {
202 $where[] = "l.query_text LIKE '%" . $db->escape($search_query) . "%'";
203}
204if ($search_tool) {
205 $where[] = "l.tool_name LIKE '%" . $db->escape($search_tool) . "%'";
206}
207if ($search_provider) {
208 $where[] = "l.provider LIKE '%" . $db->escape($search_provider) . "%'";
209}
210if ($search_time_min) {
211 $where[] = "l.execution_time >= " . floatval($search_time_min);
212}
213if ($search_time_max) {
214 $where[] = "l.execution_time <= " . floatval($search_time_max);
215}
216if ($search_status) {
217 $where[] = "l.status = '" . $db->escape($search_status) . "'";
218}
219
220$whereSQL = '';
221if (!empty($where)) {
222 $whereSQL = ' WHERE ' . implode(' AND ', $where);
223}
224
225// Get total count for pagination
226$sqlCount = "SELECT COUNT(l.rowid) as total
227 FROM " . MAIN_DB_PREFIX . "ai_request_log as l
228 LEFT JOIN " . MAIN_DB_PREFIX . "user as u ON l.fk_user = u.rowid";
229$sqlCount .= $whereSQL;
230$resqlCount = $db->query($sqlCount);
231$totalRecords = $resqlCount ? $db->fetch_object($resqlCount)->total : 0;
232
233
234$sql = "SELECT l.rowid, u.login, l.date_request, l.query_text, l.tool_name, l.provider, l.execution_time, l.status, l.error_msg, l.raw_request_payload, l.raw_response_payload
235 FROM " . MAIN_DB_PREFIX . "ai_request_log as l
236 LEFT JOIN " . MAIN_DB_PREFIX . "user as u ON l.fk_user = u.rowid";
237$sql .= $whereSQL;
238$sql .= $db->order($sortfield, $sortorder);
239$sql .= $db->plimit($limit, $offset);
240
241$resql = $db->query($sql);
242$num = $db->num_rows($resql);
243
244// Create object for list
245$object = new stdClass();
246$object->total = $totalRecords;
247
248$title = $langs->trans("AIRequestLogs");
249print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $totalRecords, 'title_ai', 0, '', '', $limit, 1, 0, 0, '');
250
251print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '" name="limitform">';
252print '<input type="hidden" name="token" value="' . newToken() . '">';
253print '<input type="hidden" name="action" value="list">';
254
255// Add all search parameters to preserve them when changing the limit
256foreach ($search_array as $key => $val) {
257 if (!empty($val) || $val === '0') {
258 print '<input type="hidden" name="' . $key . '" value="' . dol_escape_htmltag($val) . '">';
259 }
260}
261
262print '<div class="div-table-responsive-no-min">';
263print '<table class="noborder" width="100%">';
264print '<tr>';
265print '<td class="right">';
266print $langs->trans("Show") . ': ';
267print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
268print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
269print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
270print '<input type="hidden" name="page" value="'.$page.'">';
271
272// Create array of options for limit
273 $arrayoflimit = array(5, 10, 20, 50, 100, 500, 1000);
274print '<select class="flat" name="limit" onchange="this.form.submit()">';
275foreach ($arrayoflimit as $val) {
276 print '<option value="'.$val.'"';
277 if ($limit == $val) print ' selected';
278 print '>'.$val.'</option>';
279}
280
281print '</select>';
282print ' ' . $langs->trans("Entries");
283print '</td>';
284print '</tr>';
285print '</table>';
286print '</div>';
287print '</form>';
288
289// Display form for filters
290print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '" name="search_form">';
291print '<input type="hidden" name="token" value="' . newToken() . '">';
292print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
293print '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
294print '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
295print '<input type="hidden" name="page" value="' . $page . '">';
296print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
297print '<input type="hidden" name="page_y" value="">';
298print '<input type="hidden" name="mode" value="'.$mode.'">';
299
300print '<div class="div-table-responsive">';
301print '<table class="tagtable liste listwithfilterbefore">'."\n";
302
303// Fields title
304print '<tr class="liste_titre">';
305print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "l.date_request", "", $param, '', $sortfield, $sortorder);
306print_liste_field_titre("User", $_SERVER["PHP_SELF"], "u.login", "", $param, '', $sortfield, $sortorder);
307print_liste_field_titre("Query", $_SERVER["PHP_SELF"], "l.query_text", "", $param, '', $sortfield, $sortorder);
308print_liste_field_titre("MCPTool", $_SERVER["PHP_SELF"], "l.tool_name", "", $param, '', $sortfield, $sortorder);
309print_liste_field_titre("Provider", $_SERVER["PHP_SELF"], "l.provider", "", $param, '', $sortfield, $sortorder);
310print_liste_field_titre("Time", $_SERVER["PHP_SELF"], "l.execution_time", "", $param, 'align="center"', $sortfield, $sortorder);
311print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "l.status", "", $param, 'align="center"', $sortfield, $sortorder);
312print_liste_field_titre('', $_SERVER["PHP_SELF"], "", "", $param, 'align="center"');
313print '</tr>';
314// Search row
315print '<tr class="liste_titre_filter">';
316// Date search
317print '<td class="liste_titre">';
318print $form->selectDate($search_date_start, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
319print ' - ';
320print $form->selectDate($search_date_end, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("To"));
321print '</td>';
322// User search
323print '<td class="liste_titre"><input type="text" name="search_user" value="' . dol_escape_htmltag($search_user) . '" class="maxwidth100"></td>';
324// Query search
325print '<td class="liste_titre"><input type="text" name="search_query" value="' . dol_escape_htmltag($search_query) . '" class="maxwidth150"></td>';
326// Tool search
327print '<td class="liste_titre"><input type="text" name="search_tool" value="' . dol_escape_htmltag($search_tool) . '" class="maxwidth100"></td>';
328// Provider search
329print '<td class="liste_titre"><input type="text" name="search_provider" value="' . dol_escape_htmltag($search_provider) . '" class="maxwidth100"></td>';
330// Time search
331print '<td class="liste_titre center">';
332print '<input type="text" name="search_time_min" value="' . dol_escape_htmltag($search_time_min) . '" size="3" placeholder="' . dol_escape_htmltag($langs->trans('Min')) . '">';
333print '<input type="text" name="search_time_max" value="' . dol_escape_htmltag($search_time_max) . '" size="3" placeholder="' . dol_escape_htmltag($langs->trans('Max')) . '">';
334// Status search
335print '<td class="liste_titre center">';
336$status_options = array('' => $langs->trans("All"), 'success' => $langs->trans("Success"), 'confirm' => $langs->trans("Confirm"), 'error' => $langs->trans("Error"));
337print $form->selectarray('search_status', $status_options, $search_status, 0, 0, 0, '', 1); // @phan-suppress-current-line PhanPluginSuspiciousParamOrder
338print '</td>';
339// Search buttons
340print '<td class="liste_titre center">';
341$searchpicto = img_picto($langs->trans("Search"), 'search.png', '', 0, 1);
342print '<input type="image" class="liste_titre" name="button_search" src="' . $searchpicto . '" value="' . dol_escape_htmltag($langs->trans("Search")) . '" title="' . dol_escape_htmltag($langs->trans("Search")) . '">';
343$clearpicto = img_picto($langs->trans("RemoveFilter"), 'searchclear.png', '', 0, 1);
344print '<input type="image" class="liste_titre" name="button_removefilter" src="' . $clearpicto . '" value="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '" title="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '">';
345print '</td>';
346print '</tr>';
347
348// Mass action buttons
349print '<tr class="liste_titre">';
350print '<td class="liste_titre" colspan="8">';
351print '<div class="center">';
352print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=purge&token='.newToken().'" onclick="return confirm(\''.$langs->trans("ConfirmDeleteAllLogs").'\');">'.$langs->trans("ClearAllLogs").'</a></div>';
353print '</div>';
354print '</td>';
355print '</tr>';
356
357if ($resql && $num > 0) {
358 $i = 0;
359 while ($obj = $db->fetch_object($resql)) {
360 print '<tr class="oddeven">';
361
362 // Date
363 print '<td>' . dol_print_date($db->jdate($obj->date_request), 'dayhour') . '</td>';
364
365 // User
366 print '<td>' . ($obj->login ? dol_escape_htmltag($obj->login) : $langs->trans("Unknown")) . '</td>';
367
368 // Query - properly escaped
369 $shortQuery = dol_trunc($obj->query_text, 60);
370 print '<td title="' . dol_escape_htmltag($obj->query_text) . '">' . dol_escape_htmltag($shortQuery) . '</td>';
371
372 // Tool
373 print '<td>' . dol_escape_htmltag($obj->tool_name) . '</td>';
374
375 // Provider
376 print '<td>' . dol_escape_htmltag($obj->provider) . '</td>';
377
378 // Time
379 $timeColor = ($obj->execution_time > 5) ? 'color:red;' : '';
380 print '<td style="' . $timeColor . '" align="center">' . round($obj->execution_time, 2) . 's</td>';
381
382 // Status
383 $badge = 'badge-status0';
384 if ($obj->status == $langs->transnoentitiesnoconv("Success")) {
385 $badge = 'badge-status4'; // Green
386 }
387 if ($obj->status == $langs->transnoentitiesnoconv("Confirm")) {
388 $badge = 'badge-status3'; // Yellow
389 }
390 if ($obj->status == $langs->transnoentitiesnoconv('Error')) {
391 $badge = 'badge-status8'; // Red
392 }
393 print '<td align="center"><span class="badge ' . $badge . '">' . dol_escape_htmltag($obj->status) . '</span></td>';
394
395 // Details Button (Triggers Modal)
396 // We embed data attributes securely with proper UTF-8 handling
397 $reqSafe = base64_encode($obj->raw_request_payload);
398 $resSafe = base64_encode($obj->raw_response_payload);
399 $errSafe = base64_encode($obj->error_msg);
400
401 print '<td align="center">';
402 print '<a href="#" class="button button-small" onclick="openLogModal(this)"
403 data-req="' . dol_escape_htmltag($reqSafe) . '"
404 data-res="' . dol_escape_htmltag($resSafe) . '"
405 data-err="' . dol_escape_htmltag($errSafe) . '">';
406 print '<span class="fa fa-search-plus"></span> ' . $langs->trans("View");
407 print '</a>';
408 print '</td>';
409
410 print '</tr>';
411 $i++;
412 }
413} else {
414 $colspan = 8;
415 print '<tr><td colspan="' . $colspan . '" class="opacitymedium">' . $langs->trans("NoLogsFound");
416 if (!empty($where)) {
417 print ' ' . $langs->trans("MatchingSearchCriteria");
418 }
419 print '. ' . $langs->trans("TryAskingAI") . '.</td></tr>';
420}
421print '</table></div>';
422
423print '</form>';
424
425// --- MODAL HTML & JS ---
426?>
427<div id="logModal" style="display:none; position:fixed; z-index:9999; left:0; top:0; width:100%; height:100%; overflow:auto; background-color:rgba(0,0,0,0.5);">
428 <div style="background-color:#fff; margin:5% auto; padding:20px; border:1px solid #888; width:80%; max-width:900px; border-radius:8px; box-shadow:0 4px 8px rgba(0,0,0,0.2);">
429 <span style="float:right; font-size:28px; font-weight:bold; cursor:pointer;" onclick="document.getElementById('logModal').style.display='none'">&times;</span>
430 <h2><?php echo $langs->trans("LogDetails"); ?></h2>
431
432 <h3><?php echo $langs->trans("ErrorWarning"); ?></h3>
433 <div id="modalError" style="background:#fff0f0; border:1px solid #ffcdd2; color:#d32f2f; padding:10px; border-radius:4px; display:none;"></div>
434
435 <div style="display:flex; gap:20px; margin-top:15px;">
436 <div style="flex:1;">
437 <h3><?php echo $langs->trans("RequestPayload"); ?></h3>
438 <textarea id="modalReq" style="width:100%; height:300px; font-family:monospace; font-size:12px; border:1px solid #ccc;" readonly></textarea>
439 </div>
440 <div style="flex:1;">
441 <h3><?php echo $langs->trans("ResponsePayload"); ?></h3>
442 <textarea id="modalRes" style="width:100%; height:300px; font-family:monospace; font-size:12px; border:1px solid #ccc;" readonly></textarea>
443 </div>
444 </div>
445
446 <div style="text-align:right; margin-top:15px;">
447 <button class="button" onclick="document.getElementById('logModal').style.display='none'"><?php echo $langs->trans("Close"); ?></button>
448 </div>
449 </div>
450</div>
451
452<script>
453// UTF-8 safe base64 decoding function
454function base64ToUtf8(str) {
455 // Going backwards: from bytestream, to percent-encoding, to original string.
456 return decodeURIComponent(atob(str).split('').map(function(c) {
457 return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
458 }).join(''));
459}
460
461// Function to decode Unicode escape sequences in JSON strings
462function decodeUnicodeEscapes(str) {
463 // First, try to parse as JSON to handle escaped Unicode properly
464 try {
465 // If it's a JSON string, parse and stringify to decode escapes
466 const parsed = JSON.parse(str);
467 return JSON.stringify(parsed, null, 2);
468 } catch (e) {
469 // If not valid JSON, try to decode Unicode escapes in the string
470 return str.replace(/\\u([0-9a-fA-F]{4})/g, function(match, p1) {
471 return String.fromCharCode(parseInt(p1, 16));
472 });
473 }
474}
475
476// Sanitize HTML to prevent XSS
477function escapeHtml(text) {
478 const div = document.createElement('div');
479 div.textContent = text;
480 return div.innerHTML;
481}
482
483function openLogModal(btn) {
484 // Decode Base64 safely with UTF-8 support
485 const reqBase64 = btn.getAttribute('data-req') || '';
486 const resBase64 = btn.getAttribute('data-res') || '';
487 const errBase64 = btn.getAttribute('data-err') || '';
488
489 let req = '';
490 let res = '';
491 let err = '';
492
493 try {
494 // Decode Unicode escape sequences
495 if (reqBase64) {
496 req = base64ToUtf8(reqBase64);
497 req = decodeUnicodeEscapes(req);
498 }
499 if (resBase64) {
500 res = base64ToUtf8(resBase64);
501 res = decodeUnicodeEscapes(res);
502 }
503 if (errBase64) {
504 err = base64ToUtf8(errBase64);
505 err = decodeUnicodeEscapes(err);
506 }
507 } catch (e) {
508 console.error('Error decoding base64:', e);
509 // Fallback to regular atob if UTF-8 decoding fails
510 req = reqBase64 ? atob(reqBase64) : '';
511 res = resBase64 ? atob(resBase64) : '';
512 err = errBase64 ? atob(errBase64) : '';
513 }
514
515 // Sanitize content before setting it
516 document.getElementById('modalReq').value = req || '(<?php echo $langs->trans("NoRequestPayload"); ?>)';
517 document.getElementById('modalRes').value = res || '(<?php echo $langs->trans("NoResponsePayload"); ?>)';
518
519 const errDiv = document.getElementById('modalError');
520 if (err) {
521 errDiv.innerText = err;
522 errDiv.style.display = 'block';
523 } else {
524 errDiv.style.display = 'none';
525 }
526
527 document.getElementById('logModal').style.display = 'block';
528}
529</script>
530
531<?php
532llxFooter();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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:73
print $object position
Definition edit.php:206
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
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...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an 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)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
isModEnabled($module)
Is Dolibarr module enabled.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
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...
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
Definition receipt.php:487
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.