Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
60 / 60
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
UpdateImportMappingAction
100.00% covered (success)
100.00%
60 / 60
100.00% covered (success)
100.00%
2 / 2
18
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
 execute
100.00% covered (success)
100.00%
59 / 59
100.00% covered (success)
100.00%
1 / 1
17
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Importing\Application\Actions;
6
7use ImovelZapAi\Importing\Application\Services\ImportLogWriter;
8use ImovelZapAi\Importing\Domain\Enums\ImportJobStatus;
9use ImovelZapAi\Importing\Domain\Enums\ImportLogEvent;
10use ImovelZapAi\Importing\Domain\Exceptions\ImportException;
11use ImovelZapAi\Importing\Infrastructure\Persistence\Eloquent\ImportErrorModel;
12use ImovelZapAi\Importing\Infrastructure\Persistence\Eloquent\ImportJobModel;
13
14final class UpdateImportMappingAction
15{
16    public function __construct(
17        private readonly ImportLogWriter $logWriter,
18    ) {}
19
20    /**
21     * @param  array<string, mixed>  $mappingPatch
22     */
23    public function execute(ImportJobModel $job, array $mappingPatch): ImportJobModel
24    {
25        if (! in_array($job->status, [
26            ImportJobStatus::PreviewReady,
27            ImportJobStatus::AwaitingMapping,
28            ImportJobStatus::Ready,
29        ], true)) {
30            throw ImportException::invalidState(
31                $job->status instanceof ImportJobStatus ? $job->status->value : (string) $job->status,
32                'mapping',
33            );
34        }
35
36        $current = $job->mapping ?? [];
37        $merged = [
38            'property_types' => array_merge($current['property_types'] ?? [], $mappingPatch['property_types'] ?? []),
39            'purposes' => array_merge($current['purposes'] ?? [], $mappingPatch['purposes'] ?? []),
40            'states' => array_merge($current['states'] ?? [], $mappingPatch['states'] ?? []),
41            'cities' => array_merge($current['cities'] ?? [], $mappingPatch['cities'] ?? []),
42            'neighborhoods' => array_merge($current['neighborhoods'] ?? [], $mappingPatch['neighborhoods'] ?? []),
43            'issues' => array_merge($current['issues'] ?? [], $mappingPatch['issues'] ?? []),
44        ];
45
46        foreach ($mappingPatch['issue_resolutions'] ?? [] as $errorId => $resolution) {
47            ImportErrorModel::query()
48                ->where('import_job_id', $job->id)
49                ->whereKey($errorId)
50                ->update([
51                    'resolution' => (string) $resolution,
52                    'status' => 'resolved',
53                ]);
54        }
55
56        $preview = $job->preview_summary ?? [];
57        $ambiguities = [];
58        foreach ($preview['ambiguities'] ?? [] as $item) {
59            $field = $item['field'] ?? null;
60            $key = $item['key'] ?? null;
61            if ($field === null || $key === null) {
62                continue;
63            }
64
65            $bucket = match ($field) {
66                'property_type' => 'property_types',
67                'purpose' => 'purposes',
68                'state' => 'states',
69                'city' => 'cities',
70                'neighborhood' => 'neighborhoods',
71                default => null,
72            };
73
74            if ($bucket === null || empty($merged[$bucket][$key])) {
75                $ambiguities[] = $item;
76            }
77        }
78
79        $status = $ambiguities === []
80            ? (($job->error_listings ?? 0) > 0 ? ImportJobStatus::PreviewReady : ImportJobStatus::Ready)
81            : ImportJobStatus::AwaitingMapping;
82
83        $preview['ambiguities'] = $ambiguities;
84
85        $job->forceFill([
86            'mapping' => $merged,
87            'preview_summary' => $preview,
88            'status' => $status,
89        ])->save();
90
91        $this->logWriter->write(
92            $job->tenant_id,
93            $job->id,
94            ImportLogEvent::MappingUpdated,
95            message: 'Mapeamento atualizado.',
96        );
97
98        return $job->fresh(['errors', 'file']);
99    }
100}