add task post

This commit is contained in:
IluaAir
2025-08-15 01:03:48 +03:00
parent fdc688cf5e
commit 723f59d35e
8 changed files with 81 additions and 26 deletions

View File

@@ -64,7 +64,7 @@ exclude = [
# Set the maximum line length for both linting and formatting. # Set the maximum line length for both linting and formatting.
line-length = 88 line-length = 88
# Assume Python 3.9 for compatibility checks. # Assume Python 3.9 for compatibility checks.
target-version = "py39" target-version = "py312"
# Enable preview features for early access to new rules and formatting changes. # Enable preview features for early access to new rules and formatting changes.
preview = true preview = true
@@ -81,7 +81,7 @@ select = [
] ]
# Ignore specific rules within the selected groups. # Ignore specific rules within the selected groups.
ignore = [ ignore = [
"UP035", "UP",
"B903", "B903",
"B904", "B904",
"E501", "E501",

View File

@@ -1,17 +1,21 @@
from fastapi import APIRouter from typing import Annotated
from fastapi import APIRouter, Depends
from sqlalchemy import select from sqlalchemy import select
from src.api.dependacies.db_dep import sessionDep from src.api.dependacies.db_dep import sessionDep
from src.api.dependacies.user_dep import ActiveUser from src.api.dependacies.user_dep import ActiveUser
from src.models.tasks import TasksORM from src.models.tasks import TasksORM
from src.schemas.tasks import TaskADDRequest
from src.services.tasks import TaskService
router = APIRouter(prefix="/tasks", tags=["Tasks"]) router = APIRouter(prefix="/tasks", tags=["Tasks"])
@router.get("/") @router.get("/")
async def get_tasks(db: sessionDep, user: ActiveUser): async def get_tasks(session: sessionDep, user: ActiveUser):
query = select(TasksORM.id, TasksORM.description).where(TasksORM.user_id == user.id) query = select(TasksORM.id, TasksORM.description).where(TasksORM.user_id == user.id)
tasks = await db.session.execute(query) tasks = await session.session.execute(query)
result = tasks.scalars().all() result = tasks.scalars().all()
return result return result
@@ -21,7 +25,15 @@ async def get_task_id(task_id: int): ...
@router.post("/") @router.post("/")
async def post_task(): ... async def post_task(
task_data: Annotated[TaskADDRequest, Depends()],
session: sessionDep,
user: ActiveUser,
):
result = await TaskService(session).create_task(
user_id=user.id, task_data=task_data
)
return result
@router.put("/{task_id}") @router.put("/{task_id}")

View File

@@ -30,7 +30,9 @@ async def get_user_by_id(session: sessionDep, id: int, _: CurrentOrAdmin):
async def patch_user( async def patch_user(
session: sessionDep, id: int, _: CurrentOrAdmin, user_update: UserUpdate = Body() session: sessionDep, id: int, _: CurrentOrAdmin, user_update: UserUpdate = Body()
): ):
updated_user = await UserService(session).update_user(id=id, update_data=user_update) updated_user = await UserService(session).update_user(
id=id, update_data=user_update
)
return updated_user return updated_user

View File

@@ -1,37 +1,41 @@
from typing import Any from typing import Any, Generic, Mapping, Sequence, Type, TypeVar
from pydantic import BaseModel
from sqlalchemy import delete, insert, select from sqlalchemy import delete, insert, select
from sqlalchemy.ext.asyncio import AsyncSession
from src.core.database import Base from src.core.database import Base
ModelType = TypeVar("ModelType", bound=Base)
class BaseRepo:
model: type[Base]
def __init__(self, session): class BaseRepo(Generic[ModelType]):
self.session = session model: Type[ModelType]
async def get_filtered(self, *filter, **filter_by) -> list[Base]: def __init__(self, session: AsyncSession) -> None:
query = select(self.model).filter(*filter).filter_by(**filter_by) self.session: AsyncSession = session
async def get_filtered(
self, *filters: Any, **filter_by: Any
) -> Sequence[ModelType]:
query = select(self.model).filter(*filters).filter_by(**filter_by)
result = await self.session.execute(query) result = await self.session.execute(query)
models = result.scalars().all() models = result.scalars().all()
return models return models
async def create_one(self, data: BaseModel) -> Base: async def create_one(self, data: Mapping[str, Any]) -> ModelType:
statement = insert(self.model).values(data.model_dump()).returning(self.model) statement = insert(self.model).values(data).returning(self.model)
result = await self.session.execute(statement) result = await self.session.execute(statement)
obj = result.scalar_one() obj: ModelType = result.scalar_one()
return obj return obj
async def get_one_or_none(self, **filter_by: Any) -> Base | None: async def get_one_or_none(self, **filter_by: Any) -> ModelType | None:
query = select(self.model).filter_by(**filter_by) query = select(self.model).filter_by(**filter_by)
result = await self.session.execute(query) result = await self.session.execute(query)
model = result.scalars().one_or_none() model_obj: ModelType | None = result.scalars().one_or_none()
return model return model_obj
async def get_all(self, *args, **kwargs) -> list[Base]: async def get_all(self, *args: Any, **kwargs: Any) -> Sequence[ModelType]:
result = await self.get_filtered(*args, **kwargs) result: Sequence[ModelType] = await self.get_filtered(*args, **kwargs)
return result return result
async def delete_one(self, **filter_by) -> None: async def delete_one(self, **filter_by) -> None:

View File

@@ -0,0 +1,20 @@
from datetime import date
from typing import Literal
from pydantic import BaseModel, ConfigDict
class TaskADDRequest(BaseModel):
title: str
description: str | None = None
due_date: date | None = None
priority: Literal["low", "medium", "high", "critical"] = "medium"
class Task(TaskADDRequest):
id: int
user_id: int
status: Literal["open", "closed", "in_progress", "todo"]
time_spent: int
model_config = ConfigDict(from_attributes=True)

View File

@@ -15,7 +15,7 @@ class AuthService(BaseService):
email=cred.email, email=cred.email,
hashed_password=hashed_pass, hashed_password=hashed_pass,
) )
result = await self.session.user.create_one(user_to_insert) result = await self.session.user.create_one(user_to_insert.model_dump())
await self.session.commit() await self.session.commit()
return User.model_validate(result) return User.model_validate(result)

View File

@@ -1,4 +1,19 @@
from fastapi import HTTPException
from src.models.tasks import TasksORM
from src.schemas.tasks import Task, TaskADDRequest
from src.services.base import BaseService from src.services.base import BaseService
class TasksService(BaseService): ... class TaskService(BaseService):
model = TasksORM
async def create_task(self, user_id: int, task_data: TaskADDRequest) -> Task:
user = await self.session.user.get_one_or_none(id=user_id)
if user is None:
raise HTTPException(status_code=404, detail="User not found.")
data_to_insert = task_data.model_dump(exclude_none=True)
data_to_insert["user_id"] = user.id
created_task_orm = await self.session.task.create_one(data_to_insert)
await self.session.commit()
return Task.model_validate(created_task_orm)

View File

@@ -33,6 +33,8 @@ class UserService(BaseService):
async def update_user(self, id: int, update_data: UserUpdate) -> User: async def update_user(self, id: int, update_data: UserUpdate) -> User:
await self.get_user_by_filter_or_raise(id=id) await self.get_user_by_filter_or_raise(id=id)
user = await self.session.user.update_one(id=id, data=update_data.model_dump(exclude_unset=True)) user = await self.session.user.update_one(
id=id, data=update_data.model_dump(exclude_unset=True)
)
await self.session.commit() await self.session.commit()
return User.model_validate(user) return User.model_validate(user)