.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>
8.2 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | |||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12-offer-composition-drag-drop-csv-import | 03 | api |
|
|
|
|
|
|
|
|
|
12min | 2026-06-15 |
Phase 12 Plan 03: Offer Editor Query Layer & Server Actions Summary
Query layer (getOfferEditorData, getOfferListCards, getOfferFieldOptions) and server actions (saveOfferEditor + archive/tag/rename/create actions) giving Plans 04/05 a complete, type-safe, admin-only data contract for the offer editor.
Performance
- Duration: 12 min
- Started: 2026-06-15T08:15:00Z (approx)
- Completed: 2026-06-15T08:17:07Z
- Tasks: 2 completed
- Files modified: 4 (2 source, 2 new verification scripts)
Accomplishments
- Added
getOfferListCards()tosrc/lib/offer-queries.ts: returns{ id, internal_name, description, category, is_archived }peroffer_macrosrow, ordered bysort_order, including archived offers (client-side filter per UI-SPEC) - Added
getOfferEditorData(macroId): returns{ macro, tiers, availableServices, tipoTags, obiettivoTags }— tiers ordered A→B→C via SQLCASEexpression, each withassignedServiceIdsand a computedservicesTotal(coalesce(sum(unit_price::numeric), 0)joined throughoffer_tier_services), available services pre-filtered byservices.category === macro.category(D-4, best-effort when category unset) - Added
getOfferFieldOptions():{ categoria, ticket, tipo, obiettivo }distinct-value pools, mirroringgetCatalogFieldOptions's null-filter + alphabetical sort pattern - Added
saveOfferEditor(macroId, payload)tosrc/app/admin/offers/actions.ts: Zod-validates the full editor payload (tier_letterrestricted to["A","B","C"]), updatesoffer_macrosscalars, upserts each tier (update ifidpresent, insert +.returning({id})if not), delete-then-reinsertsoffer_tier_servicesper tier, and delete-then-reinserts Tipo/Obiettivotags - Added
toggleOfferArchived,addOfferTag/removeOfferTag(tipo/obiettivo dimensions),renameOfferOption(categoria/ticket/tipo/obiettivo), andcreateOfferMacro(Plan 04 "+ Nuova Offerta" target, defaultspublic_nametointernal_name) - All new actions call
requireAdmin()first; existing exports in both files left untouched
Task Commits
Each task was committed atomically:
- Task 1: Query layer — getOfferEditorData, getOfferListCards, getOfferFieldOptions -
0d742f2(feat) - Task 2: Server actions — saveOfferEditor, toggleOfferArchived, offer tag CRUD, createOfferMacro -
a372c61(feat)
Plan metadata: (this commit, follows)
Files Created/Modified
src/lib/offer-queries.ts- AddedgetOfferListCards,getOfferEditorData,getOfferFieldOptions+OfferListCard/OfferTierData/OfferEditorData/OfferFieldOptionstypes; importsoffer_tier_services,services,tags,andfrom drizzle-ormsrc/app/admin/offers/actions.ts- AddedsaveOfferEditor,toggleOfferArchived,addOfferTag,removeOfferTag,renameOfferOption,createOfferMacro+SaveOfferEditorPayload/tierSchema/saveOfferEditorSchematypes; importsoffer_tier_services,tags,and,inArrayscripts/verify-12-03-queries.ts- Typecheck-only documentation of the 5 query-layer test cases (Tests 1-5 from Task 1's<behavior>)scripts/verify-12-03-actions.ts- Typecheck-only documentation of the 9 server-action test cases (Tests 1-9 from Task 2's<behavior>)
Decisions Made
- No test runner configured in this repo (
package.jsonhas noscripts.test), and.env.local'sDATABASE_URLpoints at production per project memory — followed the plan's explicit fallback and wrotescripts/verify-12-03-queries.ts/scripts/verify-12-03-actions.tsas typecheck-only documentation of all 14 spec'd test cases, not executed against the live DB saveOfferEditoruses sequentialawaits (macro update → per-tier upsert/replace → tag replace) with no transaction wrapper, matching the existing per-statement pattern used byupdateMicroOfferServicesand the rest of this codebase
Deviations from Plan
None - plan executed exactly as written. Both tasks implemented the documented function signatures, return shapes, and validation rules verbatim; existing exports in offer-queries.ts and actions.ts were not modified.
Issues Encountered
None.
User Setup Required
None - no external service configuration required. This plan is pure source-code (query/action functions); migration 0008 was already live on production (verified per Plan 02), and no data-mutating scripts were run.
Next Phase Readiness
- Plan 04 (offer list page) can call
getOfferListCards()andcreateOfferMacrofor the "+ Nuova Offerta" button - Plan 05 (offer editor page) can call
getOfferEditorData(macroId)to populate the full editor (macro fields, tier matrix with live totals, Tipo/Obiettivo tags, category-filtered service catalog) and persist all of it via a singlesaveOfferEditor(macroId, payload)call; archive toggling viatoggleOfferArchived; tag/option CRUD viaaddOfferTag/removeOfferTag/renameOfferOption npx tsc --noEmitpasses with zero errors across the full project- No legacy
offer_micro_services/offer_services/existing-export code paths were touched
Phase: 12-offer-composition-drag-drop-csv-import Completed: 2026-06-15
Self-Check: PASSED
All created/modified files verified present on disk:
- FOUND: src/lib/offer-queries.ts
- FOUND: src/app/admin/offers/actions.ts
- FOUND: scripts/verify-12-03-queries.ts
- FOUND: scripts/verify-12-03-actions.ts
- FOUND: .planning/phases/12-offer-composition-drag-drop-csv-import/12-03-SUMMARY.md
All task commits verified present in git log: