Files
orion/app/modules/prospecting/routes/api/admin_campaigns.py
Samir Boulahtit 22ae63b414
Some checks failed
CI / validate (push) Has been cancelled
CI / ruff (push) Successful in 10s
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
refactor(prospecting): migrate SVC-006 transaction control to endpoint level
Move db.commit() from services to API endpoints and Celery tasks.
Services now use db.flush() only; endpoints own the transaction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:40:09 +01:00

121 lines
4.1 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())
db.commit()
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))
db.commit()
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)
db.commit()
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,
)
db.commit()
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),
)