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:
2025-11-27 15:34:19 -03:00
parent ed3f513075
commit 826c5fce5e

View File

@@ -204,7 +204,7 @@ def send_completed_inspection_to_n8n(inspection, db):
# No lanzamos excepción para no interrumpir el flujo normal # No lanzamos excepción para no interrumpir el flujo normal
BACKEND_VERSION = "1.0.71" BACKEND_VERSION = "1.0.72"
app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION) app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION)
# S3/MinIO configuration # S3/MinIO configuration
@@ -1057,18 +1057,6 @@ def delete_question(
if db_question.is_deleted: if db_question.is_deleted:
raise HTTPException(status_code=400, detail="La pregunta ya está eliminada") 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 # Registrar auditoría antes de eliminar
audit_log = models.QuestionAuditLog( audit_log = models.QuestionAuditLog(
question_id=question_id, question_id=question_id,
@@ -1080,15 +1068,44 @@ def delete_question(
) )
db.add(audit_log) db.add(audit_log)
# SOFT DELETE: marcar como eliminada en lugar de borrar físicamente # SOFT DELETE: marcar como eliminada
db_question.is_deleted = True db_question.is_deleted = True
db_question.updated_at = datetime.utcnow() db_question.updated_at = datetime.utcnow()
# También marcar como eliminadas todas las subpreguntas (en cascada)
subquestions = db.query(models.Question).filter(
models.Question.parent_question_id == question_id,
models.Question.is_deleted == False
).all()
subquestion_count = 0
for subq in subquestions:
subq.is_deleted = True
subq.updated_at = datetime.utcnow()
subquestion_count += 1
# Registrar auditoría de subpregunta
sub_audit_log = models.QuestionAuditLog(
question_id=subq.id,
checklist_id=subq.checklist_id,
user_id=current_user.id,
action="deleted",
old_value=f"Subpregunta eliminada en cascada: {subq.text}",
comment=f"Eliminada junto con pregunta padre #{question_id}"
)
db.add(sub_audit_log)
db.commit() db.commit()
message = "Pregunta eliminada exitosamente"
if subquestion_count > 0:
message += f" junto con {subquestion_count} subpregunta(s)"
return { return {
"message": "Pregunta eliminada exitosamente", "message": message,
"note": "Las respuestas históricas se mantienen intactas. La pregunta no aparecerá en nuevas inspecciones." "id": question_id,
"subquestions_deleted": subquestion_count,
"note": "Las respuestas históricas se mantienen intactas. Las preguntas no aparecerán en nuevas inspecciones."
} }