"""This module defines the SQL data model for users. All users are either Patients or Administrators. """ import enum from sqlalchemy import Column, ForeignKey, Integer, String, DateTime, Date, Enum, CheckConstraint from sqlalchemy.sql.functions import now from sqlalchemy.orm import relationship from backend.database.engine import Base from backend.models.devices import Device class User(Base): """Model for the users table. Contains user info common to all user classes.""" __tablename__ = "users" id = Column('id', Integer, primary_key=True, autoincrement=True, index=True) email = Column('email', String, unique=True, nullable=False) password = Column('password', String, nullable=False) created = Column('created', DateTime(timezone=True), nullable=False, server_default=now()) updated = Column('updated', DateTime(timezone=True), nullable=False, server_default=now(), onupdate=now()) first_name = Column('first_name', String, nullable=False) last_name = Column('last_name', String, nullable=False) administrator = relationship("Administrator", back_populates="user", uselist=False, cascade="all, delete") patient = relationship("Patient", back_populates="user", uselist=False, cascade="all, delete") class Administrator(Base): """Model for the administrators table. Contains user info specific to administrators.""" __tablename__ = "administrators" user_id = Column('user_id', Integer, ForeignKey('users.id', ondelete="CASCADE"), primary_key=True) user = relationship(User, back_populates="administrator", uselist=False, cascade="all, delete") class Gender(enum.Enum): """Gender (as assigned at birth) of a patient.""" male = 'm' female = 'f' class Patient(Base): """Model for the patients table. Contains user info specific to patients.""" __tablename__ = "patients" user_id = Column('user_id', Integer, ForeignKey('users.id', ondelete="CASCADE"), primary_key=True) date_of_birth = Column('date_of_birth', Date, nullable=False) gender = Column('gender', Enum(Gender), nullable=False) user = relationship(User, back_populates="patient", uselist=False, cascade="all, delete") devices = relationship(Device, back_populates="owner", uselist=True, cascade="all, delete")