Skip to content

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 без этого фильтра).

Обоснование

  1. Производительность — один дополнительный prefetch вместо N запросов по документам.
  2. Условность — prefetch только когда в ответе ожидаются планы закупок.
  3. Совместимость — при retrieve без фильтра по type поведение не меняется (сервис сам догружает позиции).

Consequences

  • (+) Меньше запросов к БД при списке планов с analize.
  • (-) Небольшое усложнение get_queryset и зависимость от формата query-параметров.

Источник: backend/narmak_v2/app/document/ADR.md (ADR-005)