From 3815d47207cfa629024b2caec7d421429e3192f0 Mon Sep 17 00:00:00 2001 From: coder-bot Date: Tue, 18 Aug 2026 16:45:51 +0000 Subject: [PATCH] WIP checkpoint: Group + membership models + migration --- backend/app/models/group.py | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 backend/app/models/group.py diff --git a/backend/app/models/group.py b/backend/app/models/group.py new file mode 100644 index 0000000..c52a1d3 --- /dev/null +++ b/backend/app/models/group.py @@ -0,0 +1,56 @@ +import enum + +from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Enum +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func + +from app.database import Base + + +class GroupMemberRole(str, enum.Enum): + OWNER = "owner" + ADMIN = "admin" + MEMBER = "member" + + +class Group(Base): + __tablename__ = "groups" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String(255), nullable=False) + description = Column(Text, nullable=True) + owner_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) + + owner = relationship("User", back_populates="owned_groups") + members = relationship( + "GroupMember", + back_populates="group", + cascade="all, delete-orphan", + order_by="GroupMember.joined_at", + ) + + +class GroupMember(Base): + __tablename__ = "group_members" + + group_id = Column( + Integer, + ForeignKey("groups.id", ondelete="CASCADE"), + primary_key=True, + ) + user_id = Column( + Integer, + ForeignKey("users.id", ondelete="CASCADE"), + primary_key=True, + ) + role = Column( + Enum(GroupMemberRole, name="group_member_role", create_type=False), + nullable=False, + default=GroupMemberRole.MEMBER, + ) + joined_at = Column(DateTime(timezone=True), server_default=func.now()) + + group = relationship("Group", back_populates="members") + user = relationship("User", back_populates="group_memberships")