Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 142 |
|
0.00% |
0 / 15 |
CRAP | |
0.00% |
0 / 1 |
| GestionaService | |
0.00% |
0 / 142 |
|
0.00% |
0 / 15 |
2756 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
| getCredentials | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
42 | |||
| encrypt | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| decrypt | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| auth | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
72 | |||
| request | |
0.00% |
0 / 41 |
|
0.00% |
0 / 1 |
182 | |||
| updateApiCredentials | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
42 | |||
| getApiDetails | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
| getLastUpdate | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
| getSyncStatus | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| setSyncStatus | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
| getG3wActive | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| updateG3wActive | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| getBudgetsByDay | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| checkDeleted | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace App\Services; |
| 4 | |
| 5 | use App\Models\TblCompanies; |
| 6 | use App\Models\TblG3WCredentials; |
| 7 | use App\Models\TblG3wLastUpdate; |
| 8 | use Illuminate\Support\Facades\Log; |
| 9 | |
| 10 | class 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 | } |