projects-filters: offset, limit, status_in фильтры для проектов в ручке with-reports #121

Merged
tsygankoviva merged 1 commits from projects-filters into test 2026-08-26 09:14:51 +03:00
4 changed files with 76 additions and 3 deletions
Showing only changes of commit 1789f58581 - Show all commits

View File

@ -75,15 +75,22 @@ async def get_projects(
async def get_projects_with_reports(
year: Optional[int] = None,
branch_id: Optional[int] = None,
limit: Optional[int] = None,
offset: Optional[int] = None,
status_in: Optional[str] = None,
db: AsyncSession = Depends(get_db),
current_user: AppUser = Depends(get_current_active_user_with_set_db),
) -> BaseListResponse[dict]:
project_service = ProjectService(db)
status_in = status_in.split(",") if status_in is not None else None
count, projects = await project_service.get_list_with_reports(
user=current_user,
with_count=True,
year=year,
branch_id=branch_id,
limit=limit,
offset=offset,
status_in=status_in,
)
return BaseListResponse(result=projects, count=count)

View File

@ -39,7 +39,13 @@ class ProjectRepository:
}
@staticmethod
def _apply_project_filters(query, year: int | None, branch_id: int | None, org_unit_ids: list[int] | None):
def _apply_project_filters(
query,
year: int | None,
branch_id: int | None,
org_unit_ids: list[int] | None,
status_in: list[str] | None = None,
):
if year is not None:
query = query.where(
exists(
@ -54,6 +60,8 @@ class ProjectRepository:
)
if branch_id is not None:
query = query.where(Project.org_unit_id == branch_id)
if status_in is not None:
query = query.where(Project.status.in_(status_in))
if org_unit_ids is not None:
if len(org_unit_ids) == 0:
query = query.where(false())
@ -162,9 +170,12 @@ class ProjectRepository:
limit: int | None = None,
with_count: bool = False,
org_unit_ids: list[int] | None = None,
status_in: list[str] | None = None,
) -> list[dict] | tuple[int, list[dict]]:
project_query = select(Project).order_by(Project.id)
project_query = self._apply_project_filters(project_query, year, branch_id, org_unit_ids)
project_query = self._apply_project_filters(
project_query, year, branch_id, org_unit_ids, status_in
)
if offset is not None:
project_query = project_query.offset(offset)
if limit is not None:
@ -193,7 +204,9 @@ class ProjectRepository:
return payload
count_query = select(func.count(Project.id))
count_query = self._apply_project_filters(count_query, year, branch_id, org_unit_ids)
count_query = self._apply_project_filters(
count_query, year, branch_id, org_unit_ids, status_in
)
total = int((await self.db.execute(count_query)).scalar() or 0)
return total, payload

View File

@ -43,6 +43,7 @@ class ProjectService:
offset: int | None = None,
limit: int | None = None,
with_count: bool = False,
status_in: list[str] | None = None,
) -> list[dict] | tuple[int, list[dict]]:
org_unit_ids = await self._allowed_org_unit_ids(user)
return await self.project_repo.get_with_reports(
@ -52,6 +53,7 @@ class ProjectService:
limit=limit,
with_count=with_count,
org_unit_ids=org_unit_ids,
status_in=status_in,
)
async def get(self, project_id: int, user: AppUser) -> dict | None:

View File

@ -276,6 +276,57 @@ def _get_project_with_reports(client, auth_headers, admin_tokens, project_id):
return next((p for p in response.json()["result"] if p["id"] == project_id), None)
def test_projects_with_reports_filters_by_single_status(client, admin_tokens, auth_headers):
created_project_id, _ = _create_project(client, admin_tokens, auth_headers)
agreed_project_id, agreed_project_name = _create_project(client, admin_tokens, auth_headers)
update_response = client.patch(
f"/api/v1/project/{agreed_project_id}",
json={"name": agreed_project_name, "status": "agreed"},
headers=auth_headers(admin_tokens),
)
assert update_response.status_code == 200
response = client.get(
"/api/v1/projects/with-reports",
params={"status_in": "agreed"},
headers=auth_headers(admin_tokens),
)
assert response.status_code == 200
payload = response.json()
project_ids = {project["id"] for project in payload["result"]}
project_statuses = {project["status"] for project in payload["result"]}
assert len(project_statuses) == 1
assert agreed_project_id in project_ids
assert created_project_id not in project_ids
assert {project["status"] for project in payload["result"]} == {"agreed"}
assert payload["count"] == len(payload["result"])
def test_projects_with_reports_filters_by_multiple_statuses(client, admin_tokens, auth_headers):
created_project_id, _ = _create_project(client, admin_tokens, auth_headers)
agreed_project_id, agreed_project_name = _create_project(client, admin_tokens, auth_headers)
update_response = client.patch(
f"/api/v1/project/{agreed_project_id}",
json={"name": agreed_project_name, "status": "agreed"},
headers=auth_headers(admin_tokens),
)
assert update_response.status_code == 200
response = client.get(
"/api/v1/projects/with-reports",
params={"status_in": "created,agreed"},
headers=auth_headers(admin_tokens),
)
assert response.status_code == 200
payload = response.json()
project_ids = {project["id"] for project in payload["result"]}
assert {created_project_id, agreed_project_id} <= project_ids
assert {project["status"] for project in payload["result"]} <= {"created", "agreed"}
assert payload["count"] == len(payload["result"])
def test_upd_project_smoke(client, admin_tokens, auth_headers):
project_id, name = _create_project(client, admin_tokens, auth_headers)