# 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.