From d2402dc21307d0c9d1bcc685315d2360d31d8163 Mon Sep 17 00:00:00 2001 From: markov Date: Wed, 25 Feb 2026 11:10:48 +0100 Subject: [PATCH] fix: ProjectMember unique constraint, task flush before action, clean models --- src/tracker/models/project.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tracker/models/project.py b/src/tracker/models/project.py index 6272eff..bb42f37 100644 --- a/src/tracker/models/project.py +++ b/src/tracker/models/project.py @@ -3,7 +3,7 @@ import uuid from typing import TYPE_CHECKING -from sqlalchemy import ForeignKey, Integer, String, Text +from sqlalchemy import ForeignKey, Integer, String, Text, UniqueConstraint from sqlalchemy.dialects.postgresql import ARRAY, UUID from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -32,15 +32,20 @@ class Project(Base): class ProjectMember(Base): + """Many-to-many: project ↔ member with role.""" __tablename__ = "project_members" project_id: Mapped[uuid.UUID] = mapped_column( - UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), primary_key=True + UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False ) member_id: Mapped[uuid.UUID] = mapped_column( - UUID(as_uuid=True), ForeignKey("members.id", ondelete="CASCADE"), primary_key=True + UUID(as_uuid=True), ForeignKey("members.id", ondelete="CASCADE"), nullable=False ) role: Mapped[str] = mapped_column(String(20), default=MemberRole.MEMBER) # owner | member project: Mapped["Project"] = relationship(back_populates="members") member: Mapped["Member"] = relationship() + + __table_args__ = ( + UniqueConstraint("project_id", "member_id", name="uq_project_member"), + )