Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.35% covered (success)
95.35%
41 / 43
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
GetGroupOlxDashboardQuery
95.35% covered (success)
95.35%
41 / 43
50.00% covered (danger)
50.00%
1 / 2
15
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
95.24% covered (success)
95.24%
40 / 42
0.00% covered (danger)
0.00%
0 / 1
14
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Publishing\Connectors\GroupOlx\Application\Queries;
6
7use Carbon\Carbon;
8use ImovelZapAi\Publishing\Connectors\GroupOlx\Application\Data\GroupOlxDashboardData;
9use ImovelZapAi\Publishing\Connectors\GroupOlx\Application\Ports\FeedStorageInterface;
10use ImovelZapAi\Publishing\Connectors\GroupOlx\Application\Ports\GroupOlxFeedValidatorInterface;
11use ImovelZapAi\Publishing\Connectors\GroupOlx\Application\Ports\GroupOlxPublicFeedInterface;
12use ImovelZapAi\Publishing\Connectors\GroupOlx\Infrastructure\Persistence\Eloquent\GroupOlxPublicationLogModel;
13use ImovelZapAi\Tenancy\Infrastructure\Persistence\Eloquent\TenantModel;
14
15/**
16 * Monta o painel Publishing do Grupo OLX a partir do feed pré-gerado e dos logs.
17 */
18final class GetGroupOlxDashboardQuery
19{
20    public function __construct(
21        private readonly FeedStorageInterface $storage,
22        private readonly GroupOlxFeedValidatorInterface $validator,
23        private readonly GroupOlxPublicFeedInterface $publicFeed,
24    ) {}
25
26    public function execute(TenantModel $tenant): GroupOlxDashboardData
27    {
28        $tenantId = (string) $tenant->id;
29        $latest = $this->storage->latest($tenantId, withXml: true);
30        $xml = $latest?->xml;
31        $available = $xml !== null && $xml !== '';
32
33        $errors = [];
34        $xmlValid = false;
35        $listingCount = 0;
36
37        if ($available) {
38            $validation = $this->validator->validateXml($xml);
39            $xmlValid = $validation->isValid();
40            $errors = $validation->errors;
41
42            if (preg_match_all('/<Listing(?:\s|>)/', $xml, $matches) > 0) {
43                $listingCount = count($matches[0]);
44            }
45        } else {
46            $errors[] = 'Feed VRSync ainda não disponível.';
47        }
48
49        $lastLog = GroupOlxPublicationLogModel::query()
50            ->where('tenant_id', $tenantId)
51            ->orderByDesc('generated_at')
52            ->first();
53
54        if ($lastLog !== null && ! $lastLog->success) {
55            $errors = array_values(array_unique([...$errors, ...$lastLog->errorList()]));
56        }
57
58        if ($lastLog !== null && $lastLog->success && $listingCount === 0) {
59            $listingCount = (int) $lastLog->listing_count;
60        }
61
62        $lastGeneratedAt = null;
63        if ($latest?->storedAt !== null) {
64            $lastGeneratedAt = Carbon::parse($latest->storedAt->format(DATE_ATOM));
65        } elseif ($lastLog?->generated_at !== null) {
66            $lastGeneratedAt = $lastLog->generated_at;
67        }
68
69        try {
70            $publicUrl = $this->publicFeed->resolveUrl($tenantId);
71        } catch (\Throwable) {
72            $publicUrl = route('publishing.group_olx.feed.public', $tenant, absolute: true);
73        }
74
75        return new GroupOlxDashboardData(
76            xmlValid: $xmlValid,
77            lastGeneratedAt: $lastGeneratedAt,
78            listingCount: $listingCount,
79            errors: $errors,
80            publicUrl: $publicUrl,
81            xmlSizeBytes: $available ? strlen($xml) : null,
82            generationDurationMs: $lastLog !== null ? (int) $lastLog->duration_ms : null,
83            available: $available,
84            storageVersion: $latest?->version,
85            contentHash: $latest?->hash ?? $lastLog?->content_hash,
86        );
87    }
88}