feat(install): agregar opcion --empty-academic en install.sh e init_db.py para inicializar base de datos sin datos demo
This commit is contained in:
+141
-90
@@ -8,6 +8,7 @@ if hasattr(sys.stderr, 'reconfigure'):
|
||||
sys.stderr.reconfigure(encoding='utf-8')
|
||||
|
||||
from app import create_app, db
|
||||
from app import models
|
||||
from app.models.user import User
|
||||
from app.models.role import Role, Permission, SYSTEM_MODULES
|
||||
from sqlalchemy import text
|
||||
@@ -313,6 +314,49 @@ def init_database():
|
||||
|
||||
# 4. Verificar o crear usuarios institucionales de cada rol
|
||||
keep_users = ('--keep-users' in sys.argv) or (os.environ.get('KEEP_USERS', '').lower() in ['1', 'true', 'yes'])
|
||||
empty_academic = any(arg in sys.argv for arg in ['--empty-academic', '--no-demo', '--clean-db', '--without-demo-data', '--skip-demo']) or \
|
||||
(os.environ.get('EMPTY_ACADEMIC', '').lower() in ['1', 'true', 'yes'])
|
||||
|
||||
if empty_academic:
|
||||
print("[*] Opción --empty-academic activa: Se configurará la base de datos limpia SIN carreras, materias, ciclos lectivos, aulas, edificios ni reservas por defecto.")
|
||||
try:
|
||||
from app.models.reservation import Reservation
|
||||
from app.models.grade import MilestoneGrade
|
||||
from app.models.milestone import AcademicMilestone
|
||||
from app.models.subject import CommissionTeacher, Commission, Subject
|
||||
from app.models.enrollment import StudentEnrollment
|
||||
from app.models.career import Career
|
||||
from app.models.classroom import ClassroomResource, Classroom
|
||||
from app.models.building import Building
|
||||
from app.models.academic_term import AcademicTerm
|
||||
|
||||
Reservation.query.delete()
|
||||
try:
|
||||
MilestoneGrade.query.delete()
|
||||
AcademicMilestone.query.delete()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
CommissionTeacher.query.delete()
|
||||
except Exception:
|
||||
pass
|
||||
StudentEnrollment.query.delete()
|
||||
Commission.query.delete()
|
||||
Subject.query.delete()
|
||||
Career.query.delete()
|
||||
try:
|
||||
ClassroomResource.query.delete()
|
||||
except Exception:
|
||||
pass
|
||||
Classroom.query.delete()
|
||||
Building.query.delete()
|
||||
AcademicTerm.query.delete()
|
||||
db.session.commit()
|
||||
print(" [OK] Tablas de carreras, materias, comisiones, aulas, edificios y reservas aseguradas vacías.")
|
||||
except Exception as pe:
|
||||
db.session.rollback()
|
||||
print(f" [!] Nota durante verificación de tablas académicas vacías: {pe}")
|
||||
|
||||
if keep_users:
|
||||
print("[*] Opción --keep-users activa: Preservando usuarios, roles y contraseñas existentes intactos (no se modifican ni pisan).")
|
||||
else:
|
||||
@@ -380,33 +424,36 @@ def init_database():
|
||||
print(f" [OK] Usuario {u_info['email']} validado (Rol: {u_info['role_name']}).")
|
||||
|
||||
# 5. Inicializar edificios institucionales oficiales
|
||||
print("[*] Verificando edificios institucionales...")
|
||||
from app.models.building import Building
|
||||
b_central = Building.query.filter_by(name='Edificio Central').first()
|
||||
if not b_central:
|
||||
b_central = Building(
|
||||
name='Edificio Central',
|
||||
code='CENTRAL',
|
||||
address='Tte. Gral. Juan Domingo Peron 802, CABA',
|
||||
floors=4,
|
||||
description='Sede central institucional de UniCABA. Aulas de grado, auditorio y laboratorios.'
|
||||
)
|
||||
db.session.add(b_central)
|
||||
else:
|
||||
b_central.address = 'Tte. Gral. Juan Domingo Peron 802, CABA'
|
||||
if not empty_academic:
|
||||
print("[*] Verificando edificios institucionales...")
|
||||
from app.models.building import Building
|
||||
b_central = Building.query.filter_by(name='Edificio Central').first()
|
||||
if not b_central:
|
||||
b_central = Building(
|
||||
name='Edificio Central',
|
||||
code='CENTRAL',
|
||||
address='Tte. Gral. Juan Domingo Peron 802, CABA',
|
||||
floors=4,
|
||||
description='Sede central institucional de UniCABA. Aulas de grado, auditorio y laboratorios.'
|
||||
)
|
||||
db.session.add(b_central)
|
||||
else:
|
||||
b_central.address = 'Tte. Gral. Juan Domingo Peron 802, CABA'
|
||||
|
||||
b_virtual = Building.query.filter_by(name='Campus Virtual').first()
|
||||
if not b_virtual:
|
||||
b_virtual = Building(
|
||||
name='Campus Virtual',
|
||||
code='VIRTUAL',
|
||||
address='Entorno Digital / Microsoft Teams - Moodle',
|
||||
floors=0,
|
||||
description='Entorno de aulas virtuales y clases a distancia'
|
||||
)
|
||||
db.session.add(b_virtual)
|
||||
db.session.commit()
|
||||
print("[OK] Edificios institucionales configurados con dirección oficial.")
|
||||
b_virtual = Building.query.filter_by(name='Campus Virtual').first()
|
||||
if not b_virtual:
|
||||
b_virtual = Building(
|
||||
name='Campus Virtual',
|
||||
code='VIRTUAL',
|
||||
address='Entorno Digital / Microsoft Teams - Moodle',
|
||||
floors=0,
|
||||
description='Entorno de aulas virtuales y clases a distancia'
|
||||
)
|
||||
db.session.add(b_virtual)
|
||||
db.session.commit()
|
||||
print("[OK] Edificios institucionales configurados con dirección oficial.")
|
||||
else:
|
||||
print("[*] Modo --empty-academic: Omitiendo creación de edificios institucionales por defecto.")
|
||||
|
||||
# 6. Inicializar catalogo dinamico de tipificaciones de hitos academicos
|
||||
print("[*] Verificando catalogo de tipificaciones de hitos academicos...")
|
||||
@@ -432,76 +479,80 @@ def init_database():
|
||||
print(f"[OK] Catalogo de tipificaciones inicializado ({MilestoneType.query.count()} tipos disponibles).")
|
||||
|
||||
# 7. Inicializar aulas, materias, comisiones y reservas de muestra
|
||||
from app.models.classroom import Classroom
|
||||
from app.models.subject import Subject, Commission
|
||||
from app.models.reservation import Reservation, ReservationStatus
|
||||
from datetime import datetime, timedelta, date
|
||||
if not empty_academic:
|
||||
from app.models.classroom import Classroom
|
||||
from app.models.subject import Subject, Commission
|
||||
from app.models.reservation import Reservation, ReservationStatus
|
||||
from datetime import datetime, timedelta, date
|
||||
|
||||
if Classroom.query.count() == 0:
|
||||
print("[*] Generando catalogo de aulas...")
|
||||
for floor in ['PB', '1', '2', '3']:
|
||||
for num in range(1, 8):
|
||||
code = f'{floor}0{num}' if floor != 'PB' else f'PB-0{num}'
|
||||
c = Classroom(
|
||||
code=code,
|
||||
building=b_central.name,
|
||||
building_id=b_central.id,
|
||||
floor=floor,
|
||||
capacity=30 + (num * 5),
|
||||
description=f'Aula física estándar {code} en {b_central.name}',
|
||||
if Classroom.query.count() == 0 and 'b_central' in locals() and b_central and 'b_virtual' in locals() and b_virtual:
|
||||
print("[*] Generando catalogo de aulas...")
|
||||
for floor in ['PB', '1', '2', '3']:
|
||||
for num in range(1, 8):
|
||||
code = f'{floor}0{num}' if floor != 'PB' else f'PB-0{num}'
|
||||
c = Classroom(
|
||||
code=code,
|
||||
building=b_central.name,
|
||||
building_id=b_central.id,
|
||||
floor=floor,
|
||||
capacity=30 + (num * 5),
|
||||
description=f'Aula física estándar {code} en {b_central.name}',
|
||||
is_active=True
|
||||
)
|
||||
db.session.add(c)
|
||||
|
||||
for v in range(1, 4):
|
||||
vc = Classroom(
|
||||
code=f'VIRTUAL-0{v}',
|
||||
building=b_virtual.name,
|
||||
building_id=b_virtual.id,
|
||||
floor='0',
|
||||
capacity=100,
|
||||
description=f'Sala virtual Microsoft Teams {v}',
|
||||
is_active=True
|
||||
)
|
||||
db.session.add(c)
|
||||
db.session.add(vc)
|
||||
db.session.commit()
|
||||
print(f"[OK] {Classroom.query.count()} aulas creadas.")
|
||||
|
||||
for v in range(1, 4):
|
||||
vc = Classroom(
|
||||
code=f'VIRTUAL-0{v}',
|
||||
building=b_virtual.name,
|
||||
building_id=b_virtual.id,
|
||||
floor='0',
|
||||
capacity=100,
|
||||
description=f'Sala virtual Microsoft Teams {v}',
|
||||
is_active=True
|
||||
)
|
||||
db.session.add(vc)
|
||||
db.session.commit()
|
||||
print(f"[OK] {Classroom.query.count()} aulas creadas.")
|
||||
# Materia y Comisión
|
||||
s = Subject.query.filter_by(code='ARQ-101').first()
|
||||
if not s:
|
||||
s = Subject(name='Arquitectura de Software', code='ARQ-101', is_active=True)
|
||||
db.session.add(s)
|
||||
db.session.commit()
|
||||
|
||||
# Materia y Comisión
|
||||
s = Subject.query.filter_by(code='ARQ-101').first()
|
||||
if not s:
|
||||
s = Subject(name='Arquitectura de Software', code='ARQ-101', is_active=True)
|
||||
db.session.add(s)
|
||||
db.session.commit()
|
||||
comm = Commission.query.filter_by(code='COM-A').first()
|
||||
if not comm:
|
||||
comm = Commission(code='COM-A', subject_id=s.id, shift='Noche', semester=2, year=2026, max_students=40, is_active=True)
|
||||
db.session.add(comm)
|
||||
db.session.commit()
|
||||
|
||||
comm = Commission.query.filter_by(code='COM-A').first()
|
||||
if not comm:
|
||||
comm = Commission(code='COM-A', subject_id=s.id, shift='Noche', semester=2, year=2026, max_students=40, is_active=True)
|
||||
db.session.add(comm)
|
||||
db.session.commit()
|
||||
|
||||
# Reservas de Hoy
|
||||
if Reservation.query.count() == 0:
|
||||
print("[*] Generando reservas de muestra...")
|
||||
today = date.today()
|
||||
classrooms = Classroom.query.all()
|
||||
docente = User.query.filter_by(email='docente@edu-space.com').first()
|
||||
for idx, cl in enumerate(classrooms[:19]):
|
||||
start_hour = 8 + (idx % 6) * 2
|
||||
r = Reservation(
|
||||
classroom_id=cl.id,
|
||||
commission_id=comm.id,
|
||||
user_id=docente.id if docente else 1,
|
||||
start_time=datetime.combine(today, datetime.min.time()) + timedelta(hours=start_hour),
|
||||
end_time=datetime.combine(today, datetime.min.time()) + timedelta(hours=start_hour + 2),
|
||||
purpose='Clase Regular',
|
||||
status=ReservationStatus.CONFIRMED.value,
|
||||
shift='Noche' if start_hour >= 18 else 'Tarde' if start_hour >= 13 else 'Mañana',
|
||||
expected_attendees=cl.capacity - 5
|
||||
)
|
||||
db.session.add(r)
|
||||
db.session.commit()
|
||||
print(f"[OK] {Reservation.query.count()} reservas creadas.")
|
||||
# Reservas de Hoy
|
||||
if Reservation.query.count() == 0:
|
||||
print("[*] Generando reservas de muestra...")
|
||||
today = date.today()
|
||||
classrooms = Classroom.query.all()
|
||||
docente = User.query.filter_by(email='docente@edu-space.com').first()
|
||||
for idx, cl in enumerate(classrooms[:19]):
|
||||
start_hour = 8 + (idx % 6) * 2
|
||||
r = Reservation(
|
||||
classroom_id=cl.id,
|
||||
commission_id=comm.id,
|
||||
user_id=docente.id if docente else 1,
|
||||
start_time=datetime.combine(today, datetime.min.time()) + timedelta(hours=start_hour),
|
||||
end_time=datetime.combine(today, datetime.min.time()) + timedelta(hours=start_hour + 2),
|
||||
purpose='Clase Regular',
|
||||
status=ReservationStatus.CONFIRMED.value,
|
||||
shift='Noche' if start_hour >= 18 else 'Tarde' if start_hour >= 13 else 'Mañana',
|
||||
expected_attendees=cl.capacity - 5
|
||||
)
|
||||
db.session.add(r)
|
||||
db.session.commit()
|
||||
print(f"[OK] {Reservation.query.count()} reservas creadas.")
|
||||
else:
|
||||
print("[*] Modo --empty-academic: Omitiendo creación de aulas, materias, comisiones y reservas de muestra.")
|
||||
print("[OK] Base de datos creada con tablas vacías para gestión académica y de espacios desde cero.")
|
||||
|
||||
print("\n[LISTO] Base de datos inicializada y lista para usar.")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user