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, colonne booking_services sbagliate, 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_show esiste 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_token ok; 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

  1. Ora (fatto): correttezza #224 + copertura seed #232 → il Booking funziona per 24/28 settori nei modelli 1:1/CAP.
  2. 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.
  3. Poi (P2): multi-notte hotel/bnb · fix buffer.
  4. 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 su pending/confirmed/checked_in, firma 14-arg, jsonb) + assert_slot_available (guardia slot-move) · SECURITY DEFINER, EXECUTE solo service_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).