Files
duty-teller/duty_teller/db/models.py
Nikolay Tatarinov b61e1ca8a5
All checks were successful
CI / lint-and-test (push) Successful in 15s
feat: add name_manually_edited field to User model and update related functionality
- Introduced a new boolean column `name_manually_edited` in the `users` table to control whether user names are overwritten during synchronization with Telegram.
- Updated the `get_or_create_user` function to respect the `name_manually_edited` flag, ensuring names are only updated when the flag is false.
- Implemented a new function `update_user_display_name` to allow manual updates of user names while setting the `name_manually_edited` flag to true.
- Enhanced unit tests to cover the new functionality and ensure correct behavior of name handling based on the `name_manually_edited` flag.
2026-02-20 09:30:58 +03:00

68 lines
2.4 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):
__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):
__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)