Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 421
0.00% covered (danger)
0.00%
0 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
GestionaController
0.00% covered (danger)
0.00%
0 / 421
0.00% covered (danger)
0.00%
0 / 14
5112
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 1
2
 updateApiCredentials
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 getApiDetails
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
 getLastUpdate
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
20
 getAcceptanceWarnings
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
42
 getSyncStatus
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 getG3wActive
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 updateG3wActive
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 getMappings
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
42
 setMappings
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 1
156
 deleteMappings
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
 getAllBudgetMonitor
0.00% covered (danger)
0.00%
0 / 121
0.00% covered (danger)
0.00%
0 / 1
182
 syncAllBudgetMonitor
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 1
42
 getDuplicatedValues
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Models\TblCompanies;
6use App\Models\TblG3WOrdersUpdateLogs;
7use App\Models\TblQuotations;
8use App\Models\TblSegmentG3wMapping;
9use App\Models\TblSourceG3wMapping;
10use App\Models\TblSources;
11use App\Models\TblStatusG3wMapping;
12use App\Models\TblTypeG3wMapping;
13use App\Models\TblUserG3wMapping;
14use App\Models\TblUsers;
15use App\Services\GestionaService;
16use App\Services\PresupuestosService;
17use Illuminate\Http\Request;
18use Illuminate\Support\Carbon;
19use Illuminate\Support\Facades\DB;
20use Illuminate\Support\Facades\Log;
21use Illuminate\Support\Facades\Schema;
22
23class GestionaController extends Controller
24{
25    protected $gestionaService;
26
27    protected $presupuestoService;
28
29    protected $tables;
30
31    public function __construct(GestionaService $gestionaService, PresupuestosService $presupuestoService)
32    {
33        $this->gestionaService = $gestionaService;
34        $this->presupuestoService = $presupuestoService;
35        $this->tables = [
36            'status' => [
37                'model' => TblStatusG3wMapping::class,
38                'index' => 'budget_status_id',
39                'relation' => 'budgetStatus',
40                'tblQuotationsG3wNameColumn' => 'status_by_g3w',
41                'tblMappingNameColumn' => 'name_g3w',
42                'tblQuotationsNameColumn' => 'budget_status_id',
43                'requestNameKey' => 'budget_status_id',
44            ],
45            'segment' => [
46                'model' => TblSegmentG3wMapping::class,
47                'index' => 'segment_id',
48                'relation' => 'segment',
49                'tblQuotationsG3wNameColumn' => 'segment_by_g3w',
50                'tblMappingNameColumn' => 'name_g3w',
51                'tblQuotationsNameColumn' => 'segment_id',
52                'requestNameKey' => 'segment_id',
53            ],
54            'type' => [
55                'model' => TblTypeG3wMapping::class,
56                'index' => 'budget_type_name',
57                'relation' => 'budgetType',
58                'tblQuotationsG3wNameColumn' => 'type_by_g3w',
59                'tblMappingNameColumn' => 'id_g3w',
60                'tblQuotationsNameColumn' => 'budget_type_id',
61                'requestNameKey' => 'id_g3w',
62            ],
63            'source' => [
64                'model' => TblSourceG3wMapping::class,
65                'index' => 'source_name',
66                'relation' => 'source',
67                'tblQuotationsG3wNameColumn' => 'source_by_g3w',
68                'tblMappingNameColumn' => 'id_g3w',
69                'tblQuotationsNameColumn' => 'source_id',
70                'requestNameKey' => 'id_g3w',
71            ],
72            'user' => [
73                'model' => TblUserG3wMapping::class,
74                'index' => 'id_fst',
75                'relation' => 'user',
76                'tblQuotationsG3wNameColumn' => 'G3W_code',
77                'tblMappingNameColumn' => 'id_fst',
78                'tblQuotationsNameColumn' => 'G3W_code',
79                'requestNameKey' => 'id_fst',
80            ],
81        ];
82    }
83
84    /**
85     * Sincroniza un presupuesto por su ID.
86     *
87     * @param  $id
88     * @return \Illuminate\Http\JsonResponse
89     */
90    public function updateApiCredentials(Request $request)
91    {
92        try {
93            $region = @getallheaders()['Region'];
94
95            if ($region == 'Catalunya') {
96                $region = 'Cataluña';
97            }
98
99            $params = $request->only(['url', 'user', 'password', 'user_id']);
100            $this->gestionaService->updateApiCredentials($params, $region);
101
102            return response()->json(['message' => 'Credentials updated successfully'], 200);
103        } catch (\Exception $e) {
104            /** @disregard P1014 */
105            $e->exceptionCode = 'UPDATE_API_CREDENTIALS_EXCEPTION';
106            report($e);
107
108            return response()->json(['error' => $e->getMessage()], 400);
109        }
110    }
111
112    /**
113     * @return \Illuminate\Http\JsonResponse
114     *
115     * @throws \Exception
116     */
117    public function getApiDetails()
118    {
119        try {
120            $region = @getallheaders()['Region'];
121
122            if ($region === 'Catalunya') {
123                $region = 'Cataluña';
124            }
125
126            $apiDetailsResponse = $this->gestionaService->getApiDetails($region);
127
128            if (! $apiDetailsResponse) {
129                throw new \Exception('Api details not found');
130            }
131
132            $apiDetails = json_decode($apiDetailsResponse->getContent(), true);
133
134            return response()->json([
135                'url' => $apiDetails['url'] ?? null,
136                'user' => $apiDetails['user'] ?? null,
137            ], 200);
138
139        } catch (\Illuminate\Database\QueryException $e) {
140            /** @disregard P1014 */
141            $e->exceptionCode = 'GET_API_DETAILS_EXCEPTION';
142            report($e);
143
144            return response()->json(['error' => $e->getMessage()], 400);
145        }
146    }
147
148    public function getLastUpdate()
149    {
150        try {
151            $region = @getallheaders()['Region'];
152
153            if ($region === 'Catalunya') {
154                $region = 'Cataluña';
155            }
156
157            $apiLastUpdateResponse = $this->gestionaService->getLastUpdate($region);
158
159            if (! $apiLastUpdateResponse) {
160                throw new \Exception('Last update not found');
161            }
162
163            $apiLastUpdate = json_decode($apiLastUpdateResponse->getContent(), true);
164
165            return response()->json([
166                'lastUpdate' => $apiLastUpdate['lastUpdate'] ?? null,
167                'updatingNow' => $apiLastUpdate['updatingNow'] ?? null,
168            ], 200);
169
170        } catch (\Illuminate\Database\QueryException $e) {
171            /** @disregard P1014 */
172            $e->exceptionCode = 'GET_LAST_UPDATE_EXCEPTION';
173            report($e);
174            Log::error('Error en getLastUpdate: '.$e->getMessage());
175
176            return response()->json(['error' => $e->getMessage()], 400);
177        }
178    }
179
180    public function getAcceptanceWarnings(Request $request)
181    {
182        try {
183            $region = @getallheaders()['Region'] ?? null;
184
185            if (! $region) {
186                return response()->json(['error' => 'Region header is missing'], 400);
187            }
188
189            if ($region == 'Catalunya') {
190                $region = 'Cataluña';
191            }
192
193            $commercial = $request->input('commercial', null);
194
195            $company = TblCompanies::where('region', $region)->first();
196            if (! $company) {
197                return response()->json([
198                    'countWarnings' => 0,
199                ], 200);
200            }
201
202            $companyId = $company->company_id;
203
204            /*$countWarnings = TblQuotations::where('sync_import', 1)
205                ->where('company_id', $companyId)
206                ->when(!empty($commercial) && $commercial !== "All", function ($query) use ($commercial) {
207                    return $query->where('commercial', $commercial);
208                })
209                ->where(function ($query) {
210                    $query->WhereIn('budget_status_id', [13, 14])
211                        ->orWhere(function ($subQuery) {
212                            $subQuery->whereNull('commercial')
213                                ->orWhereNotExists(function ($subQuery) {
214                                    $subQuery->select(DB::raw(1))
215                                        ->from('tbl_users')
216                                        ->whereColumn('tbl_users.name', 'tbl_quotations.commercial');
217                                });
218                        })
219                        ->orWhereNull('phone_number')
220                        ->orWhereNull('source_id')
221                        ->orWhereNull('budget_type_id')
222                        ->orWhere(function ($subQuery) {
223                            $subQuery->whereNull('client')
224                                ->orWhere(DB::raw('TRIM(client)'), '');
225                        })
226                        ->orWhere(function ($subQuery) {
227                            $subQuery->whereNull('email')
228                                ->orWhere(DB::raw('TRIM(email)'), '');
229                        });
230                })
231                ->count();*/
232
233            $countWarnings = TblQuotations::where('sync_import', 1)
234                ->where('company_id', $companyId)
235                ->where('g3w_warning', 1)
236                ->when(! empty($commercial) && $commercial !== 'All', function ($query) use ($commercial) {
237                    return $query->where('commercial', $commercial);
238                })
239                ->count();
240
241            return response()->json([
242                'countWarnings' => $countWarnings,
243            ], 200);
244
245        } catch (\Illuminate\Database\QueryException $e) {
246            /** @disregard P1014 */
247            $e->exceptionCode = 'ADD_WORK_STATUS_EXCEPTION';
248            report($e);
249            Log::error('Error en getAcceptanceWarnings: '.$e->getMessage());
250
251            return response()->json(['error' => $e->getMessage()], 400);
252        }
253    }
254
255    public function getSyncStatus()
256    {
257        try {
258            $region = @getallheaders()['Region'];
259
260            if ($region === 'Catalunya') {
261                $region = 'Cataluña';
262            }
263
264            return response()->json([
265                'status' => $this->gestionaService->getSyncStatus($region),
266            ], 200);
267
268        } catch (\Illuminate\Database\QueryException $e) {
269            /** @disregard P1014 */
270            $e->exceptionCode = 'GET_SYNC_STATUS_EXCEPTION';
271            report($e);
272
273            return response()->json(['error' => $e->getMessage()], 400);
274        }
275    }
276
277    public function getG3wActive()
278    {
279        try {
280            $region = @getallheaders()['Region'];
281
282            $region = urldecode($region);
283
284            if ($region === 'Catalunya') {
285                $region = 'Cataluña';
286            }
287
288            return response()->json([
289                'active' => $this->gestionaService->getG3wActive($region),
290            ], 200);
291
292        } catch (\Illuminate\Database\QueryException $e) {
293            /** @disregard P1014 */
294            $e->exceptionCode = 'GET_G3W_ACTIVE_EXCEPTION';
295            report($e);
296            Log::error('Error en getG3wActive: '.$e->getMessage());
297
298            return response()->json(['error' => $e->getMessage()], 400);
299        }
300    }
301
302    public function updateG3wActive(Request $request)
303    {
304        try {
305            $region = urldecode($request->header('Region'));
306
307            if ($region === 'Catalunya') {
308                $region = 'Cataluña';
309            }
310
311            $active = $request->input('active');
312
313            $this->gestionaService->updateG3wActive($active, $region);
314
315            return response()->json([
316                'success' => 1,
317            ], 200);
318
319        } catch (\Illuminate\Database\QueryException $e) {
320            /** @disregard P1014 */
321            $e->exceptionCode = 'UPDATE_G3W_ACTIVE_EXCEPTION';
322            report($e);
323
324            return response()->json(['error' => $e->getMessage()], 400);
325        }
326    }
327
328    public function getMappings(Request $request)
329    {
330        try {
331
332            if (! $request->has('type') || ! array_key_exists($request->type, $this->tables)) {
333                throw new \Exception('Type parameter is missing or invalid');
334            }
335
336            $tableConfig = $this->tables[$request->type];
337
338            if (isset($tableConfig['model'])) {
339                $mappings = $tableConfig['model']::with([$tableConfig['relation'] => function ($query) use ($tableConfig) {
340                    $relatedModel = (new $tableConfig['model'])->{$tableConfig['relation']}()->getRelated();
341                    $relatedTable = $relatedModel->getTable();
342
343                    if (Schema::hasColumn($relatedTable, 'priority')) {
344                        $query->orderBy('priority', 'desc');
345                    }
346                }])->get();
347            } else {
348                $mappings = DB::table($tableConfig['table'])->get();
349            }
350
351            return response()->json($mappings);
352
353        } catch (\Exception $e) {
354            /** @disregard P1014 */
355            $e->exceptionCode = 'GET_MAPPINGS_EXCEPTION';
356            report($e);
357
358            return response()->json(['error' => $e->getMessage()], 400);
359        }
360    }
361
362    public function setMappings(Request $request)
363    {
364        try {
365            if (! $request->has('type')) {
366                return response()->json(['message' => 'Not type especified']);
367            }
368
369            $tableConfig = $this->tables[$request->type];
370
371            if (! isset($tableConfig['tblQuotationsG3wNameColumn'], $tableConfig['tblMappingNameColumn'], $tableConfig['tblQuotationsNameColumn'], $tableConfig['requestNameKey'])) {
372                return response()->json(['message' => 'Missing configuration keys'], 500);
373            }
374
375            $data = $request->except('type');
376
377            if (! $request->has('id')) {
378                $tableConfig['model']::create($data);
379
380                return response()->json(['message' => $request->type.' created successfully']);
381            }
382
383            if ($tableConfig['relation'] === 'user') {
384                if (is_numeric($request['id'])) {
385                    $rowMapping = $tableConfig['model']::where('id_fst', $request['id'])->first();
386                    $data = $request->except('id');
387
388                    if (! $rowMapping) {
389                        $tableConfig['model']::create($data);
390
391                        return response()->json(['error' => 'User mapping not found'], 404);
392                    }
393
394                    $userName = TblUsers::where('id', $rowMapping->id_fst)->first()->name;
395                    $nameG3w = $rowMapping->name_g3w;
396
397                    TblQuotations::where('user_create_by_g3w', $nameG3w)
398                        ->update(['created_by' => $userName]);
399
400                    TblQuotations::where('user_commercial_by_g3w', $nameG3w)
401                        ->update(['commercial' => $userName]);
402
403                    TblQuotations::where('user_create_by_g3w', $nameG3w)
404                        ->whereNull('commercial')
405                        ->whereNull('user_commercial_by_g3w')
406                        ->update(['commercial' => $nameG3w]);
407
408                    $rowMapping->update($data);
409
410                } else {
411                    $rowMapping = $tableConfig['model']::where('name_g3w', $request['id'])->first();
412
413                    if (! $rowMapping) {
414                        return response()->json(['error' => 'User mapping not found'], 404);
415                    }
416
417                    $rowMapping->update(['id_fst' => $request['id_fst']]);
418
419                    $userName = TblUsers::where('id', $request['id_fst'])->first();
420
421                    if (! $userName) {
422                        return response()->json(['error' => 'User mapping not found'], 404);
423                    }
424
425                    TblQuotations::where('user_create_by_g3w', $request['id'])
426                        ->update(['created_by' => $userName->name]);
427
428                    TblQuotations::where('user_commercial_by_g3w', $request['id'])
429                        ->update(['commercial' => $userName->name]);
430
431                    TblQuotations::where('user_create_by_g3w', $request['id'])
432                        ->whereNull('commercial')
433                        ->whereNull('user_commercial_by_g3w')
434                        ->update(['commercial' => $userName->name]);
435
436                }
437
438                return response()->json(['message' => $request->type.' edited successfully']);
439            }
440
441            $rowMapping = $tableConfig['model']::where('id', $request['id'])->first();
442
443            if ($tableConfig['relation'] === 'source') {
444                $data = [];
445                $sourceRow = TblSources::where('source_id', $request['id_fst'])->first();
446                if (! $sourceRow) {
447                    return response()->json(['error' => 'Source mapping not found'], 404);
448                }
449
450                $data['source_name'] = $sourceRow->name;
451            }
452
453            $rowMapping->update($data);
454
455            TblQuotations::where($tableConfig['tblQuotationsG3wNameColumn'], $rowMapping[$tableConfig['tblMappingNameColumn']])
456                ->update([$tableConfig['tblQuotationsNameColumn'] => $rowMapping[$tableConfig['requestNameKey']]]);
457
458            return response()->json(['message' => $request->type.' edited successfully']);
459
460        } catch (\Illuminate\Database\QueryException $e) {
461            /** @disregard P1014 */
462            $e->exceptionCode = 'SET_MAPPING_EXCEPTION';
463            report($e);
464
465            return response()->json(['error' => $e->getMessage()], 400);
466        }
467    }
468
469    public function deleteMappings(Request $request)
470    {
471        try {
472            if (! $request->has('id')) {
473                return response()->json(['message' => 'Can`t be deleted without ID']);
474            }
475
476            if (! $request->has('type')) {
477                return response()->json(['message' => 'Not type especified']);
478            }
479
480            $tableConfig = $this->tables[$request->type];
481
482            if ($tableConfig['relation'] === 'user') {
483                $tableConfig['model']::where('id_fst', $request['id'])->delete();
484
485                return response()->json(['message' => $request->type.' deleted successfully']);
486            }
487
488            $tableConfig['model']::where('id', $request['id'])->delete();
489
490            return response()->json(['message' => $request->type.' deleted successfully']);
491
492        } catch (\Illuminate\Database\QueryException $e) {
493            /** @disregard P1014 */
494            $e->exceptionCode = 'DELETE_MAPPING_EXCEPTION';
495            report($e);
496
497            return response()->json(['error' => $e->getMessage()], 400);
498        }
499    }
500
501    public function getAllBudgetMonitor(Request $request)
502    {
503        try {
504            $data = $request->all();
505            $region = urldecode(@getallheaders()['Region']);
506            $page = $data['page'];
507
508            $daysOffset = $page * 10;
509            $endDate = Carbon::today()->subDays($daysOffset);
510            $startDate = $endDate->copy()->addDays(10);
511
512            $dataResponse = [];
513            $currentDate = $startDate->copy();
514            $companyId = TblCompanies::where('region', $region)->first()->company_id;
515            $alreadyG3wBudgets = [];
516
517            while ($currentDate > $endDate) {
518                $dateStr = $currentDate->format('Y-m-d');
519
520                $g3wBudgets = $this->gestionaService->getBudgetsByDay($dateStr, $region);
521                if (is_string($g3wBudgets)) {
522                    $g3wBudgets = json_decode($g3wBudgets, true);
523                }
524
525                $g3wBudgetIds = array_map(function ($item) {
526                    return $item['ID'];
527                }, $g3wBudgets);
528
529                $newG3wBudgetIds = array_diff($g3wBudgetIds, $alreadyG3wBudgets);
530                $alreadyG3wBudgets = array_merge($alreadyG3wBudgets, $newG3wBudgetIds);
531                $countG3wBudgets = count($newG3wBudgetIds);
532
533                $fstBudgets = TblQuotations::where('company_id', $companyId)
534                    ->where(function ($query) {
535                        $query->where('sync_import', 1)
536                            ->orWhere('sync_import_edited', 1);
537                    })
538                    ->whereDate('created_at', $dateStr)
539                    ->pluck('internal_quote_id')
540                    ->toArray();
541
542                if ($companyId == 18 || $companyId == 22) {
543                    $fstBudgets = TblQuotations::whereIn('company_id', [18, 22])
544                        ->where(function ($query) {
545                            $query->where('sync_import', 1)
546                                ->orWhere('sync_import_edited', 1);
547                        })
548                        ->whereDate('created_at', $dateStr)
549                        ->pluck('internal_quote_id')
550                        ->toArray();
551                }
552
553                $countFstBudgets = count($fstBudgets);
554
555                $missingIds = array_diff($newG3wBudgetIds, $fstBudgets);
556
557                $existingIds = TblQuotations::where('company_id', $companyId)
558                    ->where(function ($query) {
559                        $query->where('sync_import', 1)
560                            ->orWhere('sync_import_edited', 1);
561                    })
562                    ->whereIn('internal_quote_id', $missingIds)
563                    ->pluck('internal_quote_id')
564                    ->toArray();
565
566                if ($companyId == 18 || $companyId == 22) {
567                    $existingIds = TblQuotations::where('company_id', $companyId)
568                        ->where(function ($query) {
569                            $query->where('sync_import', 1)
570                                ->orWhere('sync_import_edited', 1);
571                        })
572                        ->whereIn('internal_quote_id', $missingIds)
573                        ->pluck('internal_quote_id')
574                        ->toArray();
575                }
576
577                $finalMissingIds = array_diff($missingIds, $existingIds);
578
579                $duplicatedFst = $this->getDuplicatedValues($fstBudgets);
580
581                $deletedIds = array_diff($fstBudgets, $newG3wBudgetIds);
582                foreach ($deletedIds as $key => $id) {
583                    $deleted = $this->gestionaService->checkDeleted($id, $region);
584                    if (! $deleted) {
585                        unset($deletedIds[$key]);
586                    }
587                }
588
589                $g3wOrdersUpdateLogs = TblG3WOrdersUpdateLogs::where('company_id', $companyId)
590                    ->whereDate('ended_at', $dateStr)
591                    ->where('processed_by', 'System')
592                    ->get();
593
594                $syncs = $g3wOrdersUpdateLogs->count();
595
596                $allUniqueErrorIds = [];
597
598                $syncErrorIds = $g3wOrdersUpdateLogs->flatMap(function ($item) {
599                    $ids = $item->sync_error_ids;
600                    if (is_string($ids)) {
601                        $decoded = json_decode($ids, true);
602                        $ids = is_array($decoded) ? $decoded : explode(',', $ids);
603                    }
604
605                    return (array) $ids;
606                })
607                    ->filter()
608                    ->unique()
609                    ->toArray();
610
611                $allUniqueErrorIds = array_merge($allUniqueErrorIds, $syncErrorIds);
612
613                $finalUniqueIds = array_values(array_unique($allUniqueErrorIds));
614                $countSyncErrorIds = count($finalUniqueIds);
615
616                $dataResponse[] = [
617                    'date' => $dateStr,
618                    'g3wBudgets' => array_values($newG3wBudgetIds),
619                    'countG3wBudgets' => $countG3wBudgets,
620                    'fstBudgets' => $fstBudgets,
621                    'countfstBudgets' => $countFstBudgets,
622                    'missingIds' => array_values($finalMissingIds),
623                    'duplicatedFst' => $duplicatedFst,
624                    'deletedIds' => array_values($deletedIds),
625                    'syncs' => $syncs,
626                    'syncErrorIds' => $syncErrorIds,
627                    'countSyncErrorIds' => $countSyncErrorIds,
628                ];
629
630                $currentDate->subDay();
631
632            }
633
634            usort($dataResponse, function ($a, $b) {
635                return strtotime($b['date']) - strtotime($a['date']);
636            });
637
638            return response()->json([
639                'data' => $dataResponse,
640                'meta' => [
641                    'current_page' => (int) $page,
642                    'date_range' => [
643                        'start' => $startDate->format('Y-m-d'),
644                        'end' => $endDate->format('Y-m-d'),
645                    ],
646                ]]);
647        } catch (\Exception $e) {
648            /** @disregard P1014 */
649            $e->exceptionCode = 'GET_ALL_BUDGET_MONITOR_EXCEPTION';
650            report($e);
651            Log::error('Error en getAllBudgetMonitor: '.$e->getMessage());
652
653            if ($e->getMessage() == 'API URL is not defined.') {
654                return response()->json([
655                    'error' => 'KO',
656                    'message' => 'La conexión con la API de G3W no está configurada. Por favor, configúrala en los ajustes de la empresa.',
657                ], 200);
658            }
659
660            return response()->json([
661                'message' => 'Error interno del servidor',
662            ], 500);
663        }
664    }
665
666    public function syncAllBudgetMonitor(Request $request)
667    {
668        try {
669            $data = $request->all();
670            if (app()->runningInConsole()) {
671                $region = $request->header('Region');
672            } else {
673                $headers = getallheaders();
674                $region = urldecode($headers['Region'] ?? '');
675            }
676            $day = $data['day'];
677            $dataResponse = [];
678            $companyId = TblCompanies::where('region', $region)->first()->company_id;
679            $alreadyG3wBudgets = [];
680
681            $g3wBudgets = $this->gestionaService->getBudgetsByDay($day, $region);
682
683            if (is_string($g3wBudgets)) {
684                $g3wBudgets = json_decode($g3wBudgets, true);
685            }
686
687            $g3wBudgetIds = array_map(function ($item) {
688                return $item['ID'];
689            }, $g3wBudgets);
690
691            $newG3wBudgetIds = array_diff($g3wBudgetIds, $alreadyG3wBudgets);
692            $alreadyG3wBudgets = array_merge($alreadyG3wBudgets, $newG3wBudgetIds);
693
694            $fstBudgets = TblQuotations::where('company_id', $companyId)
695                ->where('sync_import', 1)
696                ->whereDate('created_at', $day)
697                ->pluck('internal_quote_id')
698                ->toArray();
699
700            $missingIds = array_diff($newG3wBudgetIds, $fstBudgets);
701
702            $existingIds = TblQuotations::where('company_id', $companyId)
703                ->where('sync_import', 1)
704                ->whereIn('internal_quote_id', $missingIds)
705                ->pluck('internal_quote_id')
706                ->toArray();
707
708            $finalMissingIds = array_diff($missingIds, $existingIds);
709
710            $duplicatedFst = $this->getDuplicatedValues($fstBudgets);
711
712            $deletedIds = array_diff($fstBudgets, $newG3wBudgetIds);
713
714            foreach ($deletedIds as $key => $id) {
715                $deleted = $this->gestionaService->checkDeleted($id, $region);
716                if (! $deleted) {
717                    unset($deletedIds[$key]);
718                }
719            }
720
721            $this->presupuestoService->syncByIds(implode(',', $finalMissingIds), $region, $day);
722
723            $dataResponse[] = [
724                'missingIds' => array_values($finalMissingIds),
725                'deletedIds' => array_values($deletedIds),
726            ];
727
728            return response()->json([
729                'success' => true,
730                'message' => 'Presupuestos que faltan sincronizados correctamente',
731            ]);
732        } catch (\Exception $e) {
733            /** @disregard P1014 */
734            $e->exceptionCode = 'SYNC_ALL_BUDGET_MONITOR_EXCEPTION';
735            report($e);
736            Log::error('Error en getAllBudgetMonitor: '.$e->getMessage());
737
738            return response()->json([
739                'message' => 'Error interno del servidor',
740            ], 500);
741        }
742    }
743
744    private function getDuplicatedValues($fstBudgets)
745    {
746        $filteredValues = array_filter($fstBudgets, function ($value) {
747            return $value !== null;
748        });
749
750        if (empty($filteredValues)) {
751            return [];
752        }
753
754        $counts = array_count_values($filteredValues);
755        $duplicates = array_filter($counts, function ($count) {
756            return $count > 1;
757        });
758
759        return array_keys($duplicates);
760    }
761}