Compare commits

...

2 Commits

Author SHA1 Message Date
IluaAir
7e9346ec4d add base update one 2025-09-06 13:53:18 +03:00
IluaAir
d7e522d362 add patch endpoint and service update_task 2025-09-03 23:55:26 +03:00
7 changed files with 55 additions and 21 deletions

View File

@@ -1,11 +1,11 @@
from typing import Annotated
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Body, Depends
from src.api.dependacies.db_dep import sessionDep
from src.api.dependacies.task_dep import TaskFilterDep
from src.api.dependacies.user_dep import ActiveUser, TaskOwnerDep
from src.schemas.tasks import TaskADDRequest
from src.schemas.tasks import TaskADDRequest, TaskPATCHRequest
from src.services.tasks import TaskService
from src.services.users import UserService
@@ -13,14 +13,9 @@ router = APIRouter(prefix="/tasks", tags=["Tasks"])
@router.get("/")
async def get_tasks(
session: sessionDep,
user: ActiveUser,
filter: TaskFilterDep
):
async def get_tasks(session: sessionDep, user: ActiveUser, filter: TaskFilterDep):
result = await UserService(session).get_user_with_tasks(
user_id=user.id,
**filter.model_dump(exclude_unset=True)
user_id=user.id, **filter.model_dump(exclude_unset=True)
)
return result
@@ -43,6 +38,17 @@ async def post_task(
return result
@router.patch("/{id}")
async def patch_task(
session: sessionDep,
id: int,
_: TaskOwnerDep,
task_data: TaskPATCHRequest = Body(),
):
task = await TaskService(session).update_task(id, task_data)
return task
@router.delete("/{id}")
async def delete_task(
session: sessionDep,

View File

@@ -1,15 +1,20 @@
from typing import Any, Protocol
from typing import TYPE_CHECKING, Any, Protocol
from sqlalchemy.ext.asyncio import AsyncSession
from src.repository.tasks import TasksRepo
from src.repository.users import UsersRepo
if TYPE_CHECKING:
from src.repository.tasks import TasksRepo
from src.repository.users import UsersRepo
class HasId(Protocol):
id: Any
class IUOWDB(Protocol):
session: AsyncSession
user: UsersRepo
task: TasksRepo
user: 'UsersRepo'
task: 'TasksRepo'
async def __aenter__(self) -> "IUOWDB": ...

View File

@@ -1,11 +1,11 @@
from typing import Any, Generic, Mapping, Sequence, Type, TypeVar
from sqlalchemy import delete, insert, select
from sqlalchemy import delete, insert, select, update
from sqlalchemy.ext.asyncio import AsyncSession
from src.core.database import Base
from src.core.interfaces import HasId
ModelType = TypeVar("ModelType", bound=Base)
ModelType = TypeVar("ModelType", bound=HasId)
class BaseRepo(Generic[ModelType]):
@@ -44,3 +44,14 @@ class BaseRepo(Generic[ModelType]):
async def delete_one(self, **filter_by) -> None:
await self.session.execute(delete(self.model).filter_by(**filter_by))
async def update_one(self, id: int, data: Mapping[str, Any]) -> ModelType:
stmt = (
update(self.model)
.where(self.model.id == id)
.values(data)
.returning(self.model)
)
result = await self.session.execute(stmt)
model = result.scalar_one()
return model

View File

@@ -50,7 +50,11 @@ class UsersRepo(BaseRepo):
selectinload(
self.model.tasks.and_(TasksORM.id.in_(tasks_subquery))
).load_only(
TasksORM.id, TasksORM.title, TasksORM.due_date, TasksORM.priority, TasksORM.status
TasksORM.id,
TasksORM.title,
TasksORM.due_date,
TasksORM.priority,
TasksORM.status,
)
)
)

View File

@@ -1,7 +1,7 @@
from fastapi import HTTPException
from src.models.tasks import TasksORM
from src.schemas.tasks import Task, TaskADDRequest
from src.schemas.tasks import Task, TaskADDRequest, TaskPATCHRequest
from src.services.base import BaseService
@@ -27,3 +27,12 @@ class TaskService(BaseService):
async def delete_task(self, task_id: int):
await self.session.task.delete_one(id=task_id)
await self.session.commit()
async def update_task(
self, task_id: int, task_data: TaskPATCHRequest, exclude_unset: bool = True
):
task = await self.session.task.update_one(
id=task_id, data=task_data.model_dump(exclude_unset=exclude_unset)
)
await self.session.commit()
return Task.model_validate(task)

View File

@@ -49,7 +49,6 @@ class UserService(BaseService):
offset: int | None,
date_to: date | None,
date_from: date | None,
):
user = await self.session.user.get_one_with_load(
user_id=user_id,

View File

@@ -1,4 +1,4 @@
import json
import pytest
from httpx import ASGITransport, AsyncClient
from sqlalchemy import NullPool, insert