CREATE TABLE IF NOT EXISTS growth_reports ( id text PRIMARY KEY, merchant_id bigint NOT NULL REFERENCES merchants(id), terminal_id bigint REFERENCES terminals(id), terminal_source_key text, fingerprint text NOT NULL, revision integer NOT NULL DEFAULT 1 CHECK (revision > 0), status text NOT NULL CHECK (status IN ('QUEUED','ANALYZING','GENERATING','READY','PARTIAL','FAILED')), horizon_days integer NOT NULL DEFAULT 90 CHECK (horizon_days = 90), forecast_start_date date, dataset_watermark text NOT NULL, catalog_version text NOT NULL, analytics_version text NOT NULL, prompt_version text NOT NULL, schema_version text NOT NULL, model text NOT NULL, deterministic_evidence jsonb, ai_response jsonb, failure_code text, input_tokens bigint NOT NULL DEFAULT 0 CHECK (input_tokens >= 0), output_tokens bigint NOT NULL DEFAULT 0 CHECK (output_tokens >= 0), latency_ms bigint NOT NULL DEFAULT 0 CHECK (latency_ms >= 0), provider_request_id text, estimated_cost text, manual_refresh boolean NOT NULL DEFAULT false, tehran_refresh_day date, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), completed_at timestamptz ); -- statement-break ALTER TABLE growth_reports ADD COLUMN IF NOT EXISTS provider_request_id text; -- statement-break ALTER TABLE growth_reports ADD COLUMN IF NOT EXISTS estimated_cost text; -- statement-break ALTER TABLE growth_reports ALTER COLUMN deterministic_evidence DROP NOT NULL; -- statement-break CREATE UNIQUE INDEX IF NOT EXISTS growth_reports_current_fingerprint_idx ON growth_reports (merchant_id, fingerprint) WHERE manual_refresh = false AND status IN ('QUEUED','ANALYZING','GENERATING','READY','PARTIAL'); -- statement-break CREATE UNIQUE INDEX IF NOT EXISTS growth_reports_daily_merchant_refresh_idx ON growth_reports (merchant_id, tehran_refresh_day) WHERE manual_refresh = true; -- statement-break CREATE INDEX IF NOT EXISTS growth_reports_scope_latest_idx ON growth_reports (merchant_id, terminal_id, revision DESC, created_at DESC); -- statement-break CREATE INDEX IF NOT EXISTS growth_reports_pending_idx ON growth_reports (created_at) WHERE status IN ('QUEUED','ANALYZING','GENERATING'); -- statement-break CREATE TABLE IF NOT EXISTS growth_report_idempotency ( merchant_id bigint NOT NULL REFERENCES merchants(id), idempotency_key text NOT NULL, request_hash text NOT NULL, report_id text NOT NULL REFERENCES growth_reports(id) ON DELETE CASCADE, created_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (merchant_id, idempotency_key) ); -- statement-break CREATE INDEX IF NOT EXISTS growth_report_idempotency_created_idx ON growth_report_idempotency (created_at); -- statement-break INSERT INTO schema_migrations(version) VALUES (2) ON CONFLICT DO NOTHING;