From 7a59227d073aba77fc83bacacf1ae0fc79d5544c Mon Sep 17 00:00:00 2001 From: Alfonso Rafael Solis Rangel Date: Fri, 10 Jan 2025 08:48:09 -0600 Subject: [PATCH 01/14] Reasignacion de roles en las urls --- routes/web.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/routes/web.php b/routes/web.php index e8fe08a..860e8f2 100644 --- a/routes/web.php +++ b/routes/web.php @@ -116,9 +116,9 @@ config('jetstream.auth_session'), 'verified', CheckBanned::class)->name('contacto.')->group(function() { - Route::get('/contactos', [ContactoController::class, 'index'])->name('get')->middleware(CheckRoles::class . ':admingen,admin,capturista' ); + Route::get('/contactos', [ContactoController::class, 'index'])->name('get')->middleware(CheckRoles::class . ':admingen,admin,capturista,lector' ); Route::get('/contactos/crear', [ContactoController::class, 'create'])->name('create')->middleware(CheckRoles::class . ':admingen,admin,capturista' ); - Route::get('/contactos/{id}/ver', [ContactoController::class, 'show'])->name('show')->middleware(CheckRoles::class . ':admingen,admin,capturista' ); + Route::get('/contactos/{id}/ver', [ContactoController::class, 'show'])->name('show')->middleware(CheckRoles::class . ':admingen,admin,capturista,lector' ); Route::post('/contactos/crear', [ContactoController::class, 'store'])->name('store')->middleware(CheckRoles::class . ':admingen,admin,capturista' ); Route::get('/contactos/subir', [ContactoController::class, 'viewUpload'])->name('viewUpload')->middleware(CheckRoles::class . ':admingen,admin,capturista' ); Route::post('/contactos/subir', [ContactoController::class, 'upload'])->name('upload')->middleware(CheckRoles::class . ':admingen,admin,capturista' ); @@ -153,7 +153,7 @@ config('jetstream.auth_session'), 'verified', CheckBanned::class)->name('reporte.')->group(function(){ - Route::get('/reportes/contactos', [ReporteController::class, 'index'])->name('get')->middleware(CheckRoles::class . ':admingen,admin'); - Route::get('/reportes/contactos/buscar', [ReporteController::class, 'find'])->name('find')->middleware(CheckRoles::class . ':admingen,admin'); - Route::post('/reportes/contactos/exportar', [ReporteController::class, 'export'])->name('export')->middleware(CheckRoles::class . ':admingen,admin'); + Route::get('/reportes/contactos', [ReporteController::class, 'index'])->name('get')->middleware(CheckRoles::class . ':admingen,admin,capturista,lector'); + Route::get('/reportes/contactos/buscar', [ReporteController::class, 'find'])->name('find')->middleware(CheckRoles::class . ':admingen,admin,capturista,lector'); + Route::post('/reportes/contactos/exportar', [ReporteController::class, 'export'])->name('export')->middleware(CheckRoles::class . ':admingen,admin,capturista,lector'); }); \ No newline at end of file -- GitLab From 3bd2b3d1ca3ba9b6ba940d6add376187287007f9 Mon Sep 17 00:00:00 2001 From: Alfonso Rafael Solis Rangel Date: Fri, 10 Jan 2025 08:52:42 -0600 Subject: [PATCH 02/14] Error personalizado en el middleware --- app/Http/Middleware/CheckRoles.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Middleware/CheckRoles.php b/app/Http/Middleware/CheckRoles.php index 6fc699e..faf8106 100644 --- a/app/Http/Middleware/CheckRoles.php +++ b/app/Http/Middleware/CheckRoles.php @@ -24,7 +24,7 @@ public function handle(Request $request, Closure $next, ... $roles): Response } } - return abort(401); + return redirect()->back()->withErrors('No tienes los permisos necesarios para acceder a esta página.'); }else{ return $next($request); } -- GitLab From e246f99be0e423c8f671887477ca5c470c0373e8 Mon Sep 17 00:00:00 2001 From: Alfonso Rafael Solis Rangel Date: Fri, 24 Jan 2025 09:23:39 -0600 Subject: [PATCH 03/14] Cambio a string en la extension --- ..._162200_update_ext_row_telefonos_table.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 database/migrations/2025_01_10_162200_update_ext_row_telefonos_table.php diff --git a/database/migrations/2025_01_10_162200_update_ext_row_telefonos_table.php b/database/migrations/2025_01_10_162200_update_ext_row_telefonos_table.php new file mode 100644 index 0000000..3696088 --- /dev/null +++ b/database/migrations/2025_01_10_162200_update_ext_row_telefonos_table.php @@ -0,0 +1,28 @@ +string('ext')->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('telefonos', function (Blueprint $table) { + $table->integer('ext')->change(); + }); + } +}; -- GitLab From 61ae9ca43d39f336278ae15b21f448582f3a5672 Mon Sep 17 00:00:00 2001 From: Alfonso Rafael Solis Rangel Date: Fri, 24 Jan 2025 09:23:59 -0600 Subject: [PATCH 04/14] Implementacion de erores personalizados al csv --- app/Http/Controllers/ContactoController.php | 247 ++++++++++++-------- 1 file changed, 149 insertions(+), 98 deletions(-) diff --git a/app/Http/Controllers/ContactoController.php b/app/Http/Controllers/ContactoController.php index 0b824b4..996d572 100644 --- a/app/Http/Controllers/ContactoController.php +++ b/app/Http/Controllers/ContactoController.php @@ -550,108 +550,86 @@ public function viewUpload() public function upload(Request $request) { - $request->validate([ - 'csv_file' => 'required|mimes:csv,txt', - ]); - - $profesiones = Profesion::select('id', 'nombre')->get(); - - $path = $request->file('csv_file')->getRealPath(); - $content = file_get_contents($path); - $content = str_replace("\xEF\xBB\xBF", '', $content); - - $data = array_map('str_getcsv', explode("\n", $content)); - $header = array_shift($data); - - foreach ($data as $row) { - if (count($header) !== count($row)) { - continue; - } - $row = array_combine($header, $row); - - //TODO: Implementar lo mismo para los demas catalogos - - $existProfesion = $profesiones->firstWhere('nombre', $row['profesion']); - - $datosContacto = [ - 'nombre' => $row['nombre'], - 'ap_paterno' => $row['ap_paterno'], - 'ap_materno' => $row['ap_materno'], - 'cargo_desc' => $row['cargo_desc'], - 'mes_cump' => $row['mes_cump'], - 'dia_cump' => $row['dia_cump'], - 'domicilio_oficial' => $row['domicilio_oficial'], - 'codigo_postal' => $row['codigo_postal'], - 'localidad_oficial' => $row['localidad_oficial'], - 'municipio_oficial' => $row['municipio_oficial'], - 'estado' => $row['estado'], - 'pais' => $row['pais'], - 'domicilio_par' => $row['domicilio_par'], - 'codigo_postal_par' => $row['codigo_postal_par'], - 'localidad_par' => $row['localidad_par'], - 'municipio_par' => $row['municipio_par'], - 'estado_par' => $row['estado_par'], - 'pais_par' => $row['pais_par'], - 'finado' => $row['finado'], - 'foto_perfil' => 'assets/images/profile-icon.webp' - ]; - - if(isset($existProfesion)){ - $datosContacto['profesion_id'] = $existProfesion->id; - } - - $contacto = Contacto::create($datosContacto); - - // Procesar teléfonos - $numeros = explode(';', $row['numero']); - $tipos = explode(';', $row['tipo']); - $estatuses = explode(';', $row['estatus']); - $exts = explode(';', $row['ext']); - $observaciones = explode(';', $row['observaciones']); - - for ($i = 0; $i < count($numeros); $i++) { - if ( $numeros[$i] != 'null') { - Telefono::create([ - 'contacto_id' => $contacto->id, - 'numero' => $numeros[$i], - 'tipo' => $tipos[$i], - 'estatus' => $estatuses[$i], - 'ext' => $exts[$i], - 'observaciones' => $observaciones[$i], - ]); - } - } - - // Procesar redes sociales - $redes_sociales = explode(';', $row['red_social']); - $tipos_redes_sociales = explode(';', $row['tipo_red_social']); - - for ($i = 0; $i < count($redes_sociales); $i++) { - if ($redes_sociales[$i] != 'null' || $tipos_redes_sociales[$i] != 'null') { - RedesSociales::create([ - 'contacto_id' => $contacto->id, - 'red_social' => $redes_sociales[$i], - 'tipo_red_social' => $tipos_redes_sociales[$i], - ]); + try{ + $request->validate([ + 'csv_file' => 'required|mimes:csv,txt', + ]); + + $profesiones = Profesion::select('id', 'nombre')->get(); + + $path = $request->file('csv_file')->getRealPath(); + $content = file_get_contents($path); + $content = str_replace("\xEF\xBB\xBF", '', $content); + + $data = array_map('str_getcsv', explode("\n", $content)); + $header = array_shift($data); + + foreach ($data as $row) { + if (count($header) !== count($row)) { + continue; } - } - - // Procesar correos electrónicos - $correos = explode(';', $row['correo_electronico']); - $tipos_correos = explode(';', $row['tipo_correo_electronico']); - - for ($i = 0; $i < count($correos); $i++) { - if ($correos[$i] != 'null' || $tipos_correos[$i] != 'null') { - CorreoContactos::create([ - 'contacto_id' => $contacto->id, - 'correo_electronico' => $correos[$i], - 'tipo_correo_electronico' => $tipos_correos[$i], - ]); + $row = array_combine($header, $row); + + //TODO: Implementar lo mismo para los demas catalogos + + $existProfesion = $profesiones->firstWhere('nombre', $row['profesion']); + + $datosContacto = [ + 'nombre' => $row['nombre'], + 'ap_paterno' => $row['ap_paterno'], + 'ap_materno' => $row['ap_materno'], + 'cargo_desc' => $row['cargo_desc'], + 'mes_cump' => $row['mes_cump'], + 'dia_cump' => $row['dia_cump'], + 'domicilio_oficial' => $row['domicilio_oficial'], + 'codigo_postal' => $row['codigo_postal'], + 'localidad_oficial' => $row['localidad_oficial'], + 'municipio_oficial' => $row['municipio_oficial'], + 'estado' => $row['estado'], + 'pais' => $row['pais'], + 'domicilio_par' => $row['domicilio_par'], + 'codigo_postal_par' => $row['codigo_postal_par'], + 'localidad_par' => $row['localidad_par'], + 'municipio_par' => $row['municipio_par'], + 'estado_par' => $row['estado_par'], + 'pais_par' => $row['pais_par'], + 'finado' => $row['finado'], + 'foto_perfil' => 'assets/images/profile-icon.webp' + ]; + + if(isset($existProfesion)){ + $datosContacto['profesion_id'] = $existProfesion->id; } + + $contacto = Contacto::create($datosContacto); + + // Procesar teléfonos + $numeros = explode(';', $row['numero']); + $tipos = explode(';', $row['tipo']); + $estatuses = explode(';', $row['estatus']); + $exts = explode(';', $row['ext']); + $observaciones = explode(';', $row['observaciones']); + + $this->validateAndCreateTelefonos($contacto->id, $numeros, $tipos, $estatuses, $exts, $observaciones); + + // Procesar redes sociales + $redes_sociales = explode(';', $row['red_social']); + $tipos_redes_sociales = explode(';', $row['tipo_red_social']); + + $this->validateAndCreateRS($contacto->id, $redes_sociales, $tipos_redes_sociales); + + // Procesar correos electrónicos + $correos = explode(';', $row['correo_electronico']); + $tipos_correos = explode(';', $row['tipo_correo_electronico']); + + $this->validateAndCreateEmails($contacto->id, $correos, $tipos_correos); } + + return redirect()->route('contacto.get')->with('success', 'Importación de contactos almacenada correctamente'); + }catch(\Throwable $e){ + return redirect()->route('contacto.upload')->withErrors('Error al importar los contactos, favor de revisar el archivo CSV. \n' . $e->getMessage()); } - - return redirect()->route('contacto.get')->with('success', 'Importación de contactos almacenada correctamente'); + } public function obtenerEventos(Request $request){ @@ -696,6 +674,79 @@ public function obtenerEventos(Request $request){ return response()->json($eventos); } + + private function validateAndCreateTelefonos($contactoId, $numeros, $tipos, $estatuses, $exts, $observaciones) + { + for ($i = 0; $i < count($numeros); $i++) { + if ($numeros[$i] != 'null') { + if(!filter_var($numeros[$i], FILTER_VALIDATE_INT)){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El número de teléfono debe ser un número entero. Valor actual: ' . $numeros[$i]); + } + if(!in_array($tipos[$i], ['Directo', 'Particular', 'Celular', 'Conmutador'])){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El tipo de teléfono debe ser "Directo", "Particular", "Celular" o "Conmutador". Valor actual: ' . $tipos[$i]); + } + if(!in_array($estatuses[$i], ['Público', 'Privado'])){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El estatus del teléfono debe ser "Público" o "Privado". Valor actual: ' . $estatuses[$i]); + } + if(!is_string($exts[$i])){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: La extensión del teléfono debe ser una cadena de texto. Valor actual: ' . $exts[$i]); + } + if(!is_string($observaciones[$i])){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: Las observaciones del teléfono deben ser una cadena de texto. Valor actual: ' . $observaciones[$i]); + } + + Telefono::create([ + 'contacto_id' => $contactoId, + 'numero' => $numeros[$i], + 'tipo' => $tipos[$i], + 'estatus' => $estatuses[$i], + 'ext' => $exts[$i], + 'observaciones' => $observaciones[$i], + ]); + } + } + } + + private function validateAndCreateRS($contactoId, $redes_sociales, $tipos_redes_sociales) + { + for ($i = 0; $i < count($redes_sociales); $i++) { + if ($redes_sociales[$i] != 'null') { + if(!filter_var($redes_sociales[$i], FILTER_VALIDATE_URL)){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: La red social debe ser una URL válida. Valor actual: ' . $redes_sociales[$i]); + } + if(!in_array($tipos_redes_sociales[$i], ['Facebook', 'Twitter', 'Instagram', 'LinkedIn', 'Página Web'])){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El tipo de red social debe ser "Facebook", "Twitter", "Instagram", "LinkedIn" o "Página Web". Valor actual: ' . $tipos_redes_sociales[$i]); + } + + RedesSociales::create([ + 'contacto_id' => $contactoId, + 'red_social' => $redes_sociales[$i], + 'tipo_red_social' => $tipos_redes_sociales[$i], + ]); + } + } + } + + private function validateAndCreateEmails($contactoId, $correos, $tipos_correos) + { + for ($i = 0; $i < count($correos); $i++) { + if ($correos[$i] != 'null') { + if(!filter_var($correos[$i], FILTER_VALIDATE_EMAIL)){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El correo electrónico debe ser una dirección de correo válida. Valor actual: ' . $correos[$i]); + } + if(!in_array($tipos_correos[$i], ['Personal', 'Oficial'])){ + throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El tipo de correo electrónico debe ser "Personal" o "Oficial". Valor actual: ' . $tipos_correos[$i]); + } + + CorreoContactos::create([ + 'contacto_id' => $contactoId, + 'correo_electronico' => $correos[$i], + 'tipo_correo_electronico' => $tipos_correos[$i], + ]); + } + } + + } } \ No newline at end of file -- GitLab From 85a662174c8a9abba4a71a1e1fa525687398b325 Mon Sep 17 00:00:00 2001 From: Alfonso Rafael Solis Rangel Date: Thu, 30 Jan 2025 09:25:54 -0600 Subject: [PATCH 05/14] Correcciones en las filas --- app/Http/Controllers/ContactoController.php | 33 +++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/app/Http/Controllers/ContactoController.php b/app/Http/Controllers/ContactoController.php index 996d572..4ce7e08 100644 --- a/app/Http/Controllers/ContactoController.php +++ b/app/Http/Controllers/ContactoController.php @@ -563,13 +563,13 @@ public function upload(Request $request) $data = array_map('str_getcsv', explode("\n", $content)); $header = array_shift($data); + $cont = 1; foreach ($data as $row) { if (count($header) !== count($row)) { continue; } $row = array_combine($header, $row); - //TODO: Implementar lo mismo para los demas catalogos $existProfesion = $profesiones->firstWhere('nombre', $row['profesion']); @@ -610,19 +610,20 @@ public function upload(Request $request) $exts = explode(';', $row['ext']); $observaciones = explode(';', $row['observaciones']); - $this->validateAndCreateTelefonos($contacto->id, $numeros, $tipos, $estatuses, $exts, $observaciones); + $this->validateAndCreateTelefonos($contacto->id, $numeros, $tipos, $estatuses, $exts, $observaciones, $cont); // Procesar redes sociales $redes_sociales = explode(';', $row['red_social']); $tipos_redes_sociales = explode(';', $row['tipo_red_social']); - $this->validateAndCreateRS($contacto->id, $redes_sociales, $tipos_redes_sociales); + $this->validateAndCreateRS($contacto->id, $redes_sociales, $tipos_redes_sociales, $cont); // Procesar correos electrónicos $correos = explode(';', $row['correo_electronico']); $tipos_correos = explode(';', $row['tipo_correo_electronico']); - $this->validateAndCreateEmails($contacto->id, $correos, $tipos_correos); + $this->validateAndCreateEmails($contacto->id, $correos, $tipos_correos, $cont); + $cont++; } return redirect()->route('contacto.get')->with('success', 'Importación de contactos almacenada correctamente'); @@ -675,24 +676,24 @@ public function obtenerEventos(Request $request){ return response()->json($eventos); } - private function validateAndCreateTelefonos($contactoId, $numeros, $tipos, $estatuses, $exts, $observaciones) + private function validateAndCreateTelefonos($contactoId, $numeros, $tipos, $estatuses, $exts, $observaciones, $cont) { for ($i = 0; $i < count($numeros); $i++) { if ($numeros[$i] != 'null') { if(!filter_var($numeros[$i], FILTER_VALIDATE_INT)){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El número de teléfono debe ser un número entero. Valor actual: ' . $numeros[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: El número de teléfono debe ser un número entero. Valor actual: ' . $numeros[$i]); } if(!in_array($tipos[$i], ['Directo', 'Particular', 'Celular', 'Conmutador'])){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El tipo de teléfono debe ser "Directo", "Particular", "Celular" o "Conmutador". Valor actual: ' . $tipos[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: El tipo de teléfono debe ser "Directo", "Particular", "Celular" o "Conmutador". Valor actual: ' . $tipos[$i]); } if(!in_array($estatuses[$i], ['Público', 'Privado'])){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El estatus del teléfono debe ser "Público" o "Privado". Valor actual: ' . $estatuses[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: El estatus del teléfono debe ser "Público" o "Privado". Valor actual: ' . $estatuses[$i]); } if(!is_string($exts[$i])){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: La extensión del teléfono debe ser una cadena de texto. Valor actual: ' . $exts[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: La extensión del teléfono debe ser una cadena de texto. Valor actual: ' . $exts[$i]); } if(!is_string($observaciones[$i])){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: Las observaciones del teléfono deben ser una cadena de texto. Valor actual: ' . $observaciones[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: Las observaciones del teléfono deben ser una cadena de texto. Valor actual: ' . $observaciones[$i]); } Telefono::create([ @@ -707,15 +708,15 @@ private function validateAndCreateTelefonos($contactoId, $numeros, $tipos, $esta } } - private function validateAndCreateRS($contactoId, $redes_sociales, $tipos_redes_sociales) + private function validateAndCreateRS($contactoId, $redes_sociales, $tipos_redes_sociales, $cont) { for ($i = 0; $i < count($redes_sociales); $i++) { if ($redes_sociales[$i] != 'null') { if(!filter_var($redes_sociales[$i], FILTER_VALIDATE_URL)){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: La red social debe ser una URL válida. Valor actual: ' . $redes_sociales[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: La red social debe ser una URL válida. Valor actual: ' . $redes_sociales[$i]); } if(!in_array($tipos_redes_sociales[$i], ['Facebook', 'Twitter', 'Instagram', 'LinkedIn', 'Página Web'])){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El tipo de red social debe ser "Facebook", "Twitter", "Instagram", "LinkedIn" o "Página Web". Valor actual: ' . $tipos_redes_sociales[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: El tipo de red social debe ser "Facebook", "Twitter", "Instagram", "LinkedIn" o "Página Web". Valor actual: ' . $tipos_redes_sociales[$i]); } RedesSociales::create([ @@ -727,15 +728,15 @@ private function validateAndCreateRS($contactoId, $redes_sociales, $tipos_redes_ } } - private function validateAndCreateEmails($contactoId, $correos, $tipos_correos) + private function validateAndCreateEmails($contactoId, $correos, $tipos_correos, $cont) { for ($i = 0; $i < count($correos); $i++) { if ($correos[$i] != 'null') { if(!filter_var($correos[$i], FILTER_VALIDATE_EMAIL)){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El correo electrónico debe ser una dirección de correo válida. Valor actual: ' . $correos[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: El correo electrónico debe ser una dirección de correo válida. Valor actual: ' . $correos[$i]); } if(!in_array($tipos_correos[$i], ['Personal', 'Oficial'])){ - throw new \Exception('Error en la fila ' . $i+1 . ' del archivo CSV: El tipo de correo electrónico debe ser "Personal" o "Oficial". Valor actual: ' . $tipos_correos[$i]); + throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: El tipo de correo electrónico debe ser "Personal" o "Oficial". Valor actual: ' . $tipos_correos[$i]); } CorreoContactos::create([ -- GitLab From fea492c25ad6adf4020770e9a03d56fa21bbecc0 Mon Sep 17 00:00:00 2001 From: Alfonso Rafael Solis Rangel Date: Thu, 30 Jan 2025 09:36:06 -0600 Subject: [PATCH 06/14] En caso de que haya un 0 se elimina --- app/Http/Controllers/ContactoController.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Http/Controllers/ContactoController.php b/app/Http/Controllers/ContactoController.php index 4ce7e08..b2b0055 100644 --- a/app/Http/Controllers/ContactoController.php +++ b/app/Http/Controllers/ContactoController.php @@ -696,6 +696,10 @@ private function validateAndCreateTelefonos($contactoId, $numeros, $tipos, $esta throw new \Exception('Error en la fila ' . $cont . ' del archivo CSV: Las observaciones del teléfono deben ser una cadena de texto. Valor actual: ' . $observaciones[$i]); } + if($exts[$i] === 0 || $exts[$i] === '0'){ + $exts[$i] = ""; + } + Telefono::create([ 'contacto_id' => $contactoId, 'numero' => $numeros[$i], -- GitLab From 732760cf1436898cedc6e23db5247244fd69626b Mon Sep 17 00:00:00 2001 From: Alfonso Rafael Solis Rangel Date: Mon, 10 Feb 2025 15:27:29 -0600 Subject: [PATCH 07/14] Movimientos en los filtros --- app/Exports/ContactosExport.php | 42 ++++++--- app/Http/Controllers/ReporteController.php | 13 ++- app/Models/Grupos.php | 5 ++ .../views/adminGen/contactos/export.blade.php | 85 ++++++++++++++----- routes/web.php | 1 + 5 files changed, 110 insertions(+), 36 deletions(-) diff --git a/app/Exports/ContactosExport.php b/app/Exports/ContactosExport.php index 04d6da0..95bce29 100644 --- a/app/Exports/ContactosExport.php +++ b/app/Exports/ContactosExport.php @@ -5,6 +5,7 @@ use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithHeadings; use App\Models\Contacto; +use App\Models\Grupos; class ContactosExport implements FromCollection, WithHeadings { @@ -54,29 +55,51 @@ public function headings(): array private function applyFilters($query) { - if (!empty($this->filters['listas'])) { +/* if (!empty($this->filters['listas'])) { $query->orWhereHas('listas', function ($q) { $q->whereIn('listas.id', $this->filters['listas']); }); - } + } */ - if (!empty($this->filters['caracteristicas'])) { + /* if (!empty($this->filters['caracteristicas'])) { $query->orWhereHas('caracteristicas', function ($q) { $q->whereIn('caracteristicas.id', $this->filters['caracteristicas']); }); + } */ + + if(!empty($this->filters['subgrupos'])){ + $query->orWhereHas('subgrupos', function ($q) { + $q->whereIn('subgrupos.id', $this->filters['subgrupos']); + }); } - if (!empty($this->filters['grupos'])) { - $query->orWhereHas('grupos', function ($q) { - $q->whereIn('grupos.id', $this->filters['grupos']); + if(!empty($this->filters['grupos'])){ + $grupoId = $this->filters['grupos']; + $subgruposIds = Grupos::find($grupoId)->subgrupos->pluck('id')->toArray(); + $query->where(function($query) use ($grupoId, $subgruposIds) { + $query->whereHas('grupos', function ($q) use ($grupoId) { + $q->where('grupos.id', $grupoId); + })->orWhereHas('subgrupos', function ($q) use ($subgruposIds) { + $q->whereIn('subgrupos.id', $subgruposIds); + }); }); } - if (!empty($this->filters['cargos'])) { + if (!empty($this->filters['fechaInicio']) && !empty($this->filters['fechaFin'])) { + // Filtrar por rango de fechas (mes/día) + $fechaInicio = $this->filters['fechaInicio']; + $fechaFin = $this->filters['fechaFin']; + $query->where(function ($query) use ($fechaInicio, $fechaFin) { + $query->whereRaw("CONCAT(LPAD(mes_cump, 2, '0'), '-', LPAD(dia_cump, 2, '0')) >= ?", [$fechaInicio]) + ->whereRaw("CONCAT(LPAD(mes_cump, 2, '0'), '-', LPAD(dia_cump, 2, '0')) <= ?", [$fechaFin]); + }); + } + + /* if (!empty($this->filters['cargos'])) { $query->orWhereHas('cargo', function ($q) { $q->whereIn('cargos.id', $this->filters['cargos']); }); - } + } */ } private function formatContactoData($contacto) @@ -113,7 +136,6 @@ private function formatContactoData($contacto) 'Tipo' => $contacto->telefonos->pluck('tipo')->join(', ') ?? 'N/A', 'Estatus' => $contacto->telefonos->pluck('estatus')->join(', ') ?? 'N/A', 'Extensión' => $contacto->telefonos->pluck('ext')->join(', ') ?? 'N/A', - 'ID Radio' => $contacto->telefonos->pluck('id_radio')->join(', ') ?? 'N/A', 'Observaciones' => $contacto->telefonos->pluck('observaciones')->join(', ') ?? 'N/A', ]); break; @@ -146,7 +168,7 @@ private function getExtraHeadings() $headings[] = 'Cumpleaños'; break; case 'telefonos': - $headings = array_merge($headings, ['Número de teléfono', 'Tipo', 'Estatus', 'Extensión', 'ID Radio', 'Observaciones']); + $headings = array_merge($headings, ['Número de teléfono', 'Tipo', 'Estatus', 'Extensión', 'Observaciones']); break; case 'conyuge': $headings[] = 'Cónyuge'; diff --git a/app/Http/Controllers/ReporteController.php b/app/Http/Controllers/ReporteController.php index 185df6d..e839a4c 100644 --- a/app/Http/Controllers/ReporteController.php +++ b/app/Http/Controllers/ReporteController.php @@ -93,12 +93,19 @@ public function export(Request $request) $extraFields = $request->input('exportar', []); $filters = [ 'listas' => $request->input('listas', []), - 'caracteristicas' => $request->input('caracteristicas', []), - 'grupos' => $request->input('grupos', []), - 'cargos' => $request->input('cargos', []), + 'subgrupos' => $request->input('subgrupos', []), + 'grupos' => $request->input('grupo'), + 'fechaInicio' => $request->input('fechaInicio'), + 'fechaFin' => $request->input('fechaFin'), ]; // TODO: Crear archivos de exportacion: PDF, Excel return Excel::download(new ContactosExport($contactIds, $extraFields, $filters), 'contactos.xlsx'); //dd($request->all()); } + + public function getSubgrupos(Int $id) + { + $grupo = Grupos::find($id); + return response()->json($grupo->subgrupos); + } } diff --git a/app/Models/Grupos.php b/app/Models/Grupos.php index 4267462..8624fc7 100644 --- a/app/Models/Grupos.php +++ b/app/Models/Grupos.php @@ -31,6 +31,11 @@ public function contactos(): BelongsToMany { return $this->belongsToMany(Contacto::class, 'contactos_grupos', 'contacto_id', 'grupo_id'); } + + public function subgrupos(): HasMany + { + return $this->hasMany(Subgrupo::class, 'grupo_id'); + } public $timestamps = false; } diff --git a/resources/views/adminGen/contactos/export.blade.php b/resources/views/adminGen/contactos/export.blade.php index aa4e64c..3cb118d 100644 --- a/resources/views/adminGen/contactos/export.blade.php +++ b/resources/views/adminGen/contactos/export.blade.php @@ -17,7 +17,7 @@
-
+ -
+ + + +
+ + +
+ +
- @foreach($grupos as $grupo) @endforeach -
+ +
+ +
+ + +
+
+
- +
+ +
+ + +
+
+ + + -
- - - -
- - -
+
-->
@@ -147,7 +165,7 @@ class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md" let contactosSeleccionados = []; let listasSeleccion = []; let caracteristicasSeleccion = []; - let gruposSeleccion = []; + let subgruposSeleccion = []; let cargosSeleccion = []; let exportarSeleccion = []; @@ -218,15 +236,21 @@ function eliminarContacto(contactoId) { function logData() { const select = document.getElementById('archivo'); const selectedOption = select.options[select.selectedIndex]; + + const fechaInicio = document.getElementById('fechaInicio').value; + const fechaFin = document.getElementById('fechaFin').value; const data = { contactos: contactosSeleccionados, listas: listasSeleccion, caracteristicas: caracteristicasSeleccion, - grupos: gruposSeleccion, + subgrupos: subgruposSeleccion, cargos: cargosSeleccion, exportar: exportarSeleccion, archivo: selectedOption.value, + grupo: document.getElementById('grupos').value, + fechaInicio: fechaInicio ? new Date(fechaInicio).toISOString().slice(5, 10) : null, + fechaFin: fechaFin ? new Date(fechaFin).toISOString().slice(5, 10) : null, }; fetch('/reportes/contactos/exportar', { @@ -259,6 +283,21 @@ function logData() { showToast(err.message || 'Error al descargar el archivo', 'Error', 'error'); }); } + + async function cargarSubgrupos(grupoId) { + const response = await fetch(`/reportes/subgrupos/${grupoId}`); + const subgrupos = await response.json(); + + const subgruposSelect = document.getElementById('subgrupos'); + subgruposSelect.innerHTML = ''; // Limpiar los subgrupos previos + + subgrupos.forEach(subgrupo => { + const option = document.createElement('option'); + option.value = subgrupo.id; + option.textContent = subgrupo.nombre; + subgruposSelect.appendChild(option); + }); + }