mirror of
https://github.com/idrainformatica/PecFlow.git
synced 2026-06-16 12:45:42 +02:00
Implementazioni varie
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
"""
|
||||
Router scadenzario e tracking deadlines (Feature 4).
|
||||
|
||||
Endpoint:
|
||||
GET /deadlines – messaggi con scadenze imminenti
|
||||
POST /messages/{id}/deadline – imposta/modifica/rimuove scadenza
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from fastapi import APIRouter, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import and_, select
|
||||
|
||||
from app.dependencies import CurrentUser, DB
|
||||
from app.models.message import Message
|
||||
from app.schemas.message import MessageResponse
|
||||
from app.core.exceptions import NotFoundError
|
||||
|
||||
router = APIRouter(tags=["Deadlines"])
|
||||
|
||||
|
||||
class DeadlineSetRequest(BaseModel):
|
||||
deadline_at: datetime | None = None
|
||||
"""Imposta a null per rimuovere la scadenza."""
|
||||
deadline_note: str | None = None
|
||||
|
||||
|
||||
class DeadlineMessageResponse(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
id: uuid.UUID
|
||||
subject: str | None
|
||||
from_address: str | None
|
||||
to_addresses: list[str] | None = None
|
||||
direction: str
|
||||
pec_type: str
|
||||
state: str
|
||||
mailbox_id: uuid.UUID
|
||||
deadline_at: datetime | None = None
|
||||
deadline_note: str | None = None
|
||||
is_overdue: bool = False
|
||||
received_at: datetime | None = None
|
||||
sent_at: datetime | None = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
@router.get("/deadlines", response_model=list[DeadlineMessageResponse])
|
||||
async def list_deadlines(
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
days_ahead: int = Query(30, ge=1, le=365, description="Giorni da considerare in avanti"),
|
||||
include_overdue: bool = Query(True, description="Includi scadenze gia' passate"),
|
||||
) -> list[DeadlineMessageResponse]:
|
||||
"""
|
||||
Restituisce i messaggi con scadenze nel range specificato.
|
||||
|
||||
Ordinati per: scaduti prima, poi per deadline_at ASC.
|
||||
"""
|
||||
now = datetime.now(timezone.utc)
|
||||
future_limit = now + timedelta(days=days_ahead)
|
||||
|
||||
conditions = [
|
||||
Message.tenant_id == current_user.tenant_id,
|
||||
Message.deadline_at.is_not(None),
|
||||
Message.is_trashed == False, # noqa: E712
|
||||
]
|
||||
|
||||
if include_overdue:
|
||||
# Include scaduti e futuri fino al limite
|
||||
conditions.append(Message.deadline_at <= future_limit)
|
||||
else:
|
||||
# Solo scadenze future
|
||||
conditions.append(and_(Message.deadline_at > now, Message.deadline_at <= future_limit))
|
||||
|
||||
result = await db.execute(
|
||||
select(Message)
|
||||
.where(and_(*conditions))
|
||||
.order_by(Message.deadline_at)
|
||||
.limit(200)
|
||||
)
|
||||
messages = list(result.scalars().all())
|
||||
|
||||
items = []
|
||||
for msg in messages:
|
||||
is_overdue = msg.deadline_at < now if msg.deadline_at else False
|
||||
items.append(DeadlineMessageResponse(
|
||||
id=msg.id,
|
||||
subject=msg.subject,
|
||||
from_address=msg.from_address,
|
||||
to_addresses=msg.to_addresses,
|
||||
direction=msg.direction,
|
||||
pec_type=msg.pec_type,
|
||||
state=msg.state,
|
||||
mailbox_id=msg.mailbox_id,
|
||||
deadline_at=msg.deadline_at,
|
||||
deadline_note=msg.deadline_note,
|
||||
is_overdue=is_overdue,
|
||||
received_at=msg.received_at,
|
||||
sent_at=msg.sent_at,
|
||||
created_at=msg.created_at,
|
||||
))
|
||||
return items
|
||||
|
||||
|
||||
@router.post("/messages/{message_id}/deadline", response_model=DeadlineMessageResponse)
|
||||
async def set_deadline(
|
||||
message_id: uuid.UUID,
|
||||
data: DeadlineSetRequest,
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> DeadlineMessageResponse:
|
||||
"""
|
||||
Imposta, modifica o rimuove la scadenza di un messaggio.
|
||||
|
||||
Passa deadline_at=null per rimuovere la scadenza.
|
||||
"""
|
||||
result = await db.execute(
|
||||
select(Message).where(
|
||||
Message.id == message_id,
|
||||
Message.tenant_id == current_user.tenant_id,
|
||||
)
|
||||
)
|
||||
msg = result.scalar_one_or_none()
|
||||
if not msg:
|
||||
raise NotFoundError(f"Messaggio {message_id} non trovato")
|
||||
|
||||
msg.deadline_at = data.deadline_at
|
||||
msg.deadline_note = data.deadline_note
|
||||
await db.commit()
|
||||
await db.refresh(msg)
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
is_overdue = msg.deadline_at < now if msg.deadline_at else False
|
||||
|
||||
return DeadlineMessageResponse(
|
||||
id=msg.id,
|
||||
subject=msg.subject,
|
||||
from_address=msg.from_address,
|
||||
to_addresses=msg.to_addresses,
|
||||
direction=msg.direction,
|
||||
pec_type=msg.pec_type,
|
||||
state=msg.state,
|
||||
mailbox_id=msg.mailbox_id,
|
||||
deadline_at=msg.deadline_at,
|
||||
deadline_note=msg.deadline_note,
|
||||
is_overdue=is_overdue,
|
||||
received_at=msg.received_at,
|
||||
sent_at=msg.sent_at,
|
||||
created_at=msg.created_at,
|
||||
)
|
||||
Reference in New Issue
Block a user