Some checks failed
Migrates scanning pipeline from marketing-.lu-domains app into Orion module. Supports digital (domain scan) and offline (manual capture) lead channels with enrichment, scoring, campaign management, and interaction tracking. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
117 lines
4.0 KiB
Python
117 lines
4.0 KiB
Python
# app/modules/prospecting/routes/api/admin_campaigns.py
|
|
"""
|
|
Admin API routes for campaign management.
|
|
"""
|
|
|
|
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.campaign import (
|
|
CampaignPreviewRequest,
|
|
CampaignPreviewResponse,
|
|
CampaignSendCreate,
|
|
CampaignSendListResponse,
|
|
CampaignSendResponse,
|
|
CampaignTemplateCreate,
|
|
CampaignTemplateDeleteResponse,
|
|
CampaignTemplateResponse,
|
|
CampaignTemplateUpdate,
|
|
)
|
|
from app.modules.prospecting.services.campaign_service import campaign_service
|
|
from app.modules.tenancy.schemas.auth import UserContext
|
|
|
|
router = APIRouter(prefix="/campaigns")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@router.get("/templates", response_model=list[CampaignTemplateResponse])
|
|
def list_templates(
|
|
lead_type: str | None = Query(None),
|
|
active_only: bool = Query(False),
|
|
db: Session = Depends(get_db),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
):
|
|
"""List campaign templates with optional filters."""
|
|
templates = campaign_service.get_templates(db, lead_type=lead_type, active_only=active_only)
|
|
return [CampaignTemplateResponse.model_validate(t) for t in templates]
|
|
|
|
|
|
@router.post("/templates", response_model=CampaignTemplateResponse)
|
|
def create_template(
|
|
data: CampaignTemplateCreate,
|
|
db: Session = Depends(get_db),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
):
|
|
"""Create a new campaign template."""
|
|
template = campaign_service.create_template(db, data.model_dump())
|
|
return CampaignTemplateResponse.model_validate(template)
|
|
|
|
|
|
@router.put("/templates/{template_id}", response_model=CampaignTemplateResponse)
|
|
def update_template(
|
|
data: CampaignTemplateUpdate,
|
|
template_id: int = Path(...),
|
|
db: Session = Depends(get_db),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
):
|
|
"""Update a campaign template."""
|
|
template = campaign_service.update_template(db, template_id, data.model_dump(exclude_none=True))
|
|
return CampaignTemplateResponse.model_validate(template)
|
|
|
|
|
|
@router.delete("/templates/{template_id}", response_model=CampaignTemplateDeleteResponse)
|
|
def delete_template(
|
|
template_id: int = Path(...),
|
|
db: Session = Depends(get_db),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
):
|
|
"""Delete a campaign template."""
|
|
campaign_service.delete_template(db, template_id)
|
|
return CampaignTemplateDeleteResponse(message="Template deleted")
|
|
|
|
|
|
@router.post("/preview", response_model=CampaignPreviewResponse)
|
|
def preview_campaign(
|
|
data: CampaignPreviewRequest,
|
|
db: Session = Depends(get_db),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
):
|
|
"""Preview a rendered campaign for a specific prospect."""
|
|
result = campaign_service.render_campaign(db, data.template_id, data.prospect_id)
|
|
return CampaignPreviewResponse(**result)
|
|
|
|
|
|
@router.post("/send", response_model=list[CampaignSendResponse])
|
|
def send_campaign(
|
|
data: CampaignSendCreate,
|
|
db: Session = Depends(get_db),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
):
|
|
"""Send a campaign to one or more prospects."""
|
|
sends = campaign_service.send_campaign(
|
|
db,
|
|
template_id=data.template_id,
|
|
prospect_ids=data.prospect_ids,
|
|
sent_by_user_id=current_admin.user_id,
|
|
)
|
|
return [CampaignSendResponse.model_validate(s) for s in sends]
|
|
|
|
|
|
@router.get("/sends", response_model=CampaignSendListResponse)
|
|
def list_sends(
|
|
prospect_id: int | None = Query(None),
|
|
template_id: int | None = Query(None),
|
|
db: Session = Depends(get_db),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
):
|
|
"""List sent campaigns with optional filters."""
|
|
sends = campaign_service.get_sends(db, prospect_id=prospect_id, template_id=template_id)
|
|
return CampaignSendListResponse(
|
|
items=[CampaignSendResponse.model_validate(s) for s in sends],
|
|
total=len(sends),
|
|
)
|