| """ |
| Seed database with sample data for local development. |
| Run: python -m app.scripts.seed |
| """ |
| import asyncio |
| import uuid |
| from datetime import datetime, timedelta, timezone |
|
|
| from sqlalchemy import select |
|
|
| from app.core.database import async_session_factory |
| from app.core.security import hash_password |
|
|
| |
| import app.models.application |
| import app.models.resume |
| import app.models.alerts |
| import app.models.llm |
| import app.api.routes.bookmarks |
| import app.api.routes.cover_letters |
| import app.api.routes.reminders |
| import app.api.routes.qa_bank |
| import app.api.routes.webhooks |
| import app.services.analytics |
|
|
| from app.models.job import Company, Job |
| from app.models.scraper import JobSource |
| from app.models.user import Profile, User |
|
|
|
|
| SAMPLE_COMPANIES = [ |
| {"name": "Google", "slug": "google", "domain": "google.com", "industry": "Technology", "size_range": "10000+", "headquarters": "Mountain View, CA", "company_type": "public", "tech_stack": ["C++", "Python", "Go", "Kubernetes", "TensorFlow"]}, |
| {"name": "Stripe", "slug": "stripe", "domain": "stripe.com", "industry": "Fintech", "size_range": "5001-10000", "headquarters": "San Francisco, CA", "company_type": "private", "tech_stack": ["Ruby", "Java", "Scala", "PostgreSQL"]}, |
| {"name": "Vercel", "slug": "vercel", "domain": "vercel.com", "industry": "Developer Tools", "size_range": "201-500", "headquarters": "San Francisco, CA", "company_type": "startup", "tech_stack": ["TypeScript", "Next.js", "React", "Rust"]}, |
| {"name": "Anthropic", "slug": "anthropic", "domain": "anthropic.com", "industry": "AI/ML", "size_range": "501-1000", "headquarters": "San Francisco, CA", "company_type": "startup", "tech_stack": ["Python", "PyTorch", "Kubernetes", "Rust"]}, |
| {"name": "Linear", "slug": "linear", "domain": "linear.app", "industry": "Developer Tools", "size_range": "51-200", "headquarters": "San Francisco, CA", "company_type": "startup", "tech_stack": ["TypeScript", "React", "GraphQL", "PostgreSQL"]}, |
| {"name": "Figma", "slug": "figma", "domain": "figma.com", "industry": "Design", "size_range": "1001-5000", "headquarters": "San Francisco, CA", "company_type": "private", "tech_stack": ["TypeScript", "React", "WebGL", "Rust"]}, |
| {"name": "Datadog", "slug": "datadog", "domain": "datadoghq.com", "industry": "DevOps", "size_range": "5001-10000", "headquarters": "New York, NY", "company_type": "public", "tech_stack": ["Go", "Python", "Kubernetes", "Kafka"]}, |
| {"name": "Notion", "slug": "notion", "domain": "notion.so", "industry": "Productivity", "size_range": "501-1000", "headquarters": "San Francisco, CA", "company_type": "private", "tech_stack": ["TypeScript", "React", "Node.js", "PostgreSQL"]}, |
| ] |
|
|
| SAMPLE_JOBS = [ |
| {"title": "Senior Frontend Engineer", "company": "Vercel", "remote_type": "remote", "employment_type": "full_time", "seniority_level": "senior", "salary_min": 180000, "salary_max": 250000, "skills_required": ["React", "Next.js", "TypeScript", "CSS"], "description_text": "Join our frontend team to build the future of web development. You'll work on Next.js, Turbopack, and our deployment platform used by millions of developers."}, |
| {"title": "Staff Software Engineer - AI Infrastructure", "company": "Anthropic", "remote_type": "hybrid", "employment_type": "full_time", "seniority_level": "senior", "salary_min": 300000, "salary_max": 450000, "skills_required": ["Python", "Distributed Systems", "ML Infrastructure", "Kubernetes"], "description_text": "Build the infrastructure powering Claude. Work on training pipelines, inference systems, and developer APIs at scale."}, |
| {"title": "Product Engineer", "company": "Linear", "remote_type": "remote", "employment_type": "full_time", "seniority_level": "mid", "salary_min": 150000, "salary_max": 200000, "skills_required": ["React", "TypeScript", "Node.js", "PostgreSQL"], "description_text": "Build features end-to-end for our project management tool used by the best product teams. Own features from conception to deployment."}, |
| {"title": "Backend Engineer - Payments", "company": "Stripe", "remote_type": "hybrid", "employment_type": "full_time", "seniority_level": "mid", "salary_min": 175000, "salary_max": 250000, "skills_required": ["Ruby", "Java", "Distributed Systems", "SQL"], "description_text": "Build the economic infrastructure for the internet. Work on payment processing, fraud detection, and financial services APIs."}, |
| {"title": "Senior Software Engineer - Search", "company": "Google", "remote_type": "onsite", "employment_type": "full_time", "seniority_level": "senior", "salary_min": 200000, "salary_max": 350000, "skills_required": ["C++", "Python", "Distributed Systems", "Information Retrieval"], "description_text": "Improve search quality for billions of users. Work on ranking algorithms, knowledge graphs, and AI-powered features."}, |
| {"title": "Full Stack Engineer", "company": "Notion", "remote_type": "hybrid", "employment_type": "full_time", "seniority_level": "mid", "salary_min": 160000, "salary_max": 220000, "skills_required": ["React", "TypeScript", "Node.js", "PostgreSQL"], "description_text": "Build collaborative features for Notion's workspace platform. Work across the stack from real-time sync to UI components."}, |
| {"title": "Design Engineer", "company": "Figma", "remote_type": "hybrid", "employment_type": "full_time", "seniority_level": "mid", "salary_min": 170000, "salary_max": 240000, "skills_required": ["React", "TypeScript", "WebGL", "Design Systems"], "description_text": "Bridge design and engineering at Figma. Build interactive UI components, design system primitives, and creative tools."}, |
| {"title": "Senior Site Reliability Engineer", "company": "Datadog", "remote_type": "remote", "employment_type": "full_time", "seniority_level": "senior", "salary_min": 190000, "salary_max": 280000, "skills_required": ["Kubernetes", "Terraform", "Go", "Observability"], "description_text": "Keep Datadog running at scale. Own service reliability, incident response, and infrastructure automation for our monitoring platform."}, |
| {"title": "Machine Learning Engineer - NLP", "company": "Google", "remote_type": "onsite", "employment_type": "full_time", "seniority_level": "senior", "salary_min": 220000, "salary_max": 380000, "skills_required": ["Python", "PyTorch", "Transformers", "NLP"], "description_text": "Work on large language models and NLP systems. Apply cutting-edge research to production systems serving billions of queries."}, |
| {"title": "Software Engineering Intern", "company": "Stripe", "remote_type": "hybrid", "employment_type": "internship", "seniority_level": "intern", "salary_min": 80000, "salary_max": 100000, "skills_required": ["Python", "JavaScript", "SQL"], "description_text": "12-week summer internship. Work on real projects alongside experienced engineers. Past interns have shipped features used by millions."}, |
| ] |
|
|
| SAMPLE_SOURCES = [ |
| {"name": "Greenhouse - Vercel", "source_type": "ats_api", "domain": "vercel.com", "base_url": "https://boards-api.greenhouse.io/v1/boards/vercel/jobs", "ats_vendor": "greenhouse", "ats_config": {"board_token": "vercel"}}, |
| {"name": "Greenhouse - Anthropic", "source_type": "ats_api", "domain": "anthropic.com", "base_url": "https://boards-api.greenhouse.io/v1/boards/anthropic/jobs", "ats_vendor": "greenhouse", "ats_config": {"board_token": "anthropic"}}, |
| {"name": "Lever - Linear", "source_type": "ats_api", "domain": "linear.app", "base_url": "https://api.lever.co/v0/postings/linear", "ats_vendor": "lever", "ats_config": {"company_slug": "linear"}}, |
| {"name": "Ashby - Notion", "source_type": "ats_api", "domain": "notion.so", "base_url": "https://api.ashbyhq.com/posting-api/job-board", "ats_vendor": "ashby", "ats_config": {"board_slug": "notion"}}, |
| ] |
|
|
|
|
| async def seed(): |
| """Seed the database with sample data.""" |
| async with async_session_factory() as db: |
| print("🌱 Seeding database...") |
|
|
| |
| existing = await db.scalar(select(User).where(User.email == "demo@jobportal.dev")) |
| if existing: |
| print("✅ Seed data already exists. Skipping.") |
| return |
|
|
| |
| admin = User( |
| email="admin@jobportal.dev", |
| hashed_password=hash_password("admin123"), |
| full_name="Admin User", |
| role="admin", |
| is_active=True, |
| is_verified=True, |
| is_superuser=True, |
| ) |
| db.add(admin) |
|
|
| |
| demo = User( |
| email="demo@jobportal.dev", |
| hashed_password=hash_password("demo123"), |
| full_name="Demo User", |
| role="candidate", |
| is_active=True, |
| is_verified=True, |
| ) |
| db.add(demo) |
| await db.flush() |
|
|
| |
| profile = Profile( |
| user_id=demo.id, |
| headline="Full Stack Engineer", |
| location="San Francisco, CA", |
| summary="Passionate full-stack engineer with 5 years of experience building web applications.", |
| skills=[ |
| {"name": "React", "category": "Frameworks", "level": 5}, |
| {"name": "TypeScript", "category": "Languages", "level": 5}, |
| {"name": "Python", "category": "Languages", "level": 4}, |
| {"name": "Node.js", "category": "Frameworks", "level": 4}, |
| {"name": "PostgreSQL", "category": "Databases", "level": 4}, |
| {"name": "AWS", "category": "Cloud", "level": 3}, |
| {"name": "Docker", "category": "Tools", "level": 4}, |
| {"name": "Next.js", "category": "Frameworks", "level": 5}, |
| ], |
| experience=[ |
| { |
| "company": "TechCorp", |
| "title": "Senior Software Engineer", |
| "location": "San Francisco, CA", |
| "start_date": "2022-01", |
| "end_date": "", |
| "is_current": True, |
| "bullets": [ |
| "Led development of real-time collaboration features serving 100K+ daily active users", |
| "Reduced page load time by 40% through code splitting and performance optimization", |
| "Mentored 3 junior engineers and led weekly architecture reviews", |
| ], |
| }, |
| ], |
| remote_preference="remote", |
| salary_min=180000, |
| salary_max=250000, |
| salary_currency="USD", |
| open_to_work=True, |
| ) |
| db.add(profile) |
|
|
| |
| company_map = {} |
| for c in SAMPLE_COMPANIES: |
| company = Company(**c) |
| db.add(company) |
| company_map[c["name"]] = company |
| await db.flush() |
|
|
| |
| now = datetime.now(timezone.utc) |
| for i, j in enumerate(SAMPLE_JOBS): |
| company = company_map.get(j["company"]) |
| job = Job( |
| title=j["title"], |
| company_id=company.id if company else None, |
| company_name=j["company"], |
| source_url=f"https://{company.domain}/careers/{uuid.uuid4().hex[:8]}" if company else "https://example.com/jobs/1", |
| source_domain=company.domain if company else "example.com", |
| source_type="seed", |
| remote_type=j.get("remote_type"), |
| employment_type=j.get("employment_type"), |
| seniority_level=j.get("seniority_level"), |
| salary_min=j.get("salary_min"), |
| salary_max=j.get("salary_max"), |
| salary_currency="USD", |
| salary_interval="yearly", |
| skills_required=j.get("skills_required"), |
| description_text=j.get("description_text"), |
| status="active", |
| date_posted=now - timedelta(days=i * 2), |
| locations=[{"raw": "San Francisco, CA", "city": "San Francisco", "state": "CA", "country": "US"}], |
| ) |
| db.add(job) |
|
|
| |
| for s in SAMPLE_SOURCES: |
| source = JobSource(**s) |
| db.add(source) |
|
|
| await db.commit() |
| print("✅ Database seeded successfully!") |
| print(" Admin: admin@jobportal.dev / admin123") |
| print(" Demo: demo@jobportal.dev / demo123") |
| print(f" Companies: {len(SAMPLE_COMPANIES)}") |
| print(f" Jobs: {len(SAMPLE_JOBS)}") |
| print(f" Sources: {len(SAMPLE_SOURCES)}") |
|
|
|
|
| if __name__ == "__main__": |
| asyncio.run(seed()) |
|
|