Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
51 / 51 |
|
100.00% |
2 / 2 |
CRAP | |
100.00% |
1 / 1 |
| ProposalTemplateRenderer | |
100.00% |
51 / 51 |
|
100.00% |
2 / 2 |
13 | |
100.00% |
1 / 1 |
| render | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
1 | |||
| buildSnapshot | |
100.00% |
36 / 36 |
|
100.00% |
1 / 1 |
12 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace ImovelZapAi\Proposals\Application\Services; |
| 6 | |
| 7 | use ImovelZapAi\Proposals\Infrastructure\Persistence\Eloquent\ProposalModel; |
| 8 | use ImovelZapAi\Proposals\Infrastructure\Persistence\Eloquent\ProposalTemplateModel; |
| 9 | use ImovelZapAi\Publishing\Infrastructure\Persistence\Eloquent\TenantPublishingConfigModel; |
| 10 | use ImovelZapAi\Tenancy\Infrastructure\Persistence\Eloquent\TenantModel; |
| 11 | |
| 12 | final class ProposalTemplateRenderer |
| 13 | { |
| 14 | /** |
| 15 | * @param array<string, mixed> $snapshot |
| 16 | */ |
| 17 | public function render(ProposalTemplateModel $template, ProposalModel $proposal, array $snapshot): string |
| 18 | { |
| 19 | $map = [ |
| 20 | '{{client_name}}' => (string) ($snapshot['client_name'] ?? ''), |
| 21 | '{{owner_name}}' => (string) ($snapshot['owner_name'] ?? ''), |
| 22 | '{{amount}}' => (string) ($snapshot['amount_formatted'] ?? ''), |
| 23 | '{{commission}}' => (string) ($snapshot['commission_formatted'] ?? ''), |
| 24 | '{{property_address}}' => (string) ($snapshot['property_address'] ?? ''), |
| 25 | '{{property_features}}' => (string) ($snapshot['property_features'] ?? ''), |
| 26 | '{{broker_name}}' => (string) ($snapshot['broker_name'] ?? ''), |
| 27 | '{{company_name}}' => (string) ($snapshot['company_name'] ?? ''), |
| 28 | '{{logo_url}}' => (string) ($snapshot['logo_url'] ?? ''), |
| 29 | '{{intro_message}}' => (string) ($snapshot['intro_message'] ?? $proposal->intro_message ?? ''), |
| 30 | '{{proposal_number}}' => (string) $proposal->number, |
| 31 | '{{version}}' => (string) ($snapshot['version'] ?? '1'), |
| 32 | ]; |
| 33 | |
| 34 | return str_replace(array_keys($map), array_values($map), $template->body_html); |
| 35 | } |
| 36 | |
| 37 | /** @return array<string, mixed> */ |
| 38 | public function buildSnapshot(ProposalModel $proposal, int $version): array |
| 39 | { |
| 40 | $tenant = TenantModel::query()->find($proposal->tenant_id); |
| 41 | $branding = TenantPublishingConfigModel::query()->where('tenant_id', $proposal->tenant_id)->first(); |
| 42 | $property = $proposal->property; |
| 43 | $amount = $proposal->amount !== null ? 'R$ '.number_format((float) $proposal->amount, 2, ',', '.') : 'A combinar'; |
| 44 | $commission = $proposal->commission_percent !== null |
| 45 | ? number_format((float) $proposal->commission_percent, 2, ',', '.').'%' |
| 46 | : '—'; |
| 47 | |
| 48 | $address = collect([ |
| 49 | $property?->street, |
| 50 | $property?->number, |
| 51 | $property?->neighborhood?->name ?? null, |
| 52 | $property?->city?->name ?? null, |
| 53 | ])->filter()->implode(', '); |
| 54 | |
| 55 | $features = collect([ |
| 56 | $property?->bedrooms ? $property->bedrooms.' quartos' : null, |
| 57 | $property?->bathrooms ? $property->bathrooms.' banheiros' : null, |
| 58 | $property?->parking_spaces ? $property->parking_spaces.' vagas' : null, |
| 59 | $property?->useful_area ? $property->useful_area.' m²' : null, |
| 60 | ])->filter()->implode(' · '); |
| 61 | |
| 62 | return [ |
| 63 | 'version' => $version, |
| 64 | 'client_name' => $proposal->contact?->display_name ?: 'Cliente', |
| 65 | 'owner_name' => $proposal->owner_id ? 'Proprietário' : '—', |
| 66 | 'amount' => $proposal->amount, |
| 67 | 'amount_formatted' => $amount, |
| 68 | 'commission_percent' => $proposal->commission_percent, |
| 69 | 'commission_formatted' => $commission, |
| 70 | 'property_address' => $address !== '' ? $address : ($property?->title ?? 'Imóvel'), |
| 71 | 'property_features' => $features !== '' ? $features : ($property?->title ?? '—'), |
| 72 | 'broker_name' => $proposal->responsible?->name ?? 'Corretor', |
| 73 | 'company_name' => $branding?->company_name ?: ($tenant?->name ?? 'Imobiliária'), |
| 74 | 'logo_url' => $branding?->logo_url, |
| 75 | 'intro_message' => $proposal->intro_message, |
| 76 | 'property_id' => $proposal->property_id, |
| 77 | 'deal_id' => $proposal->deal_id, |
| 78 | ]; |
| 79 | } |
| 80 | } |