fixed stats 2
This commit is contained in:
@@ -109,17 +109,18 @@
|
||||
<div class="col">
|
||||
<div class="card radius-10 stat-card h-100">
|
||||
<div class="card-body">
|
||||
<div class="stat-label">Export mese (status L)</div>
|
||||
<div class="stat-value text-primary" id="kpiExport">0</div>
|
||||
<div class="stat-label">Campioni mese</div>
|
||||
<div class="stat-value text-primary" id="kpiParts">0</div>
|
||||
<small class="text-muted">Commesse: <span id="kpiExport">0</span></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card radius-10 stat-card stat-card-extra h-100">
|
||||
<div class="card-body">
|
||||
<div class="stat-label">Export anno <span id="yearLabel">—</span> (status L)</div>
|
||||
<div class="stat-value text-dark" id="kpiExportYear">0</div>
|
||||
<small class="text-muted">Dati a partire dal 16/07/2026</small>
|
||||
<div class="stat-label">Campioni anno <span id="yearLabel">—</span></div>
|
||||
<div class="stat-value" id="kpiPartsYear">0</div>
|
||||
<small class="text-muted">Commesse: <span id="kpiExportYear">0</span> · dal 16/07/2026</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,7 +155,7 @@
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card radius-10">
|
||||
<div class="card-header">
|
||||
<h6 class="mb-0">Export per cliente (idclient) <small class="text-muted">— top 15</small></h6>
|
||||
<h6 class="mb-0">Campioni per cliente (idclient) <small class="text-muted">— top 15</small></h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-wrap"><canvas id="chartClienti"></canvas></div>
|
||||
@@ -164,7 +165,7 @@
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card radius-10">
|
||||
<div class="card-header">
|
||||
<h6 class="mb-0">Export per utente (user_id) <small class="text-muted">— top 15</small></h6>
|
||||
<h6 class="mb-0">Campioni per utente (user_id) <small class="text-muted">— top 15</small></h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-wrap"><canvas id="chartUtenti"></canvas></div>
|
||||
@@ -187,7 +188,8 @@
|
||||
<tr>
|
||||
<th>ID Cliente</th>
|
||||
<th>Cliente</th>
|
||||
<th>Export</th>
|
||||
<th>Campioni</th>
|
||||
<th>Commesse</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
@@ -208,7 +210,8 @@
|
||||
<tr>
|
||||
<th>ID Utente</th>
|
||||
<th>Utente</th>
|
||||
<th>Export</th>
|
||||
<th>Campioni</th>
|
||||
<th>Commesse</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
@@ -273,6 +276,10 @@
|
||||
data: 'clientname',
|
||||
defaultContent: '—'
|
||||
},
|
||||
{
|
||||
data: 'parts',
|
||||
className: 'text-end'
|
||||
},
|
||||
{
|
||||
data: 'tot',
|
||||
className: 'text-end'
|
||||
@@ -296,6 +303,10 @@
|
||||
data: 'username',
|
||||
defaultContent: '—'
|
||||
},
|
||||
{
|
||||
data: 'parts',
|
||||
className: 'text-end'
|
||||
},
|
||||
{
|
||||
data: 'tot',
|
||||
className: 'text-end'
|
||||
@@ -359,32 +370,35 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// KPI mese
|
||||
$('#kpiExport').text(res.totals.export);
|
||||
// KPI mese — dato principale = campioni/parti, sotto le commesse
|
||||
$('#kpiParts').text(res.totals.parts ?? 0);
|
||||
$('#kpiExport').text(res.totals.export ?? 0);
|
||||
$('#kpiClienti').text(res.byClient.length);
|
||||
$('#kpiLimsSamples').text(res.limsSamples ?? 0);
|
||||
|
||||
const limsTot = parseInt(res.limsSamples ?? 0, 10);
|
||||
const partsTot = parseInt(res.totals.parts ?? 0, 10);
|
||||
if (limsTot > 0) {
|
||||
const perc = (res.totals.export / limsTot) * 100;
|
||||
const perc = (partsTot / limsTot) * 100;
|
||||
$('#kpiPerc').text(perc.toFixed(1) + '%');
|
||||
} else {
|
||||
$('#kpiPerc').text('—');
|
||||
}
|
||||
|
||||
// Box annuale
|
||||
$('#kpiExportYear').text(res.totalsYear.export);
|
||||
// Box annuale — campioni + commesse
|
||||
$('#kpiPartsYear').text(res.totalsYear ? (res.totalsYear.parts ?? 0) : 0);
|
||||
$('#kpiExportYear').text(res.totalsYear ? (res.totalsYear.export ?? 0) : 0);
|
||||
$('#yearLabel').text(res.year);
|
||||
|
||||
// Grafici
|
||||
// Grafici — valori = campioni/parti
|
||||
const clientTop = topN(res.byClient);
|
||||
const userTop = topN(res.byUser);
|
||||
chartClienti = renderBarChart(chartClienti, 'chartClienti',
|
||||
clientTop.map(r => r.clientname ? (r.clientname + ' (' + r.idclient + ')') : ('ID ' + r.idclient)),
|
||||
clientTop.map(r => r.tot), 'Export');
|
||||
clientTop.map(r => r.parts), 'Campioni');
|
||||
chartUtenti = renderBarChart(chartUtenti, 'chartUtenti',
|
||||
userTop.map(r => r.username ? (r.username + ' (' + r.user_id + ')') : ('ID ' + r.user_id)),
|
||||
userTop.map(r => r.tot), 'Export');
|
||||
userTop.map(r => r.parts), 'Campioni');
|
||||
|
||||
// Tabelle
|
||||
dtClienti.clear().rows.add(res.byClient).draw();
|
||||
|
||||
@@ -16,15 +16,18 @@ try {
|
||||
|
||||
$year = $dm->format('Y');
|
||||
|
||||
// --- Export per cliente (status = 'l', giornata su export_date, filtro mese) ---
|
||||
// --- Export per cliente (status = 'l', filtro mese) ---
|
||||
// tot = numero commesse, parts = numero parti/campioni
|
||||
$stmtC = $pdo->prepare("
|
||||
SELECT d.idclient AS idclient,
|
||||
COUNT(*) AS tot
|
||||
COUNT(DISTINCT d.iddatadb) AS tot,
|
||||
COUNT(ip.id) AS parts
|
||||
FROM datadb d
|
||||
LEFT JOIN identification_parts ip ON ip.iddatadb = d.iddatadb
|
||||
WHERE d.status = 'l'
|
||||
AND DATE_FORMAT(d.export_date, '%Y-%m') = :m
|
||||
GROUP BY d.idclient
|
||||
ORDER BY tot DESC
|
||||
ORDER BY parts DESC
|
||||
");
|
||||
$stmtC->execute(['m' => $month]);
|
||||
$byClient = $stmtC->fetchAll(PDO::FETCH_ASSOC);
|
||||
@@ -40,16 +43,19 @@ try {
|
||||
}
|
||||
|
||||
// --- Export per utente (status = 'l', filtro mese) ---
|
||||
// tot = numero commesse, parts = numero parti/campioni
|
||||
$stmtU = $pdo->prepare("
|
||||
SELECT d.user_id AS user_id,
|
||||
TRIM(CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,''))) AS username,
|
||||
COUNT(*) AS tot
|
||||
COUNT(DISTINCT d.iddatadb) AS tot,
|
||||
COUNT(ip.id) AS parts
|
||||
FROM datadb d
|
||||
LEFT JOIN auth_users u ON u.id = d.user_id
|
||||
LEFT JOIN identification_parts ip ON ip.iddatadb = d.iddatadb
|
||||
WHERE d.status = 'l'
|
||||
AND DATE_FORMAT(d.export_date, '%Y-%m') = :m
|
||||
GROUP BY d.user_id, username
|
||||
ORDER BY tot DESC
|
||||
ORDER BY parts DESC
|
||||
");
|
||||
$stmtU->execute(['m' => $month]);
|
||||
$byUser = $stmtU->fetchAll(PDO::FETCH_ASSOC);
|
||||
@@ -58,6 +64,7 @@ try {
|
||||
foreach ($byClient as &$r) {
|
||||
$r['idclient'] = $r['idclient'] !== null ? (int)$r['idclient'] : null;
|
||||
$r['tot'] = (int)$r['tot'];
|
||||
$r['parts'] = (int)$r['parts'];
|
||||
$nm = $clientNames[$r['idclient']] ?? '';
|
||||
$r['clientname'] = $nm !== '' ? $nm : null;
|
||||
}
|
||||
@@ -65,14 +72,26 @@ try {
|
||||
foreach ($byUser as &$r) {
|
||||
$r['user_id'] = $r['user_id'] !== null ? (int)$r['user_id'] : null;
|
||||
$r['tot'] = (int)$r['tot'];
|
||||
$r['parts'] = (int)$r['parts'];
|
||||
if (isset($r['username'])) $r['username'] = $r['username'] !== null && $r['username'] !== '' ? $r['username'] : null;
|
||||
}
|
||||
unset($r);
|
||||
|
||||
// --- Totale export del mese ---
|
||||
// --- Totale COMMESSE del mese ---
|
||||
$totExport = array_sum(array_column($byClient, 'tot'));
|
||||
|
||||
// --- Totale export dell'ANNO del mese selezionato ---
|
||||
// --- Totale PARTI/CAMPIONI del mese (status = 'l') ---
|
||||
$stmtP = $pdo->prepare("
|
||||
SELECT COUNT(*)
|
||||
FROM identification_parts ip
|
||||
INNER JOIN datadb d ON d.iddatadb = ip.iddatadb
|
||||
WHERE d.status = 'l'
|
||||
AND DATE_FORMAT(d.export_date, '%Y-%m') = :m
|
||||
");
|
||||
$stmtP->execute(['m' => $month]);
|
||||
$totParts = (int)$stmtP->fetchColumn();
|
||||
|
||||
// --- Totale COMMESSE dell'ANNO del mese selezionato ---
|
||||
$stmtY = $pdo->prepare("
|
||||
SELECT COUNT(*)
|
||||
FROM datadb d
|
||||
@@ -82,6 +101,17 @@ try {
|
||||
$stmtY->execute(['y' => $year]);
|
||||
$totExportYear = (int)$stmtY->fetchColumn();
|
||||
|
||||
// --- Totale PARTI dell'ANNO del mese selezionato ---
|
||||
$stmtYP = $pdo->prepare("
|
||||
SELECT COUNT(*)
|
||||
FROM identification_parts ip
|
||||
INNER JOIN datadb d ON d.iddatadb = ip.iddatadb
|
||||
WHERE d.status = 'l'
|
||||
AND YEAR(d.export_date) = :y
|
||||
");
|
||||
$stmtYP->execute(['y' => $year]);
|
||||
$totPartsYear = (int)$stmtYP->fetchColumn();
|
||||
|
||||
// --- Campioni LIMS: somma dei total_samples di tutti i giorni del mese ---
|
||||
$stmtL = $pdo->prepare("
|
||||
SELECT COALESCE(SUM(total_samples), 0)
|
||||
@@ -95,8 +125,8 @@ try {
|
||||
'success' => true,
|
||||
'month' => $month,
|
||||
'year' => (int)$year,
|
||||
'totals' => ['export' => (int)$totExport],
|
||||
'totalsYear' => ['export' => $totExportYear],
|
||||
'totals' => ['export' => (int)$totExport, 'parts' => $totParts],
|
||||
'totalsYear' => ['export' => $totExportYear, 'parts' => $totPartsYear],
|
||||
'byClient' => $byClient,
|
||||
'byUser' => $byUser,
|
||||
'limsSamples' => $limsSamples,
|
||||
|
||||
Reference in New Issue
Block a user