update sommario 3

This commit is contained in:
2026-10-16 15:57:25 +02:00
parent 3038d75045
commit c16d604ea2
+79 -45
View File
@@ -254,6 +254,27 @@ function abbonati(PDO $pdo, string $data): int
WHERE iduser IS NOT NULL AND order_date_created <= ? AND expireon >= ?", [$data, $data]);
}
$abbOggi = abbonati($pdo, date('Y-m-d'));
// Numeri di andamento (senza giudizio)
$ultimoAnno = q($pdo, "SELECT COALESCE(SUM(nticket), 0) AS lezioni, COUNT(*) AS ordini
FROM orderbook WHERE order_date_created > DATE_SUB(CURDATE(), INTERVAL 12 MONTH)")[0];
$nuoviAnno = (int) q1($pdo, "SELECT COUNT(*) FROM (SELECT iduser, MIN(order_date_created) AS primo FROM orderbook
WHERE iduser IS NOT NULL GROUP BY iduser) t WHERE t.primo > DATE_SUB(CURDATE(), INTERVAL 12 MONTH)");
$mesiDati = max(1, min(12, (int) ceil((time() - strtotime((string) (q1($pdo, "SELECT MIN(order_date_created) FROM orderbook") ?: date('Y-m-d')))) / (86400 * 30.4))));
$mesiPeriodo = $giorni / 30.4;
// Lezioni ancora da fare nei pacchetti validi oggi = riempimento "già venduto" delle prossime settimane
$portafoglio = (int) q1($pdo, "SELECT COALESCE(SUM(GREATEST(o.nticket - (SELECT COUNT(*) FROM bookingclass bc
WHERE bc.idorder = o.idorderbook AND bc.status NOT IN ('cancelled', 'waiting')
AND bc.bookingstart <= NOW()), 0)), 0)
FROM orderbook o WHERE o.expireon >= CURDATE() AND o.nticket > 0");
$info = [
['fa-ticket-alt', 'Lezioni vendute', n0($A['vendute']), n0($A['ordini']) . ' ordini · media ultimo anno: ' . n0((int) $ultimoAnno['lezioni'] / $mesiDati * $mesiPeriodo) . ' in un periodo così'],
['fa-user-plus', 'Nuovi clienti', n0($A['nuovi']), 'media ultimo anno: ' . number_format($nuoviAnno / $mesiDati, 1, ',', '.') . ' al mese'],
['fa-users', 'Persone in sala', n0($A['persone']), 'almeno una lezione frequentata nel periodo'],
['fa-layer-group', 'Lezioni già vendute da fare', n0($portafoglio), 'nei pacchetti validi oggi: è il riempimento delle prossime settimane'],
];
$abbPrima = $haAnnoPrima ? abbonati($pdo, date('Y-m-d', strtotime('-1 year'))) : abbonati($pdo, substr($d1, 0, 10));
// --- Certificati (situazione di oggi)
@@ -333,50 +354,14 @@ $add(
'con un pacchetto valido oggi'
);
// 3. Lezioni vendute
$add(
'Lezioni vendute',
'fa-ticket-alt',
n0($A['vendute']),
$trendStato($A['vendute'], $Y['vendute']),
$conf($A['vendute'], $Y['vendute'], '', false, $etichettaY),
[
'Le vendite tengono o crescono rispetto al ' . $etichettaY . '.',
'Vendite in calo: una comunicazione o un\'offerta a chi ha il pacchetto in scadenza può aiutare.',
'Vendite in forte calo: serve un\'azione commerciale (promozione, evento, newsletter).',
],
n0($A['ordini']) . ' ordini da ' . n0($A['clienti']) . ' clienti'
);
// 3. Nuovi clienti
$add(
'Nuovi clienti',
'fa-user-plus',
n0($A['nuovi']),
$trendStato($A['nuovi'], $Y['nuovi']),
$conf($A['nuovi'], $Y['nuovi'], '', false, $etichettaY),
[
'Arrivano persone nuove: la scuola si fa conoscere.',
'Meno nuovi ingressi del solito: spingi lezioni di prova e passaparola.',
'Pochi nuovi clienti: punta su prova gratuita, social ed eventi aperti.',
],
'primo acquisto nel periodo'
);
// 4. Persone attive
$add(
'Persone che praticano',
'fa-users',
n0($A['persone']),
$trendStato($A['persone'], $Y['persone']),
$conf($A['persone'], $Y['persone'], '', false, $etichettaY),
[
'La comunità che pratica è stabile o in crescita.',
'Meno persone in sala rispetto al ' . $etichettaY . ': contatta chi non viene da un po\'.',
'Calo forte di persone attive: verifica abbandoni e pacchetti non rinnovati.',
],
'almeno una lezione frequentata'
);
/*
* Vendite, nuovi clienti e persone in sala NON hanno il semaforo:
* con pacchetti da 12 lezioni (circa 3 mesi) chi compra non riordina per mesi,
* quindi le vendite di un periodo salgono e scendono a ondate anche se la scuola va bene,
* e in un bacino di paese i nuovi clienti sono pochi per natura.
* Li mostriamo come numeri di andamento (con la media mensile dell'ultimo anno come riferimento).
* Lo stato di salute lo danno "Abbonati attivi" e "Clienti che rinnovano".
*/
// 5. Riacquisto
$add(
@@ -919,6 +904,38 @@ $prevTxt = $inizioP->format('d/m/Y') . ' – ' . (clone $inizio)->modify('-1
color: var(--ink);
}
.sm-info-head {
font-size: 15px;
font-weight: 800;
color: #1f2937;
margin: 4px 0 12px;
}
.sm-info-head small {
display: block;
font-weight: 400;
font-size: 12px;
color: var(--muted);
margin-top: 2px;
}
.sm-info {
padding: 14px 16px;
display: flex;
gap: 12px;
height: 100%;
--c: #2980b9;
--bg: #e8f1fa;
}
.sm-info .sm-ind-val {
font-size: 22px;
}
.sm-info .sm-ind-det {
margin-top: 2px;
}
.sm-foot {
font-size: 12px;
color: var(--muted);
@@ -1042,6 +1059,23 @@ $prevTxt = $inizioP->format('d/m/Y') . ' – ' . (clone $inizio)->modify('-1
</div>
</div>
<!-- Numeri di andamento: senza semaforo -->
<div class="sm-info-head"><i class="fas fa-chart-line me-1"></i> Andamento del periodo <small>numeri da leggere, senza giudizio: con pacchetti lunghi e un bacino di paese le vendite vanno a ondate</small></div>
<div class="row g-3 mb-4">
<?php foreach ($info as [$ic, $tit, $val, $sub]) : ?>
<div class="col-6 col-lg-3">
<div class="sm-card sm-info">
<div class="sm-ind-ico"><i class="fas <?php echo $ic; ?>"></i></div>
<div>
<div class="sm-ind-title"><?php echo e($tit); ?></div>
<div class="sm-ind-val"><?php echo e($val); ?></div>
<div class="sm-ind-det"><?php echo e($sub); ?></div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<!-- Indicatori raggruppati per semaforo -->
<div class="row">
<?php foreach ($gruppi as $stato => [$titolo, $icona]) :
@@ -1103,7 +1137,7 @@ $prevTxt = $inizioP->format('d/m/Y') . ' – ' . (clone $inizio)->modify('-1
<?php endif; ?>
<div class="sm-foot">
Il riempimento e le lezioni perse considerano solo le lezioni già svolte. Vendite e nuovi clienti sono per data dell'ordine.
Il riempimento e le lezioni perse considerano solo le lezioni già svolte. I rinnovi vengono valutati solo a pacchetto finito.
Per tutti i dettagli apri le <a href="statistiche.php">Statistiche</a>.
</div>
</div>