- schemas/settings.py: Settings pydantic model con api_key, llm_model, nicchie_attive, tono
- routers/calendar.py: POST /api/calendar/generate, GET /api/calendar/formats
- routers/generate.py: POST /api/generate/bulk (202 + job_id), GET /job/{job_id}/status (polling), GET /job/{job_id}, POST /single
- routers/export.py: GET /api/export/{job_id}/csv (originale), POST /api/export/{job_id}/csv (modifiche inline)
- routers/settings.py: GET /api/settings/status (api_key_configured), GET /api/settings, PUT /api/settings
- main.py: include_router x4 PRIMA di SPAStaticFiles, copia prompt default al primo avvio
60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
"""Router per la gestione del calendario editoriale.
|
|
|
|
Endpoint:
|
|
- POST /api/calendar/generate — genera un calendario di 13 slot
|
|
- GET /api/calendar/formats — ritorna il mapping formati disponibili
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter
|
|
|
|
from backend.schemas.calendar import CalendarRequest, CalendarResponse
|
|
from backend.services.calendar_service import CalendarService
|
|
from backend.services.format_selector import FormatSelector
|
|
|
|
|
|
router = APIRouter(prefix="/api/calendar", tags=["calendar"])
|
|
|
|
# Istanze dei servizi (create una volta alla startup del router)
|
|
_format_selector = FormatSelector()
|
|
_calendar_service = CalendarService(format_selector=_format_selector)
|
|
|
|
|
|
@router.post("/generate", response_model=CalendarResponse)
|
|
async def generate_calendar(request: CalendarRequest) -> CalendarResponse:
|
|
"""Genera un calendario editoriale di 13 slot.
|
|
|
|
Produce un piano di pubblicazione con:
|
|
- Distribuzione PN (valore, storytelling, news, riprova_sociale, coinvolgimento, promozione)
|
|
- Livelli Schwartz L1-L5 corretti per ogni tipo di contenuto
|
|
- Formato narrativo selezionato automaticamente
|
|
- Date di pubblicazione suggerite
|
|
- Rotazione nicchie (50% generico, 50% verticali)
|
|
|
|
Args:
|
|
request: Parametri del calendario (obiettivo, settimane, nicchie, frequenza, data_inizio).
|
|
|
|
Returns:
|
|
CalendarResponse con 13 slot ordinati per fase funnel.
|
|
"""
|
|
return _calendar_service.generate_calendar(request)
|
|
|
|
|
|
@router.get("/formats")
|
|
async def get_formats() -> dict:
|
|
"""Ritorna il mapping completo dei formati narrativi disponibili.
|
|
|
|
Utile per il frontend per visualizzare quale formato viene usato
|
|
per ogni combinazione tipo_contenuto x livello_schwartz.
|
|
|
|
Returns:
|
|
Dict con le 30 combinazioni tipo x livello -> formato narrativo.
|
|
"""
|
|
return {
|
|
"mapping": _format_selector.get_mapping(),
|
|
"formati_disponibili": list(
|
|
set(_format_selector.get_mapping().values())
|
|
),
|
|
}
|