Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
DocumentVariableResolver
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
4 / 4
14
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 buildMap
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
1 / 1
10
 resolve
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 snapshot
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Documents\Application\Services;
6
7use ImovelZapAi\Documents\Infrastructure\Persistence\Eloquent\BusinessDocumentModel;
8use ImovelZapAi\Publishing\Infrastructure\Persistence\Eloquent\TenantPublishingConfigModel;
9use ImovelZapAi\Tenancy\Infrastructure\Persistence\Eloquent\TenantModel;
10
11final class DocumentVariableResolver
12{
13    public function __construct(private readonly DocumentVariableCatalog $catalog) {}
14
15    /**
16     * @return array<string, string>
17     */
18    public function buildMap(BusinessDocumentModel $document, int $version = 1): array
19    {
20        $document->loadMissing(['contact', 'property.neighborhood', 'property.city', 'responsible']);
21        $tenant = TenantModel::query()->find($document->tenant_id);
22        $branding = TenantPublishingConfigModel::query()->where('tenant_id', $document->tenant_id)->first();
23        $property = $document->property;
24        $amount = $document->amount !== null
25            ? 'R$ '.number_format((float) $document->amount, 2, ',', '.')
26            : 'A combinar';
27        $propertyAmount = $property?->price !== null
28            ? 'R$ '.number_format((float) $property->price, 2, ',', '.')
29            : $amount;
30
31        $address = collect([
32            $property?->street,
33            $property?->number,
34            $property?->neighborhood?->name,
35            $property?->city?->name,
36        ])->filter()->implode(', ');
37
38        $snapshot = $document->context_snapshot ?? [];
39
40        return [
41            'cliente.nome' => (string) ($snapshot['cliente.nome'] ?? $document->contact?->display_name ?: 'Cliente'),
42            'cliente.telefone' => (string) ($snapshot['cliente.telefone'] ?? $document->contact?->wa_id ?: ''),
43            'proprietario.nome' => (string) ($snapshot['proprietario.nome'] ?? 'Proprietário'),
44            'imovel.titulo' => (string) ($property?->title ?? 'Imóvel'),
45            'imovel.endereco' => $address !== '' ? $address : (string) ($property?->title ?? '—'),
46            'imovel.cidade' => (string) ($property?->city?->name ?? ''),
47            'imovel.valor' => $propertyAmount,
48            'imovel.condominio' => $property?->condominium_fee !== null
49                ? 'R$ '.number_format((float) $property->condominium_fee, 2, ',', '.')
50                : '—',
51            'imovel.area' => $property?->useful_area !== null ? $property->useful_area.' m²' : '—',
52            'imovel.quartos' => $property?->bedrooms !== null ? (string) $property->bedrooms : '—',
53            'imovel.descricao' => (string) ($property?->full_description ?? $property?->short_description ?? ''),
54            'documento.valor' => $amount,
55            'documento.numero' => (string) $document->number,
56            'documento.titulo' => (string) $document->title,
57            'documento.mensagem' => (string) ($document->intro_message ?? ''),
58            'corretor.nome' => (string) ($document->responsible?->name ?? 'Corretor'),
59            'corretor.creci' => (string) ($snapshot['corretor.creci'] ?? ''),
60            'corretor.telefone' => (string) ($snapshot['corretor.telefone'] ?? ''),
61            'empresa.nome' => (string) ($branding?->company_name ?: ($tenant?->name ?? 'Imobiliária')),
62            'empresa.logo' => (string) ($branding?->logo_url ?? ''),
63            'data.hoje' => now()->format('d/m/Y'),
64            '_version' => (string) $version,
65        ];
66    }
67
68    public function resolve(string $html, array $map): string
69    {
70        $search = [];
71        $replace = [];
72        foreach ($this->catalog->keys() as $key) {
73            $search[] = '{{'.$key.'}}';
74            $replace[] = (string) ($map[$key] ?? '');
75        }
76
77        return str_replace($search, $replace, $html);
78    }
79
80    /** @return array<string, mixed> */
81    public function snapshot(BusinessDocumentModel $document, int $version): array
82    {
83        $map = $this->buildMap($document, $version);
84
85        return [
86            'version' => $version,
87            'variables' => $map,
88            'company_name' => $map['empresa.nome'],
89            'client_name' => $map['cliente.nome'],
90            'amount_formatted' => $map['documento.valor'],
91        ];
92    }
93}