From b52e7191cf0dd94ca16de0d05fb23116d5f0a097 Mon Sep 17 00:00:00 2001 From: solocla Date: Thu, 15 Oct 2026 12:03:40 +0200 Subject: [PATCH] added tips to statistics --- public/userarea/sales_customer.php | 25 +- public/userarea/sales_help.js | 472 ++++++++++++++++++++ public/userarea/sales_orders_deliveries.php | 23 +- public/userarea/sales_orders_stats.php | 34 +- public/userarea/sales_orders_years.php | 54 ++- 5 files changed, 549 insertions(+), 59 deletions(-) create mode 100644 public/userarea/sales_help.js diff --git a/public/userarea/sales_customer.php b/public/userarea/sales_customer.php index 7eb608d8..823e8538 100644 --- a/public/userarea/sales_customer.php +++ b/public/userarea/sales_customer.php @@ -1204,6 +1204,7 @@ if ($action === 'data') { Consegne + @@ -1230,14 +1231,14 @@ if ($action === 'data') {
-
Ordinato e fatturato per anno
+
Ordinato e fatturato per anno
Anno in corso: valori ad oggi
-
Ultimi 24 mesi
+
Ultimi 24 mesi
Ordinato per data ordine, fatturato per data fattura
@@ -1251,6 +1252,7 @@ if ($action === 'data') { +
@@ -1527,7 +1529,7 @@ if ($action === 'data') { $('#profile').html(`
${esc(initials || '?')}
-
${esc(i.name)} ${LVL[lvl]}
+
${esc(i.name)} ${LVL[lvl]}
${esc(i.code)}${place ? ' · ' + esc(place) : ''}
${facts.join('')}
@@ -1549,22 +1551,22 @@ if ($action === 'data') { month: 'short' }); - const ytdCard = (title, icon, color, rows) => { + const ytdCard = (title, icon, color, rows, help) => { const c = yearRow(rows, CUR_Y), p = yearRow(rows, CUR_Y - 1); const v = c ? +c.ytd : 0, pv = p ? +p.ytd : 0; return `
-
${title} ${CUR_Y}
+
${title} ${CUR_Y}
${fmtEurShort(v)}
al ${label} · ${CUR_Y - 1} stessa data: ${fmtEurShort(pv)} ${deltaSpan(pct(v, pv), '')}
${CUR_Y - 1} intero: ${fmtEurShort(p ? +p.full : 0)}
`; }; - out.push(invOk ? ytdCard('Fatturato', 'fa-file-invoice-dollar', '#0f766e', d.inv.years) : - `
Fatturato
—
serve la sincronizzazione delle fatture
`); - out.push(ytdCard('Ordinato', 'fa-chart-line', '#6f42c1', d.ordYears)); + out.push(invOk ? ytdCard('Fatturato', 'fa-file-invoice-dollar', '#0f766e', d.inv.years, 'sc.inv') : + `
Fatturato
—
serve la sincronizzazione delle fatture
`); + out.push(ytdCard('Ordinato', 'fa-chart-line', '#6f42c1', d.ordYears, 'sc.ord')); const open = d.open || []; const ov = open.reduce((a, r) => a + (+r.residual_value || 0), 0); @@ -1572,7 +1574,7 @@ if ($action === 'data') { const lv = late.reduce((a, r) => a + (+r.residual_value || 0), 0); out.push(`
-
Da consegnare
+
Da consegnare
${fmtEurShort(ov)}
${fmtNum(open.length)} righe · ${fmtNum(new Set(open.map(r => r.sale_ord_id)).size)} ordini${late.length ? `
${fmtNum(late.length)} righe in ritardo · ${fmtEurShort(lv)}` : '
nessuna riga in ritardo'}
`); @@ -1581,12 +1583,12 @@ if ($action === 'data') { const p = d.inv.v12 > 0 ? d.inv.cn12 / d.inv.v12 * 100 : 0; out.push(`
-
Note di credito · 12 mesi
+
Note di credito · 12 mesi
${fmtEurShort(d.inv.cn12)}
${fmtNum(d.inv.cn12_n)} note · ${p.toLocaleString('it-IT', {maximumFractionDigits: 1})}% del fatturato
fatturato 12 mesi: ${fmtEurShort(d.inv.v12)}
`); } else { - out.push(`
Note di credito
—
serve la sincronizzazione delle fatture
`); + out.push(`
Note di credito
—
serve la sincronizzazione delle fatture
`); } $('#kpis').html(out.join('')); } @@ -1923,6 +1925,7 @@ if ($action === 'data') { }); })(); + \ No newline at end of file diff --git a/public/userarea/sales_help.js b/public/userarea/sales_help.js new file mode 100644 index 00000000..93843fe9 --- /dev/null +++ b/public/userarea/sales_help.js @@ -0,0 +1,472 @@ +/** + * sales_help.js - Guida contestuale delle pagine statistiche vendite. + * + * Uso nelle pagine: + *
...
→ aggiunge l'icona ⓘ in fondo all'elemento + * → apre la guida al click (guida di pagina) + * + * I testi sono tutti qui sotto (SALES_HELP): per cambiarli basta modificare questo file. + * Funziona anche sugli elementi creati dopo (box disegnati via JavaScript). + */ +(function () { + "use strict"; + + const SALES_HELP = { + /* ===================== GUIDE DI PAGINA ===================== */ + "page.stats": { + t: "Andamento ordini: come si usa", + b: `

Qui vedi gli ordini clienti del periodo scelto: quanti sono, quanto valgono, a che punto sono.

+
    +
  • In alto scegli il periodo (mese, trimestre, anno…) e se vuoi cliente, agente, area o stato.
  • +
  • I box colorati sono cliccabili: filtrano tutta la pagina (es. clic su In ritardo = solo ordini in ritardo).
  • +
  • I grafici sono cliccabili: un mese, una fetta, un cliente diventano un filtro.
  • +
  • L'elenco in fondo: clic su una riga per il dettaglio dell'ordine con le sue righe; si esporta in Excel.
  • +
  • Il selettore N° ordini / Valore cambia cosa misurano i grafici.
  • +
+

Gli ordini con la parola "listino" sono esclusi. I filtri restano memorizzati quando torni sulla pagina; la gomma 🧽 li azzera.

`, + }, + "page.years": { + t: "Confronto anni: come si usa", + b: `

Qui confronti gli anni tra loro e vedi la situazione ad oggi.

+
    +
  • Situazione ad oggi (in alto): portafoglio, book-to-bill e previsioni. Non dipende dagli anni scelti.
  • +
  • Chip degli anni: scegli quali anni confrontare (ognuno ha il suo colore in tutti i grafici).
  • +
  • A pari data: acceso, ogni anno è contato solo fino al giorno di oggi → confronto giusto con l'anno in corso. Spento: anni interi.
  • +
  • Clienti da richiamare e Clienti a confronto: clic su un cliente per filtrare tutta la pagina; l'icona verde apre la sua scheda.
  • +
+

Cliente, agente e area filtrano tutto, anche il fatturato.

`, + }, + "page.deliveries": { + t: "Consegne: come si usa", + b: `

Qui vedi le righe d'ordine ancora da consegnare, cioè il lavoro da spedire.

+
    +
  • Data ZIBO (rossa quando scaduta) = la settimana di consegna che abbiamo comunicato: è la scadenza che conta. La riga è in ritardo solo quando quella settimana è finita; durante la settimana compare IN SETTIMANA.
  • +
  • Data cliente (arancione quando superata) = quando il cliente l'avrebbe voluta: è un riferimento.
  • +
  • Scadenza (chip in alto), box e grafici filtrano le righe; si combinano con cliente, articolo, agente, area.
  • +
+

Cosa fare: parti dalle scadute, poi guarda i prossimi giorni e le settimane più cariche del grafico.

`, + }, + "page.customer": { + t: "Scheda cliente: come si usa", + b: `

Tutto su un cliente in una pagina. Cercalo per nome o codice, oppure clicca l'icona verde accanto a un cliente nelle altre pagine.

+
    +
  • Profilo: da quando è cliente, ultimo ordine, ogni quanto ordina di solito e il suo stato (attivo, attenzione, dormiente…).
  • +
  • Box: quest'anno rispetto allo scorso, cosa gli dobbiamo consegnare, note di credito.
  • +
  • Tabelle in fondo: righe da consegnare, ordini, articoli, fatture. Tutte esportabili in Excel.
  • +
+

Utile prima di una telefonata o di una visita. I clienti visti di recente restano a portata di clic.

`, + }, + + /* ===================== ANDAMENTO ORDINI ===================== */ + "st.orders": { + t: "Ordini", + b: `

Numero di ordini del periodo e dei filtri scelti. Sotto: confronto con lo stesso periodo dell'anno prima.

+

Clic sul box: toglie il filtro di stato e mostra tutti gli ordini.

`, + }, + "st.value": { + t: "Valore ordinato", + b: `

Somma dell'imponibile degli ordini del periodo (annullati esclusi), con il confronto con lo stesso periodo dell'anno prima.

`, + }, + "st.toship": { + t: "Da evadere", + b: `

Valore degli ordini ancora aperti (non consegnati del tutto). In rosso la parte già in ritardo.

+

Cosa fare: se la quota in ritardo cresce, guarda la pagina Consegne.

`, + }, + "st.open": { + t: "Aperti", + b: `

Ordini non ancora consegnati del tutto e non annullati. Clic per vederli.

`, + }, + "st.late": { + t: "In ritardo", + b: `

Ordini con almeno una riga aperta oltre la data ZIBO (la settimana comunicata è finita).

+
    +
  • Righe in ritardo: quante righe sono scadute; parziali = ordini dove è in ritardo solo una parte delle righe.
  • +
  • Oltre data cliente (arancione): superata la data desiderata dal cliente, ma non ancora la nostra.
  • +
  • Striscia gialla in consegna questa settimana: ordini con righe da consegnare entro domenica, non ancora in ritardo. Cliccala per vederli.
  • +
+

Cosa fare: clic sul box per la lista, poi apri gli ordini per vedere quali righe mancano.

`, + }, + "st.done": { + t: "Evasi", + b: `

Ordini completamente consegnati nel periodo scelto (per data ordine).

`, + }, + "st.toinvoice": { + t: "Da fatturare", + b: `

Ordini consegnati ma non ancora fatturati.

+

Cosa fare: segnalali all'amministrazione se restano qui a lungo.

`, + }, + "st.customers": { + t: "Clienti attivi", + b: `

Quanti clienti diversi hanno ordinato nel periodo. Sotto: in media dopo quanti giorni dall'ordine è prevista la consegna.

`, + }, + "st.monthly": { + t: "Andamento mensile", + b: `

Ordini (o valore) mese per mese nel periodo scelto. Clic su un mese per filtrare solo quel mese.

`, + }, + "st.status": { + t: "Ripartizione per stato", + b: `

Come si dividono gli ordini: aperti, evasi, bloccati, annullati. Clic su una fetta per filtrare.

`, + }, + "st.topcust": { + t: "Top 10 clienti", + b: `

I 10 clienti più importanti del periodo (per numero ordini o valore). Le barre sono divise tra ordini aperti e altri (evasi/annullati).

+

Clic su un cliente per vedere solo i suoi ordini.

`, + }, + "st.due": { + t: "Scadenze ordini aperti", + b: `

Gli ordini aperti divisi per quando vanno consegnati: già scaduti, questa settimana, la prossima, entro 30 giorni, oltre, senza data.

`, + }, + "st.items": { + t: "Top 10 articoli", + b: `

Gli articoli più ordinati nel periodo, calcolati dalle righe d'ordine. Passa sopra una barra per quantità e valore.

`, + }, + "st.area": { + t: "Per area", + b: `

Ordini (o valore) divisi per area commerciale.

`, + }, + "st.agent": { + t: "Per agente", + b: `

Ordini (o valore) divisi per agente.

`, + }, + "st.list": { + t: "Elenco ordini", + b: `

Tutti gli ordini dei filtri scelti. Clic su una riga per il dettaglio con le righe, le date e cosa resta da consegnare.

+
    +
  • IN RITARDO data ZIBO superata · PARZIALE solo alcune righe in ritardo · OLTRE DATA CLIENTE superata solo la data del cliente.
  • +
  • Il pulsante Excel scarica l'elenco come lo vedi.
  • +
`, + }, + + /* ===================== CONFRONTO ANNI ===================== */ + "yr.dash": { + t: "Situazione ad oggi", + b: `

Una fotografia di oggi, che non cambia con gli anni scelti. Segue solo i filtri cliente, agente e area (così puoi vederla anche per un agente o un cliente).

`, + }, + "yr.backlog": { + t: "Portafoglio da consegnare", + b: `

Valore di tutte le righe d'ordine ancora da consegnare.

+
    +
  • Settimane: per quante settimane di lavoro basta, al ritmo medio di fatturato degli ultimi 3 mesi.
  • +
  • In rosso la parte già oltre la data ZIBO.
  • +
+

Poche settimane = servono ordini nuovi. Tante settimane con molto in ritardo = c'è un problema di capacità o di consegne.

`, + }, + "yr.b2b": { + t: "Book-to-bill", + b: `

Confronta il lavoro che entra (ordini) con quello che esce (fatture) negli ultimi 90 giorni.

+
    +
  • 1,0 = equilibrio.
  • +
  • Sopra 1 (es. 1,20 → per ogni 100 € fatturati entrano 120 € di ordini): il portafoglio cresce 🟢
  • +
  • Sotto 1 (es. 0,80): stiamo consumando il portafoglio, tra qualche mese il fatturato rischia di calare 🔴
  • +
+

È un segnale che arriva prima del calo di fatturato.

`, + }, + "yr.fcInv": { + t: "Previsione fatturato", + b: `

Stima di come chiuderà l'anno. Si prende il fatturato ad oggi e lo si proietta con la stagionalità degli ultimi 3 anni (es. se negli anni scorsi a questa data eravamo al 78% dell'anno, oggi siamo probabilmente al 78%).

+

La forbice va dall'anno più favorevole a quello meno favorevole. Diventa più precisa man mano che l'anno avanza.

`, + }, + "yr.fcOrd": { + t: "Previsione ordinato", + b: `

Come la previsione del fatturato, ma sugli ordini ricevuti: quanto ordinato porteremo a casa entro fine anno se si continua così.

`, + }, + "yr.b2bchart": { + t: "Ordinato vs fatturato · 24 mesi", + b: `

Barre viola = ordini ricevuti nel mese · barre verdi = fatturato del mese.

+

La linea arancione è il book-to-bill su 3 mesi: sopra la riga tratteggiata dell'1 il portafoglio cresce, sotto si consuma.

+

Se la linea resta sotto 1 per diversi mesi, è il momento di spingere sugli ordini.

`, + }, + "yr.cards": { + t: "Anni a confronto", + b: `

Una carta per ogni anno scelto: valore ordinato (numero grande), numero ordini, ordine medio, clienti, fatturato e variazione rispetto all'anno prima.

+

Con A pari data acceso ogni anno è contato fino a oggi: il confronto con l'anno in corso è corretto.

`, + }, + "yr.monthly": { + t: "Ordinato per mese", + b: `

Una linea per anno, mese per mese: mostra la stagionalità e in quali mesi quest'anno va meglio o peggio.

`, + }, + "yr.cumul": { + t: "Progressivo dell'anno", + b: `

Somma da gennaio a ogni mese. Se la linea dell'anno in corso è sopra quelle degli anni scorsi, siamo avanti; se è sotto, siamo indietro.

`, + }, + "yr.invMonthly": { + t: "Fatturato per mese", + b: `

Fatturato vero per data della fattura: fatture + fatture d'acconto − note di credito (imponibile).

+

È sempre in €, anche se in alto è selezionato "N° ordini".

`, + }, + "yr.invCumul": { + t: "Fatturato progressivo", + b: `

Fatturato sommato da gennaio, anno su anno: dice se stiamo fatturando più o meno degli anni scorsi alla stessa data.

`, + }, + "yr.invTable": { + t: "Tabella dati fatturato", + b: `

Gli stessi numeri dei grafici in tabella: per mese (con progressivo e variazione) oppure l'elenco delle fatture e note di credito.

+

Pulsante Excel per scaricarli: il titolo del file riporta i filtri usati.

`, + }, + "yr.dormant": { + t: "Clienti da richiamare", + b: `

Clienti che ordinavano con regolarità (almeno 4 volte negli ultimi 3 anni) e che ora tardano rispetto al loro solito.

+
    +
  • Ritmo abituale: ogni quanti giorni ordina di solito.
  • +
  • Ritardo: giorni dall'ultimo ordine ÷ ritmo. Es. ordina ogni 30 giorni e sono passati 60 → 2×.
  • +
  • Attenzione da 1,5× · Dormiente da 2× · Probabilmente perso da 4× o oltre un anno.
  • +
  • In cima quelli che valgono di più (ordinato dei 12 mesi prima dell'ultimo ordine).
  • +
+

Cosa fare: chiamare partendo dall'alto. Esporta in Excel per dividerli tra i commerciali.

`, + }, + "yr.custcmp": { + t: "Clienti a confronto", + b: `

Ogni cliente con il suo valore (o numero ordini) negli anni scelti e la variazione tra gli ultimi due.

+
    +
  • Nuovi: non c'erano l'anno prima · Persi: non ci sono quest'anno.
  • +
  • In crescita / in calo: oltre ±10%.
  • +
+

Clic su un cliente per filtrare la pagina; l'icona verde apre la sua scheda.

`, + }, + "yr.ytd": { + t: "A pari data", + b: `

Acceso: ogni anno è contato solo fino al giorno di oggi (es. 1 gennaio – 15 ottobre). È il modo giusto per confrontare l'anno in corso con i precedenti.

+

Spento: anni interi (l'anno in corso sembrerà sempre più basso finché non finisce).

`, + }, + + /* ===================== CONSEGNE ===================== */ + "dl.horizon": { + t: "Scadenza", + b: `

Filtra le righe per quando vanno consegnate: scadute (data ZIBO o data cliente), questa settimana, la prossima, entro 30 giorni, senza data.

`, + }, + "dl.total": { + t: "Da consegnare", + b: `

Tutte le righe ancora da consegnare (con i filtri scelti) e il loro valore residuo (solo la parte non ancora consegnata).

`, + }, + "dl.lateZibo": { + t: "Scadute (data ZIBO)", + b: `

Righe la cui settimana ZIBO è finita senza consegna: sono i ritardi veri verso il cliente.

+

Cosa fare: sono la priorità. Clic sul box per vederle tutte.

`, + }, + "dl.lateClient": { + t: "Oltre data cliente", + b: `

Righe dove è superata la data desiderata dal cliente. Non sono necessariamente in ritardo per noi, ma il cliente potrebbe sollecitare.

`, + }, + "dl.next7": { + t: "Prossimi 7 giorni", + b: `

Righe da consegnare da oggi ai prossimi 7 giorni. Clic per vederle.

`, + }, + "dl.nodate": { + t: "Senza data", + b: `

Righe senza nessuna data di consegna in Mago.

+

Cosa fare: vanno completate in Mago, altrimenti non si possono pianificare.

`, + }, + "dl.weekly": { + t: "Carico consegne per settimana", + b: `

Quanto c'è da consegnare settimana per settimana (per data ZIBO; se manca, data cliente). La prima barra rossa raccoglie tutto lo scaduto.

+

Serve a vedere le settimane troppo cariche. Clic su una barra per filtrare quella settimana.

`, + }, + "dl.lateCust": { + t: "Clienti con più ritardo", + b: `

I clienti con più valore scaduto (data ZIBO superata). Clic per vedere solo le loro righe.

+

Utile per sapere chi avvisare per primo.

`, + }, + "dl.rows": { + t: "Righe da consegnare", + b: `

Ogni riga: ordine, cliente, articolo, quantità ancora da consegnare, valore e date.

+
    +
  • ZIBO sett. = settimana comunicata: rossa quando è finita, IN SETTIMANA mentre è in corso.
  • +
  • Cliente = data desiderata dal cliente (arancione se superata).
  • +
+

Pulsante Excel per scaricare l'elenco filtrato.

`, + }, + + /* ===================== SCHEDA CLIENTE ===================== */ + "sc.status": { + t: "Stato del cliente", + b: `

Calcolato sul suo ritmo d'ordine degli ultimi 3 anni:

+
    +
  • Cliente attivo ordina con il suo ritmo normale.
  • +
  • Attenzione sta tardando (1,5 volte il suo solito).
  • +
  • Dormiente 2 volte il suo solito: da chiamare.
  • +
  • Probabilmente perso 4 volte o più di un anno senza ordini.
  • +
  • Ordini occasionali troppo pochi ordini per stimare un ritmo.
  • +
`, + }, + "sc.inv": { + t: "Fatturato dell'anno", + b: `

Fatturato del cliente da gennaio ad oggi, confrontato con lo stesso periodo dell'anno scorso. Sotto: l'anno scorso intero.

`, + }, + "sc.ord": { + t: "Ordinato dell'anno", + b: `

Ordini ricevuti dal cliente da gennaio ad oggi, confrontati con lo stesso periodo dell'anno scorso.

+

Ordinato in calo e fatturato ancora alto = il fatturato calerà nei prossimi mesi.

`, + }, + "sc.open": { + t: "Da consegnare", + b: `

Valore di quello che gli dobbiamo ancora consegnare e quante righe sono in ritardo (data ZIBO superata).

+

Prima di chiamarlo, guarda la scheda "Da consegnare" qui sotto.

`, + }, + "sc.cn": { + t: "Note di credito", + b: `

Note di credito degli ultimi 12 mesi e quanto pesano sul fatturato. Diventa rosso dal 3%.

+

Una percentuale alta indica resi, contestazioni o problemi di qualità ricorrenti.

`, + }, + "sc.years": { + t: "Ordinato e fatturato per anno", + b: `

Come è cresciuto (o calato) il cliente negli anni. L'anno in corso è ad oggi, quindi più basso finché l'anno non finisce.

`, + }, + "sc.months": { + t: "Ultimi 24 mesi", + b: `

Ordini (viola) e fatture (verde) mese per mese: mostra se il cliente ordina con regolarità o a picchi, e se si sta fermando.

`, + }, + "sc.tables": { + t: "Le tabelle", + b: `
    +
  • Da consegnare: righe aperte con quantità mancante e date (ZIBO e cliente). Righe molto vecchie spesso sono da chiudere in Mago.
  • +
  • Ordini: gli ordini del cliente; clic sul numero per aprirlo.
  • +
  • Articoli: cosa compra, quanto, e il prezzo medio degli ultimi 12 mesi rispetto ai 12 precedenti: utile per verificare gli aumenti di listino.
  • +
  • Fatture: fatture, acconti e note di credito degli ultimi 3 anni.
  • +
+

Ogni tabella ha il suo pulsante Excel.

`, + }, + }; + + /* ===================== STILE ===================== */ + const CSS = ` + .sh-btn{border:0;background:transparent;color:#94a3b8;padding:0 3px;margin-left:4px;font-size:.92em;line-height:1;cursor:pointer;vertical-align:baseline;text-transform:none;letter-spacing:0} + .sh-btn:hover,.sh-btn.open{color:#198754} + .sh-page{border:1px solid #d1fae5;background:#f0fdf4;color:#166534;border-radius:999px;padding:6px 14px;font-weight:700;font-size:.88rem;cursor:pointer;white-space:nowrap} + .sh-page:hover{background:#dcfce7} + .sh-pop{position:absolute;z-index:2000;width:340px;max-width:calc(100vw - 24px);background:#fff;border:1px solid #e2e8f0;border-radius:14px; + box-shadow:0 18px 40px rgba(15,23,42,.18);padding:14px 16px 12px;font-size:.9rem;color:#1f2d3d;line-height:1.45;text-transform:none;letter-spacing:0;font-weight:400} + .sh-pop.wide{width:460px} + .sh-pop h6{font-weight:800;font-size:.98rem;margin:0 26px 8px 0;display:flex;align-items:center;gap:8px} + .sh-pop h6 i{color:#198754} + .sh-pop p{margin:0 0 8px} + .sh-pop ul{margin:0 0 8px;padding-left:18px} + .sh-pop li{margin-bottom:4px} + .sh-pop .sh-note{background:#f0fdf4;border-left:3px solid #22c55e;padding:6px 10px;border-radius:6px;color:#14532d;margin:8px 0 0} + .sh-pop .sh-x{position:absolute;right:8px;top:8px;border:0;background:transparent;color:#94a3b8;font-size:1.1rem;cursor:pointer;line-height:1;padding:4px} + .sh-pop .sh-x:hover{color:#1f2d3d} + .sh-chip{display:inline-block;font-size:.72rem;font-weight:800;border-radius:999px;padding:1px 8px;white-space:nowrap} + .sh-red{background:#fee2e2;color:#991b1b}.sh-orange{background:#ffedd5;color:#9a3412}.sh-amber{background:#fef3c7;color:#b45309} + .sh-yellow{background:#fef9c3;color:#854d0e}.sh-green{background:#dcfce7;color:#166534}.sh-grey{background:#e2e8f0;color:#334155}`; + + function injectCss() { + if (document.getElementById("sales-help-css")) return; + const st = document.createElement("style"); + st.id = "sales-help-css"; + st.textContent = CSS; + document.head.appendChild(st); + } + + /* ===================== POPOVER ===================== */ + let pop = null, + popBtn = null; + + function close() { + if (pop) pop.remove(); + if (popBtn) popBtn.classList.remove("open"); + pop = null; + popBtn = null; + } + + function open(btn, key, wide) { + const h = SALES_HELP[key]; + if (!h) return; + if (popBtn === btn) { + close(); + return; + } + close(); + pop = document.createElement("div"); + pop.className = "sh-pop" + (wide ? " wide" : ""); + pop.setAttribute("role", "dialog"); + pop.innerHTML = ` +
${h.t}
${h.b}`; + document.body.appendChild(pop); + popBtn = btn; + btn.classList.add("open"); + + // posizione: sotto l'icona, dentro lo schermo + const r = btn.getBoundingClientRect(); + const pw = pop.offsetWidth, + ph = pop.offsetHeight; + let left = r.left + window.scrollX - 12; + left = Math.max( + window.scrollX + 12, + Math.min( + left, + window.scrollX + document.documentElement.clientWidth - pw - 12, + ), + ); + let top = r.bottom + window.scrollY + 8; + if (r.bottom + ph + 16 > window.innerHeight && r.top - ph - 8 > 0) + top = r.top + window.scrollY - ph - 8; + pop.style.left = left + "px"; + pop.style.top = top + "px"; + pop.querySelector(".sh-x").addEventListener("click", close); + } + + /* ===================== ICONE ⓘ ===================== */ + function decorate(root) { + // controllo il figlio (non un attributo): se la pagina riscrive il titolo con .text() l'icona viene rimessa + (root || document).querySelectorAll("[data-help]").forEach((el) => { + if (el.querySelector(":scope > .sh-btn")) return; + const b = document.createElement("button"); + b.type = "button"; + b.className = "sh-btn"; + b.title = "Cosa vedo qui?"; + b.setAttribute("aria-label", "Aiuto"); + b.dataset.k = el.getAttribute("data-help"); + b.innerHTML = ''; + el.appendChild(b); + }); + } + + document.addEventListener( + "click", + function (e) { + const b = e.target.closest(".sh-btn"); + if (b) { + // non far scattare il click del box/riga (filtri, ordinamento...) + e.preventDefault(); + e.stopPropagation(); + open(b, b.dataset.k, false); + return; + } + const p = e.target.closest("[data-help-open]"); + if (p) { + e.preventDefault(); + open(p, p.getAttribute("data-help-open"), true); + return; + } + if (pop && !e.target.closest(".sh-pop")) close(); + }, + true, + ); + + document.addEventListener("keydown", (e) => { + if (e.key === "Escape") close(); + }); + window.addEventListener("resize", close); + + function start() { + injectCss(); + decorate(document); + // elementi disegnati dopo dal JavaScript della pagina + new MutationObserver((muts) => { + for (const m of muts) { + if (m.addedNodes.length) { + decorate(document); + break; + } + } + }).observe(document.body, { + childList: true, + subtree: true, + }); + } + + if (document.readyState === "loading") + document.addEventListener("DOMContentLoaded", start); + else start(); + + window.SALES_HELP = SALES_HELP; +})(); diff --git a/public/userarea/sales_orders_deliveries.php b/public/userarea/sales_orders_deliveries.php index e6b11d67..680eb2c7 100644 --- a/public/userarea/sales_orders_deliveries.php +++ b/public/userarea/sales_orders_deliveries.php @@ -49,6 +49,7 @@ function deliveriesWhere() 'late_client' => 'r.client_date < CURDATE()', 'week' => 'r.due_date >= CURDATE() AND YEARWEEK(r.due_date, 3) = YEARWEEK(CURDATE(), 3)', 'next_week' => 'YEARWEEK(r.due_date, 3) = YEARWEEK(CURDATE() + INTERVAL 7 DAY, 3)', + '7d' => 'r.due_date >= CURDATE() AND r.due_date <= CURDATE() + INTERVAL 7 DAY', '30d' => 'r.due_date >= CURDATE() AND r.due_date <= CURDATE() + INTERVAL 30 DAY', 'nodate' => 'r.due_date IS NULL', ]; @@ -634,13 +635,14 @@ if ($action === 'data') { Scheda cliente Consegne +
- Scadenza + Scadenza
@@ -690,31 +692,31 @@ if ($action === 'data') {
-
Da consegnare
+
Da consegnare
—
 
-
Scadute (data ZIBO)
+
Scadute (data ZIBO)
—
 
-
Oltre data cliente
+
Oltre data cliente
—
 
-
+
-
Prossimi 7 giorni
+
Prossimi 7 giorni
—
 
-
Senza data
+
Senza data
—
righe senza data di consegna
@@ -726,7 +728,7 @@ if ($action === 'data') {
-
Carico consegne per settimana
+
Carico consegne per settimana
Per data ZIBO (se manca: data cliente) · clicca una barra per filtrare
@@ -739,7 +741,7 @@ if ($action === 'data') {
-
Clienti con più ritardo
+
Clienti con più ritardo
Valore residuo scaduto (data ZIBO) · clicca per filtrare
@@ -749,7 +751,7 @@ if ($action === 'data') {
-
Righe da consegnare
+
Righe da consegnare
Ordinate per scadenza
@@ -1297,6 +1299,7 @@ if ($action === 'data') { }); })(); + \ No newline at end of file diff --git a/public/userarea/sales_orders_stats.php b/public/userarea/sales_orders_stats.php index 2cd2eb33..e7327442 100644 --- a/public/userarea/sales_orders_stats.php +++ b/public/userarea/sales_orders_stats.php @@ -938,6 +938,7 @@ if ($action === 'order') { Consegne +
@@ -1019,50 +1020,50 @@ if ($action === 'order') {
-
Ordini
+
Ordini
—
 
-
Valore ordinato
+
Valore ordinato
—
 
-
Da evadere
+
Da evadere
—
 
-
Aperti
+
Aperti
—
 
-
In ritardo
+
In ritardo
—
data ZIBO superata
 
-
Evasi
+
Evasi
—
 
-
Da fatturare
+
Da fatturare
—
evasi non fatturati
-
Clienti attivi
+
Clienti attivi
—
 
@@ -1084,7 +1085,7 @@ if ($action === 'order') {
-
Andamento mensile ordini
+
Andamento mensile ordini
Clicca un mese per filtrarlo
@@ -1093,7 +1094,7 @@ if ($action === 'order') {
-
Ripartizione per stato
+
Ripartizione per stato
Clicca una fetta per filtrare
@@ -1103,14 +1104,14 @@ if ($action === 'order') {
-
Top 10 clienti per numero ordini
+
Top 10 clienti per numero ordini
Clicca un cliente per vedere solo i suoi ordini
-
Scadenze ordini aperti
+
Scadenze ordini aperti
In base alla data di consegna prevista
@@ -1120,7 +1121,7 @@ if ($action === 'order') {
-
Top 10 articoli per numero ordini
+
Top 10 articoli per numero ordini
Dalle righe ordine · passa sopra una barra per quantità e valore
@@ -1130,13 +1131,13 @@ if ($action === 'order') {
-
Ordini per area
+
Ordini per area
-
Ordini per agente
+
Ordini per agente
@@ -1145,7 +1146,7 @@ if ($action === 'order') {
-
Elenco ordini
+
Elenco ordini
Clicca una riga per il dettaglio
@@ -2352,6 +2353,7 @@ if ($action === 'order') { }); })(); + \ No newline at end of file diff --git a/public/userarea/sales_orders_years.php b/public/userarea/sales_orders_years.php index ff198368..3844fc06 100644 --- a/public/userarea/sales_orders_years.php +++ b/public/userarea/sales_orders_years.php @@ -757,6 +757,7 @@ if ($action === 'data') { background: none; border: 0; padding: 0; + cursor: pointer; font-weight: 800; color: var(--c-ink); text-align: left; @@ -979,6 +980,7 @@ if ($action === 'data') { Consegne +
@@ -991,7 +993,7 @@ if ($action === 'data') {
@@ -1033,30 +1035,31 @@ if ($action === 'data') {
- Situazione ad oggi + Situazione ad oggi non dipende dagli anni scelti · segue i filtri cliente, agente e area
-
Ordinato vs fatturato · ultimi 24 mesi
+
Ordinato vs fatturato · ultimi 24 mesi
Barre: valori del mese · linea: book-to-bill su 3 mesi (ordinato ÷ fatturato: sopra 1 il portafoglio cresce, sotto 1 si consuma)
+
Anni a confronto
-
Andamento mensile
+
Andamento mensile
Stagionalità: un colore per anno
-
Progressivo dell'anno
+
Progressivo dell'anno
Somma da gennaio: dice se si è avanti o indietro rispetto agli anni scorsi
@@ -1067,14 +1070,14 @@ if ($action === 'data') {
-
Fatturato per mese
+
Fatturato per mese
Imponibile fatture + acconti − note di credito, per data fattura
-
Fatturato progressivo dell'anno
+
Fatturato progressivo dell'anno
Somma da gennaio del fatturato, anno su anno
@@ -1083,11 +1086,11 @@ if ($action === 'data') {
- +