Phase 3.1: Enhanced Chore Logging and Reporting System
This commit is contained in:
7
backend/app/models/__init__.py
Normal file
7
backend/app/models/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# Models package
|
||||
from app.models.user import User
|
||||
from app.models.chore import Chore
|
||||
from app.models.chore_assignment import ChoreAssignment
|
||||
from app.models.chore_completion_log import ChoreCompletionLog
|
||||
|
||||
__all__ = ["User", "Chore", "ChoreAssignment", "ChoreCompletionLog"]
|
||||
49
backend/app/models/chore.py
Normal file
49
backend/app/models/chore.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""Chore model."""
|
||||
from sqlalchemy import Boolean, Column, Integer, String, DateTime, ForeignKey, Enum as SQLEnum
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
from app.core.database import Base
|
||||
import enum
|
||||
|
||||
class ChoreFrequency(str, enum.Enum):
|
||||
"""Chore frequency options."""
|
||||
ON_TRIGGER = "on_trigger"
|
||||
DAILY = "daily"
|
||||
WEEKLY = "weekly"
|
||||
FORTNIGHTLY = "fortnightly"
|
||||
MONTHLY = "monthly"
|
||||
|
||||
class ChoreStatus(str, enum.Enum):
|
||||
"""Chore status options."""
|
||||
PENDING = "pending"
|
||||
IN_PROGRESS = "in_progress"
|
||||
COMPLETED = "completed"
|
||||
SKIPPED = "skipped"
|
||||
|
||||
class ChoreAssignmentType(str, enum.Enum):
|
||||
"""Chore assignment type - how the chore should be completed."""
|
||||
ANY_ONE = "any_one" # Only one assigned person needs to complete
|
||||
ALL_ASSIGNED = "all_assigned" # All assigned people must complete
|
||||
|
||||
class Chore(Base):
|
||||
"""Chore model."""
|
||||
__tablename__ = "chores"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
title = Column(String(200), nullable=False)
|
||||
description = Column(String(500))
|
||||
room = Column(String(50)) # bedroom1, bedroom2, kitchen, bathroom1, etc.
|
||||
frequency = Column(SQLEnum(ChoreFrequency, values_callable=lambda x: [e.value for e in x]), nullable=False)
|
||||
points = Column(Integer, default=0) # Points awarded for completing the chore
|
||||
image_url = Column(String(500)) # URL to chore image
|
||||
assignment_type = Column(SQLEnum(ChoreAssignmentType, values_callable=lambda x: [e.value for e in x]), default=ChoreAssignmentType.ANY_ONE) # How chore should be completed
|
||||
status = Column(SQLEnum(ChoreStatus, values_callable=lambda x: [e.value for e in x]), default=ChoreStatus.PENDING)
|
||||
assigned_user_id = Column(Integer, ForeignKey("users.id")) # Deprecated - use assignments instead
|
||||
due_date = Column(DateTime)
|
||||
completed_at = Column(DateTime)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
assigned_user = relationship("User", back_populates="chores") # Deprecated - use assignments
|
||||
assignments = relationship("ChoreAssignment", back_populates="chore", cascade="all, delete-orphan")
|
||||
19
backend/app/models/chore_assignment.py
Normal file
19
backend/app/models/chore_assignment.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Chore Assignment model for many-to-many user-chore relationship."""
|
||||
from sqlalchemy import Column, Integer, DateTime, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
from app.core.database import Base
|
||||
|
||||
class ChoreAssignment(Base):
|
||||
"""Junction table for assigning multiple users to chores."""
|
||||
__tablename__ = "chore_assignments"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
chore_id = Column(Integer, ForeignKey("chores.id", ondelete="CASCADE"), nullable=False)
|
||||
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
|
||||
completed_at = Column(DateTime, nullable=True)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
chore = relationship("Chore", back_populates="assignments")
|
||||
user = relationship("User", back_populates="chore_assignments")
|
||||
31
backend/app/models/chore_completion_log.py
Normal file
31
backend/app/models/chore_completion_log.py
Normal file
@@ -0,0 +1,31 @@
|
||||
"""Chore Completion Log model for tracking historical chore completions."""
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class ChoreCompletionLog(Base):
|
||||
"""
|
||||
Comprehensive log of chore completions.
|
||||
|
||||
This model tracks every completion instance, allowing for:
|
||||
- Historical completion data
|
||||
- Multiple completions of the same chore
|
||||
- Optional notes and verification
|
||||
- Weekly/monthly reporting
|
||||
"""
|
||||
__tablename__ = "chore_completion_logs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
chore_id = Column(Integer, ForeignKey("chores.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||
completed_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
||||
notes = Column(Text, nullable=True) # Optional notes about the completion
|
||||
verified_by_user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True) # Optional verification
|
||||
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
||||
|
||||
# Relationships
|
||||
chore = relationship("Chore", foreign_keys=[chore_id])
|
||||
user = relationship("User", foreign_keys=[user_id], back_populates="chore_completion_logs")
|
||||
verified_by = relationship("User", foreign_keys=[verified_by_user_id])
|
||||
18
backend/app/models/meal.py
Normal file
18
backend/app/models/meal.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""Meal model."""
|
||||
from sqlalchemy import Column, Integer, String, DateTime, Text
|
||||
from datetime import datetime
|
||||
from app.core.database import Base
|
||||
|
||||
class Meal(Base):
|
||||
"""Meal model for menu planning."""
|
||||
__tablename__ = "meals"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
title = Column(String(200), nullable=False)
|
||||
description = Column(Text)
|
||||
meal_type = Column(String(20)) # breakfast, lunch, dinner, snack
|
||||
scheduled_date = Column(DateTime)
|
||||
mealie_recipe_id = Column(String(100)) # Link to Mealie recipe
|
||||
notes = Column(Text)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
28
backend/app/models/user.py
Normal file
28
backend/app/models/user.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""User model."""
|
||||
from sqlalchemy import Boolean, Column, Integer, String, DateTime, Date
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
from app.core.database import Base
|
||||
|
||||
class User(Base):
|
||||
"""User model."""
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
username = Column(String(50), unique=True, index=True, nullable=False)
|
||||
email = Column(String(100), unique=True, index=True, nullable=False)
|
||||
full_name = Column(String(100))
|
||||
hashed_password = Column(String(200), nullable=False)
|
||||
discord_id = Column(String(100)) # For Discord integration
|
||||
profile_picture = Column(String(500)) # URL to profile picture
|
||||
avatar_url = Column(String(500)) # URL to uploaded avatar
|
||||
birthday = Column(Date, nullable=True) # Birthday for chore logic
|
||||
is_active = Column(Boolean, default=True)
|
||||
is_admin = Column(Boolean, default=False)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
# Relationships (lazy loaded to avoid circular imports)
|
||||
chores = relationship("Chore", back_populates="assigned_user", lazy="select")
|
||||
chore_assignments = relationship("ChoreAssignment", back_populates="user", lazy="select")
|
||||
chore_completion_logs = relationship("ChoreCompletionLog", foreign_keys="[ChoreCompletionLog.user_id]", back_populates="user", lazy="select")
|
||||
Reference in New Issue
Block a user