Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
DefaultDocumentTemplateSeeder
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
3 / 3
14
100.00% covered (success)
100.00%
1 / 1
 ensureForTenant
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
3
 defaultForType
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 defaultDefinitions
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
1 / 1
1
 proposalSaleBody
n/a
0 / 0
n/a
0 / 0
1
 proposalRentBody
n/a
0 / 0
n/a
0 / 0
1
 listingAgreementBody
n/a
0 / 0
n/a
0 / 0
1
 exclusivityBody
n/a
0 / 0
n/a
0 / 0
1
 receiptBody
n/a
0 / 0
n/a
0 / 0
1
 visitAuthorizationBody
n/a
0 / 0
n/a
0 / 0
1
 declarationBody
n/a
0 / 0
n/a
0 / 0
1
 termBody
n/a
0 / 0
n/a
0 / 0
1
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Documents\Application\Services;
6
7use App\Models\User;
8use ImovelZapAi\Documents\Domain\Enums\DocumentType;
9use ImovelZapAi\Documents\Infrastructure\Persistence\Eloquent\DocumentTemplateModel;
10
11final class DefaultDocumentTemplateSeeder
12{
13    public function ensureForTenant(string $tenantId, ?User $actor = null): void
14    {
15        foreach ($this->defaultDefinitions() as $type => $definition) {
16            $exists = DocumentTemplateModel::query()
17                ->where('tenant_id', $tenantId)
18                ->where('document_type', $type)
19                ->where('is_default', true)
20                ->exists();
21
22            if ($exists) {
23                continue;
24            }
25
26            DocumentTemplateModel::query()->create([
27                'tenant_id' => $tenantId,
28                'name' => $definition['name'],
29                'document_type' => $type,
30                'is_default' => true,
31                'is_system' => true,
32                'created_by' => $actor?->id,
33                'body_html' => $definition['body_html'],
34            ]);
35        }
36    }
37
38    public function defaultForType(string $tenantId, DocumentType|string $type, ?User $actor = null): DocumentTemplateModel
39    {
40        $this->ensureForTenant($tenantId, $actor);
41
42        $typeEnum = $type instanceof DocumentType ? $type : DocumentType::from($type);
43
44        return DocumentTemplateModel::query()
45            ->where('tenant_id', $tenantId)
46            ->where('document_type', $typeEnum)
47            ->where('is_default', true)
48            ->firstOrFail();
49    }
50
51    /** @return array<string, array{name: string, body_html: string}> */
52    private function defaultDefinitions(): array
53    {
54        return [
55            DocumentType::ProposalSale->value => [
56                'name' => 'Proposta de compra padrão',
57                'body_html' => $this->proposalSaleBody(),
58            ],
59            DocumentType::ProposalRent->value => [
60                'name' => 'Proposta de locação padrão',
61                'body_html' => $this->proposalRentBody(),
62            ],
63            DocumentType::ListingAgreement->value => [
64                'name' => 'Contrato de captação padrão',
65                'body_html' => $this->listingAgreementBody(),
66            ],
67            DocumentType::Exclusivity->value => [
68                'name' => 'Contrato de exclusividade padrão',
69                'body_html' => $this->exclusivityBody(),
70            ],
71            DocumentType::Receipt->value => [
72                'name' => 'Recibo padrão',
73                'body_html' => $this->receiptBody(),
74            ],
75            DocumentType::VisitAuthorization->value => [
76                'name' => 'Autorização de visita padrão',
77                'body_html' => $this->visitAuthorizationBody(),
78            ],
79            DocumentType::Declaration->value => [
80                'name' => 'Declaração padrão',
81                'body_html' => $this->declarationBody(),
82            ],
83            DocumentType::Term->value => [
84                'name' => 'Termo padrão',
85                'body_html' => $this->termBody(),
86            ],
87        ];
88    }
89
90    private function proposalSaleBody(): string
91    {
92        return <<<'HTML'
93<section>
94  <h1>Proposta de compra</h1>
95  <p>Olá <strong>{{cliente.nome}}</strong>,</p>
96  <p>Segue proposta de compra referente ao imóvel em <strong>{{imovel.endereco}}</strong>.</p>
97  <ul>
98    <li>Valor proposto: <strong>{{documento.valor}}</strong></li>
99    <li>Corretor responsável: {{corretor.nome}}</li>
100  </ul>
101  <p>{{documento.mensagem}}</p>
102  <p><em>{{empresa.nome}}</em> · {{data.hoje}}</p>
103</section>
104HTML;
105    }
106
107    private function proposalRentBody(): string
108    {
109        return <<<'HTML'
110<section>
111  <h1>Proposta de locação</h1>
112  <p>Olá <strong>{{cliente.nome}}</strong>,</p>
113  <p>Segue proposta de locação para o imóvel em <strong>{{imovel.endereco}}</strong>.</p>
114  <ul>
115    <li>Valor proposto: <strong>{{documento.valor}}</strong></li>
116    <li>Corretor responsável: {{corretor.nome}}</li>
117  </ul>
118  <p>{{documento.mensagem}}</p>
119  <p><em>{{empresa.nome}}</em> · {{data.hoje}}</p>
120</section>
121HTML;
122    }
123
124    private function listingAgreementBody(): string
125    {
126        return <<<'HTML'
127<section>
128  <h1>Contrato de captação</h1>
129  <p>Pelo presente instrumento, <strong>{{cliente.nome}}</strong> autoriza <strong>{{empresa.nome}}</strong> a promover a comercialização do imóvel situado em <strong>{{imovel.endereco}}</strong>.</p>
130  <p>Valor de referência: <strong>{{documento.valor}}</strong></p>
131  <p>Corretor responsável: {{corretor.nome}}</p>
132  <p>Data: {{data.hoje}}</p>
133</section>
134HTML;
135    }
136
137    private function exclusivityBody(): string
138    {
139        return <<<'HTML'
140<section>
141  <h1>Contrato de exclusividade</h1>
142  <p><strong>{{cliente.nome}}</strong> concede exclusividade à <strong>{{empresa.nome}}</strong> para comercialização do imóvel em <strong>{{imovel.endereco}}</strong>.</p>
143  <p>Valor de referência: <strong>{{documento.valor}}</strong></p>
144  <p>Corretor: {{corretor.nome}}</p>
145  <p>Data: {{data.hoje}}</p>
146</section>
147HTML;
148    }
149
150    private function receiptBody(): string
151    {
152        return <<<'HTML'
153<section>
154  <h1>Recibo</h1>
155  <p>Recebemos de <strong>{{cliente.nome}}</strong> a quantia de <strong>{{documento.valor}}</strong>, referente a serviços imobiliários relacionados ao imóvel em <strong>{{imovel.endereco}}</strong>.</p>
156  <p>{{empresa.nome}} · {{corretor.nome}}</p>
157  <p>Data: {{data.hoje}}</p>
158</section>
159HTML;
160    }
161
162    private function visitAuthorizationBody(): string
163    {
164        return <<<'HTML'
165<section>
166  <h1>Autorização de visita</h1>
167  <p>Autorizamos <strong>{{cliente.nome}}</strong> a visitar o imóvel localizado em <strong>{{imovel.endereco}}</strong>, acompanhado por {{corretor.nome}} (<strong>{{empresa.nome}}</strong>).</p>
168  <p>Data: {{data.hoje}}</p>
169</section>
170HTML;
171    }
172
173    private function declarationBody(): string
174    {
175        return <<<'HTML'
176<section>
177  <h1>Declaração</h1>
178  <p>Eu, <strong>{{cliente.nome}}</strong>, declaro para os devidos fins informações relacionadas ao imóvel em <strong>{{imovel.endereco}}</strong>, conforme solicitado por {{corretor.nome}} (<strong>{{empresa.nome}}</strong>).</p>
179  <p>Valor informado, quando aplicável: <strong>{{documento.valor}}</strong></p>
180  <p>Data: {{data.hoje}}</p>
181</section>
182HTML;
183    }
184
185    private function termBody(): string
186    {
187        return <<<'HTML'
188<section>
189  <h1>Termo / reserva</h1>
190  <p><strong>{{cliente.nome}}</strong> e <strong>{{empresa.nome}}</strong> firmam o presente termo referente ao imóvel em <strong>{{imovel.endereco}}</strong>.</p>
191  <p>Valor: <strong>{{documento.valor}}</strong></p>
192  <p>Corretor: {{corretor.nome}}</p>
193  <p>Data: {{data.hoje}}</p>
194</section>
195HTML;
196    }
197}