3ad2ffb771
Имя отправителя Лидерра регистрирует у МТС от лица клиента, поэтому письмо-разрешение нужно всегда. Собрал генератор бланка так, чтобы он покрывал все случаи и всегда отдавал целый документ — заполненный, где есть данные, и с прочерками, где их нет. - 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>
68 lines
2.7 KiB
PHP
68 lines
2.7 KiB
PHP
<?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('незаполненные поля');
|
||
});
|