Files

168 lines
6.2 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Herramienta de Limpieza y Reinicio de Datos Académicos para UniCABA / Edu-Space.
Permite eliminar de forma segura y en el orden estricto de claves foráneas:
- Asignaciones de aulas / Reservas (reservations)
- Inscripciones de alumnos (student_enrollments)
- Comisiones de cursada (commissions)
- Asignaturas / Materias (subjects)
- Carreras académicas (careers)
- Recursos de aula y Aulas físicas / virtuales (classroom_resources, classrooms)
PRESERVA INTOLERABLEMENTE:
- Usuarios del sistema (Users: admin, bedelia, docentes, alumnos)
- Roles y Permisos RBAC
- Edificios institucionales (Buildings)
- Registros de auditoría (AuditLogs)
"""
import sys
import os
import argparse
# Asegurar que el directorio backend está en el PYTHONPATH
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from app import create_app, db
from app.models.reservation import Reservation
from app.models.enrollment import StudentEnrollment
from app.models.milestone import AcademicMilestone
from app.models.subject import Commission, Subject
from app.models.career import Career
from app.models.classroom import Classroom, ClassroomResource
def execute_academic_reset(
reset_reservations=True,
reset_commissions=True,
reset_subjects=True,
reset_careers=True,
reset_classrooms=True
):
"""
Ejecuta el reinicio de las entidades académicas seleccionadas.
Retorna un diccionario con el conteo de registros eliminados.
"""
# Si se reinicia una entidad superior, automáticamente deben reiniciarse sus dependientes
if reset_careers:
reset_subjects = True
if reset_subjects:
reset_commissions = True
if reset_commissions or reset_classrooms:
reset_reservations = True
deleted_counts = {
'reservations': 0,
'enrollments': 0,
'commissions': 0,
'subjects': 0,
'careers': 0,
'classrooms': 0,
'classroom_resources': 0
}
try:
# 1. Eliminar Reservas (Asignaciones de aulas)
if reset_reservations:
deleted_counts['reservations'] = Reservation.query.delete()
# 2. Desvincular hitos de materias o comisiones si se van a eliminar
if reset_subjects or reset_commissions:
AcademicMilestone.query.update({
AcademicMilestone.subject_id: None,
AcademicMilestone.commission_id: None
})
db.session.flush()
# 3. Eliminar Inscripciones y Comisiones
if reset_commissions:
deleted_counts['enrollments'] = StudentEnrollment.query.delete()
deleted_counts['commissions'] = Commission.query.delete()
# 4. Eliminar Materias / Asignaturas
if reset_subjects:
deleted_counts['subjects'] = Subject.query.delete()
# 5. Eliminar Carreras
if reset_careers:
deleted_counts['careers'] = Career.query.delete()
# 6. Eliminar Recursos y Aulas
if reset_classrooms:
deleted_counts['classroom_resources'] = ClassroomResource.query.delete()
deleted_counts['classrooms'] = Classroom.query.delete()
db.session.commit()
return {
'success': True,
'deleted': deleted_counts,
'message': 'Datos académicos reiniciados exitosamente.'
}
except Exception as e:
db.session.rollback()
return {
'success': False,
'error': str(e),
'deleted': deleted_counts
}
def main():
parser = argparse.ArgumentParser(description="Limpieza y purga de datos académicos para pruebas del importador.")
parser.add_argument('--all', action='store_true', help="Eliminar todo: reservas, comisiones, asignaturas, carreras y aulas.")
parser.add_argument('--reservations', action='store_true', help="Eliminar únicamente las asignaciones de aulas.")
parser.add_argument('--classrooms', action='store_true', help="Eliminar aulas y sus asignaciones asociadas.")
parser.add_argument('--careers', action='store_true', help="Eliminar carreras, asignaturas, comisiones y asignaciones.")
parser.add_argument('--yes', '-y', action='store_true', help="Confirmar automáticamente sin preguntar.")
args = parser.parse_args()
# Si no se pasó ninguna opción específica, asumir --all si el usuario lo confirma
if not (args.all or args.reservations or args.classrooms or args.careers):
args.all = True
app = create_app()
with app.app_context():
# Mostrar estado actual de la BD
print("=" * 60)
print(" ESTADO ACTUAL DE ENTIDADES ACADÉMICAS EN BASE DE DATOS")
print("=" * 60)
print(f" - Asignaciones de Aulas (Reservas): {Reservation.query.count()}")
print(f" - Comisiones: {Commission.query.count()}")
print(f" - Asignaturas / Materias: {Subject.query.count()}")
print(f" - Carreras: {Career.query.count()}")
print(f" - Aulas (Físicas y Virtuales): {Classroom.query.count()}")
print("=" * 60)
if not args.yes:
confirm = input("\n¿Está SEGURO de eliminar los datos seleccionados? Escriba 'CONFIRMAR': ")
if confirm.strip() != 'CONFIRMAR':
print("Operación cancelada.")
sys.exit(0)
r_res = args.all or args.reservations or args.classrooms or args.careers
r_comm = args.all or args.careers
r_subj = args.all or args.careers
r_car = args.all or args.careers
r_cls = args.all or args.classrooms
print("\nEjecutando limpieza de datos...")
res = execute_academic_reset(
reset_reservations=r_res,
reset_commissions=r_comm,
reset_subjects=r_subj,
reset_careers=r_car,
reset_classrooms=r_cls
)
if res['success']:
print("\n[OK] Limpieza completada con éxito:")
for k, v in res['deleted'].items():
print(f" - {k}: {v} registros eliminados")
else:
print(f"\n[ERROR] Falló la limpieza: {res['error']}")
sys.exit(1)
if __name__ == '__main__':
main()