99 lines
3.6 KiB
Python
99 lines
3.6 KiB
Python
"""Family and Family-related models"""
|
|
|
|
from sqlalchemy import Column, Integer, String, DateTime, Boolean, ForeignKey, Enum
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime
|
|
from enum import Enum as PyEnum
|
|
from app.db.database import Base
|
|
|
|
|
|
class FamilyRole(str, PyEnum):
|
|
"""Roles in family"""
|
|
OWNER = "owner"
|
|
MEMBER = "member"
|
|
RESTRICTED = "restricted"
|
|
|
|
|
|
class Family(Base):
|
|
"""Family model - represents a family group"""
|
|
|
|
__tablename__ = "families"
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
owner_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
name = Column(String(255), nullable=False)
|
|
description = Column(String(500), nullable=True)
|
|
currency = Column(String(3), default="RUB") # ISO 4217 code
|
|
invite_code = Column(String(20), unique=True, nullable=False, index=True)
|
|
|
|
# Settings
|
|
notification_level = Column(String(50), default="all") # all, important, none
|
|
accounting_period = Column(String(20), default="month") # week, month, year
|
|
|
|
# Status
|
|
is_active = Column(Boolean, default=True)
|
|
|
|
# Timestamps
|
|
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
# Relationships
|
|
members = relationship("FamilyMember", back_populates="family", cascade="all, delete-orphan")
|
|
invites = relationship("FamilyInvite", back_populates="family", cascade="all, delete-orphan")
|
|
accounts = relationship("Account", back_populates="family", cascade="all, delete-orphan")
|
|
categories = relationship("Category", back_populates="family", cascade="all, delete-orphan")
|
|
budgets = relationship("Budget", back_populates="family", cascade="all, delete-orphan")
|
|
goals = relationship("Goal", back_populates="family", cascade="all, delete-orphan")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Family(id={self.id}, name={self.name}, currency={self.currency})>"
|
|
|
|
|
|
class FamilyMember(Base):
|
|
"""Family member model - user membership in family"""
|
|
|
|
__tablename__ = "family_members"
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
family_id = Column(Integer, ForeignKey("families.id"), nullable=False, index=True)
|
|
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
|
role = Column(Enum(FamilyRole), default=FamilyRole.MEMBER)
|
|
|
|
# Permissions
|
|
can_edit_budget = Column(Boolean, default=True)
|
|
can_manage_members = Column(Boolean, default=False)
|
|
|
|
# Timestamps
|
|
joined_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
|
|
# Relationships
|
|
family = relationship("Family", back_populates="members")
|
|
user = relationship("User", back_populates="family_members")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<FamilyMember(family_id={self.family_id}, user_id={self.user_id}, role={self.role})>"
|
|
|
|
|
|
class FamilyInvite(Base):
|
|
"""Family invite model - pending invitations"""
|
|
|
|
__tablename__ = "family_invites"
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
family_id = Column(Integer, ForeignKey("families.id"), nullable=False, index=True)
|
|
invite_code = Column(String(20), unique=True, nullable=False, index=True)
|
|
created_by_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
|
|
# Invite validity
|
|
is_active = Column(Boolean, default=True)
|
|
expires_at = Column(DateTime, nullable=True)
|
|
|
|
# Timestamps
|
|
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
|
|
# Relationships
|
|
family = relationship("Family", back_populates="invites")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<FamilyInvite(id={self.id}, family_id={self.family_id})>"
|