Files
zibo-dashboard/public/userarea/sales_help.js
T
2026-10-27 12:23:09 +01:00

733 lines
45 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* sales_help.js - Guida contestuale delle pagine statistiche vendite.
*
* Uso nelle pagine:
* <div class="chart-title" data-help="st.monthly">...</div> → aggiunge l'icona ⓘ in fondo all'elemento
* <button data-help-open="page.stats">...</button> → 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: `<p>Qui vedi <b>gli ordini clienti</b> del periodo scelto: quanti sono, quanto valgono, a che punto sono.</p>
<ul>
<li><b>In alto</b> scegli il periodo (mese, trimestre, anno…) e se vuoi cliente, agente, area o stato.</li>
<li><b>I box colorati</b> sono cliccabili: filtrano tutta la pagina (es. clic su <i>In ritardo</i> = solo ordini in ritardo).</li>
<li><b>I grafici</b> sono cliccabili: un mese, una fetta, un cliente diventano un filtro.</li>
<li><b>L'elenco in fondo</b>: clic su una riga per il dettaglio dell'ordine con le sue righe; si esporta in Excel.</li>
<li>Il selettore <b>N° ordini / Valore</b> cambia cosa misurano i grafici.</li>
</ul>
<p class="sh-note">Gli ordini con la parola "listino" sono esclusi. I filtri restano memorizzati quando torni sulla pagina; la gomma 🧽 li azzera.</p>`,
},
"page.years": {
t: "Confronto anni: come si usa",
b: `<p>Qui confronti <b>gli anni tra loro</b> e vedi <b>la situazione ad oggi</b>.</p>
<ul>
<li><b>Situazione ad oggi</b> (in alto): portafoglio, book-to-bill e previsioni. Non dipende dagli anni scelti.</li>
<li><b>Chip degli anni</b>: scegli quali anni confrontare (ognuno ha il suo colore in tutti i grafici).</li>
<li><b>A pari data</b>: acceso, ogni anno è contato solo fino al giorno di oggi → confronto giusto con l'anno in corso. Spento: anni interi.</li>
<li><b>Clienti da richiamare</b> e <b>Clienti a confronto</b>: clic su un cliente per filtrare tutta la pagina; l'icona verde apre la sua scheda.</li>
</ul>
<p class="sh-note">Cliente, agente e area filtrano tutto, anche il fatturato.</p>`,
},
"page.deliveries": {
t: "Consegne: come si usa",
b: `<p>Qui vedi <b>le righe d'ordine ancora da consegnare</b>, cioè il lavoro da spedire.</p>
<ul>
<li><b>Data ZIBO</b> (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 <span class="sh-chip sh-amber">IN SETTIMANA</span>.</li>
<li><b>Data cliente</b> (arancione quando superata) = quando il cliente l'avrebbe voluta: è un riferimento.</li>
<li><b>Scadenza</b> (chip in alto), box e grafici filtrano le righe; si combinano con cliente, articolo, agente, area.</li>
</ul>
<p class="sh-note">Cosa fare: parti dalle <b>scadute</b>, poi guarda <b>i prossimi giorni</b> e le settimane più cariche del grafico.</p>`,
},
"page.customer": {
t: "Scheda cliente: come si usa",
b: `<p>Tutto su <b>un cliente</b> in una pagina. Cercalo per nome o codice, oppure clicca l'icona verde accanto a un cliente nelle altre pagine.</p>
<ul>
<li><b>Profilo</b>: da quando è cliente, ultimo ordine, ogni quanto ordina di solito e il suo stato (attivo, attenzione, dormiente…).</li>
<li><b>Box</b>: quest'anno rispetto allo scorso, cosa gli dobbiamo consegnare, note di credito.</li>
<li><b>Tabelle</b> in fondo: righe da consegnare, ordini, articoli, fatture. Tutte esportabili in Excel.</li>
</ul>
<p class="sh-note">Utile prima di una telefonata o di una visita. I clienti visti di recente restano a portata di clic.</p>`,
},
"page.summary": {
t: "Sommario: come si legge",
b: `<p>Il <b>riepilogo per la direzione</b>: in un colpo d'occhio cosa va bene e cosa no.</p>
<ul>
<li><b>Semaforo in alto</b>: il giudizio complessivo. Il punteggio su 100 conta i verdi (100), i gialli (50) e i rossi (0).</li>
<li><b>Cosa va bene / Cosa non va</b>: gli stessi indicatori, scritti in frasi semplici; i rossi sono in cima.</li>
<li><b>Tessere</b>: ogni indicatore ha il suo colore. <span class="sh-chip sh-green">Bene</span> <span class="sh-chip sh-amber">Così così</span> <span class="sh-chip sh-red">Male</span>. Clic sulla tessera per andare alla pagina con i dettagli.</li>
<li><b>Clienti da guardare</b>: chi cresce, chi cala, chi richiamare subito. Clic sul nome per la scheda cliente.</li>
</ul>
<p class="sh-note">Il sommario guarda sempre <b>tutta l'azienda ad oggi</b>: non ha filtri. Per approfondire usa le altre pagine.</p>`,
},
/* ===================== SOMMARIO ===================== */
"sm.flow": {
t: "Nuovi ordini",
b: `<p>Quanti ordini sono entrati (per data ordine) e quanto valgono, annullati esclusi:</p>
<ul>
<li><b>Oggi</b>, confrontato con lo stesso giorno della settimana scorsa;</li>
<li><b>Ultimi 7 giorni</b>, confrontati con i 7 giorni prima;</li>
<li><b>Ultimi 30 giorni</b>, confrontati con i 30 giorni prima.</li>
</ul>
<p>▲ verde = più della volta prima · ▼ rosso = meno.</p>
<p class="sh-note">"Oggi" va letto a fine giornata: al mattino è normale che sia basso.</p>`,
},
"sm.invYtd": {
t: "Fatturato dell'anno",
b: `<p>Fatturato da gennaio a oggi rispetto allo <b>stesso periodo dell'anno scorso</b>.</p>
<p>🟢 almeno +3% · 🟡 tra −3% e +3% · 🔴 sotto −3%.</p>`,
},
"sm.ordYtd": {
t: "Ordinato dell'anno",
b: `<p>Ordini ricevuti da gennaio a oggi rispetto allo stesso periodo dell'anno scorso. È il fatturato dei prossimi mesi.</p>
<p>🟢 almeno +3% · 🟡 tra −3% e +3% · 🔴 sotto −3%.</p>`,
},
"sm.forecast": {
t: "Chiusura prevista",
b: `<p>Come chiuderà l'anno se si continua con lo stesso ritmo degli anni scorsi, confrontata con l'anno scorso intero.</p>
<p>🟢 almeno +3% · 🟡 tra −3% e +3% · 🔴 sotto −3%.</p>
<p class="sh-note">È una stima: diventa più affidabile man mano che l'anno avanza.</p>`,
},
"sm.b2b": {
t: "Book-to-bill",
b: `<p>Ordini entrati ÷ fatture emesse negli ultimi 90 giorni. Dice se il lavoro in arrivo tiene il passo con quello che consegniamo.</p>
<p>🟢 da 1,05 (il portafoglio cresce) · 🟡 tra 0,95 e 1,05 · 🔴 sotto 0,95 (lo stiamo consumando).</p>
<p class="sh-note">Il grafico mostra lo stesso valore mese per mese (su 3 mesi): la riga tratteggiata è 1.</p>`,
},
"sm.cover": {
t: "Lavoro in portafoglio",
b: `<p>Per quante <b>settimane di lavoro</b> basta quello che abbiamo da consegnare, al ritmo di fatturato degli ultimi 3 mesi.</p>
<p>🟢 almeno 8 settimane · 🟡 da 4 a 8 · 🔴 meno di 4.</p>`,
},
"sm.late": {
t: "Consegne in ritardo",
b: `<p>Quanta parte del portafoglio è già <b>oltre la settimana ZIBO</b> comunicata al cliente.</p>
<p>🟢 fino al 10% · 🟡 dal 10 al 25% · 🔴 oltre il 25%.</p>
<p class="sh-note">Cosa fare: apri Consegne e parti dalle righe scadute.</p>`,
},
"sm.risk": {
t: "Clienti a rischio",
b: `<p>Clienti abituali <b>dormienti</b> o <b>probabilmente persi</b> e quanto valevano in un anno, rispetto al giro d'affari totale.</p>
<p>🟢 fino al 3% · 🟡 dal 3 all'8% · 🔴 oltre l'8%.</p>
<p class="sh-note">Cosa fare: lista "Da richiamare subito" qui sotto, o quella completa in Confronto anni.</p>`,
},
"sm.top5": {
t: "Peso dei primi 5 clienti",
b: `<p>Quanto del fatturato degli ultimi 12 mesi viene dai 5 clienti più grandi. Più è alto, più dipendiamo da pochi nomi.</p>
<p>🟢 fino al 40% · 🟡 dal 40 al 60% · 🔴 oltre il 60%.</p>`,
},
"sm.customers": {
t: "Clienti attivi",
b: `<p>Clienti che hanno ordinato negli ultimi 12 mesi, confrontati con i 12 mesi prima. "Nuovi" = primo ordine nell'ultimo anno.</p>
<p>🟢 stabili o in crescita · 🟡 fino a −5% · 🔴 oltre −5%.</p>`,
},
"sm.cn": {
t: "Note di credito",
b: `<p>Note di credito degli ultimi 12 mesi in percentuale sul fatturato: misura resi, sconti e contestazioni.</p>
<p>🟢 fino all'1,5% · 🟡 dall'1,5 al 3% · 🔴 oltre il 3%.</p>`,
},
"sm.up": {
t: "Clienti che crescono",
b: `<p>I clienti che hanno aumentato di più (in euro) negli ultimi 12 mesi rispetto ai 12 precedenti. Da coltivare.</p>`,
},
"sm.down": {
t: "Clienti che calano",
b: `<p>I clienti che sono diminuiti di più (in euro) negli ultimi 12 mesi rispetto ai 12 precedenti.</p>
<p class="sh-note">Cosa fare: capire il motivo (concorrenza, prezzi, problemi di consegna) con una telefonata.</p>`,
},
"sm.call": {
t: "Da richiamare subito",
b: `<p>I clienti abituali più importanti che si sono fermati (dormienti o probabilmente persi), ordinati per valore.</p>`,
},
/* ===================== ANDAMENTO ORDINI ===================== */
"st.orders": {
t: "Ordini",
b: `<p>Numero di ordini del periodo e dei filtri scelti. Sotto: confronto con lo <b>stesso periodo dell'anno prima</b>.</p>
<p class="sh-note">Clic sul box: toglie il filtro di stato e mostra tutti gli ordini.</p>`,
},
"st.value": {
t: "Valore ordinato",
b: `<p>Somma dell'<b>imponibile</b> degli ordini del periodo (annullati esclusi), con il confronto con lo stesso periodo dell'anno prima.</p>`,
},
"st.toship": {
t: "Da evadere",
b: `<p>Valore degli ordini <b>ancora aperti</b> (non consegnati del tutto). In rosso la parte <b>già in ritardo</b>.</p>
<p class="sh-note">Cosa fare: se la quota in ritardo cresce, guarda la pagina Consegne.</p>`,
},
"st.open": {
t: "Aperti",
b: `<p>Ordini non ancora consegnati del tutto e non annullati. Clic per vederli.</p>`,
},
"st.late": {
t: "In ritardo",
b: `<p>Ordini con almeno <b>una riga aperta oltre la data ZIBO</b> (la settimana comunicata è finita).</p>
<ul>
<li><b>Righe in ritardo</b>: quante righe sono scadute; <b>parziali</b> = ordini dove è in ritardo solo una parte delle righe.</li>
<li><b>Oltre data cliente</b> (arancione): superata la data desiderata dal cliente, ma non ancora la nostra.</li>
<li>Striscia gialla <b>in consegna questa settimana</b>: ordini con righe da consegnare entro domenica, non ancora in ritardo. Cliccala per vederli.</li>
</ul>
<p class="sh-note">Cosa fare: clic sul box per la lista, poi apri gli ordini per vedere quali righe mancano.</p>`,
},
"st.done": {
t: "Evasi",
b: `<p>Ordini completamente consegnati nel periodo scelto (per data ordine).</p>`,
},
"st.toinvoice": {
t: "Da fatturare",
b: `<p>Ordini <b>consegnati ma non ancora fatturati</b>.</p>
<p class="sh-note">Cosa fare: segnalali all'amministrazione se restano qui a lungo.</p>`,
},
"st.customers": {
t: "Clienti attivi",
b: `<p>Quanti clienti diversi hanno ordinato nel periodo. Sotto: in media dopo quanti giorni dall'ordine è prevista la consegna.</p>`,
},
"st.monthly": {
t: "Andamento mensile",
b: `<p>Ordini (o valore) mese per mese nel periodo scelto. Clic su un mese per filtrare solo quel mese.</p>`,
},
"st.status": {
t: "Ripartizione per stato",
b: `<p>Come si dividono gli ordini: aperti, evasi, bloccati, annullati. Clic su una fetta per filtrare.</p>`,
},
"st.topcust": {
t: "Top 10 clienti",
b: `<p>I 10 clienti più importanti del periodo (per numero ordini o valore). Le barre sono divise tra ordini aperti e altri (evasi/annullati).</p>
<p class="sh-note">Clic su un cliente per vedere solo i suoi ordini.</p>`,
},
"st.due": {
t: "Scadenze ordini aperti",
b: `<p>Gli ordini aperti divisi per <b>quando vanno consegnati</b>: già scaduti, questa settimana, la prossima, entro 30 giorni, oltre, senza data.</p>`,
},
"st.items": {
t: "Top 10 articoli",
b: `<p>Gli articoli più ordinati nel periodo, calcolati dalle righe d'ordine. Passa sopra una barra per quantità e valore.</p>`,
},
"st.area": {
t: "Per area",
b: `<p>Ordini (o valore) divisi per area commerciale.</p>`,
},
"st.agent": {
t: "Per agente",
b: `<p>Ordini (o valore) divisi per agente.</p>`,
},
"st.list": {
t: "Elenco ordini",
b: `<p>Tutti gli ordini dei filtri scelti. Clic su una riga per il <b>dettaglio con le righe</b>, le date e cosa resta da consegnare.</p>
<ul>
<li><span class="sh-chip sh-red">IN RITARDO</span> data ZIBO superata · <span class="sh-chip sh-amber">PARZIALE</span> solo alcune righe in ritardo · <span class="sh-chip sh-orange">OLTRE DATA CLIENTE</span> superata solo la data del cliente.</li>
<li>Il pulsante Excel scarica l'elenco come lo vedi.</li>
</ul>`,
},
/* ===================== CONFRONTO ANNI ===================== */
"yr.dash": {
t: "Situazione ad oggi",
b: `<p>Una fotografia di <b>oggi</b>, 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).</p>`,
},
"yr.backlog": {
t: "Portafoglio da consegnare",
b: `<p>Valore di tutte le righe d'ordine <b>ancora da consegnare</b>.</p>
<ul>
<li><b>Settimane</b>: per quante settimane di lavoro basta, al ritmo medio di fatturato degli ultimi 3 mesi.</li>
<li>In rosso la parte <b>già oltre la data ZIBO</b>.</li>
</ul>
<p class="sh-note">Poche settimane = servono ordini nuovi. Tante settimane con molto in ritardo = c'è un problema di capacità o di consegne.</p>`,
},
"yr.b2b": {
t: "Book-to-bill",
b: `<p>Confronta <b>il lavoro che entra</b> (ordini) con <b>quello che esce</b> (fatture) negli ultimi 90 giorni.</p>
<ul>
<li><b>1,0</b> = equilibrio.</li>
<li><b>Sopra 1</b> (es. 1,20 → per ogni 100 € fatturati entrano 120 € di ordini): il portafoglio cresce 🟢</li>
<li><b>Sotto 1</b> (es. 0,80): stiamo consumando il portafoglio, tra qualche mese il fatturato rischia di calare 🔴</li>
</ul>
<p class="sh-note">È un segnale che arriva <b>prima</b> del calo di fatturato.</p>`,
},
"yr.fcInv": {
t: "Previsione fatturato",
b: `<p>Stima di come chiuderà l'anno. Si prende il fatturato <b>ad oggi</b> 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%).</p>
<p class="sh-note">La <b>forbice</b> va dall'anno più favorevole a quello meno favorevole. Diventa più precisa man mano che l'anno avanza.</p>`,
},
"yr.fcOrd": {
t: "Previsione ordinato",
b: `<p>Come la previsione del fatturato, ma sugli <b>ordini ricevuti</b>: quanto ordinato porteremo a casa entro fine anno se si continua così.</p>`,
},
"yr.b2bchart": {
t: "Ordinato vs fatturato · 24 mesi",
b: `<p>Barre viola = ordini ricevuti nel mese · barre verdi = fatturato del mese.</p>
<p>La <b>linea arancione</b> è il book-to-bill su 3 mesi: sopra la riga tratteggiata dell'1 il portafoglio cresce, sotto si consuma.</p>
<p class="sh-note">Se la linea resta sotto 1 per diversi mesi, è il momento di spingere sugli ordini.</p>`,
},
"yr.cards": {
t: "Anni a confronto",
b: `<p>Una carta per ogni anno scelto: valore ordinato (numero grande), numero ordini, ordine medio, clienti, fatturato e variazione rispetto all'anno prima.</p>
<p class="sh-note">Con <b>A pari data</b> acceso ogni anno è contato fino a oggi: il confronto con l'anno in corso è corretto.</p>`,
},
"yr.monthly": {
t: "Ordinato per mese",
b: `<p>Una linea per anno, mese per mese: mostra la <b>stagionalità</b> e in quali mesi quest'anno va meglio o peggio.</p>`,
},
"yr.cumul": {
t: "Progressivo dell'anno",
b: `<p>Somma da gennaio a ogni mese. Se la linea dell'anno in corso è <b>sopra</b> quelle degli anni scorsi, siamo avanti; se è sotto, siamo indietro.</p>`,
},
"yr.invMonthly": {
t: "Fatturato per mese",
b: `<p>Fatturato vero per <b>data della fattura</b>: fatture + fatture d'acconto − note di credito (imponibile).</p>
<p class="sh-note">È sempre in €, anche se in alto è selezionato "N° ordini".</p>`,
},
"yr.invCumul": {
t: "Fatturato progressivo",
b: `<p>Fatturato sommato da gennaio, anno su anno: dice se stiamo fatturando più o meno degli anni scorsi alla stessa data.</p>`,
},
"yr.invTable": {
t: "Tabella dati fatturato",
b: `<p>Gli stessi numeri dei grafici in tabella: <b>per mese</b> (con progressivo e variazione) oppure <b>l'elenco delle fatture</b> e note di credito.</p>
<p class="sh-note">Pulsante Excel per scaricarli: il titolo del file riporta i filtri usati.</p>`,
},
"yr.dormant": {
t: "Clienti da richiamare",
b: `<p>Clienti che ordinavano <b>con regolarità</b> (almeno 4 volte negli ultimi 3 anni) e che ora <b>tardano</b> rispetto al loro solito.</p>
<ul>
<li><b>Ritmo abituale</b>: ogni quanti giorni ordina di solito.</li>
<li><b>Ritardo</b>: giorni dall'ultimo ordine ÷ ritmo. Es. ordina ogni 30 giorni e sono passati 60 → 2×.</li>
<li><span class="sh-chip sh-yellow">Attenzione</span> da 1,5× · <span class="sh-chip sh-orange">Dormiente</span> da 2× · <span class="sh-chip sh-red">Probabilmente perso</span> da 4× o oltre un anno.</li>
<li>In cima quelli che <b>valgono di più</b> (ordinato dei 12 mesi prima dell'ultimo ordine).</li>
</ul>
<p class="sh-note">Cosa fare: chiamare partendo dall'alto. Esporta in Excel per dividerli tra i commerciali.</p>`,
},
"yr.custcmp": {
t: "Clienti a confronto",
b: `<p>Ogni cliente con il suo valore (o numero ordini) negli anni scelti e la variazione tra gli ultimi due.</p>
<ul>
<li><b>Nuovi</b>: non c'erano l'anno prima · <b>Persi</b>: non ci sono quest'anno.</li>
<li><b>In crescita / in calo</b>: oltre ±10%.</li>
</ul>
<p class="sh-note">Clic su un cliente per filtrare la pagina; l'icona verde apre la sua scheda.</p>`,
},
"yr.ytd": {
t: "A pari data",
b: `<p><b>Acceso</b>: 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.</p>
<p><b>Spento</b>: anni interi (l'anno in corso sembrerà sempre più basso finché non finisce).</p>`,
},
/* ===================== CONSEGNE ===================== */
"dl.horizon": {
t: "Scadenza",
b: `<p>Filtra le righe per quando vanno consegnate: scadute (data ZIBO o data cliente), questa settimana, la prossima, entro 30 giorni, senza data.</p>`,
},
"dl.total": {
t: "Da consegnare",
b: `<p>Tutte le righe ancora da consegnare (con i filtri scelti) e il loro <b>valore residuo</b> (solo la parte non ancora consegnata).</p>`,
},
"dl.lateZibo": {
t: "Scadute (data ZIBO)",
b: `<p>Righe la cui <b>settimana ZIBO è finita</b> senza consegna: sono i ritardi veri verso il cliente.</p>
<p class="sh-note">Cosa fare: sono la priorità. Clic sul box per vederle tutte.</p>`,
},
"dl.lateClient": {
t: "Oltre data cliente",
b: `<p>Righe dove è superata la <b>data desiderata dal cliente</b>. Non sono necessariamente in ritardo per noi, ma il cliente potrebbe sollecitare.</p>`,
},
"dl.next7": {
t: "Prossimi 7 giorni",
b: `<p>Righe da consegnare da oggi ai prossimi 7 giorni. Clic per vederle.</p>`,
},
"dl.nodate": {
t: "Senza data",
b: `<p>Righe senza nessuna data di consegna in Mago.</p>
<p class="sh-note">Cosa fare: vanno completate in Mago, altrimenti non si possono pianificare.</p>`,
},
"dl.weekly": {
t: "Carico consegne per settimana",
b: `<p>Quanto c'è da consegnare settimana per settimana (per data ZIBO; se manca, data cliente). La prima barra rossa raccoglie tutto lo scaduto.</p>
<p class="sh-note">Serve a vedere le settimane troppo cariche. Clic su una barra per filtrare quella settimana.</p>`,
},
"dl.lateCust": {
t: "Clienti con più ritardo",
b: `<p>I clienti con più valore <b>scaduto</b> (data ZIBO superata). Clic per vedere solo le loro righe.</p>
<p class="sh-note">Utile per sapere chi avvisare per primo.</p>`,
},
"dl.rows": {
t: "Righe da consegnare",
b: `<p>Ogni riga: ordine, cliente, articolo, quantità ancora da consegnare, valore e date.</p>
<ul>
<li><b>ZIBO sett.</b> = settimana comunicata: rossa quando è finita, <span class="sh-chip sh-amber">IN SETTIMANA</span> mentre è in corso.</li>
<li><b>Cliente</b> = data desiderata dal cliente (arancione se superata).</li>
</ul>
<p class="sh-note">Pulsante Excel per scaricare l'elenco filtrato.</p>`,
},
/* ===================== SCHEDA CLIENTE ===================== */
"sc.status": {
t: "Stato del cliente",
b: `<p>Calcolato sul suo <b>ritmo d'ordine</b> degli ultimi 3 anni:</p>
<ul>
<li><span class="sh-chip sh-green">Cliente attivo</span> ordina con il suo ritmo normale.</li>
<li><span class="sh-chip sh-yellow">Attenzione</span> sta tardando (1,5 volte il suo solito).</li>
<li><span class="sh-chip sh-orange">Dormiente</span> 2 volte il suo solito: da chiamare.</li>
<li><span class="sh-chip sh-red">Probabilmente perso</span> 4 volte o più di un anno senza ordini.</li>
<li><span class="sh-chip sh-grey">Ordini occasionali</span> troppo pochi ordini per stimare un ritmo.</li>
</ul>`,
},
"sc.inv": {
t: "Fatturato dell'anno",
b: `<p>Fatturato del cliente da gennaio <b>ad oggi</b>, confrontato con lo stesso periodo dell'anno scorso. Sotto: l'anno scorso intero.</p>`,
},
"sc.ord": {
t: "Ordinato dell'anno",
b: `<p>Ordini ricevuti dal cliente da gennaio <b>ad oggi</b>, confrontati con lo stesso periodo dell'anno scorso.</p>
<p class="sh-note">Ordinato in calo e fatturato ancora alto = il fatturato calerà nei prossimi mesi.</p>`,
},
"sc.open": {
t: "Da consegnare",
b: `<p>Valore di quello che gli dobbiamo ancora consegnare e quante righe sono <b>in ritardo</b> (data ZIBO superata).</p>
<p class="sh-note">Prima di chiamarlo, guarda la scheda "Da consegnare" qui sotto.</p>`,
},
"sc.cn": {
t: "Note di credito",
b: `<p>Note di credito degli ultimi 12 mesi e quanto pesano sul fatturato. Diventa rosso dal 3%.</p>
<p class="sh-note">Una percentuale alta indica resi, contestazioni o problemi di qualità ricorrenti.</p>`,
},
"sc.years": {
t: "Ordinato e fatturato per anno",
b: `<p>Come è cresciuto (o calato) il cliente negli anni. L'anno in corso è <b>ad oggi</b>, quindi più basso finché l'anno non finisce.</p>`,
},
"sc.months": {
t: "Ultimi 24 mesi",
b: `<p>Ordini (viola) e fatture (verde) mese per mese: mostra se il cliente ordina con regolarità o a picchi, e se si sta fermando.</p>`,
},
"sc.tables": {
t: "Le tabelle",
b: `<ul>
<li><b>Da consegnare</b>: righe aperte con quantità mancante e date (ZIBO e cliente). Righe molto vecchie spesso sono da chiudere in Mago.</li>
<li><b>Ordini</b>: gli ordini del cliente; clic sul numero per aprirlo.</li>
<li><b>Articoli</b>: cosa compra, quanto, e il <b>prezzo medio</b> degli ultimi 12 mesi rispetto ai 12 precedenti: utile per verificare gli aumenti di listino.</li>
<li><b>Matrici</b>: le matrici che ordina, con il prezzo per metro o per kg e la variazione sull'anno prima. Clic sul nome per confrontarlo con gli altri clienti.</li>
<li><b>Fatture</b>: fatture, acconti e note di credito degli ultimi 3 anni.</li>
</ul>
<p class="sh-note">Ogni tabella ha il suo pulsante Excel.</p>`,
},
/* ===================== MATRICI ===================== */
"page.matrici": {
t: "Matrici: come si legge",
b: `<p>A che prezzo vendiamo <b>ogni matrice</b>, nell'unità in cui la vendiamo: <b>€/metro</b> se a metri, <b>€/kg</b> se a chili. E quanta <b>mescola</b> consuma.</p>
<ul>
<li>I dati vengono dalle <b>righe degli ordini</b>: prezzo = imponibile della riga ÷ quantità.</li>
<li>Esclusi: righe con quantità 0 o 1 (servizi), spese, ordini annullati e "listino".</li>
<li><b>Clienti</b> in alto: scegline uno per vedere <b>cosa ordina</b> e a che prezzo.</li>
<li>Clic su una matrice (tabella, bolla o elenco) per <b>prezzi nel tempo cliente per cliente</b>, mescole e righe d'ordine.</li>
</ul>
<p class="sh-note">Le mescole sono una stima dall'ultima scheda di lavoro, senza scarto. Le righe a pezzi aspettano la conversione pezzi → metri.</p>`,
},
"mx.types": {
t: "Tipo",
b: `<p>Il tipo viene dalla lettera iniziale del campo <b>Matrice/Misura</b> di Mago:</p>
<ul>
<li><span class="sh-chip" style="background:#ede9fe;color:#5b21b6">Matrice</span> M + codice (anche in mezzo, es. Q8X8M00936P). Si cerca in anagrafica <b>senza la M</b>, con e senza revisione.</li>
<li><span class="sh-chip" style="background:#e0f2fe;color:#075985">Tubo</span> T + misura (es. T 10X15)</li>
<li><span class="sh-chip" style="background:#dcfce7;color:#166534">Rettangolo</span> R + misura (es. R 110X2)</li>
<li><span class="sh-chip" style="background:#fce7f3;color:#9d174d">Diametro</span> D + misura (es. D 3,3)</li>
<li><b>Altri</b>: Q quadrato, S, valori non riconosciuti.</li>
</ul>
<p>Avvisi accanto alle matrici: <span class="sh-chip sh-orange">non in anagrafica</span> codice che non esiste in anagrafica · <span class="sh-chip sh-orange">altra revisione</span> revisione diversa da quella in anagrafica · <span class="sh-chip sh-orange">abbinata a mano</span> da "Ricorda corrispondenza".</p>
<p class="sh-note"><b>Da sistemare</b> raccoglie matrici non in anagrafica, altre revisioni e valori non riconosciuti.</p>`,
},
"mx.k.value": {
t: "Venduto con matrice",
b: `<p>Imponibile delle righe d'ordine del periodo che hanno il campo <b>Matrice/Misura</b> compilato, con il numero di matrici dell'anagrafica e di clienti.</p>`,
},
"mx.k.qty": {
t: "Venduto a metri / a chili",
b: `<p>Quantità venduta nel periodo e <b>prezzo medio</b> (imponibile ÷ quantità) su tutte le righe in quell'unità.</p>
<p class="sh-note">Clic sul box per vedere solo le matrici vendute in quell'unità.</p>`,
},
"mx.k.mix": {
t: "Mescola consumata",
b: `<p>Kg di mescola stimati per le righe vendute nel periodo.</p>
<p><b>Ancora da produrre</b>: kg necessari per le righe ancora da consegnare (qualsiasi data). È la base per gli acquisti di mescola.</p>`,
},
"mx.k.pz": {
t: "Venduto a pezzi",
b: `<p>Righe vendute a pezzi (UM N.). Il prezzo al pezzo c'è, ma la mescola non si può stimare finché non c'è la conversione pezzi → metri.</p>`,
},
"mx.k.cover": {
t: "Copertura anagrafica",
b: `<p>Quanta parte del venduto è collegata a una <b>matrice dell'anagrafica</b> (verde), quanta è tubi, rettangoli, diametri e altri profili (viola), quanta resta da sistemare (arancio).</p>
<p class="sh-note">Cosa fare: clic sul box per la lista "Da sistemare" e completare l'anagrafica matrici o le corrispondenze.</p>`,
},
"mx.k.margin": {
t: "Margine sul grezzo",
b: `<p>Quanto resta del prezzo di vendita dopo il <b>costo della sola mescola</b>, sulle matrici dove il costo è completo.</p>
<ul>
<li>Costo mescola = g/m della scheda di lavoro × €/kg pagato in Mago (media degli ultimi 3 mesi).</li>
<li><b>Calcolato sul</b>: quota del venduto che ha un costo completo (scheda con g/m e prezzo di tutte le mescole).</li>
<li><span class="sh-chip sh-orange">da verificare</span> mescole il cui prezzo potrebbe non comprendere le materie prime (es. Der-Gom).</li>
</ul>
<p class="sh-note">Non comprende scarto, lavorazione, energia e trasporto: è il margine "lordo di mescola".</p>`,
},
"mx.margin": {
t: "Margine sul costo mescola",
b: `<p><b>Margine più basso</b>: le matrici dove il prezzo copre meno il costo della mescola. Sono le prime da rivedere nei listini.</p>
<p><b>Più margine in euro</b>: le matrici che portano più margine nel periodo (margine unitario × quantità).</p>
<p>🟢 da 60% · 🟡 da 40 a 60% · 🔴 sotto 40%.</p>
<p class="sh-note">Contano solo le matrici con costo completo. Clic su una matrice per il dettaglio con la linea del costo nel grafico.</p>`,
},
/* ===================== PREVENTIVO ===================== */
"page.quote": {
t: "Preventivo: come si usa",
b: `<ol class="ps-3">
<li>Scegli la <b>matrice</b>, il <b>cliente</b> (facoltativo) e se vendi <b>al metro o al kg</b>.</li>
<li><b>Costo</b>: le mescole della scheda di lavoro con g/m ed €/kg pagati in Mago. Puoi correggere i numeri (diventano gialli) e aggiungere scarto e altri costi.</li>
<li><b>Prezzo</b>: scegli il ricarico sul costo. Il prezzo suggerito si calcola da solo; il <b>prezzo proposto</b> si può arrotondare a mano.</li>
<li>Confronta con <b>ultimo prezzo al cliente</b>, media di mercato e forbice, poi scrivi un commento e <b>Salva</b>.</li>
</ol>
<p class="sh-note">I preventivi salvati restano in fondo alla pagina e si riaprono con un clic. Stampa per avere un foglio pulito.</p>`,
},
"pv.cost": {
t: "Costo",
b: `<ul>
<li><b>€/metro</b> = somma di g/m × €/kg ÷ 1000 di ogni mescola della scheda di lavoro.</li>
<li><b>€/kg</b> (vendita a chili) = media dei €/kg pesata sui g/m.</li>
<li>€/kg = media pagata in Mago negli ultimi 3 mesi. <span class="sh-chip sh-amber">prezzo vecchio</span> = nessun acquisto recente, si usa l'ultimo. <span class="sh-chip sh-orange">da verificare</span> = fornitore in conto lavoro.</li>
</ul>
<p class="sh-note">Le correzioni valgono solo per questo preventivo e vengono salvate con lui.</p>`,
},
"pv.scrap": {
t: "Scarto %",
b: `<p>Percentuale di mescola persa in produzione (avvii, sfridi, scarti). Il costo della mescola viene aumentato di questa percentuale.</p>`,
},
"pv.other": {
t: "Altri costi",
b: `<p>Costi per metro o per kg da aggiungere alla mescola: lavorazioni esterne (biadesivo, giunzione, raspatura), imballo, trasporto, quota di lavorazione.</p>`,
},
"pv.price": {
t: "Prezzo suggerito",
b: `<p><b>Prezzo suggerito</b> = costo totale × (1 + ricarico %). Es. costo 0,50 €/m con ricarico 100% → 1,00 €/m.</p>
<p>Il pulsante <b>come mercato</b> usa il ricarico che oggi si ottiene con il prezzo medio di vendita della matrice.</p>
<p>🟢 margine da 60% · 🟡 da 40 a 60% · 🔴 sotto 40% (margine = (prezzo − costo) ÷ prezzo).</p>`,
},
"pv.offered": {
t: "Prezzo proposto",
b: `<p>È il prezzo che finisce nel preventivo: parte dal suggerito e si può arrotondare a mano. Accanto, il margine che ne risulta.</p>`,
},
"pv.refs": {
t: "Confronto",
b: `<ul>
<li><b>Ultimo prezzo al cliente</b> e <b>media cliente</b>: cosa ha pagato finora.</li>
<li><b>Media mercato</b>: prezzo medio di tutti i clienti negli ultimi 12 mesi.</li>
<li>La percentuale verde/rossa dice quanto il prezzo proposto è sopra o sotto.</li>
</ul>`,
},
"pv.chart": {
t: "Costo e prezzi nel tempo",
b: `<p>Mese per mese: <b>costo della mescola</b> (con i prezzi pagati in quel mese), <b>prezzo medio</b> di tutti i clienti e del cliente scelto. Le righe orizzontali sono il costo totale e il prezzo proposto.</p>
<p class="sh-note">Se la linea del costo sale e quella dei prezzi no, il margine si sta riducendo.</p>`,
},
"mx.map": {
t: "Mappa dei prezzi",
b: `<p>Ogni bolla è una matrice venduta nel periodo (le prime 150 per valore).</p>
<ul>
<li><b>Verso destra</b>: più quantità venduta (scala logaritmica).</li>
<li><b>Verso l'alto</b>: prezzo medio più alto.</li>
<li><b>Più grande</b>: più fatturato.</li>
</ul>
<p class="sh-note">Le bolle in basso a destra sono matrici molto vendute a prezzo basso: le prime da guardare per un aumento.</p>`,
},
"mx.moves": {
t: "Prezzi in movimento",
b: `<p>Prezzo medio degli <b>ultimi 12 mesi</b> rispetto ai <b>12 mesi precedenti</b>, per le matrici vendute in entrambi i periodi.</p>
<p class="sh-note">Serve a verificare che gli aumenti di listino siano stati applicati e a scoprire cali non voluti.</p>`,
},
"mx.table": {
t: "Classifica matrici",
b: `<ul>
<li><b>Prezzo medio</b>: imponibile ÷ quantità del periodo.</li>
<li><b>Forbice</b>: prezzo minimo e massimo praticato. Barra <span class="sh-chip sh-green">verde</span> fino al 10% di differenza, <span class="sh-chip sh-amber">gialla</span> fino al 25%, <span class="sh-chip sh-red">rossa</span> oltre.</li>
<li><b>12 mesi</b>: prezzo mese per mese e variazione sui 12 mesi precedenti.</li>
<li><b>Costo mescola</b>: €/m o €/kg della sola mescola. <span class="sh-chip sh-red">parziale</span> = manca il prezzo o il g/m di qualche mescola (costo sottostimato).</li>
<li><b>Margine</b>: (prezzo − costo mescola) ÷ prezzo.</li>
<li><b>Mescola</b>: kg stimati, oppure il motivo per cui mancano (<span class="sh-chip sh-amber">a pezzi</span>, <span class="sh-chip sh-red">g/m mancante</span>).</li>
</ul>
<p class="sh-note">La stessa matrice venduta a metri e a chili compare su due righe.</p>`,
},
"mx.mix": {
t: "Mescole consumate per mese",
b: `<p>Kg di mescola stimati dalle vendite, mese per mese.</p>
<ul>
<li>Si usa l'<b>ultima scheda di lavoro</b> della matrice (prima quelle attive).</li>
<li>Righe a metri: kg = metri × g/m di ciascuna mescola ÷ 1000.</li>
<li>Righe a chili: i kg si dividono tra le mescole in proporzione ai g/m; senza g/m in parti uguali (2 mescole 50/50, 3 mescole 33%).</li>
</ul>
<p class="sh-note">Per ora senza scarto.</p>`,
},
"mx.mixneed": {
t: "Fabbisogno mescole",
b: `<p><b>Venduto</b>: kg di mescola delle righe ordinate nel periodo.</p>
<p><b>Da produrre</b>: kg che servono per le righe <b>ancora da consegnare</b>, qualsiasi sia la data dell'ordine.</p>
<p class="sh-note">Quando avremo il costo delle mescole, da qui si calcolerà anche il costo grezzo.</p>`,
},
"mx.dprice": {
t: "Prezzo nel tempo",
b: `<p>Ogni punto è una <b>riga d'ordine</b>: altezza = prezzo, colore = cliente (i primi 8 per valore, gli altri insieme).</p>
<p>La linea scura è il <b>prezzo medio del mese</b>. Punti sotto la linea = clienti che pagano meno della media.</p>
<p>La <b>linea rossa tratteggiata</b> è il costo della mescola mese per mese (prezzi pagati in quel mese): la distanza dalla linea dei prezzi è il margine.</p>
<p class="sh-note">Nella tabella Clienti, "Rispetto alla media" mostra di quanto ognuno paga più o meno, "Margine" quanto resta dopo la mescola.</p>`,
},
};
/* ===================== 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 = `<button type="button" class="sh-x" aria-label="Chiudi">&times;</button>
<h6><i class="fa-solid fa-circle-info"></i>${h.t}</h6>${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 = '<i class="fa-solid fa-circle-info"></i>';
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;
})();