Часть 2 из 6. Живая смета медийной кампании «за показы»: из аудитории (окно
дней) и частоты → показы × 120₽/1000 = сумма клиенту (наценка не видна).
- CampaignEstimateService: size×частота=показы, сумма по ad_settings.client_cpm_rub
через AdImpressionPricing (bcmath, вверх до копейки); порог MIN_AUDIENCE=100.
- AdvertisingCampaignController::audienceSize — при переданной frequency добавляет
в ответ impressions/cpm_rub/cost_rub; без частоты ответ прежний (обратная совместимость).
- Аудитория (deals за N дней + свой список, дедуп, RLS) и порог 100 уже были в модуле.
- Тест сметы обёрнут в DatabaseTransactions (мутация глобальной ad_settings не утекает).
Тесты: 17/17 зелёные (вкл. проверку отсутствия утечки цены + регресс).
Spec: docs/superpowers/specs/2026-07-25-yandex-reklama-medijnaya-pokazy-design.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>