fix(schemas): Add missing List import in goal schemas
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-08-25 19:16:19 +01:00
parent e76c917f8d
commit 92a21f70b4
2 changed files with 44 additions and 33 deletions

View File

@@ -8,6 +8,7 @@ from app.core.config import settings
from app.api.v1.schemas.counter import CounterListResponse, Counter, CounterCreateRequest, CounterCreateResponse
# Обновляем импорты для схем целей
from app.api.v1.schemas.goal import GoalListResponse, Goal, GoalCreateRequest, GoalCreateResponse, CreatedGoal
from app.api.v1.schemas.goal import GoalDeleteRequest, GoalDeleteResponse
router = APIRouter()
bearer_scheme = HTTPBearer()
@@ -205,45 +206,45 @@ async def create_custom_goals_for_counter(
return GoalCreateResponse(created_goals=created_goals_list)
# --- НОВЫЙ ЭНДПОИНТ: Удаление цели ---
# --- ЭНДПОИНТ: Массовое удаление целей ---
@router.delete(
"/{counter_id}/goals/{goal_id}",
status_code=status.HTTP_204_NO_CONTENT,
summary="Удаление цели в счетчике"
"/{counter_id}/goals",
response_model=GoalDeleteResponse,
summary="Массовое удаление целей в счетчике"
)
async def delete_goal_in_counter(
async def delete_goals_in_counter(
counter_id: int,
goal_id: int,
request_body: GoalDeleteRequest,
credentials: Annotated[HTTPAuthorizationCredentials, Depends(bearer_scheme)]
):
"""
Удаляет указанную цель в указанном счетчике.
В случае успеха возвращает пустой ответ со статусом 204.
Удаляет цели в указанном счетчике по списку их ID.
Возвращает отчет о выполненной операции.
"""
token = credentials.credentials
logger.info(f"Attempting to delete goal ID: {goal_id} from counter ID: {counter_id}")
goal_ids_to_delete = request_body.goal_ids
logger.info(f"Attempting to delete {len(goal_ids_to_delete)} goals from counter ID: {counter_id}")
url = f"{settings.YANDEX_METRIKA_API_URL}/management/v1/counter/{counter_id}/goal/{goal_id}"
headers = {'Authorization': f'OAuth {token}'}
deleted_count = 0
failed_ids = {}
try:
async with httpx.AsyncClient() as client:
response = await client.delete(url, headers=headers)
response.raise_for_status()
logger.success(f"Successfully deleted goal ID: {goal_id} from counter {counter_id}.")
# При успехе стандартно возвращается пустой ответ
return
async with httpx.AsyncClient() as client:
for goal_id in goal_ids_to_delete:
url = f"{settings.YANDEX_METRIKA_API_URL}/management/v1/counter/{counter_id}/goal/{goal_id}"
try:
response = await client.delete(url, headers=headers)
response.raise_for_status()
logger.success(f"Successfully deleted goal ID: {goal_id}")
deleted_count += 1
except httpx.HTTPStatusError as e:
error_details = e.response.json()
error_message = error_details.get('message', 'Unknown error')
logger.error(f"Failed to delete goal ID: {goal_id}. Reason: {error_message}")
failed_ids[goal_id] = error_message
except Exception as e:
logger.error(f"An unexpected error occurred while deleting goal ID: {goal_id}.")
failed_ids[goal_id] = "Unexpected server error"
except httpx.HTTPStatusError as e:
error_details = e.response.json()
logger.error(f"Yandex Metrika API error during goal deletion: {e.response.status_code} - {error_details}")
raise HTTPException(
status_code=e.response.status_code,
detail=f"Yandex API Error: {error_details.get('message', 'Unknown error')}"
)
except Exception as e:
logger.opt(exception=True).error("An unexpected error occurred during goal deletion.")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An internal server error occurred."
)
message = f"Operation completed. Deleted {deleted_count} out of {len(goal_ids_to_delete)} goals."
return GoalDeleteResponse(deleted_count=deleted_count, failed_ids=failed_ids, message=message)

View File

@@ -1,5 +1,5 @@
from pydantic import BaseModel, Field
from typing import List
from typing import List, Dict, Any # <-- ИЗМЕНЕНИЕ ЗДЕСЬ
# Схема для ОДНОЙ цели в списке (для GET запроса)
class Goal(BaseModel):
@@ -11,7 +11,6 @@ class Goal(BaseModel):
class GoalListResponse(BaseModel):
goals: List[Goal]
# --- ИЗМЕНЕНИЯ ЗДЕСЬ ---
# Схема для ОДНОЙ кастомной цели в запросе на создание (для POST)
class CustomGoalIn(BaseModel):
identifier: str = Field(..., description="Уникальный идентификатор JS-события")
@@ -28,4 +27,15 @@ class CreatedGoal(BaseModel):
# Схема ответа после создания целей
class GoalCreateResponse(BaseModel):
created_goals: List[CreatedGoal]
created_goals: List[CreatedGoal]
# --- Схемы для массового удаления ---
class GoalDeleteRequest(BaseModel):
"""Схема запроса на массовое удаление целей."""
goal_ids: List[int] = Field(..., description="Список ID целей для удаления")
class GoalDeleteResponse(BaseModel):
"""Схема ответа после массового удаления."""
deleted_count: int
failed_ids: Dict[int, Any]
message: str