Files
portal/app/tests/Feature/Bot/LivePricesTest.php
T
Дмитрий 47afefbb10 feat(bot): цены бот тянет сам из настроек — вручную актуализировать больше не надо
Вопрос владельца: «а цены в нём надо актуализировать руками или он сам тянет?»
Ответ был неприятный: руками. Цифры (300/50 руб, тарифные ступени) стояли текстом
в статьях — поменяли бы цену в админке, бот продолжил бы врать про деньги.

Теперь в статьях стоят метки {{цена_подбора}}, {{цена_изучения}}, {{тарифы}},
а сервис LivePrices подставляет живые значения из system_settings и pricing_tiers
В МОМЕНТ ОТВЕТА — без переиндексации базы знаний. Нет цены в настройках — метка
не протекает клиенту, бот отсылает к экрану, где цена написана всегда.

Из текстов экскурсий цифры цен тоже убраны (фронт не знает БД): шаг подсвечивает
строку с ценой в самом окне — она всегда актуальная.

Проверено живьём: поменял цену в настройках на 450 — бот сразу назвал 450.
Pest 42/42 (3 новых теста), Vitest каталога 8/8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 14:06:04 +03:00

78 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\KnowledgeChunk;
use App\Services\Bot\BotAnswerService;
use App\Services\Bot\LivePrices;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
uses(RefreshDatabase::class);
/**
* Цены в инструкции — метками, а не цифрами (вопрос владельца 12.07.2026:
* «цены надо актуализировать руками или он сам тянет?»). Поменяли цену в админке —
* бот обязан назвать новую в ту же секунду, без переиндексации базы знаний.
*/
beforeEach(function () {
config()->set('services.yandexgpt', [
'api_key' => 'k', 'folder_id' => 'f', 'model' => 'yandexgpt-lite/latest',
'endpoint' => 'https://llm.api.cloud.yandex.net/foundationModels/v1/completion',
'timeout_seconds' => 8,
]);
});
function setPrice(string $key, string $value): void
{
DB::table('system_settings')->updateOrInsert(
['key' => $key],
['value' => $value, 'type' => 'int', 'updated_at' => now()]
);
}
it('подставляет живую цену сбора и изучения из настроек', function () {
setPrice('autopodbor_price_search_rub', '450');
setPrice('autopodbor_price_study_rub', '70');
$prices = app(LivePrices::class);
expect($prices->substitute('Подбор — {{цена_подбора}}, изучение — {{цена_изучения}}.'))
->toBe('Подбор — 450 ₽, изучение — 70 ₽.');
});
it('цена изменилась в админке — бот называет новую без переиндексации', function () {
setPrice('autopodbor_price_search_rub', '300');
KnowledgeChunk::create([
'source_path' => 'help/k.md', 'title' => 'Собрать конкурентов', 'tour' => 'collect-competitors',
'topics' => 'собрать конкурентов, цена подбора', 'chunk_index' => 0,
'content' => 'Цена — {{цена_подбора}} за подбор. Деньги спишутся только при результате.',
]);
// владелец поднял цену в админке
setPrice('autopodbor_price_search_rub', '500');
Http::fake(['*' => Http::response([
'result' => ['alternatives' => [['message' => ['text' => 'Подбор стоит 500 ₽.']]]],
], 200)]);
app(BotAnswerService::class)->answer('сколько стоит собрать конкурентов?');
Http::assertSent(function ($request) {
$system = $request['messages'][0]['text'];
// В ИИ уходит живая цена, а не старая и не сама метка.
return str_contains($system, '500 ₽')
&& ! str_contains($system, '300 ₽')
&& ! str_contains($system, '{{');
});
});
it('цены нет в настройках — метка не протекает клиенту', function () {
DB::table('system_settings')->where('key', 'autopodbor_price_search_rub')->delete();
expect(app(LivePrices::class)->substitute('Цена — {{цена_подбора}}.'))
->not->toContain('{{');
});