f7eb7eec23
.planning/ documentava in dettaglio cio che era vecchio e per niente cio
che e in produzione: le fasi 11-22 (v2.1 e v2.2, chiuse a giugno) erano
ancora in phases/ mentre v1.0 e v2.0 stavano gia in milestones/, e il
lavoro degli ultimi due mesi - gate OTP e ciclo di vita dei retainer, cioe
quello che gira su hub.iamcavalli.net - non aveva nessuna cartella.
- phases/{11,12,14} -> milestones/v2.1-phases/, phases/{18..22} ->
milestones/v2.2-phases/. Ora phases/ contiene solo la milestone in
corso, che e quello che state.cjs conta per il progresso
- v2.1-ROADMAP.md ricostruito: era l'unica milestone senza archivio,
interrotta dal reset del 19/06 e mai chiusa formalmente
- v2.3-ROADMAP.md + v2.3-REQUIREMENTS.md: v2.3 e stata eseguita fuori dal
ciclo GSD, non esistono PLAN/SUMMARY per fase. L'archivio E la doc
- REQUIREMENTS.md riscritto per v2.4 con il backlog reale
- phases/13 e phases/26: SUMMARY ricostruiti da commit, migration e
STATUS.md. 26 e il primo numero libero
- research/: cancellate 4 varianti dello stesso PITFALLS e FEATURES/
SUMMARY, superati da PROJECT.md. Diverse anti-feature erano ormai
contraddette dai fatti (il Kanban e stato costruito in Phase 19,
l'email in v2.3, il time tracking esiste)
- cancellati UI-RULES.md e DESIGN-SYSTEM.md (CLAUDE.md li dichiara
superseded: impongono l'inverso della regola attuale) e HANDOFF.md,
fermo al 13/06
- SECURITY-*.md -> security/: audit chiuso, ma i report restano la doc di
cosa e stato ruotato e perche
- PROJECT.md/MILESTONES.md/ROADMAP.md allineati: milestone corrente v2.4,
sessione OTP 90gg non 30, migrazioni fino alla 0016
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
92 lines
6.0 KiB
Markdown
92 lines
6.0 KiB
Markdown
---
|
||
phase: 12
|
||
phase_name: offer-editor-tier-tag-prezzo-pubblico
|
||
source: user mockups + decisions (2026-06-14)
|
||
status: decisions-locked
|
||
---
|
||
|
||
# Phase 12 — Context (User Decisions)
|
||
|
||
> Catturato da 2 mockup utente + risposte dirette il 2026-06-14. Questo documento è
|
||
> **autorevole** per il planner: dove confligge con la roadmap originale ("drag&drop + CSV"),
|
||
> vince questo. La Phase 12 è stata **ri-scoped** da "Offer Composition Drag&Drop & CSV Import"
|
||
> a **"Offer Editor — Tier A/B/C, Tag & Prezzo Pubblico"**.
|
||
|
||
## Decisioni bloccate
|
||
|
||
| # | Decisione | Valore |
|
||
|---|-----------|--------|
|
||
| D-1 | Scope | Editor offerte completo (lista + dettaglio). Import CSV/Notion (ex OFFER-12) **rimandato** a fase futura. |
|
||
| D-2 | UX composizione tier | **Matrice di checkbox** servizio × tier (A/B/C), NON drag&drop puro. Totale servizi live per colonna/tier. `@dnd-kit` usato solo (eventualmente) per riordinare le righe. |
|
||
| D-3 | Fonte servizi | Catalogo unificato `services` (Phase 11), **non** il legacy `offer_services`. |
|
||
| D-4 | Filtro servizi per categoria | Il servizio porta già, a livello di catalogo, la designazione di categoria offerta (entry / signature / retainer). L'editor mostra/pre-filtra nella matrice i servizi pertinenti alla categoria dell'offerta in modifica. |
|
||
| D-5 | Prezzo | Per ogni tier: **Totale servizi** (auto-somma dei servizi spuntati) + **Prezzo Pubblico** (manuale, indipendente). Coerente con la decisione PROJECT.md "prezzi pacchetti per-preventivo, non da catalogo". |
|
||
| D-6 | Schema | **Solo additivo** (Data Safety LOCKED). Riusare le tabelle offerte esistenti, non ricostruire. |
|
||
|
||
## Modello dati (intento — il planner produce la migration esatta)
|
||
|
||
Mappatura mockup → schema esistente (`src/db/schema.ts`):
|
||
|
||
- **Offerta** → `offer_macros` (esiste: `internal_name`, `public_name`, `transformation_promise`, `sort_order`).
|
||
Aggiunte additive previste: descrizione breve, flag `is_archived`, campi strutturati della
|
||
promessa di trasformazione (Cliente Ideale / Risultato / tempo / Pain / Metodo).
|
||
- **Tier A/B/C** → `offer_micros` (esiste: `macro_id`, `cumulative_price`, `duration_months`, ...).
|
||
Aggiunte additive previste: lettera tier (`A`|`B`|`C`) e `public_price` (prezzo pubblico manuale).
|
||
Un'offerta = una macro con (fino a) 3 micro-tier.
|
||
- **Matrice servizi × tier** → junction tier ↔ `services`. La junction legacy `offer_micro_services`
|
||
punta a `offer_services`; **non modificarla**. Approccio additivo consigliato: **nuova tabella di
|
||
junction** (es. `offer_tier_services`: tier_id → `offer_micros.id`, service_id → `services.id`) così
|
||
da non toccare dati legacy e agganciare il catalogo unificato. Il planner decide il nome/struttura
|
||
esatti; deve restare additivo.
|
||
- **Tag multi-dimensione** (categoria / ticket / tipo / obiettivo) → riusare la tabella polimorfica
|
||
`tags` (`entity_type`, `entity_id`, `name`) di Phase 11 con `entity_type = "offer_macros"` (o simile).
|
||
Le 4 dimensioni vanno distinte: il planner valuta se serve un campo `dimension` additivo sulla
|
||
tabella `tags`, oppure colonne single-select dedicate su `offer_macros` per categoria/ticket (singole)
|
||
+ tag multipli per tipo/obiettivo. Da chiarire in research; resta additivo.
|
||
- **Designazione categoria del servizio** (entry/signature/retainer, D-4): verificare se va su
|
||
`services.category` (single-select già esistente), su un tag, o su una nuova colonna additiva
|
||
dedicata. NON sovrascrivere la semantica attuale di `services.category`/`services.fase` se già usata
|
||
diversamente in `/admin/catalog` — il planner verifica l'uso corrente prima di scegliere.
|
||
|
||
## UI (riferimento mockup)
|
||
|
||
**Lista offerte** (`/admin/offers` ridisegnata): card filtrabili per categoria (Entry / Signature /
|
||
Retainer Offer come chip colorati), ogni card = nome custom + breve descrizione + chip categoria;
|
||
toggle "mostra offerte archiviate"; bottone "+ Nuova Offerta".
|
||
|
||
**Editor offerta**: nome custom editabile in alto; chip Categoria + Ticket; chip Tipo (Audit /
|
||
Done For You) e Obiettivo (Primo Acquisto / Up Scala Valore / Lead Generation); tabella "servizi
|
||
inclusi" con colonne A / B / C e checkbox per cella, prezzo del servizio a sinistra; riga "Totale dei
|
||
servizi" (auto) e "Prezzo Pubblico" (manuale) per ogni tier; blocco "Promessa di Trasformazione"
|
||
strutturato (Aiuto Cliente Ideale / A ottenere Risultato / in tempo / Senza Pain / Grazie a Metodo);
|
||
bottone "Salva Offerta".
|
||
|
||
Stile: continuità con Phase 11 (vista database Notion-like, palette brand #1A463C / #DEF168, EditableCell,
|
||
OptionMultiSelect/tag, server actions `requireAdmin`-guarded). Vedi `12-UI-SPEC.md` (da rigenerare su
|
||
questo scope).
|
||
|
||
## Vincoli (da CLAUDE.md / PROJECT.md)
|
||
|
||
- **Data Safety LOCKED**: migration solo additive su `clients`/`projects`/`payments`/`phases`; nessun
|
||
drop/truncate. Anche le tabelle offerte vanno estese, non ricostruite.
|
||
- **Migration manuali**: `drizzle-kit generate` è non funzionante (snapshot fuori sync da migration 0001) —
|
||
scrivere SQL a mano seguendo la convenzione 0003-0007. Applicare a **prod** via SSH+docker exec
|
||
**PRIMA** di pushare codice che dipende dal nuovo schema (DB prod firewalled, raggiungibile solo via SSH).
|
||
- `quote_items` mai esposti via client API. L'editor offerte è admin-only (`/admin/*`, sessione Auth.js).
|
||
|
||
## Fuori scope (questa fase)
|
||
|
||
- Import CSV / import da Notion (OFFER-12, rimandato).
|
||
- Sezioni analitiche Notion (psicologia/rating/performance — OFFER-14, v2).
|
||
- Collegamento offerta→preventivo/pagamento (Proposal AI, Phase 16/17).
|
||
- Pagina pubblica dell'offerta (Phase 17).
|
||
|
||
## Domande risolte (erano aperte nel primo RESEARCH)
|
||
|
||
1. Placement composer → **`/admin/offers` ridisegnata** (lista + editor). ✓
|
||
2. Persistenza offerta → **macro = offerta, micro = tier A/B/C** (riuso additivo). ✓
|
||
3. Tag audit CSV → **N/A** (import rimandato). ✓
|
||
4. Duplicati / parsing CSV → **N/A** (import rimandato). ✓
|
||
5. Prezzi servizi editabili → **no inline qui**: il tier ha totale auto + prezzo pubblico manuale; i
|
||
prezzi unitari restano gestiti nel catalogo `services` (Phase 11). ✓
|