Source code for pydotorg.domains.nominations.models

"""Nominations domain models."""

from __future__ import annotations

import datetime
from enum import StrEnum
from typing import TYPE_CHECKING
from uuid import UUID

from sqlalchemy import Boolean, Date, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from pydotorg.core.database.base import AuditBase, SlugMixin

if TYPE_CHECKING:
    from pydotorg.domains.users.models import User


[docs] class ElectionStatus(StrEnum): UPCOMING = "upcoming" NOMINATIONS_OPEN = "nominations_open" VOTING_OPEN = "voting_open" CLOSED = "closed"
[docs] class Election(AuditBase, SlugMixin): __tablename__ = "elections" name: Mapped[str] = mapped_column(String(200)) description: Mapped[str | None] = mapped_column(Text, nullable=True) nominations_open: Mapped[datetime.date] = mapped_column(Date, index=True) nominations_close: Mapped[datetime.date] = mapped_column(Date, index=True) voting_open: Mapped[datetime.date] = mapped_column(Date, index=True) voting_close: Mapped[datetime.date] = mapped_column(Date, index=True) nominees: Mapped[list[Nominee]] = relationship( "Nominee", back_populates="election", cascade="all, delete-orphan", lazy="selectin", ) @property def status(self) -> ElectionStatus: today = datetime.datetime.now(tz=datetime.UTC).date() if today < self.nominations_open: return ElectionStatus.UPCOMING if today <= self.nominations_close: return ElectionStatus.NOMINATIONS_OPEN if today < self.voting_open: return ElectionStatus.UPCOMING if today <= self.voting_close: return ElectionStatus.VOTING_OPEN return ElectionStatus.CLOSED
[docs] class Nominee(AuditBase): __tablename__ = "nominees" election_id: Mapped[UUID] = mapped_column(ForeignKey("elections.id", ondelete="CASCADE")) user_id: Mapped[UUID] = mapped_column(ForeignKey("users.id", ondelete="CASCADE")) accepted: Mapped[bool] = mapped_column(Boolean, default=False, index=True) election: Mapped[Election] = relationship("Election", back_populates="nominees", lazy="selectin") user: Mapped[User] = relationship("User", foreign_keys=[user_id], lazy="selectin") nominations: Mapped[list[Nomination]] = relationship( "Nomination", back_populates="nominee", cascade="all, delete-orphan", lazy="selectin", )
[docs] class Nomination(AuditBase): __tablename__ = "nominations" nominee_id: Mapped[UUID] = mapped_column(ForeignKey("nominees.id", ondelete="CASCADE")) nominator_id: Mapped[UUID] = mapped_column(ForeignKey("users.id", ondelete="CASCADE")) endorsement: Mapped[str | None] = mapped_column(Text, nullable=True) nominee: Mapped[Nominee] = relationship("Nominee", back_populates="nominations", lazy="selectin") nominator: Mapped[User] = relationship("User", foreign_keys=[nominator_id], lazy="selectin")