granddoc is_active: регистрозависимое сравнение == "Действующий" расходится с документированным lowercase doc_status_name → флаг и сортировка ломаются #1618

Closed
opened 2026-06-16 17:21:02 +00:00 by bot-backend · 0 comments
Collaborator

Severity: medium · Категория: logic/data-correctness · Файл: backend/app/services/site_finder/granddoc_lookup.py:100

Файл: backend/app/services/site_finder/granddoc_lookup.py:100. Код: is_active = r["doc_status_name"] == "Действующий" — точное регистрозависимое сравнение с литералом заглавной Д. Источник значения: planning_harvest.py:107 пишет props.get("doc_status_name") в БД без нормализации регистра. DDL/COMMENT (data/sql/134_planning_projects.sql:39,55) документируют хранимое значение как lowercase ('действующий'/'утверждён'/...). ИМПАКТ: при lowercase в БД is_active=False для ВСЕХ записей → (1) result.sort (строки 115-116, ключ not d["is_active"]) теряет приоритизацию действующих документов; (2) документированный UI-флаг «действующий» в ИРД-блоке analyze никогда не True → ложная картина статуса разработки. Также хрупко к регистру/пробелам/вариантам из WFS. ФИКС: нормализовать сравнение — is_active = (r["doc_status_name"] or "").strip().casefold() == "действующий" (или сравнение по набору допустимых значений с casefold). Опционально нормализовать регистр на этапе harvest. Добавить тест на lowercase-значение.

Почему баг: При несовпадении регистра is_active=False для всех строк: (1) ключ сортировки result.sort (lines 115-117, not d["is_active"]) теряет приоритизацию действующих документов; (2) документированный UI-флаг статуса разработки (цель модуля — показать «действующий») никогда не становится True → ложная картина в ИРД-блоке analyze. Сравнение также хрупко к вариантам/пробелам из WFS. Соседний код gknspecial_harvest.py:234 сравнивает с заглавной 'Действующий', но это ДРУГОЙ WFS-слой/поле (zone_state_v) — не подтверждает кейс именно doc_status_name.

Как чинить: Сравнивать без учёта регистра/пробелов: is_active = (r["doc_status_name"] or "").strip().lower() == "действующий". Желательно сначала подтвердить реальные distinct-значения doc_status_name в PROD planning_projects и закрепить нормализацию (CASE/LOWER в SQL либо на harvest-стороне).


deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.78 · unit B40

**Severity:** medium · **Категория:** logic/data-correctness · **Файл:** `backend/app/services/site_finder/granddoc_lookup.py:100` Файл: backend/app/services/site_finder/granddoc_lookup.py:100. Код: is_active = r["doc_status_name"] == "Действующий" — точное регистрозависимое сравнение с литералом заглавной Д. Источник значения: planning_harvest.py:107 пишет props.get("doc_status_name") в БД без нормализации регистра. DDL/COMMENT (data/sql/134_planning_projects.sql:39,55) документируют хранимое значение как lowercase ('действующий'/'утверждён'/...). ИМПАКТ: при lowercase в БД is_active=False для ВСЕХ записей → (1) result.sort (строки 115-116, ключ not d["is_active"]) теряет приоритизацию действующих документов; (2) документированный UI-флаг «действующий» в ИРД-блоке analyze никогда не True → ложная картина статуса разработки. Также хрупко к регистру/пробелам/вариантам из WFS. ФИКС: нормализовать сравнение — is_active = (r["doc_status_name"] or "").strip().casefold() == "действующий" (или сравнение по набору допустимых значений с casefold). Опционально нормализовать регистр на этапе harvest. Добавить тест на lowercase-значение. **Почему баг:** При несовпадении регистра is_active=False для всех строк: (1) ключ сортировки result.sort (lines 115-117, not d["is_active"]) теряет приоритизацию действующих документов; (2) документированный UI-флаг статуса разработки (цель модуля — показать «действующий») никогда не становится True → ложная картина в ИРД-блоке analyze. Сравнение также хрупко к вариантам/пробелам из WFS. Соседний код gknspecial_harvest.py:234 сравнивает с заглавной 'Действующий', но это ДРУГОЙ WFS-слой/поле (zone_state_v) — не подтверждает кейс именно doc_status_name. **Как чинить:** Сравнивать без учёта регистра/пробелов: is_active = (r["doc_status_name"] or "").strip().lower() == "действующий". Желательно сначала подтвердить реальные distinct-значения doc_status_name в PROD planning_projects и закрепить нормализацию (CASE/LOWER в SQL либо на harvest-стороне). --- <sub>deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.78 · unit B40</sub>
bot-backend added the
week ревью 1
label 2026-06-16 17:21:02 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1618
No description provided.