feat(chat): в письме владельцу вся переписка и откуда клиент
This commit is contained in:
@@ -107,11 +107,8 @@ class ProcessChatMessageJob implements ShouldQueue
|
||||
|
||||
$rows = BotDialog::query()
|
||||
->where('chat_id', $this->chatId)
|
||||
->orderByDesc('id')
|
||||
->limit(8)
|
||||
->get(['direction', 'message'])
|
||||
->reverse()
|
||||
->values();
|
||||
->orderBy('id')
|
||||
->get(['direction', 'message', 'source', 'user_id']);
|
||||
|
||||
$question = $rows
|
||||
->filter(fn (BotDialog $d) => $d->direction === 'in')
|
||||
@@ -122,12 +119,16 @@ class ProcessChatMessageJob implements ShouldQueue
|
||||
->map(fn (BotDialog $d) => ($d->direction === 'in' ? 'Клиент: ' : 'Бот: ').$d->message)
|
||||
->all();
|
||||
|
||||
$client = $rows->firstWhere(fn (BotDialog $d) => $d->direction === 'in');
|
||||
$source = (string) ($client->source ?? 'portal');
|
||||
$userId = $client->user_id !== null ? (int) $client->user_id : null;
|
||||
|
||||
$to = (string) config('services.support.email');
|
||||
if ($to !== '') {
|
||||
// Письмо — В ОЧЕРЕДЬ. Прогон 12.07.2026: почта не ответила → упала вся задача
|
||||
// (tries=1), и клиент, оставивший номер, не получил НИЧЕГО.
|
||||
try {
|
||||
Mail::to($to)->queue(new BotContactRequestMail($phone, $question, $this->chatId, $transcript));
|
||||
Mail::to($to)->queue(new BotContactRequestMail($phone, $question, $this->chatId, $transcript, $source, $userId));
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Не удалось поставить в очередь письмо с контактом', [
|
||||
'chat_id' => $this->chatId,
|
||||
|
||||
@@ -23,13 +23,17 @@ class BotContactRequestMail extends Mailable
|
||||
/**
|
||||
* @param string $phone нормализованный номер (79161234567)
|
||||
* @param string $question вопрос, на котором бот спасовал
|
||||
* @param list<string> $transcript последние реплики чата («Клиент: …», «Бот: …»)
|
||||
* @param list<string> $transcript вся переписка чата («Клиент: …», «Бот: …»)
|
||||
* @param string $source 'portal' (личный кабинет) или 'landing' (гость)
|
||||
* @param int|null $userId ID клиента, если он вошёл в кабинет; null для гостя
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $phone,
|
||||
public readonly string $question,
|
||||
public readonly string $chatId,
|
||||
public readonly array $transcript = [],
|
||||
public readonly string $source = 'portal',
|
||||
public readonly ?int $userId = null,
|
||||
) {}
|
||||
|
||||
public function envelope(): Envelope
|
||||
@@ -48,6 +52,8 @@ class BotContactRequestMail extends Mailable
|
||||
'question' => $this->question,
|
||||
'chatId' => $this->chatId,
|
||||
'transcript' => $this->transcript,
|
||||
'source' => $this->source,
|
||||
'userId' => $this->userId,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
<p>Клиент писал в чат Лидерры, бот не смог ответить сам и попросил телефон для связи.</p>
|
||||
<ul>
|
||||
<li><strong>Телефон клиента:</strong> {{ $phone }}</li>
|
||||
<li><strong>Откуда:</strong>
|
||||
@if ($source === 'portal' && $userId !== null)
|
||||
личный кабинет, клиент вошёл (ID {{ $userId }})
|
||||
@elseif ($source === 'portal')
|
||||
личный кабинет
|
||||
@else
|
||||
лендинг liderra.ru (гость, не зарегистрирован)
|
||||
@endif
|
||||
</li>
|
||||
<li><strong>Вопрос клиента:</strong> {{ $question }}</li>
|
||||
<li><strong>Чат:</strong> {{ $chatId }}</li>
|
||||
<li><strong>Время:</strong> {{ now()->format('d.m.Y H:i') }} МСК</li>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Jobs\Bot\ProcessChatMessageJob;
|
||||
use App\Mail\BotContactRequestMail;
|
||||
use App\Models\BotDialog;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('в письме владельцу — вся переписка и откуда клиент', function () {
|
||||
Mail::fake();
|
||||
config(['services.support.email' => 'support@liderra.ru']);
|
||||
$chat = str_repeat('a', 32);
|
||||
|
||||
// Длинный разговор: 13 реплик — старый лимит в 8 их бы обрезал.
|
||||
for ($i = 1; $i <= 6; $i++) {
|
||||
BotDialog::create(['chat_id' => $chat, 'direction' => 'in', 'message' => "вопрос {$i}", 'source' => 'portal', 'user_id' => 42, 'created_at' => now()]);
|
||||
BotDialog::create(['chat_id' => $chat, 'direction' => 'out', 'message' => "ответ {$i}", 'created_at' => now()]);
|
||||
}
|
||||
BotDialog::create(['chat_id' => $chat, 'direction' => 'out', 'message' => 'Оставьте номер телефона, и специалист свяжется.', 'created_at' => now()]);
|
||||
$in = BotDialog::create(['chat_id' => $chat, 'direction' => 'in', 'message' => '+7 999 000-11-22', 'source' => 'portal', 'user_id' => 42, 'created_at' => now()]);
|
||||
|
||||
(new ProcessChatMessageJob($chat, (int) $in->id, '+7 999 000-11-22'))->handle();
|
||||
|
||||
Mail::assertQueued(BotContactRequestMail::class, function (BotContactRequestMail $mail) {
|
||||
return count($mail->transcript) >= 13
|
||||
&& str_contains($mail->transcript[0], 'вопрос 1')
|
||||
&& $mail->source === 'portal'
|
||||
&& $mail->userId === 42;
|
||||
});
|
||||
});
|
||||
|
||||
it('письмо про гостя с лендинга помечено как гость', function () {
|
||||
Mail::fake();
|
||||
config(['services.support.email' => 'support@liderra.ru']);
|
||||
$chat = str_repeat('b', 32);
|
||||
|
||||
BotDialog::create(['chat_id' => $chat, 'direction' => 'in', 'message' => 'а вы вообще законно работаете?', 'source' => 'landing', 'user_id' => null, 'created_at' => now()]);
|
||||
BotDialog::create(['chat_id' => $chat, 'direction' => 'out', 'message' => 'Оставьте номер телефона, и специалист свяжется.', 'created_at' => now()]);
|
||||
$in = BotDialog::create(['chat_id' => $chat, 'direction' => 'in', 'message' => '89990001122', 'source' => 'landing', 'user_id' => null, 'created_at' => now()]);
|
||||
|
||||
(new ProcessChatMessageJob($chat, (int) $in->id, '89990001122'))->handle();
|
||||
|
||||
Mail::assertQueued(BotContactRequestMail::class, fn (BotContactRequestMail $mail) => $mail->source === 'landing' && $mail->userId === null);
|
||||
});
|
||||
Reference in New Issue
Block a user