Scadenzario aggiunta pratiche
This commit is contained in:
@@ -33,6 +33,7 @@ from app.models.message import Message
|
||||
from app.schemas.fascicolo import (
|
||||
FascicoloAddMessagesRequest,
|
||||
FascicoloCreate,
|
||||
FascicoloDeadlineResponse,
|
||||
FascicoloMessageItem,
|
||||
FascicoloRemoveMessagesRequest,
|
||||
FascicoloResponse,
|
||||
@@ -73,6 +74,33 @@ async def list_fascicoli(
|
||||
return [_to_response(f, cnt) for f, cnt in rows]
|
||||
|
||||
|
||||
@router.get("/fascicoli/scadenzario", response_model=list[FascicoloDeadlineResponse])
|
||||
async def list_fascicoli_scadenzario(
|
||||
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 fascicoli gia' scaduti"),
|
||||
) -> list[FascicoloDeadlineResponse]:
|
||||
"""
|
||||
Scadenzario pratiche: fascicoli con scadenza imminente o scaduta.
|
||||
|
||||
Ordinati per scadenza ASC (scaduti prima, poi futuri).
|
||||
"""
|
||||
svc = FascicoloService(db)
|
||||
rows = await svc.list_fascicoli_scadenzario(
|
||||
current_user.tenant_id,
|
||||
days_ahead=days_ahead,
|
||||
include_overdue=include_overdue,
|
||||
)
|
||||
items = []
|
||||
for fascicolo, cnt, is_overdue in rows:
|
||||
resp = FascicoloDeadlineResponse.model_validate(fascicolo)
|
||||
resp.message_count = cnt
|
||||
resp.is_overdue = is_overdue
|
||||
items.append(resp)
|
||||
return items
|
||||
|
||||
|
||||
@router.post("/fascicoli", response_model=FascicoloResponse, status_code=status.HTTP_201_CREATED)
|
||||
async def create_fascicolo(
|
||||
data: FascicoloCreate,
|
||||
|
||||
@@ -90,3 +90,24 @@ class MessageFascicoloSummary(BaseModel):
|
||||
categoria: Optional[str] = None
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# ─── Scadenzario fascicoli ────────────────────────────────────────────────────
|
||||
|
||||
class FascicoloDeadlineResponse(BaseModel):
|
||||
"""Fascicolo con scadenza per lo scadenzario pratiche."""
|
||||
id: uuid.UUID
|
||||
tenant_id: uuid.UUID
|
||||
titolo: str
|
||||
numero_pratica: Optional[str] = None
|
||||
stato: str
|
||||
categoria: Optional[str] = None
|
||||
responsabile_id: Optional[uuid.UUID] = None
|
||||
scadenza: Optional[datetime] = None
|
||||
note: Optional[str] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
message_count: int = 0
|
||||
is_overdue: bool = False
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
@@ -3,7 +3,7 @@ Service per la gestione dei Fascicoli (fascicolazione pratiche).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from sqlalchemy import delete, func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -268,3 +268,57 @@ class FascicoloService:
|
||||
.order_by(Fascicolo.titolo)
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
# ─── Scadenzario fascicoli ────────────────────────────────────────────────
|
||||
|
||||
async def list_fascicoli_scadenzario(
|
||||
self,
|
||||
tenant_id: uuid.UUID,
|
||||
days_ahead: int = 30,
|
||||
include_overdue: bool = True,
|
||||
) -> list[tuple[Fascicolo, int, bool]]:
|
||||
"""
|
||||
Restituisce lista di (Fascicolo, message_count, is_overdue) per lo scadenzario.
|
||||
|
||||
Filtra fascicoli con scadenza impostata nel range richiesto.
|
||||
Ordinati: scaduti prima (ASC scadenza), poi futuri (ASC scadenza).
|
||||
"""
|
||||
now = datetime.now(timezone.utc)
|
||||
future_limit = now + timedelta(days=days_ahead)
|
||||
|
||||
count_sub = (
|
||||
select(
|
||||
FascicoloMessage.fascicolo_id,
|
||||
func.count(FascicoloMessage.message_id).label("cnt"),
|
||||
)
|
||||
.group_by(FascicoloMessage.fascicolo_id)
|
||||
.subquery()
|
||||
)
|
||||
|
||||
stmt = (
|
||||
select(Fascicolo, func.coalesce(count_sub.c.cnt, 0).label("message_count"))
|
||||
.outerjoin(count_sub, Fascicolo.id == count_sub.c.fascicolo_id)
|
||||
.where(
|
||||
Fascicolo.tenant_id == tenant_id,
|
||||
Fascicolo.scadenza.is_not(None),
|
||||
)
|
||||
.order_by(Fascicolo.scadenza.asc())
|
||||
)
|
||||
|
||||
if include_overdue:
|
||||
# Scaduti (qualsiasi data passata) + futuri fino al limite
|
||||
stmt = stmt.where(Fascicolo.scadenza <= future_limit)
|
||||
else:
|
||||
# Solo scadenze future entro il limite
|
||||
stmt = stmt.where(
|
||||
Fascicolo.scadenza > now,
|
||||
Fascicolo.scadenza <= future_limit,
|
||||
)
|
||||
|
||||
result = await self.db.execute(stmt)
|
||||
rows = result.all()
|
||||
|
||||
return [
|
||||
(fascicolo, int(cnt), fascicolo.scadenza < now if fascicolo.scadenza else False)
|
||||
for fascicolo, cnt in rows
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user