Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 146 |
|
0.00% |
0 / 15 |
CRAP | |
0.00% |
0 / 1 |
| GestionaService | |
0.00% |
0 / 146 |
|
0.00% |
0 / 15 |
2970 | |
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 / 43 |
|
0.00% |
0 / 1 |
210 | |||
| updateApiCredentials | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
56 | |||
| 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 | namespace App\Services; |
| 3 | |
| 4 | use App\Models\TblCompanies; |
| 5 | use App\Models\TblG3WCredentials; |
| 6 | use App\Models\TblG3wLastUpdate; |
| 7 | use Illuminate\Support\Facades\Log; |
| 8 | |
| 9 | class 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 | } |