Pianeta Booking · audit settoriale + roadmap di rifinitura — 2026-06-05
Giro completo del Pianeta Booking su tutti i 28 settori: cosa serve a ognuno, dove siamo, cosa rifinire. Deriva dalla sessione di hardening (#224) + estensione seed (#232). Autore: Claude (sessione busy-bhabha).
TL;DR
- #224 (MERGED) ha reso il Booking corretto end-to-end: prima era rotto in prod (status fantasma
pending_confirmation, colonnebooking_servicessbagliate, race double-booking). Ora: inserimento atomico (advisory lock + capacity), schema LIVE allineato, deposito Stripe, guardia sugli spostamenti, editor servizi dashboard funzionante. - #232 ha portato i servizi di default da 10 → 24 settori su 28 (56 → 113 servizi). I 4 esclusi (boutique, concept-store, ecommerce, wholesale) sono retail puro: niente prenotazione core.
- Il motore regge oggi i settori 1:1 e a-capacità (consulenze, visite, classi, camere singola-notte). Non regge ancora 3 modelli veri: multi-risorsa (più operatori), inventario tavoli ristorante, soggiorni multi-notte. Sono le 3 voci in cima alla roadmap.
1 · Cosa serve a ogni settore (matrice)
Legenda modello: 1:1 (un cliente/slot/operatore) · CAP (N posti/slot, es. classe) · TAVOLI (inventario di unità per dimensione) · NOTTI (intervallo di date) · RISORSA (capacità = numero di operatori/stanze).
| Macro | Settore | Modello reale | Stato motore | Nota |
|---|---|---|---|---|
| Hospitality | ristorante | TAVOLI (+party size) | ⚠️ parziale | capacity oggi = "prenotazioni concorrenti", non "tavoli da N". Serve inventario tavoli. |
| Hospitality | bar | TAVOLI / CAP | ⚠️ parziale | come ristorante; aperitivo/evento ok come CAP |
| Hospitality | hotel | NOTTI + RISORSA(stanze) | ⚠️ parziale | oggi 1 slot da 24h, niente check-in→out multi-notte |
| Hospitality | bnb | NOTTI | ⚠️ parziale | idem hotel |
| Salute&Bellezza | parrucchiere | RISORSA (stylist) | ⚠️ gap | capacityOverride:1 → salone con 3 stylist accetta 1/slot invece di 3 |
| Salute&Bellezza | estetica | RISORSA (cabine/operatori) | ⚠️ gap | come parrucchiere |
| Salute&Bellezza | gym | CAP (posti classe) | ✅ ok | capacity da servizio (classi 10-12), PT 1:1 |
| Salute&Bellezza | studio-medico | RISORSA (medici) / 1:1 | ⚠️ gap se multi-medico | singolo medico ok; poliambulatorio no |
| Servizi-pro | studio-legale / commercialista / tecnico / consulente | 1:1 / piccolo gruppo | ✅ ok | consulenze, firme, riunioni |
| Servizi-pro | immobiliari | 1:1 + CAP (open house) | ✅ ok | visite singole + open house cap20 |
| Eventi | wedding-planner | 1:1 (incontri) | ✅ ok | incontri/sopralluoghi |
| Creativi | fotografo / studio-video / studio-registrazione / produttore-musicale | 1:1 / a-ore / RISORSA(sala) | ✅ ok base | sessioni e blocchi; multi-sala = RISORSA futura |
| Creativi | musicista / designer / illustratore / copywriter | 1:1 (lezioni/consulenze) | ✅ ok | |
| Agenzie | agenzia-comunicazione / web-agency | 1:1 / gruppo | ✅ ok | discovery/strategia/workshop |
| Vendita | boutique / concept-store / ecommerce / wholesale | — | ➖ N/A | retail: niente prenotazione core (eventuale "appuntamento in negozio" = backlog) |
Lettura: ~18/24 settori sono già serviti bene dal motore attuale (1:1 + CAP). I 6 che soffrono ricadono tutti in 3 pattern mancanti.
2 · Punti di miglioramento (prioritizzati)
P1 — Multi-risorsa (il gap di maggior valore)
Chi: parrucchiere, estetica, studio-medico multi-medico, studi creativi multi-sala.
Oggi: resolveSectorPattern forza capacityOverride:1; la capacità è per-servizio, non per-operatore. Un salone con 3 stylist accetta 1 prenotazione/slot.
Serve: la tabella booking_team_calendars esiste già (FK bookings.resource_id). Modellare la capacità come numero di risorse attive del workspace (o assegnazione per-risorsa), e contare gli overlap per risorsa sia in availability.ts sia in create_booking_atomic.
Stima: media (DB: usare resource_id; availability per-risorsa; UI: scelta operatore opzionale). È una feature, non una patch — decisione di prodotto sul livello (capacità aggregata vs scelta operatore).
P1 — Inventario tavoli ristorante/bar
Oggi: "Tavolo 4 persone" con capacity=4 viene interpretato come "4 prenotazioni concorrenti di quel servizio", semantica sbagliata. Un ristorante ha N tavoli da 2/4/6 e ogni prenotazione occupa 1 tavolo adatto al party_size.
Serve: modello inventario (quanti tavoli per dimensione) + matching prenotazione→tavolo per party size. party_size esiste già su bookings ma non entra nella matematica della capacità.
Stima: media. Decisione prodotto: tavoli nominali vs pool per dimensione.
P2 — Soggiorni multi-notte (hotel/bnb)
Oggi: la camera è 1 slot da 1440min (1 notte). Niente range check-in→check-out, niente blocco notti consecutive, niente inventario stanze per tipo. Serve: prenotazione a intervallo di date + decremento disponibilità per ogni notte del range. Stima: media-alta. Modello distinto dagli slot orari.
P2 — Semantica del buffer in availability.ts
generateSlotsForRange fa cursor += granularityMin + bufferMin. Per il ristorante (granularità 30 + buffer 15) gli slot partono ogni 45min invece di 30. Per i settori a griglia (ristorante/gym) il buffer non dovrebbe spostare la griglia di partenza, solo l'occupazione. Da rivedere: buffer come estensione dell'occupazione, non del passo.
P3 — Coerenza dati price_chf (NULL vs 0.00)
Servizi senza pagamento anticipato sono a volte NULL (tavolo, sopralluogo, revisione) e a volte 0.00 (prova gratuita). Semanticamente: NULL = "su richiesta / nessun anticipo", 0.00 = "gratis". Va bene così ma andrebbe documentato come regola e reso coerente nel seed e nell'editor (oggi l'editor scrive sempre un numero).
P3 — Rifiniture di flusso (UX / completezza)
- No-show: stato
no_showesiste ma manca l'azione UI e una policy (penale/deposito trattenuto). - Reminder:
booking-reminder-smart(Inngest) esiste; verificare che sia agganciato per tutti i source e con la lingua del cliente. - Conferma: il deposito pagato ora conferma (
pending→confirmed); manca il caso "conferma manuale senza deposito" in evidenza nella dashboard (il bottone c'è, ma il loop pending→confirmed→reminder va verificato end-to-end per settore). - Cancellazione cliente:
cancel_tokenok; valutare finestra di cancellazione (es. no-cancel < X ore) per settori a deposito. - Rate-limit booking: 4 endpoint (cancel/services/slots-available/widget-create) sono ancora su limiter in-memory; migrare a Upstash distribuito (severità bassa, già notato in #226).
- CONTRACT.md widget: commenti ancora con
pending_confirmation(solo docs).
P3 — Retail (boutique/concept-store/ecommerce/wholesale)
Niente prenotazione core. Eventuale "appuntamento in negozio / personal shopping" come servizio opzionale singolo se emerge la domanda. Non prioritario.
3 · Roadmap consigliata
- Ora (fatto): correttezza #224 + copertura seed #232 → il Booking funziona per 24/28 settori nei modelli 1:1/CAP.
- Prossimo (P1): multi-risorsa (sblocca parrucchiere/estetica/poliambulatori — settori top-7) + inventario tavoli (sblocca ristorante/bar — settore top-1). Sono i due che mancano ai settori a più alto volume.
- Poi (P2): multi-notte hotel/bnb · fix buffer.
- Rifiniture (P3): no-show UI + policy, verifica reminder/conferma per settore, rate-limit distribuito, coerenza prezzi, cleanup docs.
4 · Stato prod verificato (2026-06-05)
create_booking_atomic(overlap supending/confirmed/checked_in, firma 14-arg, jsonb) +assert_slot_available(guardia slot-move) · SECURITY DEFINER, EXECUTE soloservice_role· advisor security 0 WARN.- Smoke test live (rolled back): inserimento via RPC su servizio reale →
ok=true, status=pending. ✅ - 24/28 settori con servizi di default (113 servizi).