Files
ipam_control/docs/changes/018-patch-null-handling/PLAN.md
T

23 lines
2.2 KiB
Markdown
Raw Normal View History

# PATCH адреса: null даёт ложный 409 (изменение 018)
Находка ревью № 8, серьёзность — низкая.
## Context
`update_address` (`app/api/v1/prefixes.py`) использует `model_dump(exclude_unset=True)` без `exclude_none`: `{"description": null}` пишет NULL в колонку NOT NULL →
`IntegrityError` → 409 «Запись с такими значениями уже существует» (воспроизведено). Остальные PATCH-эндпоинты исключают `None`.
## Решение
1. Единая семантика PATCH: `null` для текстовых полей — «очистить» (записать `""`), для `status` — 422 (обязательное поле), для `device_id` — отвязать устройство (`None`, как сейчас).
Реализация — в `AddressUpdate` через `field_validator`: текстовые `None → ""`, `status` — тип `AddressStatus` без `None`-варианта (поле по-прежнему необязательное).
2. Проверить тем же правилом `PrefixUpdate`, `DeviceUpdate`, `VrfUpdate`, `UserUpdate`: где `exclude_none` скрывает намерение очистить поле (`note`, `description`) — применить то же приведение.
3. Общий обработчик `IntegrityError` оставить как страховку, но текст «Конфликт с существующими данными» (уже так в `main.py`); сообщение
«Запись с такими значениями уже существует» в `commit()` по умолчанию заменить на нейтральное — сейчас оно вводит в заблуждение при нарушении NOT NULL/FK.
## Файлы
`app/schemas.py`, `app/api/v1/prefixes.py`, `app/services.py` (текст по умолчанию), `tests/test_api.py`.
## Тест
PATCH адреса `{"description": null}` → 200 и `description == ""`; `{"status": null}` → 422.
## Проверка
`pytest -q`; в UI правка адреса с очисткой описания.