Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from pecha_api.plans.reviews.plan_reviews_models import PlanReview
from pecha_api.plans.favorites.favorites_models import Favorite
from pecha_api.plans.users.plan_users_model import UserPlanProgress
from pecha_api.user_follows.user_follows_model import UserFollow
from pecha_api.plans.users.plan_users_model import UserTaskCompletion
from pecha_api.users.users_models import Users, SocialMediaAccount, PasswordReset

Expand Down
4 changes: 4 additions & 0 deletions pecha_api/plans/response_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
FILE_TOO_LARGE = "File size exceeds 5MB limit"
AUTHOR_ALREADY_EXISTS = "Author already exists"
BAD_REQUEST = "Bad request"
FORBIDDEN = "Forbidden"
PLAN_DAY_NOT_FOUND = "Plan day not found"
TASK_SAME_DAY_NOT_ALLOWED = "Task is already in the same day"
PLAN_NOT_FOUND = "Plan not found"
EMAIL_IS_SENT = "Email is sent. Please check your email to verify your account."

TASK_NOT_FOUND = "Task not found"
UNAUTHORIZED_TASK_DELETE = "You are not authorized to delete this task"
17 changes: 15 additions & 2 deletions pecha_api/plans/tasks/plan_tasks_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pecha_api.plans.tasks.plan_tasks_models import PlanTask
from pecha_api.plans.tasks.plan_tasks_response_model import CreateTaskRequest, TaskDTO
from pecha_api.plans.auth.plan_auth_models import ResponseError
from pecha_api.plans.response_message import BAD_REQUEST
from pecha_api.plans.response_message import BAD_REQUEST, TASK_NOT_FOUND


def save_task(db: Session, new_task: PlanTask):
Expand All @@ -40,11 +40,24 @@ def get_tasks_by_item_ids(db: Session, plan_item_ids: List[UUID]) -> List[PlanTa
return tasks

def get_task_by_id(db: Session, task_id: UUID) -> PlanTask:
task = db.query(PlanTask).filter(PlanTask.id == task_id).first()
if not task:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ResponseError(error=BAD_REQUEST, message=TASK_NOT_FOUND).model_dump())
return task

def delete_task(db: Session, task_id: UUID):
task = get_task_by_id(db=db, task_id=task_id)
try:
db.delete(task)
db.commit()
except Exception as e:
db.rollback()
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ResponseError(error=BAD_REQUEST, message=str(e)).model_dump())
return db.query(PlanTask).filter(PlanTask.id == task_id).first()

def update_task_day(db: Session, task_id: UUID, target_day_id: UUID, display_order: int) -> PlanTask:
task = get_task_by_id(db=db, task_id=task_id)
task.plan_item_id = target_day_id
task.display_order = display_order
db.commit()
return task
return task
2 changes: 2 additions & 0 deletions pecha_api/plans/tasks/plan_tasks_response_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

# Request/Response Models
class CreateTaskRequest(BaseModel):
plan_id: UUID
day_id: UUID
title: str
description: Optional[str] = None
estimated_time: Optional[int] = None
Expand Down
17 changes: 14 additions & 3 deletions pecha_api/plans/tasks/plan_tasks_services.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from pecha_api.plans.tasks.plan_tasks_repository import save_task, get_task_by_id, delete_task
from pecha_api.plans.tasks.plan_tasks_response_model import CreateTaskRequest, TaskDTO, UpdateTaskDayRequest, UpdatedTaskDayResponse
from pecha_api.plans.tasks.plan_tasks_repository import save_task, update_task_day
from pecha_api.plans.authors.plan_authors_service import validate_and_extract_author_details
from uuid import UUID
from fastapi import HTTPException
from pecha_api.db.database import SessionLocal
from pecha_api.plans.items.plan_items_repository import get_plan_item, get_plan_item_by_id
from pecha_api.plans.tasks.plan_tasks_models import PlanTask
from sqlalchemy import func
from pecha_api.plans.response_message import PLAN_DAY_NOT_FOUND, BAD_REQUEST, TASK_SAME_DAY_NOT_ALLOWED
from fastapi import HTTPException
from starlette import status
from pecha_api.plans.response_message import PLAN_DAY_NOT_FOUND, BAD_REQUEST, TASK_SAME_DAY_NOT_ALLOWED, FORBIDDEN, UNAUTHORIZED_TASK_DELETE
from pecha_api.plans.auth.plan_auth_models import ResponseError

def _get_max_display_order(plan_item_id: UUID) -> int:
Expand Down Expand Up @@ -41,6 +43,15 @@ async def create_new_task(token: str, create_task_request: CreateTaskRequest, pl
estimated_time=saved_task.estimated_time,
)

async def delete_task_by_id(task_id: UUID, token: str):
current_author = validate_and_extract_author_details(token=token)

with SessionLocal() as db:
task = get_task_by_id(db=db, task_id=task_id)
if task.created_by != current_author.email:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ResponseError(error=FORBIDDEN, message=UNAUTHORIZED_TASK_DELETE).model_dump())
delete_task(db=db, task_id=task_id)

async def change_task_day_service(token: str, task_id: UUID, update_task_request: UpdateTaskDayRequest) -> UpdatedTaskDayResponse:
validate_and_extract_author_details(token=token)

Expand All @@ -60,4 +71,4 @@ async def change_task_day_service(token: str, task_id: UUID, update_task_request
display_order=task.display_order,
estimated_time=task.estimated_time,
title=task.title,
)
)
25 changes: 16 additions & 9 deletions pecha_api/plans/tasks/plan_tasks_views.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is task_route so change it to
plans_router = APIRouter(
prefix="/cms/tasks",
tags=["Task"]
)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For create task, move the plan iD AND DAY ID TO THE CreateTaskRequest Body. Endpoint should be

@plans_router.post("", status_code=status.HTTP_201_CREATED, response_model=TaskDTO)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,41 @@
from typing import Annotated
from uuid import UUID
from starlette import status

from pecha_api.plans.tasks.plan_tasks_response_model import CreateTaskRequest, TaskDTO, UpdateTaskDayRequest, UpdatedTaskDayResponse
from pecha_api.plans.tasks.plan_tasks_services import create_new_task, change_task_day_service
from pecha_api.plans.tasks.plan_tasks_services import create_new_task, change_task_day_service, delete_task_by_id

oauth2_scheme = HTTPBearer()
# Create router for plan endpoints
plans_router = APIRouter(
prefix="/cms/plan",
prefix="/cms/tasks",
tags=["Task"]
)


@plans_router.post("/{plan_id}/day/{day_id}/tasks", status_code=status.HTTP_201_CREATED, response_model=TaskDTO)
@plans_router.post("", status_code=status.HTTP_201_CREATED, response_model=TaskDTO)
async def create_task(
authentication_credential: Annotated[HTTPAuthorizationCredentials, Depends(oauth2_scheme)],
create_task_request: CreateTaskRequest,
plan_id: UUID,
day_id: UUID,
):
new_task: TaskDTO = await create_new_task(
token=authentication_credential.credentials,
create_task_request=create_task_request,
plan_id=plan_id,
day_id=day_id,
plan_id=create_task_request.plan_id,
day_id=create_task_request.day_id,
)
return new_task

@plans_router.put("/task/{task_id}", response_model=UpdatedTaskDayResponse)
@plans_router.delete("/{task_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_task(
task_id: UUID,
authentication_credential: Annotated[HTTPAuthorizationCredentials, Depends(oauth2_scheme)],
):
await delete_task_by_id(
task_id=task_id,
token=authentication_credential.credentials
)

@plans_router.put("/{task_id}", response_model=UpdatedTaskDayResponse)
async def change_task_day(
authentication_credential: Annotated[HTTPAuthorizationCredentials, Depends(oauth2_scheme)],
task_id: UUID,
Expand Down
Loading
Loading