mitlist/be/app/schemas/chore.py
mohamad 5f6f988118
All checks were successful
Deploy to Production, build images and push to Gitea Registry / build_and_push (pull_request) Successful in 1m37s
feat: Enhance chore creation and assignment functionality
This commit introduces significant updates to the chore management system, including:

- Refactoring the `create_chore` function to streamline the creation process and enforce assignment rules based on chore type.
- Adding support for assigning chores to users, ensuring that group chores can only be assigned to group members and personal chores can only be assigned to the creator.
- Updating the API endpoints and frontend components to accommodate the new assignment features, including loading group members for assignment selection.
- Enhancing the user interface to display assignment options and manage chore assignments effectively.

These changes aim to improve the functionality and user experience of the chore management system.
2025-06-22 21:27:04 +02:00

126 lines
4.7 KiB
Python

from __future__ import annotations
from datetime import date, datetime
from typing import Optional, List, Any
from pydantic import BaseModel, ConfigDict, field_validator, model_validator
from ..models import ChoreFrequencyEnum, ChoreTypeEnum, ChoreHistoryEventTypeEnum
from .user import UserPublic
class ChoreAssignmentPublic(BaseModel):
pass
class ChoreHistoryPublic(BaseModel):
id: int
event_type: ChoreHistoryEventTypeEnum
event_data: Optional[dict[str, Any]] = None
changed_by_user: Optional[UserPublic] = None
timestamp: datetime
model_config = ConfigDict(from_attributes=True)
class ChoreAssignmentHistoryPublic(BaseModel):
id: int
event_type: ChoreHistoryEventTypeEnum
event_data: Optional[dict[str, Any]] = None
changed_by_user: Optional[UserPublic] = None
timestamp: datetime
model_config = ConfigDict(from_attributes=True)
class ChoreBase(BaseModel):
name: str
description: Optional[str] = None
frequency: ChoreFrequencyEnum
custom_interval_days: Optional[int] = None
next_due_date: date # For creation, this will be the initial due date
type: ChoreTypeEnum
@model_validator(mode='after')
def validate_custom_frequency(self):
if self.frequency == ChoreFrequencyEnum.custom:
if self.custom_interval_days is None or self.custom_interval_days <= 0:
raise ValueError("custom_interval_days must be a positive integer when frequency is 'custom'")
return self
class ChoreCreate(ChoreBase):
group_id: Optional[int] = None
parent_chore_id: Optional[int] = None
assigned_to_user_id: Optional[int] = None
@model_validator(mode='after')
def validate_group_id_with_type(self):
if self.type == ChoreTypeEnum.group and self.group_id is None:
raise ValueError("group_id is required for group chores")
if self.type == ChoreTypeEnum.personal and self.group_id is not None:
# Automatically clear group_id for personal chores instead of raising an error
self.group_id = None
return self
class ChoreUpdate(BaseModel):
name: Optional[str] = None
description: Optional[str] = None
frequency: Optional[ChoreFrequencyEnum] = None
custom_interval_days: Optional[int] = None
next_due_date: Optional[date] = None # Allow updating next_due_date directly if needed
type: Optional[ChoreTypeEnum] = None
group_id: Optional[int] = None
parent_chore_id: Optional[int] = None # Allow moving a chore under a parent or removing association
# last_completed_at should generally not be updated directly by user
@model_validator(mode='after')
def validate_group_id_with_type(self):
if self.type == ChoreTypeEnum.group and self.group_id is None:
raise ValueError("group_id is required for group chores")
if self.type == ChoreTypeEnum.personal and self.group_id is not None:
# Automatically clear group_id for personal chores instead of raising an error
self.group_id = None
return self
class ChorePublic(ChoreBase):
id: int
group_id: Optional[int] = None
created_by_id: int
last_completed_at: Optional[datetime] = None
parent_chore_id: Optional[int] = None
created_at: datetime
updated_at: datetime
creator: Optional[UserPublic] = None # Embed creator UserPublic schema
assignments: List[ChoreAssignmentPublic] = []
history: List[ChoreHistoryPublic] = []
child_chores: List[ChorePublic] = []
model_config = ConfigDict(from_attributes=True)
# Chore Assignment Schemas
class ChoreAssignmentBase(BaseModel):
chore_id: int
assigned_to_user_id: int
due_date: date
class ChoreAssignmentCreate(ChoreAssignmentBase):
pass
class ChoreAssignmentUpdate(BaseModel):
# Only completion status and perhaps due_date can be updated for an assignment
is_complete: Optional[bool] = None
due_date: Optional[date] = None # If rescheduling an existing assignment is allowed
assigned_to_user_id: Optional[int] = None # For reassigning the chore
class ChoreAssignmentPublic(ChoreAssignmentBase):
id: int
is_complete: bool
completed_at: Optional[datetime] = None
created_at: datetime
updated_at: datetime
# Embed ChorePublic and UserPublic for richer responses
chore: Optional[ChorePublic] = None
assigned_user: Optional[UserPublic] = None
history: List[ChoreAssignmentHistoryPublic] = []
model_config = ConfigDict(from_attributes=True)
# To handle potential circular imports if ChorePublic needs GroupPublic and GroupPublic needs ChorePublic
# We can update forward refs after all models are defined.
ChorePublic.model_rebuild()
ChoreAssignmentPublic.model_rebuild()