initial skeleton: FastAPI + SQLAlchemy + schema rendicontazione + template RE-START
This commit is contained in:
162
app/routers/schemas.py
Normal file
162
app/routers/schemas.py
Normal file
@@ -0,0 +1,162 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user