364 lines
15 KiB
PHP
364 lines
15 KiB
PHP
<?php
|
|
include('include/headscript.php');
|
|
|
|
$template_id = intval($_GET['id'] ?? 0);
|
|
if (!$template_id) {
|
|
header("Location: xlstemplates_grid.php?status=error&message=" . urlencode("Template ID mancante"));
|
|
exit;
|
|
}
|
|
|
|
$user_id = $iduserlogin ?? 1;
|
|
$show_all_users = isset($_GET['all_users']) && $_GET['all_users'] == '1';
|
|
$allowedLimits = [20, 40, 60, 100];
|
|
$rawLimit = (int)($_GET['limit'] ?? 20);
|
|
$perPage = in_array($rawLimit, $allowedLimits) ? $rawLimit : 20;
|
|
$page = max(1, (int)($_GET['page'] ?? 1));
|
|
|
|
$db = DBHandlerSelect::getInstance();
|
|
$pdo = $db->getConnection();
|
|
$logDir = __DIR__ . '/logs/api/';
|
|
|
|
// Estrae un riassunto breve dell'errore dal file di log della commessa
|
|
function extractErrorSummary(string $logDir, ?string $logFile): string
|
|
{
|
|
if (empty($logFile)) return '';
|
|
$path = $logDir . basename($logFile);
|
|
if (!is_file($path)) return '';
|
|
$content = @file_get_contents($path);
|
|
if ($content === false || $content === '') return '';
|
|
|
|
// 1) prova col "detail" del JSON del 500
|
|
if (preg_match('/"detail"\s*:\s*"([^"]+)"/', $content, $m)) {
|
|
return trim(stripcslashes($m[1]));
|
|
}
|
|
// 2) fallback: ultima riga MESSAGE:
|
|
if (preg_match_all('/^MESSAGE:\s*(.+)$/m', $content, $m) && !empty($m[1])) {
|
|
return trim(end($m[1]));
|
|
}
|
|
return '';
|
|
}
|
|
|
|
// Query: solo le righe in errore per questo template
|
|
$userFilter = $show_all_users ? '' : 'AND d.user_id = ?';
|
|
$baseWhere = "WHERE d.templateid = ? AND d.status = 'x' {$userFilter}";
|
|
$baseParams = [$template_id];
|
|
if (!$show_all_users) $baseParams[] = $user_id;
|
|
|
|
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM datadb d {$baseWhere}");
|
|
$countStmt->execute($baseParams);
|
|
$totalRows = (int)$countStmt->fetchColumn();
|
|
$totalPages = max(1, (int)ceil($totalRows / $perPage));
|
|
if ($page > $totalPages) $page = $totalPages;
|
|
|
|
$stmt = $pdo->prepare("
|
|
SELECT d.*, CONCAT(u.first_name, ' ', u.last_name) AS user_name
|
|
FROM datadb d
|
|
LEFT JOIN auth_users u ON d.user_id = u.id
|
|
{$baseWhere}
|
|
ORDER BY d.export_date DESC, d.iddatadb DESC
|
|
LIMIT {$perPage} OFFSET " . (($page - 1) * $perPage) . "
|
|
");
|
|
$stmt->execute($baseParams);
|
|
$rowsData = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
?>
|
|
<!doctype html>
|
|
<html lang="it">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
|
<?php include('cssinclude.php'); ?>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
<style>
|
|
.err-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.err-table th,
|
|
.err-table td {
|
|
padding: 8px 10px;
|
|
border-bottom: 1px solid #dee2e6;
|
|
vertical-align: top;
|
|
}
|
|
|
|
.err-table th {
|
|
background: #f8f9fa;
|
|
text-align: left;
|
|
font-weight: 600;
|
|
color: #495057;
|
|
}
|
|
|
|
.err-table tr:hover {
|
|
background: #fff8f8;
|
|
}
|
|
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 2px 8px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.status-x {
|
|
background: #dc3545;
|
|
color: #fff;
|
|
}
|
|
|
|
.err-msg {
|
|
color: #b02a37;
|
|
max-width: 420px;
|
|
white-space: normal;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.commessa-code {
|
|
font-size: 0.8em;
|
|
color: #555;
|
|
display: block;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.action-btn {
|
|
padding: 5px 8px;
|
|
margin-right: 4px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
color: #fff;
|
|
text-decoration: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.btn-resend {
|
|
background: #28a745;
|
|
}
|
|
|
|
.btn-log {
|
|
background: #17a2b8;
|
|
}
|
|
|
|
.btn-revert {
|
|
background: #fd7e14;
|
|
}
|
|
|
|
.pager-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
background: #f8f9fa;
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 6px;
|
|
padding: 6px 14px;
|
|
font-size: 13px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.pager-num,
|
|
.pager-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 28px;
|
|
height: 28px;
|
|
padding: 0 6px;
|
|
border: 1px solid #ced4da;
|
|
border-radius: 4px;
|
|
text-decoration: none;
|
|
color: #495057;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
.pager-num.active {
|
|
background: #0d6efd;
|
|
color: #fff;
|
|
border-color: #0d6efd;
|
|
}
|
|
</style>
|
|
<title>Export Errors - <?= htmlspecialchars($titlewebsite ?? '', ENT_QUOTES, 'UTF-8'); ?></title>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="wrapper">
|
|
<?php include('include/navbar.php'); ?>
|
|
<?php include('include/topbar.php'); ?>
|
|
<div class="page-wrapper">
|
|
<div class="page-content">
|
|
|
|
<div class="mb-3 d-flex align-items-center gap-2">
|
|
<a href="imported.php?id=<?= $template_id ?>" class="btn btn-warning me-2">Imported (i)</a>
|
|
<a href="tolims.php?id=<?= $template_id ?>" class="btn btn-success me-2">To LIMS (l)</a>
|
|
<a href="errors.php?id=<?= $template_id ?>" class="btn btn-danger">Errors (x)</a>
|
|
<span class="ms-3">
|
|
<label class="form-check-label" style="font-size:13px; cursor:pointer;">
|
|
<?php $tp = $_GET;
|
|
unset($tp['all_users']);
|
|
$toggleBase = 'errors.php?' . http_build_query($tp); ?>
|
|
<input type="checkbox" class="form-check-input" <?= $show_all_users ? 'checked' : '' ?>
|
|
onchange="window.location.href='<?= htmlspecialchars($toggleBase) ?>' + (this.checked ? '&all_users=1' : '')">
|
|
Show all users
|
|
</label>
|
|
</span>
|
|
<span class="text-muted" style="font-size:12px;">(<?= count($rowsData) ?> of <?= $totalRows ?> errori<?= !$show_all_users ? ' — my records' : '' ?>)</span>
|
|
</div>
|
|
|
|
<?php if ($totalPages > 1):
|
|
$pageQuery = $_GET;
|
|
unset($pageQuery['page']);
|
|
$pageBase = 'errors.php?' . http_build_query($pageQuery); ?>
|
|
<div class="pager-bar">
|
|
<span>Pagina <?= $page ?> di <?= $totalPages ?> — <?= $totalRows ?> righe</span>
|
|
<span>
|
|
<?php for ($p = 1; $p <= $totalPages; $p++): ?>
|
|
<a href="<?= htmlspecialchars($pageBase . '&page=' . $p) ?>" class="pager-num <?= $p === $page ? 'active' : '' ?>"><?= $p ?></a>
|
|
<?php endfor; ?>
|
|
</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card radius-10">
|
|
<div class="card-header">
|
|
<span style="font-weight:600;"><i class="fas fa-triangle-exclamation" style="color:#dc3545;"></i> Export falliti verso il LIMS</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<?php if (empty($rowsData)): ?>
|
|
<p class="text-muted mb-0">Nessun errore di export. 🎉</p>
|
|
<?php else: ?>
|
|
<div style="overflow-x:auto;">
|
|
<table class="err-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:170px;">Azioni</th>
|
|
<th>Status</th>
|
|
<th>Client</th>
|
|
<th>Errore</th>
|
|
<th style="width:150px;">Data export</th>
|
|
<th>File import</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($rowsData as $row):
|
|
$errMsg = extractErrorSummary($logDir, $row['log_file'] ?? null); ?>
|
|
<tr data-id="<?= (int)$row['iddatadb'] ?>">
|
|
<td>
|
|
<button type="button" class="action-btn btn-resend resend-btn" data-iddatadb="<?= (int)$row['iddatadb'] ?>" title="Reinvia al LIMS"><i class="fas fa-paper-plane"></i></button>
|
|
<?php if (!empty($row['log_file'])): ?>
|
|
<a href="download_logs.php?iddatadb=<?= (int)$row['iddatadb'] ?>" class="action-btn btn-log" title="Scarica log"><i class="fas fa-file-download"></i></a>
|
|
<?php endif; ?>
|
|
<button type="button" class="action-btn btn-revert revert-btn" data-iddatadb="<?= (int)$row['iddatadb'] ?>" title="Riporta a Imported"><i class="fas fa-rotate-left"></i></button>
|
|
</td>
|
|
<td>
|
|
<span class="status-badge status-x">Error</span>
|
|
<?php if (!empty($row['commessaweb'])): ?>
|
|
<span class="commessa-code"><?= htmlspecialchars($row['commessaweb']) ?></span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><span class="client-text" data-client-id="<?= htmlspecialchars((string)($row['idclient'] ?? '')) ?>"><?= htmlspecialchars((string)($row['idclient'] ?? '')) ?></span></td>
|
|
<td class="err-msg"><?= htmlspecialchars($errMsg ?: '—') ?></td>
|
|
<td><?= htmlspecialchars((string)($row['export_date'] ?? '')) ?></td>
|
|
<td><?php if (!empty($row['filename_import'])): ?><a href="imported_trf/<?= htmlspecialchars($row['filename_import']) ?>" target="_blank">File</a><?php endif; ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="overlay toggle-icon"></div>
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
<?php include('jsinclude.php'); ?>
|
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
<script>
|
|
$(function() {
|
|
// Risoluzione nomi cliente (come in tolims.php)
|
|
(function() {
|
|
const ids = new Set();
|
|
document.querySelectorAll('.client-text').forEach(el => {
|
|
const id = el.dataset.clientId;
|
|
if (id) ids.add(id);
|
|
});
|
|
ids.forEach(id => {
|
|
fetch('search_clienti.php?id=' + encodeURIComponent(id))
|
|
.then(r => r.json())
|
|
.then(j => {
|
|
const it = (j.results || [])[0];
|
|
if (it) document.querySelectorAll('.client-text[data-client-id="' + id + '"]').forEach(el => el.textContent = it.text);
|
|
})
|
|
.catch(() => {});
|
|
});
|
|
})();
|
|
|
|
// Reinvia: richiama export_to_lims.php. Se la commessa era già stata creata,
|
|
// il CHECK PRELIMINARE la verifica nel LIMS e non ne crea una seconda.
|
|
$(document).on('click', '.resend-btn', function() {
|
|
const $btn = $(this);
|
|
const iddatadb = $btn.data('iddatadb');
|
|
if (!confirm('Reinviare questa commessa al LIMS? Se risulta già nel LIMS verrà solo riallineata, altrimenti ne verrà creata una nuova.')) return;
|
|
|
|
const original = $btn.html();
|
|
$btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i>');
|
|
|
|
$.ajax({
|
|
url: 'export_to_lims.php',
|
|
method: 'POST',
|
|
dataType: 'json',
|
|
data: {
|
|
iddatadb: iddatadb
|
|
},
|
|
success: function(res) {
|
|
if (res && res.success) {
|
|
const $tr = $('tr[data-id="' + iddatadb + '"]');
|
|
$tr.css('background', '#d4edda');
|
|
setTimeout(() => $tr.fadeOut(300, () => $tr.remove()), 500);
|
|
} else {
|
|
alert('Ancora errore: ' + ((res && res.message) ? res.message : 'invio non riuscito'));
|
|
$btn.prop('disabled', false).html(original);
|
|
}
|
|
},
|
|
error: function() {
|
|
alert('Errore di rete durante il reinvio.');
|
|
$btn.prop('disabled', false).html(original);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Revert a Imported (i)
|
|
$(document).on('click', '.revert-btn', function() {
|
|
const $btn = $(this);
|
|
const iddatadb = $btn.data('iddatadb');
|
|
if (!confirm('Riportare questo record a Imported (i)?')) return;
|
|
$.ajax({
|
|
url: 'revert_status.php',
|
|
method: 'POST',
|
|
dataType: 'json',
|
|
data: {
|
|
iddatadb: iddatadb,
|
|
status: 'i'
|
|
},
|
|
success: function(res) {
|
|
if (res && res.success) {
|
|
const $tr = $('tr[data-id="' + iddatadb + '"]');
|
|
$tr.fadeOut(300, () => $tr.remove());
|
|
} else {
|
|
alert('Errore: ' + ((res && res.message) ? res.message : 'operazione non riuscita'));
|
|
}
|
|
},
|
|
error: function() {
|
|
alert('Errore di rete.');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|