-- Additive: timer per fase/task e data di consegna attesa sul progetto. -- -- ── time_entries.phase_id / task_id ────────────────────────────────────────── -- Il timer nasce a livello di progetto: time_entries aveva la sola project_id, -- quindi "quanto e' costata questa fase" non era una domanda che si potesse -- fare. Le due colonne sono NULLABLE e project_id resta obbligatoria: ogni -- entry e' sempre attribuita a un progetto, il dettaglio e' un di piu'. -- Le righe esistenti restano valide con entrambe a NULL, cioe' "tempo di -- progetto, non imputato a una fase" — che e' esattamente cio' che sono. -- -- ON DELETE SET NULL, non CASCADE, ed e' la scelta che conta qui: cancellare un -- task NON deve cancellare il tempo tracciato su di esso. Sono ore lavorate, e -- quindi storico fatturabile; l'entry ricade a livello progetto e il totale del -- progetto non cambia mai. Con CASCADE, ripulire una fase avrebbe silenziosamente -- abbassato il fatturato tracciato. -- -- ── projects.due_date ──────────────────────────────────────────────────────── -- La consegna attesa e' normalmente DERIVATA: project_offers.start_date + -- offer_micros.duration_months. Questa colonna e' l'override manuale, e vince -- sulla derivata quando e' valorizzata. Nullable per forza: la stragrande -- maggioranza dei progetti continuera' a non averla, ed e' giusto cosi' — -- un campo obbligatorio in piu' su ogni progetto e' un campo che invecchia. -- -- Nessun DROP, nessun TRUNCATE, nessuna colonna rimossa o modificata. -- Applicare a prod via SSH+docker exec PRIMA di pushare il codice dipendente. -- Idempotente: safe to re-run. ALTER TABLE time_entries ADD COLUMN IF NOT EXISTS phase_id text REFERENCES phases(id) ON DELETE SET NULL; ALTER TABLE time_entries ADD COLUMN IF NOT EXISTS task_id text REFERENCES tasks(id) ON DELETE SET NULL; -- Il rollup per fase raggruppa su queste due colonne a ogni apertura del -- progetto: senza indice diventa una scansione piena appena le entry crescono. CREATE INDEX IF NOT EXISTS time_entries_phase_idx ON time_entries (phase_id); CREATE INDEX IF NOT EXISTS time_entries_task_idx ON time_entries (task_id); ALTER TABLE projects ADD COLUMN IF NOT EXISTS due_date timestamptz;