185 lines
6.9 KiB
Python
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()
|