from __future__ import annotations from datetime import datetime from enum import Enum from typing import Optional from sqlalchemy import DateTime, ForeignKey, Index, String, UniqueConstraint, text from sqlalchemy.dialects.mysql import BIGINT, TINYINT from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.db.base import Base class RoleName(str, Enum): ADMIN = "ADMIN" CUSTOMER_ADMIN = "CUSTOMER_ADMIN" CUSTOMER_USER = "CUSTOMER_USER" class Role(Base): __tablename__ = "roles" __table_args__ = (UniqueConstraint("name", name="uniq_role_name"),) id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(64), nullable=False) description: Mapped[Optional[str]] = mapped_column(String(255)) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False) updated_at: Mapped[datetime] = mapped_column( DateTime, server_default=text("CURRENT_TIMESTAMP"), onupdate=text("CURRENT_TIMESTAMP"), nullable=False ) users: Mapped[list["User"]] = relationship("User", back_populates="role") class User(Base): __tablename__ = "users" __table_args__ = ( UniqueConstraint("username", name="uniq_username"), UniqueConstraint("email", name="uniq_email"), Index("idx_users_role", "role_id"), Index("idx_users_customer", "customer_id"), ) id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True) username: Mapped[str] = mapped_column(String(64), nullable=False) email: Mapped[Optional[str]] = mapped_column(String(128)) password_hash: Mapped[str] = mapped_column(String(255), nullable=False) role_id: Mapped[int] = mapped_column(ForeignKey("roles.id", ondelete="RESTRICT", onupdate="CASCADE"), nullable=False) customer_id: Mapped[Optional[int]] = mapped_column( ForeignKey("customers.id", ondelete="SET NULL", onupdate="CASCADE") ) is_active: Mapped[int] = mapped_column(TINYINT(1), server_default=text("1"), nullable=False) last_login_at: Mapped[Optional[datetime]] = mapped_column(DateTime) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False) updated_at: Mapped[datetime] = mapped_column( DateTime, server_default=text("CURRENT_TIMESTAMP"), onupdate=text("CURRENT_TIMESTAMP"), nullable=False ) role: Mapped[Role] = relationship("Role", back_populates="users") customer: Mapped[Optional["Customer"]] = relationship("Customer", back_populates="users")