20. Анализ плана закупок — Prefetch при фильтрации по procurement_plan
Date: 2026-02-08
Status
Accepted
Context
При списке документов с type__key__in=procurement_plan для каждого документа вызывается сервис анализа, которому нужны позиции плана и офферы. Без prefetch возникает N+1: отдельные запросы на каждый документ.
Decision
В DocumentViewSet.get_queryset() после построения базового queryset проверять наличие в query-параметрах type__key__in значения procurement_plan. При наличии применять: queryset.prefetch_related('procurement_plan_positions', 'procurement_plan_positions__counterparty_offers').
Сервис в _get_plan_positions() использует prefetch: при наличии _prefetched_objects_cache['procurement_plan_positions'] загружает позиции и офферы из кэша, иначе выполняет отдельный запрос (например, при одиночном retrieve без этого фильтра).
Обоснование
- Производительность — один дополнительный prefetch вместо N запросов по документам.
- Условность — prefetch только когда в ответе ожидаются планы закупок.
- Совместимость — при retrieve без фильтра по type поведение не меняется (сервис сам догружает позиции).
Consequences
- (+) Меньше запросов к БД при списке планов с analize.
- (-) Небольшое усложнение get_queryset и зависимость от формата query-параметров.
Источник: backend/narmak_v2/app/document/ADR.md (ADR-005)