Files
portal/app/tests/Unit/ClientSms/ConsentDocxWriterTest.php
T
Дмитрий 3ad2ffb771 feat(смс-клиент): бланк письма-разрешения — Word на все 8 случаев + выбор правообладателя
Имя отправителя Лидерра регистрирует у МТС от лица клиента, поэтому письмо-разрешение
нужно всегда. Собрал генератор бланка так, чтобы он покрывал все случаи и всегда
отдавал целый документ — заполненный, где есть данные, и с прочерками, где их нет.

- ConsentLetterBuilder — единый источник текста письма на все 8 комбинаций
  «объект (юр.наименование/название ИП/товарный знак/домен) × правообладатель
  (юрлицо/ИП/физлицо)» строго по образцам МТС. Паспорт физлица не храним — прочерк.
- ConsentDocxWriter — рендер в РЕДАКТИРУЕМЫЙ Word (.docx) вместо PDF, чтобы клиент
  дописал недостающее; акцент про паспорт («должны совпадать с документом на право»).
- consentForm(): убрана жёсткая блокировка (бланк отдаётся всегда), добавлен выбор
  правообладателя owner_type/owner_name — домен/знак могут быть на физлице даже
  у клиента-юрлица/ИП, тогда письмо от этого физлица.
- Экран: подсказки «как назвать имя» под каждый вид, общее правило (до 11 знаков,
  латиницей), радио «на кого зарегистрирован домен/знак» + поле ФИО, кнопка бланка
  активна после ввода имени, ярлык «Скачать бланк разрешения (Word)».
- consent-form.blade.php удалён (заменён docx); phpoffice/phpword ^1.4 в composer.

Тесты: бэкенд ClientSms 116, фронт SMS-спеки 44 — зелёные; pint чисто.

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

68 lines
2.7 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\ConsentDocxWriter;
/**
* Письмо-разрешение рендерится в РЕДАКТИРУЕМЫЙ Word (.docx), а не PDF — клиенту
* нужно дописать паспорт/№ ТЗ/срок перед печатью. Проверяем: на выходе валидный
* docx (ZIP-контейнер OOXML) и внутри — текст письма.
*/
/** Достаёт текст word/document.xml из docx-байтов. */
function docxText(string $bytes): string
{
$tmp = tempnam(sys_get_temp_dir(), 'docx');
file_put_contents($tmp, $bytes);
$zip = new ZipArchive;
$zip->open($tmp);
$xml = $zip->getFromName('word/document.xml');
$zip->close();
@unlink($tmp);
// Убираем XML-теги — остаётся видимый текст.
return strip_tags((string) $xml);
}
it('на выходе валидный docx (ZIP), а не PDF', function () {
$bytes = (new ConsentDocxWriter)->render(
['title_object' => 'доменного имени', 'body' => 'ТЕЛО-ПИСЬМА-МАРКЕР', 'signer' => 'ООО «Ромашка»', 'is_individual' => false],
true,
);
// docx = ZIP: сигнатура «PK». PDF был бы «%PDF».
expect(substr($bytes, 0, 2))->toBe('PK');
expect(substr($bytes, 0, 4))->not->toBe('%PDF');
});
it('внутри docx — тело письма и подписант', function () {
$bytes = (new ConsentDocxWriter)->render(
['title_object' => 'доменного имени', 'body' => 'ТЕЛО-ПИСЬМА-МАРКЕР', 'signer' => 'ООО «Ромашка»', 'is_individual' => false],
true,
);
$text = docxText($bytes);
expect($text)->toContain('ПИСЬМО-РАЗРЕШЕНИЕ');
expect($text)->toContain('ТЕЛО-ПИСЬМА-МАРКЕР');
expect($text)->toContain('ООО «Ромашка»');
});
it('физлицо → внутри есть акцент про паспорт', function () {
$bytes = (new ConsentDocxWriter)->render(
['title_object' => 'доменного имени', 'body' => 'тело', 'signer' => 'Пётр Петров', 'is_individual' => true],
true,
);
expect(docxText($bytes))->toContain('Заполните реквизиты паспорта');
});
it('реквизиты не заполнены → внутри памятка про прочерки', function () {
$bytes = (new ConsentDocxWriter)->render(
['title_object' => 'доменного имени', 'body' => 'тело', 'signer' => 'подпись', 'is_individual' => false],
false,
);
expect(docxText($bytes))->toContain('незаполненные поля');
});