from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey from sqlalchemy.orm import relationship from datetime import datetime, timezone from database import Base def _utcnow(): return datetime.now(timezone.utc) class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String, unique=True, nullable=False, index=True) pin_hash = Column(String, nullable=False) password_hash = Column(String, nullable=True) email = Column(String, nullable=True) role = Column(String, nullable=False) # 'waiter' | 'manager' | 'sysadmin' is_active = Column(Boolean, default=True, nullable=False) full_name = Column(String, nullable=True) nickname = Column(String, nullable=True) mobile_phone = Column(String, nullable=True) avatar_url = Column(String, nullable=True) created_at = Column(DateTime(timezone=True), default=_utcnow) orders_opened = relationship("Order", foreign_keys="Order.opened_by", back_populates="opener") orders_closed = relationship("Order", foreign_keys="Order.closed_by", back_populates="closer") order_items = relationship("OrderItem", foreign_keys="OrderItem.added_by", back_populates="added_by_user") items_paid = relationship("OrderItem", foreign_keys="OrderItem.paid_by", back_populates="paid_by_user") order_assignments = relationship("OrderWaiter", back_populates="waiter") zone_assignments = relationship("WaiterZone", back_populates="waiter", cascade="all, delete-orphan") primary_assignments = relationship( "AssistantAssignment", foreign_keys="AssistantAssignment.primary_waiter_id", back_populates="primary_waiter", ) assistant_assignments = relationship( "AssistantAssignment", foreign_keys="AssistantAssignment.assistant_waiter_id", back_populates="assistant_waiter", ) class WaiterZone(Base): """Maps a waiter to a table group they are allowed to operate in. If a waiter has NO rows here, they see NOTHING. A sentinel row with group_id=NULL means 'all zones'.""" __tablename__ = "waiter_zones" id = Column(Integer, primary_key=True, index=True) waiter_id = Column(Integer, ForeignKey("users.id"), nullable=False) group_id = Column(Integer, ForeignKey("table_groups.id"), nullable=True) # NULL = all zones assigned_at = Column(DateTime(timezone=True), default=_utcnow) waiter = relationship("User", back_populates="zone_assignments") group = relationship("TableGroup", back_populates="waiter_zones") class AssistantAssignment(Base): __tablename__ = "assistant_assignments" id = Column(Integer, primary_key=True, index=True) primary_waiter_id = Column(Integer, ForeignKey("users.id"), nullable=False) assistant_waiter_id = Column(Integer, ForeignKey("users.id"), nullable=False) assigned_at = Column(DateTime(timezone=True), default=_utcnow) primary_waiter = relationship("User", foreign_keys=[primary_waiter_id], back_populates="primary_assignments") assistant_waiter = relationship("User", foreign_keys=[assistant_waiter_id], back_populates="assistant_assignments")