Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 142
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
GestionaService
0.00% covered (danger)
0.00%
0 / 142
0.00% covered (danger)
0.00%
0 / 15
2756
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 getCredentials
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
42
 encrypt
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 decrypt
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 auth
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
72
 request
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 1
182
 updateApiCredentials
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
42
 getApiDetails
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getLastUpdate
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getSyncStatus
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 setSyncStatus
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getG3wActive
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 updateG3wActive
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getBudgetsByDay
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 checkDeleted
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace App\Services;
4
5use App\Models\TblCompanies;
6use App\Models\TblG3WCredentials;
7use App\Models\TblG3wLastUpdate;
8use Illuminate\Support\Facades\Log;
9
10class GestionaService
11{
12    protected $apiUrl;
13
14    protected $user;
15
16    protected $password;
17
18    protected $accessToken;
19
20    protected $region;
21
22    protected $credentials;
23
24    protected $appUser;
25
26    protected $encryptKey;
27
28    protected $cipher;
29
30    public function __construct()
31    {
32        $this->encryptKey = env('ENCRYPT_KEY');
33        if (! $this->encryptKey) {
34            throw new \Exception('Encryption key not set in environment variables');
35        }
36
37        $this->cipher = 'AES-256-CBC';
38
39        $this->appUser = @getallheaders()['Name'] ?? 'System';
40    }
41
42    public function getCredentials($region)
43    {
44
45        if ($region === 'Catalunya') {
46            $region = 'Cataluña';
47        }
48
49        $this->credentials = TblG3WCredentials::where('region', $region)->first();
50
51        if (! $this->credentials) {
52            TblG3WCredentials::create([
53                'region' => $region,
54            ]);
55            $this->credentials = TblG3WCredentials::where('region', $region)->first();
56        }
57
58        $this->user = $this->credentials->user ? $this->decrypt($this->credentials->user) : null;
59        $this->password = $this->credentials->password ? $this->decrypt($this->credentials->password) : null;
60        $this->apiUrl = $this->credentials->url ? $this->decrypt($this->credentials->url) : null;
61    }
62
63    /**
64     * @return false|string
65     */
66    private function encrypt($data)
67    {
68        $iv = substr(hash('sha256', $this->encryptKey), 0, 16);
69
70        return openssl_encrypt($data, $this->cipher, $this->encryptKey, 0, $iv);
71    }
72
73    /**
74     * @return false|string
75     */
76    private function decrypt($encryptedData)
77    {
78        $iv = substr(hash('sha256', $this->encryptKey), 0, 16);
79
80        return openssl_decrypt($encryptedData, $this->cipher, $this->encryptKey, 0, $iv);
81    }
82
83    /**
84     * @return void
85     *
86     * @throws \Exception
87     */
88    protected function auth($region)
89    {
90        try {
91            $this->getCredentials($region);
92            if (! $this->apiUrl || ! $this->user || ! $this->password) {
93                throw new \Exception('Incomplete credentials: URL, user, or password missing.');
94            }
95
96            $url = "{$this->apiUrl}login";
97
98            $curl = curl_init();
99            curl_setopt_array($curl, [
100                CURLOPT_URL => $url,
101                CURLOPT_RETURNTRANSFER => true,
102                CURLOPT_POST => true,
103                CURLOPT_POSTFIELDS => json_encode([
104                    'email' => $this->user,
105                    'password' => $this->password,
106                ]),
107                CURLOPT_HTTPHEADER => [
108                    'Accept: application/json',
109                    'Content-Type: application/json',
110                ],
111            ]);
112
113            $response = curl_exec($curl);
114
115            if (curl_errno($curl)) {
116                throw new \Exception('cURL error: '.curl_error($curl));
117            }
118
119            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
120            curl_close($curl);
121
122            if ($httpCode !== 200) {
123                throw new \Exception('Authentication error: '.$response);
124            }
125
126            $responseData = json_decode($response, true);
127            $this->accessToken = $responseData['accessToken'] ?? null;
128
129            if (! $this->accessToken) {
130                throw new \Exception('No access token returned.');
131            }
132        } catch (\Exception $e) {
133            Log::channel('g3w')->error('Error in auth: '.$e->getMessage());
134            throw new \Exception('Authentication failed: '.$e->getMessage());
135        }
136    }
137
138    /**
139     * @return mixed
140     *
141     * @throws \Exception
142     */
143    public function request($method, $endpoint, $region, array $data = [])
144    {
145        try {
146            $this->getCredentials($region);
147
148            if (! $this->apiUrl) {
149                throw new \Exception('API URL is not defined.');
150            }
151
152            if (! $this->accessToken) {
153                $this->auth($region);
154            }
155
156            $url = "{$this->apiUrl}{$endpoint}";
157            $curl = curl_init();
158
159            curl_setopt_array($curl, [
160                CURLOPT_URL => $url,
161                CURLOPT_RETURNTRANSFER => true,
162                CURLOPT_CUSTOMREQUEST => strtoupper($method),
163                CURLOPT_HTTPHEADER => [
164                    'Authorization: Bearer '.$this->accessToken,
165                    'Accept: application/json',
166                    'Content-Type: application/json',
167                ],
168            ]);
169
170            if (in_array(strtoupper($method), ['POST', 'PUT', 'PATCH']) && ! empty($data)) {
171                curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
172            }
173
174            $response = curl_exec($curl);
175
176            if (curl_errno($curl)) {
177                throw new \Exception('cURL error: '.curl_error($curl));
178            }
179
180            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
181            curl_close($curl);
182
183            if ($httpCode === 401) {
184                $this->auth($region);
185
186                return $this->request($method, $endpoint, $region, $data);
187            }
188
189            if ($httpCode < 200 || $httpCode >= 300) {
190                Log::channel('g3w')->error('API Response Error: '.$response);
191
192                $errorResponse = json_decode($response, true);
193                $errorMessage = is_array($errorResponse) && isset($errorResponse['message'])
194                    ? $errorResponse['message']
195                    : 'Request error: '.$response;
196
197                throw new \Exception($errorMessage);
198            }
199
200            $responseData = json_decode($response, true);
201
202            if (json_last_error() !== JSON_ERROR_NONE) {
203                throw new \Exception('Invalid JSON response: '.$response);
204            }
205
206            return $responseData;
207        } catch (\Exception $e) {
208            Log::channel('g3w')->error('Error in request: '.$e->getMessage());
209            throw $e;
210        }
211    }
212
213    /**
214     * @return true
215     *
216     * @throws \Exception
217     */
218    public function updateApiCredentials($params, $region = null)
219    {
220        try {
221            $this->getCredentials($region);
222
223            $updateData = [];
224            if (isset($params['url'])) {
225                if (substr($params['url'], -1) !== '/') {
226                    $params['url'] .= '/';
227                }
228                $updateData['url'] = $this->encrypt($params['url']);
229            }
230
231            if (isset($params['user'])) {
232                $updateData['user'] = $this->encrypt($params['user']);
233            }
234
235            if (isset($params['password'])) {
236                $updateData['password'] = $this->encrypt($params['password']);
237            }
238
239            $updateData['user_id'] = $params['user_id'] ?? null;
240
241            TblG3WCredentials::where('region', $region)->update($updateData);
242
243            return true;
244        } catch (\Exception $e) {
245            Log::channel('g3w')->error('Error updating credentials for region '.$this->region.': '.$e->getMessage());
246            throw $e;
247        }
248    }
249
250    /**
251     * @return \Illuminate\Http\JsonResponse
252     */
253    public function getApiDetails($region = null)
254    {
255        $this->getCredentials($region);
256        if (! $this->credentials) {
257            return response()->json(['message' => 'No credentials found'], 404);
258        }
259
260        return response()->json([
261            'url' => $this->decrypt($this->credentials->url),
262            'user' => $this->decrypt($this->credentials->user),
263        ]);
264    }
265
266    /**
267     * @return \Illuminate\Http\JsonResponse
268     */
269    public function getLastUpdate($region)
270    {
271        $lastUpdate = TblG3wLastUpdate::where('region', $region)->first();
272
273        if (! $lastUpdate) {
274            return response()->json(['message' => 'No last update found'], 404);
275        }
276
277        return response()->json([
278            'lastUpdate' => $lastUpdate->updated_at->format('Y-m-d H:i:s'),
279            'updatingNow' => $lastUpdate->updatingNow,
280        ]);
281    }
282
283    public function getSyncStatus($region)
284    {
285        if ($region === "'Catalunya'") {
286            $region = 'Cataluña';
287        }
288
289        return TblG3wLastUpdate::where('region', $region)->first()->updatingNow ?? 0;
290
291    }
292
293    public function setSyncStatus($status, $region)
294    {
295        if ($region === 'Catalunya' || $region === "'Catalunya'") {
296            $region = 'Cataluña';
297        }
298
299        $record = TblG3wLastUpdate::where('region', $region)->first();
300
301        $record->updatingNow = $status;
302        $record->save();
303    }
304
305    public function getG3wActive($region)
306    {
307        return TblCompanies::where('region', $region)->first()->g3W_active ?? 0;
308    }
309
310    public function updateG3wActive($active, $region)
311    {
312        $record = TblCompanies::where('region', $region)->first();
313
314        $record->g3W_active = $active;
315        $record->save();
316    }
317
318    public function getBudgetsByDay($date, $region)
319    {
320        return $this->request('get', 'presupuesto?fecha='.$date, $region, []);
321    }
322
323    public function checkDeleted($id, $region)
324    {
325        try {
326            $this->request('get', "presupuesto/{$id}", $region, []);
327
328            return false;
329        } catch (\Exception $e) {
330            if (str_contains($e->getMessage(), 'No se ha encontrado el presupuesto')) {
331                return true;
332            }
333
334            return false;
335        }
336
337    }
338}