Files
portal/app/tests/Feature/ClientTg/TariffServiceTest.php
T
Дмитрий 6f469fb13d feat(телеграм-реклама): деньги на общем балансе + чистка СМС-фантазий + медиа объявления
Денежная модель (куски 1-2): реклама в Телеграме (МТС Маркетолог, робот-в-браузере)
оплачивается с ОБЩЕГО баланса тенанта (как СМС), наценка 40%. Списание при запуске,
возврат при отказе модерации/сбое/отмене (сальдо-идемпотентность tg_ad_charge/tg_ad_refund).
Старый рекламный кошелёк-заморозка убран из потока кампаний (таблицы ad_wallets НЕ удалены).
Новый TelegramCampaignChargeService (зеркало SmsChargeService); F5 money-safety сохранён
(сбой с mts_campaign_id → needs_review без возврата). Уборщик добивает зависшие queued с возвратом.

Чистка СМС-наследия (аудит модуля построчно 5 проверяющими): модуль ресейлит ПОКАЗЫ рекламы,
а не рассылку сообщений — вырезаны выдуманные сущности, механически скопированные из СМС:
- «имя/бренд отправителя» + помесячная абонплата (в телеге МТС имени отправителя нет):
  ChargeTgNameFeeJob, TelegramSenderService, SenderController, модели Sender/Setting,
  фронт-панель TelegramSenderPanel, админ-карточка, updateTgSettings, тип tg_name_fee.
  Таблицы client_tg_senders/_settings дропнуты.
- мёртвые таблицы client_tg_messages (доставка по номеру) и client_tg_templates (шаблоны
  сообщений) — без модели/использования, дропнуты (миграция 000017, create-миграции удалены).
- client_tg_optouts переосмыслен как ручной список «не показывать этим номерам» (не «отписки»).
- лексика рассылки → рекламы: «Авторассылка»→«Авто-реклама», «кошелёк/заморожено»→«общий баланс».

Медиа объявления (реальный пробел показов): новый POST /api/telegram/campaigns/{id}/media
(картинка/видео к черновику, png/jpg/gif/mp4 ≤50 МБ, замена удаляет старый файл) + поле
загрузки в форме кабинета. Робот уже принимал media_path (RunTelegramCampaignJob → mediaFile
→ cabinet.js fillAdMedia) — не хватало только приёма файла от клиента.

Схема: db/CHANGELOG_schema.md v8.94 (CHECK += tg_ad_charge/tg_ad_refund) + v8.95 (дроп
СМС-таблиц, tg_name_fee убран). Тесты зелёные поштучно (квирк партиций — гонять по одному):
Schema/Models/AdminTg/CampaignCharge/CampaignApi/Audience/Media; фронт advertising-telegram-view
19 + admin-tg/auto-rule 24. pint/deptrac(0) чисто; larastan исключён (Pest-$this шум). Робот
bots/mts-telegram-ads НЕ трогали.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 06:26:07 +03:00

53 lines
2.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
use App\Services\ClientTg\TelegramTariffService;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('ступень выбирается по объёму показов (границы)', function () {
$p = app(TelegramTariffService::class);
expect($p->pricePerImpressionRub(0))->toBe('0.45') // volume floored to >=1
->and($p->pricePerImpressionRub(999))->toBe('0.45')
->and($p->pricePerImpressionRub(1000))->toBe('0.42')
->and($p->pricePerImpressionRub(4999))->toBe('0.42')
->and($p->pricePerImpressionRub(5000))->toBe('0.40')
->and($p->pricePerImpressionRub(9999))->toBe('0.40')
->and($p->pricePerImpressionRub(10000))->toBe('0.38')
->and($p->pricePerImpressionRub(49999))->toBe('0.38')
->and($p->pricePerImpressionRub(50000))->toBe('0.36')
->and($p->pricePerImpressionRub(500000))->toBe('0.36');
});
it('смета = объём показов × цена ступени', function () {
$p = app(TelegramTariffService::class);
// 500 показов → ступень 0.45 → 225.00
expect($p->estimateRub(500))->toBe('225.00')
// 1000 показов → ступень 0.42 → 420.00
->and($p->estimateRub(1000))->toBe('420.00')
// 5000 показов → ступень 0.40 → 2000.00
->and($p->estimateRub(5000))->toBe('2000.00')
// 0 показов → 0.00
->and($p->estimateRub(0))->toBe('0.00');
});
it('клиентская смета = базовая смета × наценка (по умолчанию 1.40)', function () {
config()->set('client_tg.markup', '1.40');
$p = app(TelegramTariffService::class);
// 500 показов: база 225.00 × 1.40 = 315.00
expect($p->clientEstimateRub(500))->toBe('315.00')
// 1000 показов: база 420.00 × 1.40 = 588.00
->and($p->clientEstimateRub(1000))->toBe('588.00')
// 0 показов → 0.00
->and($p->clientEstimateRub(0))->toBe('0.00');
});
it('наценка берётся из config (переопределяемая)', function () {
config()->set('client_tg.markup', '2.00');
$p = app(TelegramTariffService::class);
// 500 показов: база 225.00 × 2.00 = 450.00
expect($p->clientEstimateRub(500))->toBe('450.00');
});