← back to B Version 1
database/schema.sql
142 lines
-- Dear Bubbe Database Schema
-- PostgreSQL / SQLite compatible
CREATE TABLE IF NOT EXISTS dear_bubbe_entries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Source information
original_source VARCHAR(100) CHECK (original_source IN (
'Dear Abby',
'Ann Landers',
'Public Domain',
'Bubbe Original',
'User Submitted'
)),
original_date DATE,
original_question_text TEXT,
source_url TEXT,
-- Bubbe transformation
bubbe_rewritten_question TEXT NOT NULL,
bubbe_answer TEXT NOT NULL,
-- Categorization
category VARCHAR(50) CHECK (category IN (
'family',
'romance',
'dating',
'marriage',
'health',
'money',
'etiquette',
'work',
'neighbors',
'holidays',
'grief',
'kids',
'teens',
'pets',
'mother-in-law',
'cheating',
'friendship',
'moral-dilemma',
'awkward',
'misc'
)) NOT NULL,
tags TEXT[], -- Array of tags for additional categorization
-- Tone/style
tone VARCHAR(50) DEFAULT 'yiddish-grandma',
yiddish_level VARCHAR(20) CHECK (yiddish_level IN ('light', 'medium', 'heavy')) DEFAULT 'medium',
sarcasm_level INTEGER CHECK (sarcasm_level BETWEEN 1 AND 5) DEFAULT 3,
-- SMS compatibility
sms_length_ok BOOLEAN DEFAULT TRUE,
character_count INTEGER,
-- Scheduling
sent_count INTEGER DEFAULT 0,
last_sent_date TIMESTAMP,
next_eligible_date DATE,
-- Quality control
approved BOOLEAN DEFAULT TRUE,
flagged BOOLEAN DEFAULT FALSE,
notes TEXT,
-- Metadata
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Indexes for performance
CREATE INDEX idx_category ON dear_bubbe_entries(category);
CREATE INDEX idx_sent_count ON dear_bubbe_entries(sent_count);
CREATE INDEX idx_next_eligible ON dear_bubbe_entries(next_eligible_date);
CREATE INDEX idx_approved ON dear_bubbe_entries(approved);
-- SMS delivery log
CREATE TABLE IF NOT EXISTS sms_delivery_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
entry_id UUID REFERENCES dear_bubbe_entries(id),
phone_number VARCHAR(20),
sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
delivery_status VARCHAR(20) CHECK (delivery_status IN (
'queued',
'sent',
'delivered',
'failed',
'undelivered'
)),
twilio_sid VARCHAR(100),
error_message TEXT,
cost DECIMAL(10,4)
);
CREATE INDEX idx_sms_entry_id ON sms_delivery_log(entry_id);
CREATE INDEX idx_sms_sent_at ON sms_delivery_log(sent_at);
-- User subscriptions
CREATE TABLE IF NOT EXISTS subscribers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
phone_number VARCHAR(20) UNIQUE NOT NULL,
timezone VARCHAR(50) DEFAULT 'America/New_York',
delivery_time TIME DEFAULT '08:00:00',
active BOOLEAN DEFAULT TRUE,
-- Preferences
categories_preference TEXT[], -- Specific categories they want
frequency VARCHAR(20) CHECK (frequency IN ('daily', 'weekdays', 'weekly')) DEFAULT 'daily',
-- Metadata
subscribed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
unsubscribed_at TIMESTAMP,
total_messages_received INTEGER DEFAULT 0
);
CREATE INDEX idx_subscribers_active ON subscribers(active);
CREATE INDEX idx_subscribers_phone ON subscribers(phone_number);
-- User feedback
CREATE TABLE IF NOT EXISTS feedback (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
entry_id UUID REFERENCES dear_bubbe_entries(id),
subscriber_id UUID REFERENCES subscribers(id),
rating INTEGER CHECK (rating BETWEEN 1 AND 5),
feedback_text TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Statistics view
CREATE VIEW bubbe_stats AS
SELECT
category,
COUNT(*) as total_entries,
SUM(sent_count) as total_sends,
AVG(character_count) as avg_length,
COUNT(CASE WHEN sms_length_ok THEN 1 END) as sms_compatible
FROM dear_bubbe_entries
WHERE approved = TRUE
GROUP BY category;