Files
portal/app/tests/Unit/ClientSms/PhoneFileReaderTest.php
T
Дмитрий bc573a99eb feat(смс-клиент): своя база — загрузка Excel, пример файла, оператор через ДаДату, отброшенные не молча
Доработки экрана «Моя база» клиентской СМС-рассылки по просьбе владельца:

- Кривые номера больше не выбрасываются молча: uploadContacts/uploadContactsFile
  возвращают rejected + rejected_samples, экран показывает «Добавлено: N,
  не распознали: M (например: …) — проверьте формат».
- Таблица базы — только «Номер» и «Оператор» (колонку «Имя» убрал).
- Загрузка базы Excel-файлом: сервис ClientSmsPhoneFileReader (phpspreadsheet)
  читает первую колонку, пропускает заголовок, номера-как-числа не уходят в
  научную нотацию; endpoint POST /api/sms/contacts/file; на экране — выбор файла
  и кнопка «Загрузить файл».
- «Скачать пример файла»: ClientSmsBaseExampleWriter + GET /api/sms/contacts/example
  — готовый .xlsx с колонкой «Телефон» и образцами номеров.
- Оператор через ДаДату: EnrichClientSmsContactsOperatorJob обогащает добавленные
  номера (DaDataPhoneClient.provider) в фоне, под tenant-контекстом (RLS), с
  защитой дневного бюджета (DaDataBudgetGuard); сбой ДаДаты не роняет прогон,
  оператор остаётся пустым; уже известного оператора не перезапрашиваем.

Тесты: бэкенд ClientSms 130/130, фронт СМС-спеки 63/63 — зелёные; pint чист;
портал пересобран. Синтетические номера 7999… в тестах.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 21:11:13 +03:00

76 lines
2.6 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\ClientSms\ClientSmsPhoneFileReader;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
/**
* Клиент загружает свою базу номеров Excel-файлом. Читаем только первую колонку;
* заголовок («Телефон») пропускаем; номер, записанный как число, не должен
* превратиться в научную нотацию.
*/
/**
* Собирает временный .xlsx: значения в колонку A. $numericRows — индексы (с 0),
* которые записать как ЧИСЛО (иначе — как строку).
*
* @param list<string> $colA
* @param list<int> $numericRows
*/
function makeXlsx(array $colA, array $numericRows = []): string
{
$ss = new Spreadsheet;
$sheet = $ss->getActiveSheet();
foreach (array_values($colA) as $i => $v) {
$ref = 'A'.($i + 1);
if (in_array($i, $numericRows, true)) {
$sheet->setCellValueExplicit($ref, $v, DataType::TYPE_NUMERIC);
} else {
$sheet->setCellValueExplicit($ref, $v, DataType::TYPE_STRING);
}
}
$path = tempnam(sys_get_temp_dir(), 'xlsxtest').'.xlsx';
(new XlsxWriter($ss))->save($path);
return $path;
}
it('читает номера из первой колонки и пропускает заголовок', function () {
$path = makeXlsx(['Телефон', '+7 913 519-12-64', '89135191264']);
$rows = (new ClientSmsPhoneFileReader)->read($path);
expect($rows)->toBe(['+7 913 519-12-64', '89135191264']);
@unlink($path);
});
it('без заголовка читает все строки', function () {
$path = makeXlsx(['79001234567', '79007654321']);
$rows = (new ClientSmsPhoneFileReader)->read($path);
expect($rows)->toBe(['79001234567', '79007654321']);
@unlink($path);
});
it('номер, записанный как число, не уходит в научную нотацию', function () {
$path = makeXlsx(['79135191264'], numericRows: [0]);
$rows = (new ClientSmsPhoneFileReader)->read($path);
expect($rows)->toBe(['79135191264']);
@unlink($path);
});
it('пропускает пустые ячейки', function () {
$path = makeXlsx(['79001234567', '', ' ', '79007654321']);
$rows = (new ClientSmsPhoneFileReader)->read($path);
expect($rows)->toBe(['79001234567', '79007654321']);
@unlink($path);
});