Skip to content

Commit 83177a9

Browse files
Merge pull request #15 from C216-Distribuid-System-Project/feat/AR-task_route
feat(tasks): add CRUD endpoints for task management module
2 parents 8d1d782 + afa2773 commit 83177a9

File tree

6 files changed

+224
-0
lines changed

6 files changed

+224
-0
lines changed

src/models/project_model.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ class Project(Base):
2929
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
3030

3131
user = relationship("User", back_populates="projects")
32+
tasks = relationship("Task", back_populates="project", cascade="all, delete-orphan")

src/models/task_model.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from sqlalchemy.orm import relationship
2+
from src.modules.database_conection import Base
3+
from sqlalchemy import (
4+
Column,
5+
Integer,
6+
String,
7+
Text,
8+
ForeignKey,
9+
TIMESTAMP,
10+
func,
11+
Boolean,
12+
DATETIME,
13+
)
14+
15+
16+
class Task(Base):
17+
"""
18+
Represents a task entity in the to-do list application.
19+
20+
Attributes:
21+
id (int): Primary key identifier for the task.
22+
user_id (int): Foreign key referencing the user who owns the task.
23+
project_id (int, optional): Foreign key referencing the project the task belongs to.
24+
title (str): Title of the task.
25+
description (str, optional): Detailed description of the task.
26+
due_date (datetime, optional): Deadline for the task.
27+
reminder (bool): Flag to enable reminders.
28+
completed (bool): Status of the task (completed or not).
29+
created_at (datetime): Timestamp when the task was created.
30+
updated_at (datetime): Timestamp when the task was last updated.
31+
user (User): Relationship to the User model.
32+
project (Project): Relationship to the Project model.
33+
"""
34+
35+
__tablename__ = "tasks"
36+
37+
id = Column(Integer, primary_key=True, index=True)
38+
user_id = Column(
39+
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
40+
)
41+
project_id = Column(
42+
Integer, ForeignKey("projects.id", ondelete="CASCADE"), nullable=True
43+
)
44+
title = Column(String(255), nullable=False)
45+
description = Column(Text, nullable=True)
46+
due_date = Column(DATETIME, nullable=True)
47+
reminder = Column(Boolean, default=False)
48+
completed = Column(Boolean, default=False)
49+
created_at = Column(TIMESTAMP, server_default=func.now())
50+
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
51+
52+
user = relationship("User", back_populates="tasks")
53+
project = relationship("Project", back_populates="tasks")

src/models/user_model.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ class User(Base):
2929

3030
# Relationship to projects
3131
projects = relationship("Project", back_populates="user", cascade="all, delete-orphan")
32+
33+
tasks = relationship("Task", back_populates="user", cascade="all, delete-orphan")

src/modules/modules_api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from fastapi import APIRouter
22

33
from src.routes.user_routes import user_router
4+
from src.routes.task_routes import task_router
45
from src.routes.project_routes import project_router
56
from src.routes.authentication_routes import authentication_router
67

@@ -10,3 +11,4 @@
1011
router.include_router(authentication_router)
1112
router.include_router(user_router)
1213
router.include_router(project_router)
14+
router.include_router(task_router)

src/routes/task_routes.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
from typing import List
2+
from sqlalchemy.orm import Session
3+
from src.utils.utils import get_db
4+
from src.models.user_model import User
5+
from src.models.task_model import Task
6+
from src.utils.security import get_current_user
7+
from fastapi import APIRouter, Depends, HTTPException, status
8+
from src.schemas.tasks.tasks_schema import TaskCreate, TaskResponse
9+
10+
task_router = APIRouter(prefix="/tasks", tags=["tasks"])
11+
12+
13+
@task_router.post("/", response_model=TaskResponse, status_code=status.HTTP_201_CREATED)
14+
def create_task(
15+
task: TaskCreate,
16+
db: Session = Depends(get_db),
17+
current_user: User = Depends(get_current_user),
18+
):
19+
"""
20+
Create a new task for the authenticated user.
21+
"""
22+
new_task = Task(**task.model_dump(), user_id=current_user.id)
23+
db.add(new_task)
24+
db.commit()
25+
db.refresh(new_task)
26+
return new_task
27+
28+
29+
@task_router.get("/", response_model=List[TaskResponse])
30+
def list_tasks(
31+
db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
32+
):
33+
"""
34+
List all tasks for the authenticated user.
35+
"""
36+
return db.query(Task).filter(Task.user_id == current_user.id).all()
37+
38+
39+
@task_router.get("/{task_id}", response_model=TaskResponse)
40+
def get_task(
41+
task_id: int,
42+
db: Session = Depends(get_db),
43+
current_user: User = Depends(get_current_user),
44+
):
45+
"""
46+
Get a specific task by its ID for the authenticated user.
47+
"""
48+
task = (
49+
db.query(Task)
50+
.filter(Task.id == task_id, Task.user_id == current_user.id)
51+
.first()
52+
)
53+
if not task:
54+
raise HTTPException(
55+
status_code=status.HTTP_404_NOT_FOUND,
56+
detail=f"Tarefa com id {task_id} não encontrada.",
57+
)
58+
return task
59+
60+
61+
@task_router.put("/{task_id}", response_model=TaskResponse)
62+
def update_task(
63+
task_id: int,
64+
task_update: TaskCreate,
65+
db: Session = Depends(get_db),
66+
current_user: User = Depends(get_current_user),
67+
):
68+
"""
69+
Update a specific task for the authenticated user.
70+
"""
71+
db_task = (
72+
db.query(Task)
73+
.filter(Task.id == task_id, Task.user_id == current_user.id)
74+
.first()
75+
)
76+
if not db_task:
77+
raise HTTPException(
78+
status_code=status.HTTP_404_NOT_FOUND,
79+
detail=f"Tarefa com id {task_id} não encontrada.",
80+
)
81+
82+
for key, value in task_update.model_dump().items():
83+
setattr(db_task, key, value)
84+
85+
db.commit()
86+
db.refresh(db_task)
87+
return db_task
88+
89+
90+
@task_router.delete("/{task_id}", status_code=status.HTTP_204_NO_CONTENT)
91+
def delete_task(
92+
task_id: int,
93+
db: Session = Depends(get_db),
94+
current_user: User = Depends(get_current_user),
95+
):
96+
"""
97+
Delete a specific task for the authenticated user.
98+
"""
99+
task = (
100+
db.query(Task)
101+
.filter(Task.id == task_id, Task.user_id == current_user.id)
102+
.first()
103+
)
104+
if not task:
105+
raise HTTPException(
106+
status_code=status.HTTP_404_NOT_FOUND,
107+
detail=f"Tarefa com id {task_id} não encontrada.",
108+
)
109+
db.delete(task)
110+
db.commit()

src/schemas/tasks/tasks_schema.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from typing import Optional
2+
from datetime import datetime
3+
from pydantic import BaseModel
4+
5+
6+
class TaskBase(BaseModel):
7+
"""
8+
Base schema for a task.
9+
10+
Attributes:
11+
title (str): Title of the task.
12+
description (Optional[str]): Description of the task.
13+
project_id (Optional[int]): ID of the project the task belongs to.
14+
due_date (Optional[datetime]): Deadline for the task.
15+
reminder (bool): Flag for reminders.
16+
completed (bool): Status of the task.
17+
"""
18+
19+
title: str
20+
description: Optional[str] = None
21+
project_id: Optional[int] = None
22+
due_date: Optional[datetime] = None
23+
reminder: bool = False
24+
completed: bool = False
25+
26+
27+
class TaskCreate(TaskBase):
28+
"""
29+
Schema for creating a new task. Inherits from TaskBase.
30+
"""
31+
32+
pass
33+
34+
35+
class TaskResponse(TaskBase):
36+
"""
37+
Schema for API responses for tasks.
38+
39+
Inherits from TaskBase and adds fields for the task ID,
40+
creation timestamp, and last update timestamp.
41+
42+
Attributes:
43+
id (int): Unique identifier for the task.
44+
created_at (datetime): Timestamp when the task was created.
45+
updated_at (datetime): Timestamp when the task was last updated.
46+
47+
Config:
48+
from_attributes (bool): Enables population from ORM objects.
49+
"""
50+
51+
id: int
52+
created_at: datetime
53+
updated_at: datetime
54+
55+
class Config:
56+
from_attributes = True

0 commit comments

Comments
 (0)