import datetime from typing import TYPE_CHECKING, Optional 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 from models import Deal, DealEmployees 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 UserDepartmentSection(BaseModel): __tablename__ = 'user_department_section' section_id: Mapped[int] = mapped_column(ForeignKey('department_sections.id'), primary_key=True) section: Mapped["DepartmentSection"] = relationship(lazy='selectin', back_populates='users') user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) user: Mapped["User"] = relationship(lazy="selectin", back_populates='department_sections') is_chief: Mapped[bool] = mapped_column(nullable=False, default=False, server_default='0') 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='') patronymic: 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) passport_data: Mapped[str] = mapped_column(nullable=True, comment='Серия и номер паспорта') 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[str] = 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" ) managed_deals: Mapped[list["Deal"]] = relationship( back_populates="manager", uselist=True, ) passport_images = relationship( 'PassportImage', back_populates='user', lazy='selectin', cascade="all, delete-orphan" ) deals: Mapped[list['DealEmployees']] = relationship( back_populates='user', lazy='selectin' ) department_sections: Mapped[list[UserDepartmentSection]] = relationship( "UserDepartmentSection", back_populates='user', lazy="noload", ) class InviteCode(BaseModel): __tablename__ = 'invite_codes' code: Mapped[str] = mapped_column(primary_key=True) is_activated: Mapped[bool] = mapped_column(nullable=False, default=False) user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) user: Mapped["User"] = relationship('User', foreign_keys=[user_id]) created_at: Mapped[datetime.datetime] = mapped_column(nullable=False) created_by_id: Mapped[int] = mapped_column(ForeignKey('users.id')) created_by: Mapped["User"] = relationship('User', foreign_keys=[created_by_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' ) class PassportImage(BaseModel): __tablename__ = 'passport_images' id: Mapped[int] = mapped_column(primary_key=True) user_id = mapped_column(ForeignKey('users.id'), nullable=False) user: Mapped["User"] = relationship(back_populates='passport_images') image_url: Mapped[str] = mapped_column(nullable=False) class Department(BaseModel): __tablename__ = 'departments' id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(unique=True) sections: Mapped[list['DepartmentSection']] = relationship( back_populates='department', lazy='selectin', cascade='all, delete', ) class DepartmentSection(BaseModel): __tablename__ = 'department_sections' id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(index=True) department_id: Mapped[Optional[int]] = mapped_column(ForeignKey('departments.id')) department: Mapped["Department"] = relationship( back_populates='sections', lazy='selectin', ) parent_department_section_id: Mapped[Optional[int]] = mapped_column(ForeignKey('department_sections.id')) parent_department_section: Mapped["DepartmentSection"] = relationship( "DepartmentSection", back_populates="sections", lazy='selectin', remote_side=[id], ) sections: Mapped[list["DepartmentSection"]] = relationship( "DepartmentSection", back_populates="parent_department_section", uselist=True, cascade='all, delete', ) users: Mapped[list[UserDepartmentSection]] = relationship( "UserDepartmentSection", lazy='selectin', back_populates='section', cascade='all, delete', )