Files
duty-teller/duty_teller/db/models.py
Nikolay Tatarinov 86f6d66865
All checks were successful
CI / lint-and-test (push) Successful in 17s
chore: add changelog and documentation updates
- Created a new `CHANGELOG.md` file to document all notable changes to the project, adhering to the Keep a Changelog format.
- Updated `CONTRIBUTING.md` to include instructions for building and previewing documentation using MkDocs.
- Added `mkdocs.yml` configuration for documentation generation, including navigation structure and theme settings.
- Enhanced various documentation files, including API reference, architecture overview, configuration reference, and runbook, to provide comprehensive guidance for users and developers.
- Included new sections in the README for changelog and documentation links, improving accessibility to project information.
2026-02-20 15:32:10 +03:00

72 lines
2.6 KiB
Python

"""SQLAlchemy ORM models for users and duties."""
from sqlalchemy import Boolean, ForeignKey, Integer, BigInteger, Text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
class Base(DeclarativeBase):
"""Declarative base for all models."""
pass
class User(Base):
"""Telegram user and display name; may have telegram_user_id=None for import-only users."""
__tablename__ = "users"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
telegram_user_id: Mapped[int | None] = mapped_column(
BigInteger, unique=True, nullable=True
)
full_name: Mapped[str] = mapped_column(Text, nullable=False)
username: Mapped[str | None] = mapped_column(Text, nullable=True)
first_name: Mapped[str | None] = mapped_column(Text, nullable=True)
last_name: Mapped[str | None] = mapped_column(Text, nullable=True)
phone: Mapped[str | None] = mapped_column(Text, nullable=True)
name_manually_edited: Mapped[bool] = mapped_column(
Boolean, nullable=False, server_default="0", default=False
)
duties: Mapped[list["Duty"]] = relationship("Duty", back_populates="user")
class CalendarSubscriptionToken(Base):
"""One active calendar subscription token per user; token_hash is unique."""
__tablename__ = "calendar_subscription_tokens"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id"), nullable=False
)
token_hash: Mapped[str] = mapped_column(Text, nullable=False, unique=True)
created_at: Mapped[str] = mapped_column(Text, nullable=False)
class Duty(Base):
"""Single duty/unavailable/vacation slot (UTC start_at/end_at, event_type)."""
__tablename__ = "duties"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id"), nullable=False
)
# UTC, ISO 8601 with Z suffix (e.g. 2025-01-15T09:00:00Z)
start_at: Mapped[str] = mapped_column(Text, nullable=False)
end_at: Mapped[str] = mapped_column(Text, nullable=False)
# duty | unavailable | vacation
event_type: Mapped[str] = mapped_column(Text, nullable=False, server_default="duty")
user: Mapped["User"] = relationship("User", back_populates="duties")
class GroupDutyPin(Base):
"""Stores which message to update in each group for the pinned duty notice."""
__tablename__ = "group_duty_pins"
chat_id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
message_id: Mapped[int] = mapped_column(Integer, nullable=False)