gendesign/backend/app/schemas/custom_poi.py
lekss361 485f489bd2 feat(#254): user_custom_pois — backend schema + CRUD + scoring integration
- SQL migration 101_user_custom_pois.sql: table with GEOGRAPHY(POINT) + GIST index
- Pydantic schemas: CustomPoiCreate / CustomPoiUpdate / CustomPoiOut
- Service custom_pois.py: CRUD + get_overlaps_for_scoring (1km radius, psycopg v3 CAST)
- API /api/v1/custom-pois: POST(201)/GET/PATCH/DELETE, X-Session-Id header auth
- Scoring in analyze_parcel: custom POI block after OSM POI loop,
  decay weight * max(0, 1 - dist/1000), custom_poi_score_items in response
- Tests: CRUD + validation (weight/lon/lat 422) + scoring integration (mock-based)
- Vault: Schema_User_Custom_Pois.md + Endpoint_Parcel_Analyze v3.9 section
2026-05-17 09:34:33 +03:00

60 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Pydantic schemas для user_custom_pois (#254).
CustomPoiCreate — тело POST-запроса.
CustomPoiUpdate — тело PATCH-запроса (все поля опциональны).
CustomPoiOut — ответ API (включает id, created_at, updated_at).
"""
from __future__ import annotations
from datetime import datetime
from pydantic import BaseModel, Field
# Диапазон весов кастомных POI шире системных ([-5, 5]),
# чтобы пользователь мог сильно усилить или исключить POI.
_CUSTOM_WEIGHT_MIN: float = -5.0
_CUSTOM_WEIGHT_MAX: float = 5.0
class CustomPoiCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=200, description="Отображаемое название точки")
category: str | None = Field(None, max_length=100, description="Произвольная категория")
weight: float = Field(
...,
ge=_CUSTOM_WEIGHT_MIN,
le=_CUSTOM_WEIGHT_MAX,
description="Вес точки в scoring [-5, 5]",
)
lon: float = Field(..., ge=-180.0, le=180.0, description="Долгота WGS-84")
lat: float = Field(..., ge=-90.0, le=90.0, description="Широта WGS-84")
parcel_cad: str | None = Field(
None,
max_length=100,
description="Кадастровый номер участка; NULL = глобальная для пользователя",
)
notes: str | None = Field(None, max_length=2000, description="Примечания")
class CustomPoiUpdate(BaseModel):
name: str | None = Field(None, min_length=1, max_length=200)
category: str | None = None
weight: float | None = Field(None, ge=_CUSTOM_WEIGHT_MIN, le=_CUSTOM_WEIGHT_MAX)
lon: float | None = Field(None, ge=-180.0, le=180.0)
lat: float | None = Field(None, ge=-90.0, le=90.0)
parcel_cad: str | None = Field(None, max_length=100)
notes: str | None = None
class CustomPoiOut(BaseModel):
id: int
user_id: str
parcel_cad: str | None
name: str
category: str | None
weight: float
lon: float
lat: float
notes: str | None
created_at: datetime
updated_at: datetime