diff --git a/be/app/api/v1/endpoints/chores.py b/be/app/api/v1/endpoints/chores.py
index bb2ac5a..8e77254 100644
--- a/be/app/api/v1/endpoints/chores.py
+++ b/be/app/api/v1/endpoints/chores.py
@@ -241,7 +241,7 @@ async def create_group_chore(
chore_payload = chore_in.model_copy(update={"group_id": group_id, "type": ChoreTypeEnum.group})
try:
- return await crud_chore.create_chore(db=db, chore_in=chore_payload, user_id=current_user.id, group_id=group_id)
+ return await crud_chore.create_chore(db=db, chore_in=chore_payload, user_id=current_user.id)
except GroupNotFoundError as e:
logger.warning(f"Group {e.group_id} not found for chore creation by user {current_user.email}.")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
@@ -397,7 +397,7 @@ async def list_my_assignments(
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to retrieve assignments")
@router.get(
- "/chores/{chore_id}/assignments",
+ "/{chore_id}/assignments",
response_model=PyList[ChoreAssignmentPublic],
summary="List Chore Assignments",
tags=["Chore Assignments"]
diff --git a/be/app/crud/chore.py b/be/app/crud/chore.py
index d7ed793..f260b45 100644
--- a/be/app/crud/chore.py
+++ b/be/app/crud/chore.py
@@ -70,24 +70,37 @@ async def get_all_user_chores(db: AsyncSession, user_id: int) -> List[Chore]:
async def create_chore(
db: AsyncSession,
chore_in: ChoreCreate,
- user_id: int,
- group_id: Optional[int] = None
+ user_id: int
) -> Chore:
- """Creates a new chore, either personal or within a specific group."""
+ """Creates a new chore, and if specified, an assignment for it."""
async with db.begin_nested() if db.in_transaction() else db.begin():
+ # Validate chore type and group
if chore_in.type == ChoreTypeEnum.group:
- if not group_id:
+ if not chore_in.group_id:
raise ValueError("group_id is required for group chores")
- group = await get_group_by_id(db, group_id)
+ group = await get_group_by_id(db, chore_in.group_id)
if not group:
- raise GroupNotFoundError(group_id)
- if not await is_user_member(db, group_id, user_id):
- raise PermissionDeniedError(detail=f"User {user_id} not a member of group {group_id}")
+ raise GroupNotFoundError(chore_in.group_id)
+ if not await is_user_member(db, chore_in.group_id, user_id):
+ raise PermissionDeniedError(detail=f"User {user_id} not a member of group {chore_in.group_id}")
else: # personal chore
- if group_id:
+ if chore_in.group_id:
raise ValueError("group_id must be None for personal chores")
- chore_data = chore_in.model_dump(exclude_unset=True, exclude={'group_id'})
+ # Validate assigned user if provided
+ if chore_in.assigned_to_user_id:
+ if chore_in.type == ChoreTypeEnum.group:
+ # For group chores, assigned user must be a member of the group
+ if not await is_user_member(db, chore_in.group_id, chore_in.assigned_to_user_id):
+ raise PermissionDeniedError(detail=f"Assigned user {chore_in.assigned_to_user_id} is not a member of group {chore_in.group_id}")
+ else: # Personal chore
+ # For personal chores, you can only assign it to yourself
+ if chore_in.assigned_to_user_id != user_id:
+ raise PermissionDeniedError(detail="Personal chores can only be assigned to the creator.")
+
+ assigned_user_id = chore_in.assigned_to_user_id
+ chore_data = chore_in.model_dump(exclude_unset=True, exclude={'assigned_to_user_id'})
+
if 'parent_chore_id' in chore_data and chore_data['parent_chore_id']:
parent_chore = await get_chore_by_id(db, chore_data['parent_chore_id'])
if not parent_chore:
@@ -95,7 +108,6 @@ async def create_chore(
db_chore = Chore(
**chore_data,
- group_id=group_id,
created_by_id=user_id,
)
@@ -105,6 +117,24 @@ async def create_chore(
db.add(db_chore)
await db.flush()
+ # Create an assignment if a user was specified
+ if assigned_user_id:
+ assignment = ChoreAssignment(
+ chore_id=db_chore.id,
+ assigned_to_user_id=assigned_user_id,
+ due_date=db_chore.next_due_date,
+ is_complete=False
+ )
+ db.add(assignment)
+ await db.flush() # Flush to get the assignment ID
+ await create_assignment_history_entry(
+ db,
+ assignment_id=assignment.id,
+ event_type=ChoreHistoryEventTypeEnum.ASSIGNED,
+ changed_by_user_id=user_id,
+ event_data={'assigned_to': assigned_user_id}
+ )
+
await create_chore_history_entry(
db,
chore_id=db_chore.id,
diff --git a/be/app/schemas/chore.py b/be/app/schemas/chore.py
index 99ab229..808af2b 100644
--- a/be/app/schemas/chore.py
+++ b/be/app/schemas/chore.py
@@ -45,6 +45,7 @@ class ChoreBase(BaseModel):
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):
diff --git a/fe/src/components/ChoreItem.vue b/fe/src/components/ChoreItem.vue
index cf9a1f5..783bc0e 100644
--- a/fe/src/components/ChoreItem.vue
+++ b/fe/src/components/ChoreItem.vue
@@ -27,8 +27,9 @@