"""时态纪念日模型(辰正 §5.3)。""" from datetime import datetime from sqlalchemy import Boolean, DateTime, ForeignKey, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.core.ids import new_anniversary_id from app.core.time import utc_now from app.db.base import Base class TimeAnniversary(Base): """纪念日 / 特殊日子(辰正设计 §5.3)。 枚举值(calendar / kind / subject_type / source)以契约字典 ``docs/contracts/contract-glossary.md`` §11.4.1–§11.4.4 为单一事实源。 """ __tablename__ = "time_anniversaries" id: Mapped[str] = mapped_column(String(80), primary_key=True, default=new_anniversary_id) character_id: Mapped[str] = mapped_column(String(80), ForeignKey("characters.id"), index=True) name: Mapped[str] = mapped_column(String(200), nullable=False) calendar: Mapped[str] = mapped_column(String(20), nullable=False) # solar / lunar date: Mapped[str] = mapped_column(String(20), nullable=False) # 公历 ISO 或农历日期编码 recurs_yearly: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) kind: Mapped[str] = mapped_column( String(40), nullable=False ) # birthday / anniversary / milestone / custom subject_type: Mapped[str] = mapped_column( String(40), nullable=False ) # user / character_self / relationship / custom source: Mapped[str] = mapped_column( String(40), nullable=False, default="manual" ) # auto / manual / imported metadata_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=utc_now, onupdate=utc_now )