# app/modules/prospecting/routes/api/admin_enrichment.py """ Admin API routes for enrichment/scanning pipeline. """ import logging from fastapi import APIRouter, Depends, Path, Query from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.modules.prospecting.schemas.enrichment import ( ContactScrapeResponse, FullEnrichmentResponse, HttpCheckBatchItem, HttpCheckBatchResponse, HttpCheckResult, ScanBatchResponse, ScanSingleResponse, ScoreComputeBatchResponse, ) from app.modules.prospecting.services.enrichment_service import enrichment_service from app.modules.prospecting.services.prospect_service import prospect_service from app.modules.prospecting.services.scoring_service import scoring_service from app.modules.tenancy.schemas.auth import UserContext router = APIRouter(prefix="/enrichment") logger = logging.getLogger(__name__) @router.post("/http-check/{prospect_id}", response_model=HttpCheckResult) def http_check_single( prospect_id: int = Path(...), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Run HTTP connectivity check for a single prospect.""" prospect = prospect_service.get_by_id(db, prospect_id) result = enrichment_service.check_http(db, prospect) db.commit() return HttpCheckResult(**result) @router.post("/http-check/batch", response_model=HttpCheckBatchResponse) def http_check_batch( limit: int = Query(100, ge=1, le=500), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Run HTTP check for pending prospects.""" prospects = prospect_service.get_pending_http_check(db, limit=limit) results = [] for prospect in prospects: result = enrichment_service.check_http(db, prospect) results.append(HttpCheckBatchItem(domain=prospect.domain_name, **result)) db.commit() return HttpCheckBatchResponse(processed=len(results), results=results) @router.post("/tech-scan/{prospect_id}", response_model=ScanSingleResponse) def tech_scan_single( prospect_id: int = Path(...), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Run technology scan for a single prospect.""" prospect = prospect_service.get_by_id(db, prospect_id) profile = enrichment_service.scan_tech_stack(db, prospect) db.commit() return ScanSingleResponse(domain=prospect.domain_name, profile=profile is not None) @router.post("/tech-scan/batch", response_model=ScanBatchResponse) def tech_scan_batch( limit: int = Query(100, ge=1, le=500), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Run tech scan for pending prospects.""" prospects = prospect_service.get_pending_tech_scan(db, limit=limit) count = 0 for prospect in prospects: result = enrichment_service.scan_tech_stack(db, prospect) if result: count += 1 db.commit() return ScanBatchResponse(processed=len(prospects), successful=count) @router.post("/performance/{prospect_id}", response_model=ScanSingleResponse) def performance_scan_single( prospect_id: int = Path(...), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Run PageSpeed audit for a single prospect.""" prospect = prospect_service.get_by_id(db, prospect_id) profile = enrichment_service.scan_performance(db, prospect) db.commit() return ScanSingleResponse(domain=prospect.domain_name, profile=profile is not None) @router.post("/performance/batch", response_model=ScanBatchResponse) def performance_scan_batch( limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Run performance scan for pending prospects.""" prospects = prospect_service.get_pending_performance_scan(db, limit=limit) count = 0 for prospect in prospects: result = enrichment_service.scan_performance(db, prospect) if result: count += 1 db.commit() return ScanBatchResponse(processed=len(prospects), successful=count) @router.post("/contacts/{prospect_id}", response_model=ContactScrapeResponse) def scrape_contacts_single( prospect_id: int = Path(...), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Scrape contacts for a single prospect.""" prospect = prospect_service.get_by_id(db, prospect_id) contacts = enrichment_service.scrape_contacts(db, prospect) db.commit() return ContactScrapeResponse(domain=prospect.domain_name, contacts_found=len(contacts)) @router.post("/full/{prospect_id}", response_model=FullEnrichmentResponse) def full_enrichment( prospect_id: int = Path(...), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Run full enrichment pipeline for a single prospect.""" prospect = prospect_service.get_by_id(db, prospect_id) # Step 1: HTTP check enrichment_service.check_http(db, prospect) # Step 2: Tech scan (if has website) tech_profile = None if prospect.has_website: tech_profile = enrichment_service.scan_tech_stack(db, prospect) # Step 3: Performance scan (if has website) perf_profile = None if prospect.has_website: perf_profile = enrichment_service.scan_performance(db, prospect) # Step 4: Contact scrape (if has website) contacts = [] if prospect.has_website: contacts = enrichment_service.scrape_contacts(db, prospect) # Step 5: Compute score db.refresh(prospect) score = scoring_service.compute_score(db, prospect) db.commit() return FullEnrichmentResponse( domain=prospect.domain_name, has_website=prospect.has_website, tech_scanned=tech_profile is not None, perf_scanned=perf_profile is not None, contacts_found=len(contacts), score=score.score, lead_tier=score.lead_tier, ) @router.post("/score-compute/batch", response_model=ScoreComputeBatchResponse) def compute_scores_batch( limit: int = Query(500, ge=1, le=5000), db: Session = Depends(get_db), current_admin: UserContext = Depends(get_current_admin_api), ): """Compute or recompute scores for all prospects.""" count = scoring_service.compute_all(db, limit=limit) db.commit() return ScoreComputeBatchResponse(scored=count)