diff --git a/api/src/api/endpoints/me.py b/api/src/api/endpoints/me.py index 30be0b4..8ca157a 100644 --- a/api/src/api/endpoints/me.py +++ b/api/src/api/endpoints/me.py @@ -9,7 +9,8 @@ from typing import Annotated from fastapi import APIRouter, Depends from src.api.dependencies.auth import Principal, current_user -from src.schemas.me import MeResponse, RegionalOfficeOut +from src.schemas.directories import RegionalOfficeBrief +from src.schemas.me import MeResponse router = APIRouter(tags=["me"]) @@ -24,7 +25,7 @@ async def get_me(principal: Annotated[Principal, Depends(current_user)]) -> MeRe # пользователь найден по email, поэтому он заполнен; пустая строка — лишь для типов (колонка nullable) email=user.email or "", full_name=user.full_name, - regional_office=RegionalOfficeOut(id=office.id, name=office.name, is_head_office=office.is_head_office), + regional_office=RegionalOfficeBrief.model_validate(office), business_segment=user.business_segment, roles=sorted(principal.roles), permissions=sorted(principal.permissions), diff --git a/api/src/schemas/directories.py b/api/src/schemas/directories.py index 711a61e..3b139b2 100644 --- a/api/src/schemas/directories.py +++ b/api/src/schemas/directories.py @@ -19,14 +19,19 @@ def _blank_to_none(value: str | None) -> str | None: return stripped or None -class RegionalOfficeOut(BaseModel): - """Филиал (`GET /directories/regional-offices`).""" +class RegionalOfficeBrief(BaseModel): + """Филиал кратко: профиль `GET /me` (форма ответа Среза 0 — без `is_active`).""" model_config = ConfigDict(from_attributes=True) id: uuid.UUID name: str is_head_office: bool + + +class RegionalOfficeOut(RegionalOfficeBrief): + """Филиал целиком (`GET /directories/regional-offices`, пользователи администратора).""" + is_active: bool diff --git a/api/src/schemas/me.py b/api/src/schemas/me.py index ea11a2a..2365003 100644 --- a/api/src/schemas/me.py +++ b/api/src/schemas/me.py @@ -5,14 +5,7 @@ import uuid from pydantic import BaseModel, ConfigDict from src.models.enums import BusinessSegment - - -class RegionalOfficeOut(BaseModel): - """Филиал пользователя.""" - - id: uuid.UUID - name: str - is_head_office: bool +from src.schemas.directories import RegionalOfficeBrief class MeResponse(BaseModel): @@ -23,7 +16,7 @@ class MeResponse(BaseModel): id: uuid.UUID email: str full_name: str - regional_office: RegionalOfficeOut + regional_office: RegionalOfficeBrief business_segment: BusinessSegment | None roles: list[str] permissions: list[str] diff --git a/api/tests/test_auth_deps.py b/api/tests/test_auth_deps.py index db37f87..1e0da35 100644 --- a/api/tests/test_auth_deps.py +++ b/api/tests/test_auth_deps.py @@ -34,7 +34,8 @@ from src.models.access import AppUser, Role, UserRole from src.models.directories import RegionalOffice from src.models.enums import BusinessSegment from src.repositories.users import AmbiguousUserError, load_principal_data -from src.schemas.me import MeResponse, RegionalOfficeOut +from src.schemas.directories import RegionalOfficeBrief +from src.schemas.me import MeResponse SECRET = "test-secret-for-auth-deps-0123456789abcdef" OTHER_SECRET = "foreign-secret-for-auth-deps-0123456789ab" @@ -487,7 +488,7 @@ async def test_repository_raises_on_ambiguity(seeded: AsyncSession) -> None: def test_me_response_schema_serializes_enum_and_null_segment() -> None: - office = RegionalOfficeOut(id=uuid.uuid4(), name="ГО", is_head_office=True) + office = RegionalOfficeBrief(id=uuid.uuid4(), name="ГО", is_head_office=True) fields: dict[str, Any] = { "id": uuid.uuid4(), "email": "a@b.c", diff --git a/api/tests/test_uow_and_errors.py b/api/tests/test_uow_and_errors.py index cf9d1da..9d95f08 100644 --- a/api/tests/test_uow_and_errors.py +++ b/api/tests/test_uow_and_errors.py @@ -36,7 +36,7 @@ from src.db.db import get_async_session from src.models.directories import RegionalOffice from src.models.enums import AuditAction, AuditSection from src.schemas.common import ErrorDetail, Page, PageParams -from src.schemas.me import RegionalOfficeOut +from src.schemas.directories import RegionalOfficeBrief from src.services.audit import AuditService from tests.pg_helpers import alembic_async @@ -141,8 +141,8 @@ def test_domain_error_extra_cannot_shadow_code_or_message() -> None: def test_page_serializes() -> None: - office = RegionalOfficeOut(id=CONFLICT_ID, name="ГО", is_head_office=True) - page = Page[RegionalOfficeOut](items=[office], total=7, limit=1, offset=3) + office = RegionalOfficeBrief(id=CONFLICT_ID, name="ГО", is_head_office=True) + page = Page[RegionalOfficeBrief](items=[office], total=7, limit=1, offset=3) assert page.model_dump(mode="json") == { "items": [{"id": str(CONFLICT_ID), "name": "ГО", "is_head_office": True}], "total": 7,