77f61fb1d1
Слияние feat/client-telegram-ads с main 8bdd58e8. Десять швов разобраны вручную:
денежный файл AdWalletService взят из main целиком — проверено поимённо, что все три
починки на месте: свой контекст клиента, оживление брони, таяние заморозки. В расписании
объединены оба набора заданий: телеграмные два и рекламные четыре. В боковом меню и в
мобильном «Ещё» сохранён пункт «Рекламный кошелёк», подписи поправлены — на реальные
экраны ведут ОБА канала. Словарь, пример настроек и журнал схемы объединены.
Сверх самого слияния:
- Журнал схемы: телеграмные записи v8.86-v8.95 перенумерованы в v9.18-v9.27, блок
переставлен наверх, пометки «номер предварительный» сняты и заменены одной врезкой
о перенумерации. Задвоенных номеров не осталось. Врезка шапки теперь называет и
телеграмные таблицы: их DDL, как и рекламный, живёт только в дельта-миграциях.
- Новый сторож денег tests/Feature/ClientTg/TgMoneyUnderRealRoleTest.php: списание и
возврат под боевой ролью crm_app_user. С контекстом клиента деньги двигаются, без
контекста возврат падает громко. Обычные тесты ходят суперюзером и этот класс дыр
увидеть не могут.
- Помощник rejectedCampaign переименован в tgRejectedCampaign: одноимённый помощник
есть у рекламного модуля, помощники Pest глобальные, полный прогон падал фаталом.
Каждая ветка по отдельности этого увидеть не могла.
- Два теста уведомлений считали ВСЮ таблицу целиком вместо строк своего пользователя:
в одиночку зелёные, в полном прогоне красные. Счёт сужен до конкретного пользователя.
- Убраны две проверки отменённой сущности «своё имя отправителя» — сама сущность
дропнута в v9.27 как СМС-фантазия, её адрес отдаёт 405.
Прогоны: телеграм 193/193, реклама 336/336 при 1029 проверках, вместе 532/532,
экраны 1704/1708, сборка фронта чисто, полный Unit+Feature 3923/3960. Шестнадцать
падений полного прогона совпадают построчно с прогоном ветки без телеграма — слияние
не добавило ни одного. Статанализ в свежем каталоге запустить не удалось: он требует
сгенерированного файла-подсказки, которого нет в репозитории, и без него молча падает
на обеих ветках.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
32 lines
1.3 KiB
PHP
32 lines
1.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Services\Advertising\AdImpressionPricing;
|
|
|
|
it('оценивает показы как аудитория × частота', function () {
|
|
$p = new AdImpressionPricing;
|
|
expect($p->impressionsForAudience(1630, 15))->toBe(24450);
|
|
expect($p->impressionsForAudience(0, 15))->toBe(0);
|
|
expect($p->impressionsForAudience(100, 1))->toBe(100);
|
|
});
|
|
|
|
it('считает клиентскую сумму по 120 ₽ за 1000 показов, округляя ВВЕРХ до копейки', function () {
|
|
$p = new AdImpressionPricing;
|
|
expect($p->clientCostRub(24450, '120.00'))->toBe('2934.00');
|
|
expect($p->clientCostRub(1, '120.00'))->toBe('0.12');
|
|
expect($p->clientCostRub(7, '120.00'))->toBe('0.84');
|
|
expect($p->clientCostRub(0, '120.00'))->toBe('0.00');
|
|
});
|
|
|
|
it('округляет неровную сумму вверх до копейки (клиент не недоплачивает)', function () {
|
|
$p = new AdImpressionPricing;
|
|
expect($p->clientCostRub(1, '125.00'))->toBe('0.13');
|
|
});
|
|
|
|
it('считает маржу как списано клиенту минус расход Яндекса', function () {
|
|
$p = new AdImpressionPricing;
|
|
expect($p->marginRub('2934.00', '1956.00'))->toBe('978.00');
|
|
expect($p->marginRub('100.00', '100.00'))->toBe('0.00');
|
|
});
|