docs: Complete documentation overhaul for v2.0

README.md - Full rewrite:
- New feature overview (Command Center, Marketplace, Alerts)
- Updated project structure with all new files/directories
- Complete server deployment guide
- Environment variables for all features
- API endpoint documentation for new routes
- UI component reference
- Troubleshooting guide

DATABASE_MIGRATIONS.md - Expanded:
- All 6 new tables with full SQL schemas
- Indexes for performance
- Environment variables (Moz API, Stripe)
- Verification queries
- Rollback instructions
- Scheduler job reference

Tables documented:
1. domain_listings (For Sale marketplace)
2. listing_inquiries (Buyer messages)
3. listing_views (Analytics)
4. sniper_alerts (Personalized alerts)
5. sniper_alert_matches (Matched auctions)
6. domain_seo_data (SEO cache for Tycoon)
This commit is contained in:
yves.gugger
2025-12-10 17:07:23 +01:00
parent 8d5bd95147
commit 4cb5f42d90
2 changed files with 497 additions and 979 deletions

View File

@ -1,37 +1,35 @@
# Database Migrations Guide # Database Migrations Guide
## Overview ## Quick Overview
This document lists all database tables that need to be created when deploying Pounce to a new server. When deploying Pounce to a new server, these tables need to be created:
## Required Tables ```
✅ Core Tables (17) - User, Subscription, Domain, TLD, etc.
### Core Tables (Already Implemented) 🆕 New Tables (6) - Listings, Sniper Alerts, SEO Data
```
| 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) ## Automatic Migration
These tables were added for the **"For Sale" Marketplace** and **Sniper Alerts** features: The easiest way to create all tables:
#### 1. Domain Listings (For Sale Marketplace) ```bash
cd backend
source venv/bin/activate
python scripts/init_db.py
```
This creates all tables from the SQLAlchemy models automatically.
---
## Manual SQL Migration
If you need to run migrations manually (e.g., on an existing database), use the SQL below.
### NEW Table 1: Domain Listings (For Sale Marketplace)
```sql ```sql
-- Main listing table -- Main listing table
@ -45,13 +43,13 @@ CREATE TABLE domain_listings (
asking_price FLOAT, asking_price FLOAT,
min_offer FLOAT, min_offer FLOAT,
currency VARCHAR(3) DEFAULT 'USD', currency VARCHAR(3) DEFAULT 'USD',
price_type VARCHAR(20) DEFAULT 'fixed', price_type VARCHAR(20) DEFAULT 'fixed', -- 'fixed', 'negotiable', 'make_offer'
pounce_score INTEGER, pounce_score INTEGER,
estimated_value FLOAT, estimated_value FLOAT,
verification_status VARCHAR(20) DEFAULT 'not_started', verification_status VARCHAR(20) DEFAULT 'not_started', -- 'not_started', 'pending', 'verified', 'failed'
verification_code VARCHAR(64), verification_code VARCHAR(64),
verified_at TIMESTAMP, verified_at TIMESTAMP,
status VARCHAR(30) DEFAULT 'draft', status VARCHAR(30) DEFAULT 'draft', -- 'draft', 'published', 'sold', 'expired', 'removed'
show_valuation BOOLEAN DEFAULT TRUE, show_valuation BOOLEAN DEFAULT TRUE,
allow_offers BOOLEAN DEFAULT TRUE, allow_offers BOOLEAN DEFAULT TRUE,
featured BOOLEAN DEFAULT FALSE, featured BOOLEAN DEFAULT FALSE,
@ -67,8 +65,11 @@ CREATE INDEX idx_listings_user_id ON domain_listings(user_id);
CREATE INDEX idx_listings_domain ON domain_listings(domain); CREATE INDEX idx_listings_domain ON domain_listings(domain);
CREATE INDEX idx_listings_slug ON domain_listings(slug); CREATE INDEX idx_listings_slug ON domain_listings(slug);
CREATE INDEX idx_listings_status ON domain_listings(status); CREATE INDEX idx_listings_status ON domain_listings(status);
CREATE INDEX idx_listings_price ON domain_listings(asking_price);
``` ```
### NEW Table 2: Listing Inquiries
```sql ```sql
-- Contact inquiries from potential buyers -- Contact inquiries from potential buyers
CREATE TABLE listing_inquiries ( CREATE TABLE listing_inquiries (
@ -80,7 +81,7 @@ CREATE TABLE listing_inquiries (
company VARCHAR(200), company VARCHAR(200),
message TEXT NOT NULL, message TEXT NOT NULL,
offer_amount FLOAT, offer_amount FLOAT,
status VARCHAR(20) DEFAULT 'new', status VARCHAR(20) DEFAULT 'new', -- 'new', 'read', 'replied', 'archived'
ip_address VARCHAR(45), ip_address VARCHAR(45),
user_agent VARCHAR(500), user_agent VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW(), created_at TIMESTAMP DEFAULT NOW(),
@ -89,8 +90,11 @@ CREATE TABLE listing_inquiries (
); );
CREATE INDEX idx_inquiries_listing_id ON listing_inquiries(listing_id); CREATE INDEX idx_inquiries_listing_id ON listing_inquiries(listing_id);
CREATE INDEX idx_inquiries_status ON listing_inquiries(status);
``` ```
### NEW Table 3: Listing Views
```sql ```sql
-- Analytics: page views -- Analytics: page views
CREATE TABLE listing_views ( CREATE TABLE listing_views (
@ -104,41 +108,53 @@ CREATE TABLE listing_views (
); );
CREATE INDEX idx_views_listing_id ON listing_views(listing_id); CREATE INDEX idx_views_listing_id ON listing_views(listing_id);
CREATE INDEX idx_views_date ON listing_views(viewed_at);
``` ```
#### 2. Sniper Alerts ### NEW Table 4: Sniper Alerts
```sql ```sql
-- Saved filter configurations for personalized alerts -- Saved filter configurations for personalized auction alerts
CREATE TABLE sniper_alerts ( CREATE TABLE sniper_alerts (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id), user_id INTEGER NOT NULL REFERENCES users(id),
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
description VARCHAR(500), description VARCHAR(500),
-- Filter criteria (stored as JSON for flexibility)
filter_criteria JSONB NOT NULL DEFAULT '{}', filter_criteria JSONB NOT NULL DEFAULT '{}',
tlds VARCHAR(500),
keywords VARCHAR(500), -- Quick filters (also stored as columns for fast queries)
exclude_keywords VARCHAR(500), tlds VARCHAR(500), -- comma-separated: "com,net,io"
keywords VARCHAR(500), -- comma-separated search terms
exclude_keywords VARCHAR(500), -- words to exclude
max_length INTEGER, max_length INTEGER,
min_length INTEGER, min_length INTEGER,
max_price FLOAT, max_price FLOAT,
min_price FLOAT, min_price FLOAT,
max_bids INTEGER, max_bids INTEGER,
ending_within_hours INTEGER, ending_within_hours INTEGER,
platforms VARCHAR(200), platforms VARCHAR(200), -- "GoDaddy,Sedo,NameJet"
-- Vanity filters
no_numbers BOOLEAN DEFAULT FALSE, no_numbers BOOLEAN DEFAULT FALSE,
no_hyphens BOOLEAN DEFAULT FALSE, no_hyphens BOOLEAN DEFAULT FALSE,
exclude_chars VARCHAR(50), exclude_chars VARCHAR(50),
-- Notification settings
notify_email BOOLEAN DEFAULT TRUE, notify_email BOOLEAN DEFAULT TRUE,
notify_sms BOOLEAN DEFAULT FALSE, notify_sms BOOLEAN DEFAULT FALSE,
notify_push BOOLEAN DEFAULT FALSE, notify_push BOOLEAN DEFAULT FALSE,
max_notifications_per_day INTEGER DEFAULT 10, max_notifications_per_day INTEGER DEFAULT 10,
cooldown_minutes INTEGER DEFAULT 30, cooldown_minutes INTEGER DEFAULT 30,
-- Status
is_active BOOLEAN DEFAULT TRUE, is_active BOOLEAN DEFAULT TRUE,
matches_count INTEGER DEFAULT 0, matches_count INTEGER DEFAULT 0,
notifications_sent INTEGER DEFAULT 0, notifications_sent INTEGER DEFAULT 0,
last_matched_at TIMESTAMP, last_matched_at TIMESTAMP,
last_notified_at TIMESTAMP, last_notified_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(), created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW() updated_at TIMESTAMP DEFAULT NOW()
); );
@ -147,6 +163,8 @@ CREATE INDEX idx_alerts_user_id ON sniper_alerts(user_id);
CREATE INDEX idx_alerts_active ON sniper_alerts(is_active); CREATE INDEX idx_alerts_active ON sniper_alerts(is_active);
``` ```
### NEW Table 5: Sniper Alert Matches
```sql ```sql
-- Matched auctions for each alert -- Matched auctions for each alert
CREATE TABLE sniper_alert_matches ( CREATE TABLE sniper_alert_matches (
@ -164,128 +182,159 @@ CREATE TABLE sniper_alert_matches (
); );
CREATE INDEX idx_matches_alert_id ON sniper_alert_matches(alert_id); CREATE INDEX idx_matches_alert_id ON sniper_alert_matches(alert_id);
CREATE INDEX idx_matches_domain ON sniper_alert_matches(domain);
CREATE INDEX idx_matches_notified ON sniper_alert_matches(notified);
``` ```
#### 3. SEO Data (Tycoon Feature) ### NEW Table 6: SEO Data (Tycoon Feature)
```sql ```sql
-- Cached SEO metrics for domains -- Cached SEO metrics for domains (Moz API or estimation)
CREATE TABLE domain_seo_data ( CREATE TABLE domain_seo_data (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
domain VARCHAR(255) NOT NULL UNIQUE, domain VARCHAR(255) NOT NULL UNIQUE,
domain_authority INTEGER,
page_authority INTEGER, -- Core metrics
spam_score INTEGER, domain_authority INTEGER, -- 0-100
page_authority INTEGER, -- 0-100
spam_score INTEGER, -- 0-100
total_backlinks INTEGER, total_backlinks INTEGER,
referring_domains INTEGER, referring_domains INTEGER,
top_backlinks JSONB,
notable_backlinks TEXT, -- Backlink analysis
top_backlinks JSONB, -- [{domain, authority, page}, ...]
notable_backlinks TEXT, -- comma-separated high-value domains
-- Notable link flags
has_wikipedia_link BOOLEAN DEFAULT FALSE, has_wikipedia_link BOOLEAN DEFAULT FALSE,
has_gov_link BOOLEAN DEFAULT FALSE, has_gov_link BOOLEAN DEFAULT FALSE,
has_edu_link BOOLEAN DEFAULT FALSE, has_edu_link BOOLEAN DEFAULT FALSE,
has_news_link BOOLEAN DEFAULT FALSE, has_news_link BOOLEAN DEFAULT FALSE,
seo_value_estimate FLOAT,
data_source VARCHAR(50) DEFAULT 'moz', -- Value estimation
seo_value_estimate FLOAT, -- Estimated $ value based on SEO metrics
-- Metadata
data_source VARCHAR(50) DEFAULT 'estimated', -- 'moz', 'estimated'
last_updated TIMESTAMP DEFAULT NOW(), last_updated TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP, expires_at TIMESTAMP, -- Cache expiry (7 days)
fetch_count INTEGER DEFAULT 0 fetch_count INTEGER DEFAULT 0
); );
CREATE INDEX idx_seo_domain ON domain_seo_data(domain); CREATE INDEX idx_seo_domain ON domain_seo_data(domain);
CREATE INDEX idx_seo_da ON domain_seo_data(domain_authority);
``` ```
--- ---
## Migration Commands ## All Tables Summary
### Using Alembic (Recommended) ### Core Tables (Already Implemented)
```bash | Table | Purpose |
cd backend |-------|---------|
| `users` | User accounts and authentication |
| `subscriptions` | Subscription plans (Scout, Trader, Tycoon) |
| `domains` | Tracked domains in watchlists |
| `domain_checks` | Domain availability check history |
| `tld_prices` | TLD price history (886+ TLDs) |
| `tld_info` | TLD metadata and categories |
| `portfolio_domains` | User-owned domains |
| `domain_valuations` | Domain valuation history |
| `domain_auctions` | Scraped auction listings |
| `auction_scrape_logs` | Scraping job logs |
| `newsletter_subscribers` | Email newsletter list |
| `price_alerts` | TLD price change alerts |
| `admin_activity_logs` | Admin action audit log |
| `blog_posts` | Blog content |
# Generate migration ### New Tables (v2.0)
alembic revision --autogenerate -m "Add marketplace and sniper alert tables"
# Apply migration | Table | Purpose | Required For |
alembic upgrade head |-------|---------|--------------|
``` | `domain_listings` | For Sale marketplace | `/command/listings`, `/buy` |
| `listing_inquiries` | Buyer messages | Marketplace inquiries |
### Manual SQL (Alternative) | `listing_views` | View analytics | Listing stats |
| `sniper_alerts` | Alert configurations | `/command/alerts` |
Run the SQL statements above in order on your PostgreSQL database. | `sniper_alert_matches` | Matched auctions | Alert notifications |
| `domain_seo_data` | SEO metrics cache | `/command/seo` (Tycoon) |
--- ---
## Verification ## Verification
After running migrations, verify tables exist: After migration, verify all tables exist:
```sql ```sql
-- PostgreSQL
SELECT table_name SELECT table_name
FROM information_schema.tables FROM information_schema.tables
WHERE table_schema = 'public' WHERE table_schema = 'public'
AND table_name IN ( ORDER BY table_name;
'domain_listings',
'listing_inquiries', -- Should include:
'listing_views', -- domain_listings
'sniper_alerts', -- listing_inquiries
'sniper_alert_matches', -- listing_views
'domain_seo_data' -- sniper_alerts
); -- sniper_alert_matches
-- domain_seo_data
``` ```
--- ---
## Feature References ## Environment Variables for New Features
These tables implement features from: ### Moz API (Optional - for real SEO data)
- **analysis_3.md** - "Micro-Marktplatz" (For Sale Landing Pages) ```env
- **analysis_3.md** - "Sniper Alerts" (Strategie 4: Alerts nach Maß) MOZ_ACCESS_ID=your_moz_access_id
- **concept.md** - "For Sale Pages" marketplace feature MOZ_SECRET_KEY=your_moz_secret_key
```
Without these variables, the SEO analyzer uses **estimation mode** based on domain characteristics (length, TLD, keywords).
### Stripe (Required for payments)
```env
STRIPE_SECRET_KEY=sk_live_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
STRIPE_PRICE_TRADER=price_xxx # €9/month
STRIPE_PRICE_TYCOON=price_xxx # €29/month
```
--- ---
## API Endpoints ## Scheduler Jobs
### Listings (For Sale) These background jobs run automatically when the backend starts:
| Method | Endpoint | Description | | Job | Schedule | Table Affected |
|--------|----------|-------------| |-----|----------|----------------|
| GET | `/api/v1/listings` | Browse public listings | | Sniper Alert Matching | Every 15 min | `sniper_alert_matches` |
| GET | `/api/v1/listings/{slug}` | View listing details | | Auction Scrape | Hourly | `domain_auctions` |
| POST | `/api/v1/listings/{slug}/inquire` | Contact seller | | TLD Price Scrape | Daily 03:00 | `tld_prices` |
| POST | `/api/v1/listings` | Create listing (auth) | | Domain Check | Daily 06:00 | `domain_checks` |
| 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 | ## Rollback
|--------|----------|-------------|
| 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) If you need to remove the new tables:
| Method | Endpoint | Description | ```sql
|--------|----------|-------------| DROP TABLE IF EXISTS sniper_alert_matches CASCADE;
| GET | `/api/v1/seo/{domain}` | Full SEO analysis (Tycoon) | DROP TABLE IF EXISTS sniper_alerts CASCADE;
| POST | `/api/v1/seo/batch` | Batch analyze domains (Tycoon) | DROP TABLE IF EXISTS listing_views CASCADE;
| GET | `/api/v1/seo/{domain}/quick` | Quick summary (Trader+) | DROP TABLE IF EXISTS listing_inquiries CASCADE;
DROP TABLE IF EXISTS domain_listings CASCADE;
**Environment Variables for Moz API:** DROP TABLE IF EXISTS domain_seo_data CASCADE;
```
MOZ_ACCESS_ID=your_access_id
MOZ_SECRET_KEY=your_secret_key
``` ```
Without these, the system uses estimation mode based on domain characteristics. ---
## Related Documentation
- `README.md` - Full deployment guide
- `DEPLOYMENT.md` - Server setup details
- `backend/app/models/` - SQLAlchemy model definitions

1215
README.md

File diff suppressed because it is too large Load Diff