- Nuevo modelo StudentEnrollment (tabla student_enrollments)
con inscripcion unica por alumno/comision, estado y notas
- Migracion automatica en init_db.py (CREATE TABLE IF NOT EXISTS)
- Rutas /admin/commissions/ para Bedelia y Admin:
listado con filtros, detalle, asignar docente,
inscribir/dar de baja alumnos, cambiar estado
- Blueprint my_subjects_bp en /mis-materias:
Docente ve solo sus comisiones asignadas
Alumno ve solo sus inscripciones activas
Admin/Bedelia ven todo
- Templates: admin/commissions/list.html, detail.html
my_subjects/list.html, detail.html
- Navbar actualizado por rol:
Docente y Alumno: 'Mis Materias'
Bedelia y Admin: 'Gestion de Comisiones'
50 lines
1.9 KiB
Python
50 lines
1.9 KiB
Python
from app import db
|
|
from datetime import datetime
|
|
|
|
|
|
class StudentEnrollment(db.Model):
|
|
"""Association table: student (User) ↔ Commission enrollment managed by Bedelía."""
|
|
__tablename__ = 'student_enrollments'
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
student_id = db.Column(
|
|
db.Integer,
|
|
db.ForeignKey('users.id', ondelete='CASCADE'),
|
|
nullable=False,
|
|
index=True
|
|
)
|
|
commission_id = db.Column(
|
|
db.Integer,
|
|
db.ForeignKey('commissions.id', ondelete='CASCADE'),
|
|
nullable=False,
|
|
index=True
|
|
)
|
|
status = db.Column(db.String(20), nullable=False, default='activo') # activo | retirado | condicional
|
|
enrolled_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
notes = db.Column(db.Text, nullable=True)
|
|
|
|
# Unique constraint: a student can only be enrolled once per commission
|
|
__table_args__ = (
|
|
db.UniqueConstraint('student_id', 'commission_id', name='uq_student_commission'),
|
|
)
|
|
|
|
# Relationships
|
|
student = db.relationship('User', backref=db.backref('enrollments', lazy='dynamic', cascade='all, delete-orphan'))
|
|
commission = db.relationship('Commission', backref=db.backref('enrollments', lazy='dynamic', cascade='all, delete-orphan'))
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'id': self.id,
|
|
'student_id': self.student_id,
|
|
'student_name': self.student.name if self.student else None,
|
|
'student_email': self.student.email if self.student else None,
|
|
'commission_id': self.commission_id,
|
|
'status': self.status,
|
|
'enrolled_at': self.enrolled_at.isoformat() if self.enrolled_at else None,
|
|
'notes': self.notes,
|
|
}
|
|
|
|
def __repr__(self):
|
|
return f'<StudentEnrollment student={self.student_id} commission={self.commission_id} status={self.status}>'
|