Backend v1.0.71:
- Implementado soft delete para preguntas
- Nuevas columnas: is_deleted (boolean), updated_at (timestamp)
- Migración SQL: add_soft_delete_to_questions.sql
- Endpoint DELETE marca preguntas como eliminadas en lugar de borrarlas
- GET /api/checklists/{id} filtra preguntas eliminadas (is_deleted=false)
- Validación de subpreguntas activas antes de eliminar
- Índices agregados para optimizar queries
- Mantiene integridad de respuestas históricas y PDFs generados
- Permite limpiar checklists sin afectar inspecciones completadas
This commit is contained in:
@@ -204,7 +204,7 @@ def send_completed_inspection_to_n8n(inspection, db):
|
||||
# No lanzamos excepción para no interrumpir el flujo normal
|
||||
|
||||
|
||||
BACKEND_VERSION = "1.0.69"
|
||||
BACKEND_VERSION = "1.0.71"
|
||||
app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION)
|
||||
|
||||
# S3/MinIO configuration
|
||||
@@ -780,13 +780,17 @@ def get_checklists(
|
||||
|
||||
@app.get("/api/checklists/{checklist_id}", response_model=schemas.ChecklistWithQuestions)
|
||||
def get_checklist(checklist_id: int, db: Session = Depends(get_db)):
|
||||
checklist = db.query(models.Checklist).options(
|
||||
joinedload(models.Checklist.questions)
|
||||
).filter(models.Checklist.id == checklist_id).first()
|
||||
checklist = db.query(models.Checklist).filter(models.Checklist.id == checklist_id).first()
|
||||
|
||||
if not checklist:
|
||||
raise HTTPException(status_code=404, detail="Checklist no encontrado")
|
||||
|
||||
# Cargar solo preguntas NO eliminadas
|
||||
checklist.questions = db.query(models.Question).filter(
|
||||
models.Question.checklist_id == checklist_id,
|
||||
models.Question.is_deleted == False
|
||||
).order_by(models.Question.order).all()
|
||||
|
||||
# Agregar allowed_mechanics
|
||||
permissions = db.query(models.ChecklistPermission.mechanic_id).filter(
|
||||
models.ChecklistPermission.checklist_id == checklist.id
|
||||
@@ -1050,6 +1054,21 @@ def delete_question(
|
||||
if not db_question:
|
||||
raise HTTPException(status_code=404, detail="Pregunta no encontrada")
|
||||
|
||||
if db_question.is_deleted:
|
||||
raise HTTPException(status_code=400, detail="La pregunta ya está eliminada")
|
||||
|
||||
# Verificar si tiene subpreguntas activas
|
||||
active_subquestions = db.query(models.Question).filter(
|
||||
models.Question.parent_question_id == question_id,
|
||||
models.Question.is_deleted == False
|
||||
).count()
|
||||
|
||||
if active_subquestions > 0:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"No se puede eliminar la pregunta porque tiene {active_subquestions} subpregunta(s) activa(s). Elimina primero las subpreguntas."
|
||||
)
|
||||
|
||||
# Registrar auditoría antes de eliminar
|
||||
audit_log = models.QuestionAuditLog(
|
||||
question_id=question_id,
|
||||
@@ -1061,9 +1080,16 @@ def delete_question(
|
||||
)
|
||||
db.add(audit_log)
|
||||
|
||||
db.delete(db_question)
|
||||
# SOFT DELETE: marcar como eliminada en lugar de borrar físicamente
|
||||
db_question.is_deleted = True
|
||||
db_question.updated_at = datetime.utcnow()
|
||||
|
||||
db.commit()
|
||||
return {"message": "Pregunta eliminada"}
|
||||
|
||||
return {
|
||||
"message": "Pregunta eliminada exitosamente",
|
||||
"note": "Las respuestas históricas se mantienen intactas. La pregunta no aparecerá en nuevas inspecciones."
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/questions/{question_id}/audit", response_model=List[schemas.QuestionAuditLog])
|
||||
|
||||
@@ -83,7 +83,11 @@ class Question(Base):
|
||||
# AI Analysis
|
||||
ai_prompt = Column(Text, nullable=True) # Prompt personalizado para análisis de IA de esta pregunta
|
||||
|
||||
# Soft Delete
|
||||
is_deleted = Column(Boolean, default=False) # Soft delete: mantiene integridad de respuestas históricas
|
||||
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
|
||||
# Relationships
|
||||
checklist = relationship("Checklist", back_populates="questions")
|
||||
|
||||
@@ -126,6 +126,7 @@ class QuestionBase(BaseModel):
|
||||
parent_question_id: Optional[int] = None
|
||||
show_if_answer: Optional[str] = None
|
||||
ai_prompt: Optional[str] = None
|
||||
is_deleted: bool = False
|
||||
|
||||
class QuestionCreate(QuestionBase):
|
||||
checklist_id: int
|
||||
@@ -137,6 +138,7 @@ class Question(QuestionBase):
|
||||
id: int
|
||||
checklist_id: int
|
||||
created_at: datetime
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
Reference in New Issue
Block a user