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