163 lines
6.1 KiB
Python
163 lines
6.1 KiB
Python
"""
|
|
Endpoint gestione schema rendicontazione per bando.
|
|
"""
|
|
import copy
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy.exc import IntegrityError
|
|
from ..db import get_db
|
|
from ..auth import AuthUser, get_current_user, require_superadmin
|
|
from ..models import CallRemissionSchema
|
|
from ..schemas import RemissionSchemaOut, RemissionSchemaCreate, RemissionSchemaUpdate, ApiResponse
|
|
from ..templates import RESTART_TEMPLATE
|
|
|
|
router = APIRouter(prefix="/api/rendicontazione-schemas", tags=["rendicontazione-schemas"])
|
|
|
|
|
|
@router.get("/{call_id}", response_model=ApiResponse)
|
|
def get_schema(call_id: int, db: Session = Depends(get_db), user: AuthUser = Depends(get_current_user)):
|
|
"""Legge lo schema di rendicontazione per un bando. 404 se non esiste."""
|
|
schema = db.query(CallRemissionSchema).filter(CallRemissionSchema.call_id == call_id).first()
|
|
if not schema:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Nessuno schema di rendicontazione per call_id={call_id}. Usa POST per crearlo.",
|
|
)
|
|
return ApiResponse(data=RemissionSchemaOut.model_validate(schema).model_dump(mode="json"))
|
|
|
|
|
|
@router.post("/{call_id}", response_model=ApiResponse)
|
|
def create_schema(
|
|
call_id: int,
|
|
body: RemissionSchemaCreate,
|
|
db: Session = Depends(get_db),
|
|
user: AuthUser = Depends(require_superadmin),
|
|
):
|
|
"""Crea uno schema di rendicontazione per un bando. Fallisce se esiste già."""
|
|
existing = db.query(CallRemissionSchema).filter(CallRemissionSchema.call_id == call_id).first()
|
|
if existing:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail=f"Schema già esistente per call_id={call_id}. Usa PUT per aggiornarlo.",
|
|
)
|
|
schema = CallRemissionSchema(
|
|
call_id=call_id,
|
|
schema_json=body.schema_json,
|
|
status="DRAFT",
|
|
created_by=user.user_id,
|
|
)
|
|
db.add(schema)
|
|
db.commit()
|
|
db.refresh(schema)
|
|
return ApiResponse(
|
|
message=f"Schema creato per call_id={call_id}",
|
|
data=RemissionSchemaOut.model_validate(schema).model_dump(mode="json"),
|
|
)
|
|
|
|
|
|
@router.put("/{call_id}", response_model=ApiResponse)
|
|
def update_schema(
|
|
call_id: int,
|
|
body: RemissionSchemaUpdate,
|
|
db: Session = Depends(get_db),
|
|
user: AuthUser = Depends(require_superadmin),
|
|
):
|
|
"""Aggiorna schema esistente. Blocca modifiche se già PUBLISHED."""
|
|
schema = db.query(CallRemissionSchema).filter(CallRemissionSchema.call_id == call_id).first()
|
|
if not schema:
|
|
raise HTTPException(status_code=404, detail=f"Schema non trovato per call_id={call_id}")
|
|
if schema.status == "PUBLISHED":
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail="Schema PUBLISHED non modificabile. Crea una nuova versione.",
|
|
)
|
|
if body.schema_json is not None:
|
|
schema.schema_json = body.schema_json
|
|
db.commit()
|
|
db.refresh(schema)
|
|
return ApiResponse(
|
|
message=f"Schema aggiornato per call_id={call_id}",
|
|
data=RemissionSchemaOut.model_validate(schema).model_dump(mode="json"),
|
|
)
|
|
|
|
|
|
@router.post("/{call_id}/initialize-restart", response_model=ApiResponse)
|
|
def initialize_restart(
|
|
call_id: int,
|
|
db: Session = Depends(get_db),
|
|
user: AuthUser = Depends(require_superadmin),
|
|
):
|
|
"""Inizializza schema per un bando usando il template RE-START. Fallisce se esiste già."""
|
|
existing = db.query(CallRemissionSchema).filter(CallRemissionSchema.call_id == call_id).first()
|
|
if existing:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail=f"Schema già esistente per call_id={call_id}. Usa PUT per modificarlo.",
|
|
)
|
|
schema = CallRemissionSchema(
|
|
call_id=call_id,
|
|
schema_json=copy.deepcopy(RESTART_TEMPLATE),
|
|
status="DRAFT",
|
|
created_by=user.user_id,
|
|
)
|
|
db.add(schema)
|
|
db.commit()
|
|
db.refresh(schema)
|
|
return ApiResponse(
|
|
message=f"Schema RE-START inizializzato per call_id={call_id}",
|
|
data=RemissionSchemaOut.model_validate(schema).model_dump(mode="json"),
|
|
)
|
|
|
|
|
|
@router.post("/{call_id}/publish", response_model=ApiResponse)
|
|
def publish_schema(
|
|
call_id: int,
|
|
db: Session = Depends(get_db),
|
|
user: AuthUser = Depends(require_superadmin),
|
|
):
|
|
"""Pubblica lo schema (status DRAFT -> PUBLISHED). Una volta pubblicato, non è più editabile."""
|
|
from datetime import datetime, timezone
|
|
schema = db.query(CallRemissionSchema).filter(CallRemissionSchema.call_id == call_id).first()
|
|
if not schema:
|
|
raise HTTPException(status_code=404, detail=f"Schema non trovato per call_id={call_id}")
|
|
if schema.status == "PUBLISHED":
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail="Schema già pubblicato.",
|
|
)
|
|
schema.status = "PUBLISHED"
|
|
schema.published_at = datetime.now(timezone.utc)
|
|
schema.published_by = user.user_id
|
|
db.commit()
|
|
db.refresh(schema)
|
|
return ApiResponse(
|
|
message=f"Schema pubblicato per call_id={call_id}",
|
|
data=RemissionSchemaOut.model_validate(schema).model_dump(mode="json"),
|
|
)
|
|
|
|
|
|
@router.delete("/{call_id}", response_model=ApiResponse)
|
|
def delete_schema(
|
|
call_id: int,
|
|
db: Session = Depends(get_db),
|
|
user: AuthUser = Depends(require_superadmin),
|
|
):
|
|
"""Cancella schema. Consentito solo in DRAFT."""
|
|
schema = db.query(CallRemissionSchema).filter(CallRemissionSchema.call_id == call_id).first()
|
|
if not schema:
|
|
raise HTTPException(status_code=404, detail=f"Schema non trovato per call_id={call_id}")
|
|
if schema.status == "PUBLISHED":
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail="Schema PUBLISHED non cancellabile.",
|
|
)
|
|
db.delete(schema)
|
|
db.commit()
|
|
return ApiResponse(message=f"Schema cancellato per call_id={call_id}")
|
|
|
|
|
|
@router.get("/templates/restart", response_model=ApiResponse)
|
|
def get_restart_template(user: AuthUser = Depends(require_superadmin)):
|
|
"""Restituisce il template RE-START senza persisterlo. Utile per preview."""
|
|
return ApiResponse(data=RESTART_TEMPLATE)
|