← back to Ventura Corridor

db/migrations/017_magazine_addons.sql

75 lines

-- Migration 017 — magazine layer add-ons created ad-hoc during the
-- 2026-05-06 overnight loop session: monthly cover picker, reader feedback
-- intake, sponsor inquiries persistence, coverage snapshot history.

-- Issue cover picker (iter 138 + 144 image upload)
CREATE TABLE IF NOT EXISTS magazine_issues (
  issue_month       TEXT PRIMARY KEY,                         -- 'YYYY-MM'
  cover_feature_id  BIGINT REFERENCES magazine_features(id) ON DELETE SET NULL,
  cover_caption     TEXT,
  cover_kicker      TEXT,
  cover_image_path  TEXT,                                     -- filename in data/covers/
  cover_set_at      TIMESTAMPTZ,
  published_at      TIMESTAMPTZ,
  notes             TEXT
);

-- Reader feedback intake (iter 130 + 143 George email)
CREATE TABLE IF NOT EXISTS reader_feedback (
  id           BIGSERIAL PRIMARY KEY,
  feature_id   BIGINT,                                         -- nullable; comments on whole issue ok
  kind         TEXT NOT NULL,                                  -- typo|correction|tip|complaint|praise|note
  body         TEXT NOT NULL,
  contact      TEXT,                                           -- optional reader email
  source_path  TEXT,                                           -- where the form was submitted from
  received_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  reviewed     BOOLEAN NOT NULL DEFAULT FALSE
);
CREATE INDEX IF NOT EXISTS idx_reader_feedback_received_at ON reader_feedback (received_at DESC);
CREATE INDEX IF NOT EXISTS idx_reader_feedback_unreviewed ON reader_feedback (received_at DESC) WHERE NOT reviewed;

-- Sponsor inquiries persistence (paired with /sponsor.html, iter ~127)
CREATE TABLE IF NOT EXISTS sponsor_inquiries (
  id                BIGSERIAL PRIMARY KEY,
  feature_id        BIGINT,
  biz_name          TEXT,
  contact_name      TEXT NOT NULL,
  contact_email     TEXT NOT NULL,
  contact_phone     TEXT,
  tier              TEXT,                                       -- 'spread' | 'cover' | 'ask'
  notes             TEXT,
  received_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  status            TEXT NOT NULL DEFAULT 'new',                -- new | responded | closed | spam
  email_message_id  TEXT
);
CREATE INDEX IF NOT EXISTS idx_sponsor_inquiries_received_at ON sponsor_inquiries (received_at DESC);
CREATE INDEX IF NOT EXISTS idx_sponsor_inquiries_status ON sponsor_inquiries (status, received_at DESC);

-- Daily coverage snapshots (iter 158, populates /coverage.html growth line)
CREATE TABLE IF NOT EXISTS coverage_snapshots (
  id                BIGSERIAL PRIMARY KEY,
  taken_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  total_biz         INTEGER NOT NULL,
  biz_with_features INTEGER NOT NULL,
  total_features    INTEGER NOT NULL,
  drafts            INTEGER NOT NULL,
  reviewed          INTEGER NOT NULL,
  published         INTEGER NOT NULL,
  spiked            INTEGER NOT NULL,
  feedback_total    INTEGER NOT NULL DEFAULT 0,
  feedback_unread   INTEGER NOT NULL DEFAULT 0,
  inquiries_total   INTEGER NOT NULL DEFAULT 0,
  inquiries_open    INTEGER NOT NULL DEFAULT 0,
  notes             TEXT
);
CREATE INDEX IF NOT EXISTS idx_coverage_snapshots_taken_at ON coverage_snapshots (taken_at);

-- Editor margin notes column on features (iter 149) — only add if not already there
ALTER TABLE magazine_features
  ADD COLUMN IF NOT EXISTS notes TEXT;

-- Initial empty row for current month so the cover picker has a row to PATCH
INSERT INTO magazine_issues (issue_month, cover_set_at)
SELECT to_char(now(),'YYYY-MM'), now()
ON CONFLICT (issue_month) DO NOTHING;