Skip to content

18. Анализ плана закупок — экономия: ср. 2 последних закупки + план vs ср. 3 последних we_buy

Date: 2026-02-08

Status

Accepted

Context

Требование: экономия считается как сравнение «среднее значение 2 последних закупки + планируемая закупка» с «среднее значение 3 последних осуществлённых we_buy».

Decision

  1. Базовый уровень (историческая цена): средняя цена за единицу по 3 последним осуществлённым we_buy — офферы с we_buy=True, purchase_order__isnull=False, по ассортименту позиций плана, сортировка по response_date/offer_date, последние 3 (агрегат по плану: средневзвешенная по количеству).

  2. Текущий уровень: средняя цена по 2 последним поставкам (supply) по каждому ассортименту позиций плана + средняя цена по принятым офферам этого плана (planned_purchase_avg). Сравнение: «текущий» = комбинация средних (при наличии плановых офферов — среднее между avg_last_2_supplies и planned_purchase_avg; иначе только supply).

  3. Экономия: savings_vs_baseline = baseline - current (положительное = экономия). interpretation: «экономия» / «перерасход» / «нет_данных_по_ассортименту».

Расчёт ведётся по ассортименту позиций плана; при отсутствии ассортимента у позиций возвращается interpretation: нет_данных_по_ассортименту.

Обоснование

  1. Соответствие ТЗ — явная формула с 2 supply и 3 we_buy.
  2. Осуществлённые we_buy — в коде уже используется связка we_buy=True и purchase_order__isnull=False; та же трактовка применена здесь.
  3. По ассортименту — сравнение цен по тем же номенклатурам, что и в плане, снижает искажения.

Альтернативы

  • Сравнивать только по сумме (без разбивки по ассортименту) — отвергнуто: смешивание разных номенклатур даёт неинформативную среднюю цену.
  • «2 последних закупки» как 2 документа supply целиком — возможно; выбрана трактовка «2 последние позиции supply по каждому ассортименту» для более точной цены по номенклатуре.

Consequences

  • (+) Фин. директор видит тренд цен и экономию/перерасход относительно истории.
  • (-) При малом количестве supply/we_buy в БД показатели могут быть нестабильными или null.

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