fix(db): anadir migraciones DDL para columnas extendidas de users, subjects y commissions

This commit is contained in:
2026-09-23 14:36:44 -03:00
parent a19f3911fe
commit bddd382c96
2 changed files with 122 additions and 18 deletions
+107 -15
View File
@@ -22,21 +22,29 @@ def init_database():
# 2. Migraciones incrementales seguras para bases de datos existentes
if db.engine.url.drivername != 'sqlite':
# Columnas extendidas de users
db.session.execute(text("""
ALTER TABLE users ADD COLUMN IF NOT EXISTS preferred_language VARCHAR(10) DEFAULT NULL;
"""))
db.session.execute(text("""
ALTER TABLE users ADD COLUMN IF NOT EXISTS theme_preference VARCHAR(10) DEFAULT 'auto' NOT NULL;
"""))
db.session.execute(text("""
ALTER TABLE users ADD COLUMN IF NOT EXISTS role_id INTEGER REFERENCES roles(id) ON DELETE SET NULL;
ALTER TABLE users ADD COLUMN IF NOT EXISTS first_name VARCHAR(100);
ALTER TABLE users ADD COLUMN IF NOT EXISTS last_name VARCHAR(100);
ALTER TABLE users ADD COLUMN IF NOT EXISTS phone VARCHAR(50);
ALTER TABLE users ADD COLUMN IF NOT EXISTS personal_email VARCHAR(255);
ALTER TABLE users ADD COLUMN IF NOT EXISTS address VARCHAR(255);
ALTER TABLE users ADD COLUMN IF NOT EXISTS document_type VARCHAR(20) DEFAULT 'DNI';
ALTER TABLE users ADD COLUMN IF NOT EXISTS document_number VARCHAR(30);
CREATE INDEX IF NOT EXISTS ix_users_document_number ON users (document_number);
"""))
# Columnas extendidas de subjects
db.session.execute(text("""
ALTER TABLE subjects ADD COLUMN IF NOT EXISTS career_id INTEGER REFERENCES careers(id) ON DELETE SET NULL;
"""))
db.session.execute(text("""
ALTER TABLE subjects ALTER COLUMN code TYPE VARCHAR(50);
ALTER TABLE subjects ADD COLUMN IF NOT EXISTS is_short_course BOOLEAN DEFAULT FALSE;
"""))
# Infraestructura: buildings y classrooms
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS buildings (
id SERIAL PRIMARY KEY,
@@ -49,7 +57,26 @@ def init_database():
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
);
ALTER TABLE classrooms ADD COLUMN IF NOT EXISTS building_id INTEGER REFERENCES buildings(id) ON DELETE SET NULL;
"""))
# Columnas extendidas de commissions
db.session.execute(text("""
ALTER TABLE commissions ADD COLUMN IF NOT EXISTS shift VARCHAR(30);
ALTER TABLE commissions ADD COLUMN IF NOT EXISTS virtual_link VARCHAR(500);
ALTER TABLE commissions ADD COLUMN IF NOT EXISTS grades_closed BOOLEAN DEFAULT FALSE;
ALTER TABLE commissions ADD COLUMN IF NOT EXISTS grades_closed_at TIMESTAMP WITHOUT TIME ZONE;
ALTER TABLE commissions ADD COLUMN IF NOT EXISTS grades_closed_by INTEGER REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE commissions ADD COLUMN IF NOT EXISTS acta_number VARCHAR(50);
"""))
# Columnas extendidas de reservations
db.session.execute(text("""
ALTER TABLE reservations ADD COLUMN IF NOT EXISTS shift VARCHAR(30);
ALTER TABLE reservations ADD COLUMN IF NOT EXISTS virtual_link VARCHAR(500);
"""))
# Tablas de soporte: audit_logs
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS audit_logs (
id SERIAL PRIMARY KEY,
@@ -66,15 +93,8 @@ def init_database():
CREATE INDEX IF NOT EXISTS ix_audit_logs_module ON audit_logs (module);
CREATE INDEX IF NOT EXISTS ix_audit_logs_created_at ON audit_logs (created_at);
"""))
db.session.execute(text("""
ALTER TABLE classrooms ADD COLUMN IF NOT EXISTS building_id INTEGER REFERENCES buildings(id) ON DELETE SET NULL;
"""))
db.session.execute(text("""
ALTER TABLE commissions ADD COLUMN IF NOT EXISTS shift VARCHAR(30);
"""))
db.session.execute(text("""
ALTER TABLE reservations ADD COLUMN IF NOT EXISTS shift VARCHAR(30);
"""))
# Tablas de soporte: student_enrollments
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS student_enrollments (
id SERIAL PRIMARY KEY,
@@ -89,7 +109,79 @@ def init_database():
CREATE INDEX IF NOT EXISTS ix_student_enrollments_student_id ON student_enrollments (student_id);
CREATE INDEX IF NOT EXISTS ix_student_enrollments_commission_id ON student_enrollments (commission_id);
"""))
# Tablas de soporte: commission_teachers
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS commission_teachers (
id SERIAL PRIMARY KEY,
commission_id INTEGER NOT NULL REFERENCES commissions(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role VARCHAR(50) DEFAULT 'Titular' NOT NULL,
is_primary BOOLEAN DEFAULT FALSE NOT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
CONSTRAINT uq_commission_teacher UNIQUE (commission_id, user_id)
);
CREATE INDEX IF NOT EXISTS ix_commission_teachers_commission_id ON commission_teachers (commission_id);
CREATE INDEX IF NOT EXISTS ix_commission_teachers_user_id ON commission_teachers (user_id);
"""))
# Tablas de soporte: system_settings
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS system_settings (
id SERIAL PRIMARY KEY,
key VARCHAR(100) UNIQUE NOT NULL,
value TEXT,
description VARCHAR(255),
category VARCHAR(50) DEFAULT 'system',
is_encrypted BOOLEAN DEFAULT FALSE,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS ix_system_settings_key ON system_settings (key);
"""))
# Tablas de soporte: moodle_sync_tasks
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS moodle_sync_tasks (
id SERIAL PRIMARY KEY,
action VARCHAR(50) NOT NULL,
entity_type VARCHAR(50) NOT NULL,
entity_id VARCHAR(100),
payload TEXT NOT NULL,
status VARCHAR(20) DEFAULT 'PENDING',
attempts INTEGER DEFAULT 0,
max_attempts INTEGER DEFAULT 5,
error_message TEXT,
next_retry_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS ix_moodle_sync_tasks_action ON moodle_sync_tasks (action);
CREATE INDEX IF NOT EXISTS ix_moodle_sync_tasks_status ON moodle_sync_tasks (status);
CREATE INDEX IF NOT EXISTS ix_moodle_sync_tasks_next_retry_at ON moodle_sync_tasks (next_retry_at);
"""))
db.session.commit()
else:
try:
cursor = db.session.connection().connection.cursor()
cursor.execute("PRAGMA table_info(users)")
existing_cols = [row[1] for row in cursor.fetchall()]
for col_name, col_def in [
('preferred_language', 'VARCHAR(10)'),
('theme_preference', "VARCHAR(10) DEFAULT 'auto'"),
('role_id', 'INTEGER'),
('first_name', 'VARCHAR(100)'),
('last_name', 'VARCHAR(100)'),
('phone', 'VARCHAR(50)'),
('personal_email', 'VARCHAR(255)'),
('address', 'VARCHAR(255)'),
('document_type', "VARCHAR(20) DEFAULT 'DNI'"),
('document_number', 'VARCHAR(30)')
]:
if col_name not in existing_cols:
cursor.execute(f"ALTER TABLE users ADD COLUMN {col_name} {col_def}")
db.session.commit()
except Exception:
pass
print("[OK] Esquema y tablas actualizadas con éxito.")
# 3. Crear o sincronizar roles predeterminados y matriz de permisos