feat: пагинация

This commit is contained in:
Artem Tsyrulnikov
2025-12-15 23:18:59 +03:00
parent 83a81f46f7
commit 2339471956
25 changed files with 151 additions and 121 deletions

View File

@@ -4,6 +4,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -16,13 +17,14 @@ async def get_placements_analytics(
workspace_id: uuid.UUID,
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
project_id: uuid.UUID | None = None,
) -> dto.GetPlacementsAnalyticsOutput:
) -> Page[dto.PlacementAnalyticsOutput]:
input = dto.GetPlacementsAnalyticsInput(
user_id=current_user.user_id,
workspace_id=workspace_id,
project_id=project_id,
)
return await deps.get_usecase().get_placements_analytics(input)
result = await deps.get_usecase().get_placements_analytics(input)
return paginate(result) # type: ignore[no-any-return]
@analytics_router.get('/creatives')
@@ -30,13 +32,14 @@ async def get_creatives_analytics(
workspace_id: uuid.UUID,
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
project_id: uuid.UUID | None = None,
) -> dto.GetCreativesAnalyticsOutput:
) -> Page[dto.CreativeAnalyticsOutput]:
input = dto.GetCreativesAnalyticsInput(
user_id=current_user.user_id,
workspace_id=workspace_id,
project_id=project_id,
)
return await deps.get_usecase().get_creatives_analytics(input)
result = await deps.get_usecase().get_creatives_analytics(input)
return paginate(result) # type: ignore[no-any-return]
@analytics_router.get('/channels')
@@ -44,13 +47,14 @@ async def get_channel_analytics(
workspace_id: uuid.UUID,
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
project_id: uuid.UUID | None = None,
) -> dto.GetChannelAnalyticsOutput:
) -> Page[dto.ChannelAnalyticsOutput]:
input = dto.GetChannelAnalyticsInput(
user_id=current_user.user_id,
workspace_id=workspace_id,
project_id=project_id,
)
return await deps.get_usecase().get_channel_analytics(input)
result = await deps.get_usecase().get_channel_analytics(input)
return paginate(result) # type: ignore[no-any-return]
@analytics_router.get('/spending')

View File

@@ -2,6 +2,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -13,6 +14,7 @@ channels_router = APIRouter(prefix='/channels', tags=['channels'])
async def get_channels(
_: Annotated[JWTPayload, Depends(deps.get_current_user)],
username: str | None = None,
) -> dto.GetChannelsOutput:
) -> Page[dto.ChannelOutput]:
input = dto.GetChannelsInput(username=username)
return await deps.get_usecase().get_channels(input=input)
result = await deps.get_usecase().get_channels(input=input)
return paginate(result) # type: ignore[no-any-return]

View File

@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Depends, Query
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -16,7 +17,7 @@ async def list_creatives(
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
project_id: uuid.UUID | None = None,
include_archived: bool = False,
) -> dto.GetCreativesOutput:
) -> Page[dto.CreativeOutput]:
input = dto.GetCreativesInput(
user_id=current_user.user_id,
workspace_id=workspace_id,
@@ -24,7 +25,8 @@ async def list_creatives(
include_archived=include_archived,
)
return await deps.get_usecase().get_creatives(input=input)
result = await deps.get_usecase().get_creatives(input=input)
return paginate(result) # type: ignore[no-any-return]
@creatives_router.get('/{creative_id}')

View File

@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -18,7 +19,7 @@ async def list_placements(
placement_channel_id: uuid.UUID | None = None,
creative_id: uuid.UUID | None = None,
include_archived: bool = False,
) -> dto.GetPlacementsOutput:
) -> Page[dto.PlacementOutput]:
input = dto.GetPlacementsInput(
user_id=current_user.user_id,
workspace_id=workspace_id,
@@ -28,7 +29,8 @@ async def list_placements(
include_archived=include_archived,
)
return await deps.get_usecase().get_placements(input=input)
result = await deps.get_usecase().get_placements(input=input)
return paginate(result) # type: ignore[no-any-return]
@placements_router.get('/{placement_id}')

View File

@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -14,10 +15,11 @@ projects_router = APIRouter(prefix='/workspaces/{workspace_id}/projects', tags=[
async def get_workspace_projects(
workspace_id: uuid.UUID,
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
) -> dto.GetWorkspaceProjectsOutput:
) -> Page[dto.ProjectOutput]:
input = dto.GetWorkspaceProjectsInput(
user_id=current_user.user_id,
workspace_id=workspace_id,
)
return await deps.get_usecase().get_workspace_projects(input=input)
result = await deps.get_usecase().get_workspace_projects(input=input)
return paginate(result) # type: ignore[no-any-return]

View File

@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -18,13 +19,14 @@ async def get_purchase_plan_channels(
workspace_id: uuid.UUID,
project_id: uuid.UUID,
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
) -> dto.GetPurchasePlanChannelsOutput:
) -> Page[dto.PurchasePlanChannelOutput]:
input = dto.GetPurchasePlanChannelsInput(
user_id=current_user.user_id,
workspace_id=workspace_id,
project_id=project_id,
)
return await deps.get_usecase().get_purchase_plan_channels(input=input)
result = await deps.get_usecase().get_purchase_plan_channels(input=input)
return paginate(result) # type: ignore[no-any-return]
@purchase_plan_channels_router.post('')

View File

@@ -4,6 +4,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -18,7 +19,7 @@ async def get_views_history(
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
from_date: datetime.datetime | None = None,
to_date: datetime.datetime | None = None,
) -> dto.GetViewsHistoryOutput:
) -> Page[dto.PostViewsHistoryOutput]:
input_data = dto.GetViewsHistoryInput(
placement_id=placement_id,
user_id=current_user.user_id,
@@ -27,4 +28,5 @@ async def get_views_history(
to_date=to_date,
)
return await deps.get_usecase().get_views_history(input=input_data)
result = await deps.get_usecase().get_views_history(input=input_data)
return paginate(result) # type: ignore[no-any-return]

View File

@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -14,11 +15,12 @@ workspace_invites_router = APIRouter(prefix='/workspaces/{workspace_id}/invites'
async def list_workspace_invites(
workspace_id: uuid.UUID,
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
) -> dto.GetWorkspaceInvitesOutput:
return await deps.get_usecase().get_workspace_invites(
) -> Page[dto.WorkspaceInviteOutput]:
result = await deps.get_usecase().get_workspace_invites(
workspace_id=workspace_id,
user_id=current_user.user_id,
)
return paginate(result) # type: ignore[no-any-return]
@workspace_invites_router.post('')

View File

@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -14,11 +15,12 @@ workspace_members_router = APIRouter(prefix='/workspaces/{workspace_id}/members'
async def list_workspace_members(
workspace_id: uuid.UUID,
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
) -> dto.GetWorkspaceMembersOutput:
return await deps.get_usecase().get_workspace_members(
) -> Page[dto.WorkspaceMemberOutput]:
result = await deps.get_usecase().get_workspace_members(
workspace_id=workspace_id,
user_id=current_user.user_id,
)
return paginate(result) # type: ignore[no-any-return]
@workspace_members_router.put('/{workspace_user_id}/permissions')

View File

@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from fastapi_pagination import Page, paginate
from src import deps, dto
from src.adapter.jwt import JWTPayload
@@ -13,8 +14,9 @@ workspaces_router = APIRouter(prefix='/workspaces', tags=['workspaces'])
@workspaces_router.get('')
async def list_workspaces(
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
) -> dto.GetWorkspacesOutput:
return await deps.get_usecase().get_workspaces(current_user.user_id)
) -> Page[dto.WorkspaceMembershipOutput]:
result = await deps.get_usecase().get_workspaces(current_user.user_id)
return paginate(result) # type: ignore[no-any-return]
@workspaces_router.post('')