""" 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)