Commit Graph

14 Commits

Author SHA1 Message Date
simone 43238341c1 feat: service offer tags, catalog cleanup, offer editor filter
- Import 58 offer membership tags for all 55 services (entity_type="services")
  via scripts/import-service-offer-tags.ts (already run on prod)
- ServiceTable: remove Categoria column, rename Tag → Offerta; QuickAddRow
  no longer has a category field (offer tags set post-creation)
- offer-queries: getOfferEditorData fetches offerTags per service (join on
  tags WHERE entity_type="services") and exposes them in OfferEditorData
- OfferEditorClient: filter chips above "Servizi Inclusi" — Tutti / Entry
  Offer / Signature Offer / Retainer Offer, derived from actual tag data

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 21:58:34 +02:00
simone 696a95950c chore: add Notion service import scripts
scripts/reset-and-import-services.ts — deletes 3 legacy test services,
imports 55 services from Notion "DB Offerta: Attività SC" CSV export
(Signature Offer / Entry Offer / Retainer Offer, with fase metadata).

scripts/import-services-notion.ts — standalone idempotent version.

Run via SSH tunnel with DATABASE_URL pointed at 127.0.0.1:54321.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 21:46:17 +02:00
simone a372c613e2 feat(12-03): add offer editor server actions
- saveOfferEditor(macroId, payload): persists macro scalars, per-tier
  upsert (tier_letter Zod-validated A/B/C), offer_tier_services
  delete-then-reinsert, and Tipo/Obiettivo tags delete-then-reinsert,
  all in one call
- toggleOfferArchived(macroId, archived) for OFFER-18
- addOfferTag/removeOfferTag/renameOfferOption for Tipo/Obiettivo/
  Categoria/Ticket dimensions, mirroring catalog option-pool pattern
- createOfferMacro(formData) — Plan 04 "+ Nuova Offerta" target
- scripts/verify-12-03-actions.ts documents the 9 spec'd test cases
  (typecheck-only, requireAdmin needs a request context)
2026-06-15 10:17:07 +02:00
simone 0d742f2328 feat(12-03): add offer editor query layer
- getOfferListCards() for Plan 04 list page (category + archive status)
- getOfferEditorData(macroId) returns macro fields, A/B/C tiers with
  assignedServiceIds + computed servicesTotal, category-filtered
  availableServices, and tipoTags/obiettivoTags
- getOfferFieldOptions() for categoria/ticket/tipo/obiettivo select pools
- scripts/verify-12-03-queries.ts documents the 5 spec'd test cases
  (typecheck-only, no test runner configured, prod DB not mutated)
2026-06-15 10:15:19 +02:00
simone 89d15eeb54 feat(12-01): add migration 0008 for offer tier schema + idempotent push script
- Hand-write 0008_offer_tier_schema.sql: additive ALTER TABLE ADD COLUMN IF NOT EXISTS for offer_macros/offer_micros, guarded DO-block CHECK constraint on tier_letter, CREATE TABLE IF NOT EXISTS offer_tier_services + index
- Append journal entry for 0008_offer_tier_schema following the 0006 entry shape
- Add scripts/push-12-offer-tier-schema.ts: idempotent push script with PRODUCTION DEPLOY NOTE — BLOCKING step for Plan 02 (SSH+docker exec) before Wave 3 query layer
2026-06-14 21:19:10 +02:00
simone e858a8f577 feat(catalog): Notion-style shared select fields (tag/pacchetto/categoria/fase)
Turn the catalog into Notion/Airtable select properties:
- Tag + Pacchetto: multi-select with a SHARED pool — created values persist and
  are selectable from a dropdown across all services (no more re-typing)
- Categoria + Fase: single-select chips with the same dropdown + create-on-the-fly
- Rename an option once -> propagates to every row (renameServiceOption)
- Deterministic colors per value (shared option-colors util)
- Quick-add row now sets name+description+categoria+fase+prezzo then Enter (active)
- Search broadened to name/categoria/fase/tag/pacchetto

Data model (additive): tag/pacchetto in polymorphic tags table (entity_type
services / services.pacchetto); categoria/fase as single-select columns on
services (new: services.fase). Pools derived from distinct values.

New: OptionSelect, OptionMultiSelect, option-colors. Removed tag-multi-select.
Migration 0007_add_services_fase.sql must be applied before runtime.

tsc + eslint + next build clean. CSV bulk import (OFFER-12) stays Phase 12.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:40:34 +02:00
simone 2f2589f0b9 feat(11-01): add tag-assignment migration and validation scripts (OFFER-13/D-02)
- scripts/migrate-tags.ts: idempotently assigns the "Offerta" tag to every
  services row where migrated_from = 'offer_services' (D-02)
- scripts/validate-tags-migration.ts: row-count + orphan checks for the
  tags consolidation dimension of OFFER-13

NOTE: Not yet executed against the dev/staging DB (178.104.27.55:54321) —
that host is firewalled and only reachable via SSH+docker exec per project
memory, which is out of scope for this agent's authorization. Execution of
this script, scripts/migrate-services.ts, scripts/validate-services-migration.ts,
and scripts/push-11-tags-migration.ts is documented as a pending access gate
in 11-01-SUMMARY.md.
2026-06-13 15:27:07 +02:00
simone 4773487d0c feat(11-01): add tags table to schema with migration and push script
- Add polymorphic tags table (entity_type/entity_id/name) with unique
  index on (entity_type, entity_id, name) and lookup index on
  (entity_type, entity_id) — pattern follows comments table (D-05/D-06/D-07)
- Add Tag/NewTag types and tagsRelations (no direct FK, query-time join)
- Hand-write src/db/migrations/0006_add_tags_table.sql following the
  established project convention (drizzle-kit generate is unusable here —
  meta/_journal.json snapshots out of sync since 0001, pre-existing since
  Phase 8) and add journal entry for 0006_add_tags_table
- Add scripts/push-11-tags-migration.ts (idempotent CREATE TABLE/INDEX IF
  NOT EXISTS) with production deploy note for manual SSH+docker exec apply
2026-06-13 15:26:14 +02:00
simone 008a43469d feat(10-redo-C): CRM leads module — schema, services, UI (Phase 10 redo)
Stage C of staged Phase 10 redo. Restores dangling phase10-wip work:
- schema.ts: leads expansion + activities/reminders tables + relations
- lead-service.ts / lead-validators.ts service layer
- /admin/leads list + detail + actions, LeadTable/LeadDetail/LeadForm
- LogActivityModal, SendQuoteModal, FollowUpWidget on dashboard
- migration 0005 (applied to prod DB in Stage B, along with
  previously-missing 0001/0003/0004 — root cause of all post-deploy
  500s: prod DB had no migrations applied since 0000)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 20:58:14 +02:00
simone f727954dfb feat(08-02): create Phase 8 migration and validation script
- Create SQL migration 0003_offer_phases_quote_templates.sql
  - Creates offers_phases, offer_phase_services, quotes, leads tables
  - Adds new columns to quote_items, projects, phases (additive-only)
  - Includes proper FK constraints, indexes, and CHECK constraints
  - ZERO DATA LOSS: No drops, no truncates — fully reversible

- Create validation script scripts/validate-phase8-migration.ts
  - Checks all 4 new tables exist
  - Verifies 7 new columns added to existing tables
  - Validates FK references intact
  - Exit code 0 on success, 1 on failure

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-11 07:15:27 +02:00
simone 23a9f8ad8c feat(07-unified-service-catalog): add net-new services informational check to validation script
- Check 6: Count of services with migrated_from IS NULL (net-new rows created via /admin/catalog after migration)
- Printed as informational line at the end of validation output
- Does not fail validation if count is zero (expected for fresh test runs)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-11 06:26:24 +02:00
simone de0888b3ec feat(07-unified-service-catalog): add migration and validation scripts
Task 2: Idempotent backfill script (migrate-services.ts)
- Migrates service_catalog (21 rows) → services with migrated_from='service_catalog'
- Migrates offer_services (35 rows) → services with migrated_from='offer_services'
- Name collision detection: appends ' (Offer)' suffix to prevent overwrites
- Idempotent via (migrated_from, migrated_id) lookups — re-runs are safe no-ops
- Categorizes services: 'catalog' for operational pricing, 'offer' for marketing pricing
- Maps service_catalog.description → services.description
- Maps offer_services.transformation_description → services.description
- Maps service_catalog.unit_price → services.unit_price
- Maps offer_services.price → services.unit_price

Task 3: Validation script (validate-services-migration.ts)
- Check 1: Row counts match (service_catalog/offer_services rows == migrated rows)
- Check 2: No orphaned migrated_id references (all point to existing source rows)
- Check 3: Existing quote_items.service_id FKs remain valid (untouched)
- Check 4: Existing offer_micro_services.service_id FKs remain valid (untouched)
- Check 5: Report any unresolved name collisions (post-migration integrity)
- Exits 0 only if all checks PASS

Plus: push-services-migration.ts helper for direct SQL execution when drizzle-kit unavailable.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-11 06:21:44 +02:00
simone 63c9f750df feat(04-01): multi-project schema migration — projects, settings, FK pivot
- schema.ts: add projects table, settings kv table, slug on clients;
  migrate 6 FK from client_id to project_id (phases, payments, documents, notes,
  time_entries, quote_items); update all relations and TypeScript types
- admin-queries.ts: fix getAllClientsWithPayments + getClientFullDetail to aggregate
  through projects; add getAllProjectsWithPayments, getProjectFullDetail,
  getClientWithProjects, ClientWithProjects type
- settings.ts: new file — getSetting, updateSetting, getTargetHourlyRate, SETTINGS_KEYS
- Fix all downstream files: actions.ts, quote-actions.ts, new/actions.ts,
  timer-actions.ts, approve/route.ts, comment/route.ts, TimerCell.tsx,
  analytics-queries.ts, client-view.ts, seed.ts
- DB migration applied to Coolify Postgres (all test data cleared, schema rebuilt)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 21:58:15 +02:00
Simone Cavalli 073eec7193 feat(seed): add seed script + fix Tailwind scanning adjacent projects
- scripts/seed.ts: inserts one complete test client with 3 phases,
  6 tasks, 4 deliverables, 2 payments, 2 documents, 2 notes; prints
  shareable URL to console
- globals.css: add @source not directives to exclude .01_projects/
  and .claude/ — Tailwind v4 was scanning the SparklingOrbit .venv
  Python files and generating invalid CSS class [-:|] from a regex
  pattern in a markdown-it table parser, causing dev server 500s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 23:33:03 +02:00