Files

185 lines
6.9 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.grade import MilestoneGrade
from app.models.subject import Commission, Subject, CommissionTeacher
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,
'commission_teachers': 0,
'milestones': 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()
db.session.flush()
# 2. Eliminar calificaciones e hitos evaluativos vinculados a comisiones o materias
if reset_subjects or reset_commissions or reset_careers:
try:
MilestoneGrade.query.delete()
deleted_counts['milestones'] = AcademicMilestone.query.delete()
except Exception as me:
print("Notice during milestones cleanup:", me)
db.session.flush()
# 3. Eliminar Docentes de comisión, Inscripciones de alumnos y Comisiones
if reset_commissions or reset_subjects or reset_careers:
try:
deleted_counts['commission_teachers'] = CommissionTeacher.query.delete()
except Exception as cte:
print("Notice during commission teachers cleanup:", cte)
db.session.flush()
deleted_counts['enrollments'] = StudentEnrollment.query.delete()
db.session.flush()
deleted_counts['commissions'] = Commission.query.delete()
db.session.flush()
# 4. Eliminar Materias / Asignaturas
if reset_subjects or reset_careers:
deleted_counts['subjects'] = Subject.query.delete()
db.session.flush()
# 5. Eliminar Carreras
if reset_careers:
deleted_counts['careers'] = Career.query.delete()
db.session.flush()
# 6. Eliminar Recursos y Aulas
if reset_classrooms:
deleted_counts['classroom_resources'] = ClassroomResource.query.delete()
deleted_counts['classrooms'] = Classroom.query.delete()
db.session.flush()
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()