cosmo_backend/app/models/db/menu.py

65 lines
2.6 KiB
Python

"""
Menu ORM model
"""
from sqlalchemy import Column, String, Integer, Boolean, Text, TIMESTAMP, ForeignKey, Index
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
from app.database import Base
class Menu(Base):
"""Backend menu items"""
__tablename__ = "menus"
id = Column(Integer, primary_key=True, autoincrement=True)
parent_id = Column(Integer, ForeignKey('menus.id', ondelete='CASCADE'), nullable=True, comment="Parent menu ID (NULL for root)")
name = Column(String(100), nullable=False, comment="Menu name")
title = Column(String(100), nullable=False, comment="Display title")
icon = Column(String(100), nullable=True, comment="Icon name (e.g., 'settings', 'database')")
path = Column(String(255), nullable=True, comment="Route path (e.g., '/admin/celestial-bodies')")
component = Column(String(255), nullable=True, comment="Component path (e.g., 'admin/CelestialBodies')")
sort_order = Column(Integer, default=0, nullable=False, comment="Display order (ascending)")
is_active = Column(Boolean, default=True, nullable=False, comment="Menu active status")
description = Column(Text, nullable=True, comment="Menu description")
created_at = Column(TIMESTAMP, server_default=func.now())
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
# Relationships
children = relationship("Menu", back_populates="parent", cascade="all, delete-orphan")
parent = relationship("Menu", back_populates="children", remote_side=[id])
role_menus = relationship("RoleMenu", back_populates="menu", cascade="all, delete-orphan")
# Indexes
__table_args__ = (
Index("idx_menus_parent_id", "parent_id"),
Index("idx_menus_sort_order", "sort_order"),
)
def __repr__(self):
return f"<Menu(id={self.id}, name='{self.name}', path='{self.path}')>"
class RoleMenu(Base):
"""Role-Menu relationship (which menus each role can access)"""
__tablename__ = "role_menus"
id = Column(Integer, primary_key=True, autoincrement=True)
role_id = Column(Integer, ForeignKey('roles.id', ondelete='CASCADE'), nullable=False)
menu_id = Column(Integer, ForeignKey('menus.id', ondelete='CASCADE'), nullable=False)
created_at = Column(TIMESTAMP, server_default=func.now())
# Relationships
role = relationship("Role", back_populates="menus")
menu = relationship("Menu", back_populates="role_menus")
# Constraints
__table_args__ = (
Index("idx_role_menus_role_id", "role_id"),
Index("idx_role_menus_menu_id", "menu_id"),
)
def __repr__(self):
return f"<RoleMenu(role_id={self.role_id}, menu_id={self.menu_id})>"