"""Person and Name. A Person carries living/deceased status and a per-person privacy override; the display identity lives in one or more Name rows (variants, married names, aliases) so name changes over time are first-class. """ import uuid from sqlalchemy import Boolean, ForeignKey, Integer, String, Text, text from sqlalchemy import Enum as SAEnum from sqlalchemy.orm import Mapped, mapped_column from app.models.base import Base from app.models.enums import PersonPrivacy from app.models.mixins import SoftDelete, TenantScoped, Timestamps, UUIDPrimaryKey class Person(Base, UUIDPrimaryKey, TenantScoped, Timestamps, SoftDelete): __tablename__ = "persons" # Free-form to stay inclusive; not a closed enum. gender: Mapped[str | None] = mapped_column(String(32)) # NULL = unknown (let the living-person rule derive it); True/False = asserted. is_living: Mapped[bool | None] = mapped_column(Boolean) privacy: Mapped[PersonPrivacy] = mapped_column( SAEnum(PersonPrivacy, name="person_privacy"), default=PersonPrivacy.inherit, server_default=PersonPrivacy.inherit.value, ) notes: Mapped[str | None] = mapped_column(Text) class Name(Base, UUIDPrimaryKey, TenantScoped, Timestamps, SoftDelete): __tablename__ = "names" person_id: Mapped[uuid.UUID] = mapped_column( ForeignKey("persons.id", ondelete="CASCADE"), index=True ) # Open vocabulary (birth, married, alias, religious, ...) for GEDCOM fidelity. name_type: Mapped[str] = mapped_column(String(32), default="birth", server_default="birth") given: Mapped[str | None] = mapped_column(String(255)) surname: Mapped[str | None] = mapped_column(String(255)) prefix: Mapped[str | None] = mapped_column(String(64)) suffix: Mapped[str | None] = mapped_column(String(64)) nickname: Mapped[str | None] = mapped_column(String(128)) # Original full form preserved verbatim (round-trip fidelity). display_name: Mapped[str | None] = mapped_column(String(512)) is_primary: Mapped[bool] = mapped_column( Boolean, default=False, server_default=text("false") ) sort_order: Mapped[int] = mapped_column(Integer, default=0, server_default="0")