# Database Migrations Guide

## Overview

This document lists all database tables that need to be created when deploying Pounce to a new server.

## Required Tables

### Core Tables (Already Implemented)

| Table | Model | Description |
|-------|-------|-------------|
| `users` | User | User accounts and authentication |
| `subscriptions` | Subscription | User subscription plans (Scout, Trader, Tycoon) |
| `domains` | Domain | Tracked domains in watchlists |
| `domain_checks` | DomainCheck | Domain availability check history |
| `tld_prices` | TLDPrice | TLD price history |
| `tld_info` | TLDInfo | TLD metadata |
| `portfolio_domains` | PortfolioDomain | User-owned domains |
| `domain_valuations` | DomainValuation | Domain valuation history |
| `domain_auctions` | DomainAuction | Scraped auction listings |
| `auction_scrape_logs` | AuctionScrapeLog | Scraping job logs |
| `newsletter_subscribers` | NewsletterSubscriber | Email newsletter list |
| `price_alerts` | PriceAlert | TLD price change alerts |
| `admin_activity_logs` | AdminActivityLog | Admin action audit log |
| `blog_posts` | BlogPost | Blog content |

---

### NEW Tables (To Be Created)

These tables were added for the **"For Sale" Marketplace** and **Sniper Alerts** features:

#### 1. Domain Listings (For Sale Marketplace)

```sql
-- Main listing table
CREATE TABLE domain_listings (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL REFERENCES users(id),
    domain VARCHAR(255) NOT NULL UNIQUE,
    slug VARCHAR(300) NOT NULL UNIQUE,
    title VARCHAR(200),
    description TEXT,
    asking_price FLOAT,
    min_offer FLOAT,
    currency VARCHAR(3) DEFAULT 'USD',
    price_type VARCHAR(20) DEFAULT 'fixed',
    pounce_score INTEGER,
    estimated_value FLOAT,
    verification_status VARCHAR(20) DEFAULT 'not_started',
    verification_code VARCHAR(64),
    verified_at TIMESTAMP,
    status VARCHAR(30) DEFAULT 'draft',
    show_valuation BOOLEAN DEFAULT TRUE,
    allow_offers BOOLEAN DEFAULT TRUE,
    featured BOOLEAN DEFAULT FALSE,
    view_count INTEGER DEFAULT 0,
    inquiry_count INTEGER DEFAULT 0,
    expires_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    published_at TIMESTAMP
);

CREATE INDEX idx_listings_user_id ON domain_listings(user_id);
CREATE INDEX idx_listings_domain ON domain_listings(domain);
CREATE INDEX idx_listings_slug ON domain_listings(slug);
CREATE INDEX idx_listings_status ON domain_listings(status);
```

```sql
-- Contact inquiries from potential buyers
CREATE TABLE listing_inquiries (
    id SERIAL PRIMARY KEY,
    listing_id INTEGER NOT NULL REFERENCES domain_listings(id) ON DELETE CASCADE,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) NOT NULL,
    phone VARCHAR(50),
    company VARCHAR(200),
    message TEXT NOT NULL,
    offer_amount FLOAT,
    status VARCHAR(20) DEFAULT 'new',
    ip_address VARCHAR(45),
    user_agent VARCHAR(500),
    created_at TIMESTAMP DEFAULT NOW(),
    read_at TIMESTAMP,
    replied_at TIMESTAMP
);

CREATE INDEX idx_inquiries_listing_id ON listing_inquiries(listing_id);
```

```sql
-- Analytics: page views
CREATE TABLE listing_views (
    id SERIAL PRIMARY KEY,
    listing_id INTEGER NOT NULL REFERENCES domain_listings(id) ON DELETE CASCADE,
    ip_address VARCHAR(45),
    user_agent VARCHAR(500),
    referrer VARCHAR(500),
    user_id INTEGER REFERENCES users(id),
    viewed_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_views_listing_id ON listing_views(listing_id);
```

#### 2. Sniper Alerts

```sql
-- Saved filter configurations for personalized alerts
CREATE TABLE sniper_alerts (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL REFERENCES users(id),
    name VARCHAR(100) NOT NULL,
    description VARCHAR(500),
    filter_criteria JSONB NOT NULL DEFAULT '{}',
    tlds VARCHAR(500),
    keywords VARCHAR(500),
    exclude_keywords VARCHAR(500),
    max_length INTEGER,
    min_length INTEGER,
    max_price FLOAT,
    min_price FLOAT,
    max_bids INTEGER,
    ending_within_hours INTEGER,
    platforms VARCHAR(200),
    no_numbers BOOLEAN DEFAULT FALSE,
    no_hyphens BOOLEAN DEFAULT FALSE,
    exclude_chars VARCHAR(50),
    notify_email BOOLEAN DEFAULT TRUE,
    notify_sms BOOLEAN DEFAULT FALSE,
    notify_push BOOLEAN DEFAULT FALSE,
    max_notifications_per_day INTEGER DEFAULT 10,
    cooldown_minutes INTEGER DEFAULT 30,
    is_active BOOLEAN DEFAULT TRUE,
    matches_count INTEGER DEFAULT 0,
    notifications_sent INTEGER DEFAULT 0,
    last_matched_at TIMESTAMP,
    last_notified_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_alerts_user_id ON sniper_alerts(user_id);
CREATE INDEX idx_alerts_active ON sniper_alerts(is_active);
```

```sql
-- Matched auctions for each alert
CREATE TABLE sniper_alert_matches (
    id SERIAL PRIMARY KEY,
    alert_id INTEGER NOT NULL REFERENCES sniper_alerts(id) ON DELETE CASCADE,
    domain VARCHAR(255) NOT NULL,
    platform VARCHAR(50) NOT NULL,
    current_bid FLOAT NOT NULL,
    end_time TIMESTAMP NOT NULL,
    auction_url VARCHAR(500),
    notified BOOLEAN DEFAULT FALSE,
    clicked BOOLEAN DEFAULT FALSE,
    matched_at TIMESTAMP DEFAULT NOW(),
    notified_at TIMESTAMP
);

CREATE INDEX idx_matches_alert_id ON sniper_alert_matches(alert_id);
```

#### 3. SEO Data (Tycoon Feature)

```sql
-- Cached SEO metrics for domains
CREATE TABLE domain_seo_data (
    id SERIAL PRIMARY KEY,
    domain VARCHAR(255) NOT NULL UNIQUE,
    domain_authority INTEGER,
    page_authority INTEGER,
    spam_score INTEGER,
    total_backlinks INTEGER,
    referring_domains INTEGER,
    top_backlinks JSONB,
    notable_backlinks TEXT,
    has_wikipedia_link BOOLEAN DEFAULT FALSE,
    has_gov_link BOOLEAN DEFAULT FALSE,
    has_edu_link BOOLEAN DEFAULT FALSE,
    has_news_link BOOLEAN DEFAULT FALSE,
    seo_value_estimate FLOAT,
    data_source VARCHAR(50) DEFAULT 'moz',
    last_updated TIMESTAMP DEFAULT NOW(),
    expires_at TIMESTAMP,
    fetch_count INTEGER DEFAULT 0
);

CREATE INDEX idx_seo_domain ON domain_seo_data(domain);
```

---

## Migration Commands

### Using Alembic (Recommended)

```bash
cd backend

# Generate migration
alembic revision --autogenerate -m "Add marketplace and sniper alert tables"

# Apply migration
alembic upgrade head
```

### Manual SQL (Alternative)

Run the SQL statements above in order on your PostgreSQL database.

---

## Verification

After running migrations, verify tables exist:

```sql
SELECT table_name 
FROM information_schema.tables 
WHERE table_schema = 'public' 
AND table_name IN (
    'domain_listings',
    'listing_inquiries', 
    'listing_views',
    'sniper_alerts',
    'sniper_alert_matches',
    'domain_seo_data'
);
```

---

## Feature References

These tables implement features from:

- **analysis_3.md** - "Micro-Marktplatz" (For Sale Landing Pages)
- **analysis_3.md** - "Sniper Alerts" (Strategie 4: Alerts nach Maß)
- **concept.md** - "For Sale Pages" marketplace feature

---

## API Endpoints

### Listings (For Sale)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/listings` | Browse public listings |
| GET | `/api/v1/listings/{slug}` | View listing details |
| POST | `/api/v1/listings/{slug}/inquire` | Contact seller |
| POST | `/api/v1/listings` | Create listing (auth) |
| GET | `/api/v1/listings/my` | Get my listings (auth) |
| PUT | `/api/v1/listings/{id}` | Update listing (auth) |
| DELETE | `/api/v1/listings/{id}` | Delete listing (auth) |
| POST | `/api/v1/listings/{id}/verify-dns` | Start verification |
| GET | `/api/v1/listings/{id}/verify-dns/check` | Check verification |

### Sniper Alerts

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/sniper-alerts` | Get my alerts |
| POST | `/api/v1/sniper-alerts` | Create alert |
| PUT | `/api/v1/sniper-alerts/{id}` | Update alert |
| DELETE | `/api/v1/sniper-alerts/{id}` | Delete alert |
| GET | `/api/v1/sniper-alerts/{id}/matches` | Get matched auctions |
| POST | `/api/v1/sniper-alerts/{id}/test` | Test alert criteria |

### SEO Data (Tycoon Only)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/seo/{domain}` | Full SEO analysis (Tycoon) |
| POST | `/api/v1/seo/batch` | Batch analyze domains (Tycoon) |
| GET | `/api/v1/seo/{domain}/quick` | Quick summary (Trader+) |

**Environment Variables for Moz API:**
```
MOZ_ACCESS_ID=your_access_id
MOZ_SECRET_KEY=your_secret_key
```

Without these, the system uses estimation mode based on domain characteristics.

