from typing import TYPE_CHECKING from sqlalchemy import BigInteger, Table, ForeignKey, Column from sqlalchemy.orm import Mapped, mapped_column, relationship from enums.user import UserRole from models.base import BaseModel from models.work_shifts import WorkShift if TYPE_CHECKING: from models.payroll import PayRate, PaymentRecord role_permissions = Table( 'role_permissions', BaseModel.metadata, Column('role_key', ForeignKey('roles.key'), primary_key=True), Column('permission_key', ForeignKey('permissions.key'), primary_key=True) ) user_position = Table( 'user_position', BaseModel.metadata, Column('position_key', ForeignKey('positions.key'), primary_key=True), Column('user_id', ForeignKey('users.id'), primary_key=True, unique=True) ) user_pay_rate = Table( 'user_pay_rate', BaseModel.metadata, Column('pay_rate_id', ForeignKey('pay_rates.id'), primary_key=True), Column('user_id', ForeignKey('users.id'), primary_key=True, unique=True) ) class Permission(BaseModel): __tablename__ = 'permissions' key: Mapped[str] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column() roles: Mapped[list["Role"]] = relationship('Role', secondary=role_permissions, back_populates='permissions') class Role(BaseModel): __tablename__ = 'roles' key: Mapped[str] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column() permissions: Mapped[list["Permission"]] = relationship('Permission', secondary=role_permissions, back_populates='roles', lazy='selectin') # users: Mapped[list["User"]] = relationship("User", back_populates="users") class User(BaseModel): __tablename__ = 'users' id: Mapped[int] = mapped_column(primary_key=True) first_name: Mapped[str] = mapped_column(nullable=False, server_default='') second_name: Mapped[str] = mapped_column(nullable=False, server_default='') comment: Mapped[str] = mapped_column(nullable=False, server_default='') telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True) phone_number: Mapped[str] = mapped_column(nullable=True) is_admin: Mapped[bool] = mapped_column(nullable=False, default=False) is_blocked: Mapped[bool] = mapped_column(nullable=False, server_default='0') is_deleted: Mapped[bool] = mapped_column(nullable=False, server_default='0') role_key: Mapped[int] = mapped_column(ForeignKey('roles.key'), server_default=UserRole.user) role: Mapped["Role"] = relationship( 'Role', lazy='joined' ) position: Mapped["Position"] = relationship( 'Position', secondary=user_position, uselist=False, back_populates='users', lazy="joined" ) pay_rate: Mapped["PayRate"] = relationship( "PayRate", secondary=user_pay_rate, uselist=False, lazy="joined" ) payment_records: Mapped[list["PaymentRecord"]] = relationship( "PaymentRecord", back_populates="user", uselist=True, foreign_keys="PaymentRecord.user_id" ) work_shifts: Mapped[list["WorkShift"]] = relationship( "WorkShift", back_populates="user", uselist=True, foreign_keys="WorkShift.user_id" ) class Position(BaseModel): __tablename__ = 'positions' key: Mapped[str] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column() users: Mapped["User"] = relationship( 'User', secondary=user_position, uselist=False, back_populates='position' )