diff --git a/app/Exports/ContactosExport.php b/app/Exports/ContactosExport.php index 390a244881266455cf1bac6ab4995be488e3387d..1e77de1863f112e7d96eaa08984ee3aa3f06dc9e 100644 --- a/app/Exports/ContactosExport.php +++ b/app/Exports/ContactosExport.php @@ -71,33 +71,33 @@ public function headings(): array private function applyFilters($query) { - /* if(!empty($this->filters['subgrupos'])){ + if(count($this->filters['subgrupos']) > 2){ $query->orWhereHas('subgrupos', function ($q) { $q->whereIn('subgrupos.id', $this->filters['subgrupos']); }); - } */ - - if (!empty($this->filters['subgrupos'])) { - $query->orWhereHas('subgrupos', function ($q) { - $q->whereIn('subgrupos.id', $this->filters['subgrupos']); - }); - } elseif (!empty($this->filters['grupos'])) { - $grupoId = $this->filters['grupos']; - $subgruposIds = Grupos::find(153)->subgrupos->pluck('id')->toArray(); - - $query->where(function ($query) use ($grupoId, $subgruposIds) { - // Contactos directamente en el grupo - $query->orWhereHas('grupos', function ($q) use ($grupoId) { - $q->where('grupos.id', $grupoId); + }else{ + if (!empty($this->filters['subgrupos'])) { + $query->orWhereHas('subgrupos', function ($q) { + $q->whereIn('subgrupos.id', $this->filters['subgrupos']); }); - - // Contactos en subgrupos del grupo (solo si hay subgrupos) - if (!empty($subgruposIds)) { - $query->orWhereHas('subgrupos', function ($q) use ($subgruposIds) { - $q->whereIn('subgrupos.id', $subgruposIds); + } elseif (!empty($this->filters['grupos'])) { + $grupoId = $this->filters['grupos']; + $subgruposIds = Grupos::find($grupoId)->subgrupos->pluck('id')->toArray(); + + $query->where(function ($query) use ($grupoId, $subgruposIds) { + // Contactos directamente en el grupo + $query->orWhereHas('grupos', function ($q) use ($grupoId) { + $q->where('grupos.id', $grupoId); }); - } - }); + + // Contactos en subgrupos del grupo (solo si hay subgrupos) + if (!empty($subgruposIds)) { + $query->orWhereHas('subgrupos', function ($q) use ($subgruposIds) { + $q->whereIn('subgrupos.id', $subgruposIds); + }); + } + }); + } } if ($this->filters['mesInicio'] != "NaN" && $this->filters['diaInicio'] != "NaN") { diff --git a/app/Exports/ListasExport.php b/app/Exports/ListasExport.php new file mode 100644 index 0000000000000000000000000000000000000000..5175fb491a5381f3d56a6f06843c95c239663e7c --- /dev/null +++ b/app/Exports/ListasExport.php @@ -0,0 +1,145 @@ +lista_id = $lista_id; + $this->extraFields = $extraFields; + } + + public function collection() + { + $lista = Lista::with(['grupos', 'subgrupos', 'contactos'])->find($this->lista_id); + $contactos = new Collection(); + $contactos = $contactos->merge($lista->contactos); + + foreach ($lista->grupos as $grupo) { + $contactos = $contactos->merge($grupo->contactos); + + foreach ($grupo->subgrupos as $subgrupo) { + $contactos = $contactos->merge($subgrupo->contactos); + } + } + foreach($lista->subgrupos as $subgrupo){ + $contactos = $contactos->merge($subgrupo->contactos); + } + + $contactos = $contactos->unique('id'); + + return $contactos->map(function($contacto){ + return $this->formatContactoData($contacto); + }); + } + + public function headings(): array + { + $defaultHeadings = ['Profesión', 'Nombre', 'Apellido Paterno', 'Apellido Materno', 'Cargo', 'Descripción del cargo', 'Grupo', 'Subgrupo']; + $extraHeadings = $this->getExtraHeadings(); + return array_merge($defaultHeadings, $extraHeadings); + } + + private function formatContactoData($contacto) + { + $defaultData = [ + 'Profesión' => $contacto->profesion->abreviatura ?? 'N/A', + 'Nombre' => $contacto->nombre, + 'Apellido Paterno' => $contacto->ap_paterno, + 'Apellido Materno' => $contacto->ap_materno ?? '', + 'Cargo' => $contacto->cargo->nombre ?? 'N/A', + 'Descripción del cargo' => $contacto->cargo_desc ?? 'N/A', + 'Grupo' => $contacto->grupos->pluck('nombre')[0] ?? 'N/A', + 'Subgrupo' => $contacto->subgrupos->pluck('nombre')[0] ?? 'N/A', + ]; + + $extraData = []; + $fields = $this->extraFields; + + if (in_array('todos', $fields)) { + $fields = ['domicilio', 'cumpleanos', 'telefonos', 'conyuge', 'email']; + } + + foreach ($fields as $field) { + switch ($field) { + case 'domicilio': + $extraData = array_merge($extraData, [ + 'Domicilio Oficial' => $contacto->domicilio_oficial ?? 'N/A', + 'Código Postal' => $contacto->codigo_postal ?? 'N/A', + 'Localidad Oficial' => $contacto->localidad_oficial ?? 'N/A', + 'Municipio Oficial' => $contacto->municipio_oficial ?? 'N/A', + 'Estado' => $contacto->estado ?? 'N/A', + 'País' => $contacto->pais ?? 'N/A', + ]); + break; + case 'cumpleanos': + $extraData['Cumpleaños'] = $contacto->mes_cump && $contacto->dia_cump + ? $contacto->mes_cump . '/' . $contacto->dia_cump + : 'N/A'; + break; + case 'telefonos': + $extraData = array_merge($extraData, [ + 'Número de teléfono' => $contacto->telefonos->pluck('numero')->join(', ') ?? 'N/A', + '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', + 'Observaciones' => $contacto->telefonos->pluck('observaciones')->join(', ') ?? 'N/A', + ]); + break; + case 'conyuge': + $extraData['Cónyuge'] = $contacto->pareja + ? $contacto->pareja->nombre . ' ' . $contacto->pareja->ap_paterno . ' ' . $contacto->pareja->ap_materno + : 'N/A'; + break; + case 'email': + $extraData = array_merge($extraData, [ + 'Correo Electrónico' => $contacto->correos->pluck('correo_electronico')->join(', ') ?? 'N/A', + 'Tipo de Correo Electrónico' => $contacto->correos->pluck('tipo_correo_electronico')->join(', ') ?? 'N/A', + ]); + break; + } + } + + return array_merge($defaultData, $extraData); + } + + private function getExtraHeadings() + { + $headings = []; + $fields = $this->extraFields; + + if (in_array('todos', $fields)) { + $fields = ['domicilio', 'cumpleanos', 'telefonos', 'conyuge', 'email']; + } + + foreach ($fields as $field) { + switch ($field) { + case 'domicilio': + $headings = array_merge($headings, ['Domicilio Oficial', 'Código Postal', 'Localidad Oficial', 'Municipio Oficial', 'Estado', 'País']); + break; + case 'cumpleanos': + $headings[] = 'Cumpleaños'; + break; + case 'telefonos': + $headings = array_merge($headings, ['Número de teléfono', 'Tipo', 'Estatus', 'Extensión', 'Observaciones']); + break; + case 'conyuge': + $headings[] = 'Cónyuge'; + break; + case 'email': + $headings = array_merge($headings, ['Correo Electrónico', 'Tipo de Correo Electrónico']); + break; + } + } + return $headings; + } +} diff --git a/app/Http/Controllers/ContactoController.php b/app/Http/Controllers/ContactoController.php index b2b0055eb782afa5ef988e0c464bd8c134269cf0..753868ec521c2af6d482fd32d5c1c98114005c3e 100644 --- a/app/Http/Controllers/ContactoController.php +++ b/app/Http/Controllers/ContactoController.php @@ -26,7 +26,7 @@ class ContactoController extends Controller */ public function index() { - $contactos = Contacto::with('profesion', 'cargo')->get(); + $contactos = Contacto::with('profesion', 'cargo', 'grupos', 'subgrupos')->get(); return view('adminGen.contactos.index', compact('contactos')); } @@ -646,7 +646,7 @@ public function obtenerEventos(Request $request){ }); } }) - ->select('id', 'nombre', 'ap_paterno', 'ap_materno', 'mes_cump', 'dia_cump') + ->select('id', 'nombre', 'ap_paterno', 'ap_materno', 'mes_cump', 'dia_cump', 'cargo_desc') ->get(); // Obtener aniversarios de instituciones en el rango de fechas visible @@ -661,7 +661,8 @@ public function obtenerEventos(Request $request){ 'title' => $contacto->nombre . ' ' . $contacto->ap_paterno. ' ' . $contacto->ap_materno, 'start' => now()->year . '-' . str_pad($contacto->mes_cump, 2, '0', STR_PAD_LEFT) . '-' . str_pad($contacto->dia_cump, 2, '0', STR_PAD_LEFT), 'className' => 'success', - 'description' => 'Cumpleaños de ' . $contacto->nombre, + 'cargo' => $contacto->cargo->nombre ?? 'Sin información', + 'description' => $contacto->cargo_desc ?? 'Sin información', ]; })->merge($aniversarios->map(function ($institucion) { return [ diff --git a/app/Http/Controllers/ReporteController.php b/app/Http/Controllers/ReporteController.php index 35417cefe40338ee4666cc0d53ccdde0f71eddb6..c20c10041c454f9e5ab27c8c7ba6ba6e8d53652d 100644 --- a/app/Http/Controllers/ReporteController.php +++ b/app/Http/Controllers/ReporteController.php @@ -10,10 +10,13 @@ use Illuminate\Http\Request; use App\Exports\ContactosExport; +use App\Exports\ListasExport; +use App\Models\Subgrupo; use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Support\Facades\Storage; use Maatwebsite\Excel\Facades\Excel; use ZipArchive; +use Illuminate\Support\Str; class ReporteController extends Controller { @@ -26,7 +29,8 @@ public function index() $caracteristicas = Caracteristicas::get(); $grupos = Grupos::get(); $listas = Lista::get(); - return view('adminGen.contactos.export', compact('cargos', 'caracteristicas', 'grupos', 'listas')); + $subgrupos = Subgrupo::get(); + return view('adminGen.contactos.export', compact('cargos', 'caracteristicas', 'grupos', 'listas', 'subgrupos')); } /** @@ -88,11 +92,15 @@ public function find(Request $request) public function export(Request $request) { if(is_null($request->archivo)){ - return response()->json(['Error, No seleccionaste un archivo de exportación valido.'], 400); + return response()->json(['message' => 'No seleccionaste un archivo de exportación valido.'], 400); } $contactIds = array_column($request->input('contactos', []), 'id'); $extraFields = $request->input('exportar', []); + if(!$extraFields){ + return response()->json(['message' => 'No seleccionaste campos a exportar.'], 400); + } + $filters = [ 'listas' => $request->input('listas', []), 'subgrupos' => $request->input('subgrupos', []), @@ -102,34 +110,39 @@ public function export(Request $request) 'mesFin' => $request->input('mesFin'), 'diaFin' => $request->input('diaFin'), ]; - $export = new ContactosExport($contactIds, $extraFields, $filters); - if($request->archivo == 'excel'){ - return Excel::download($export, 'contactos.xlsx'); - }else if($request->archivo == 'pdf'){ - $pdf = Pdf::loadView('adminGen.contactos.contactos_pdf', ['contactos' => $export->collection()])->setPaper('A1', 'landscape');; - return $pdf->download('contactos.pdf'); - }else if($request->archivo == 'ambos'){ - $excelPath = storage_path('app/public/contactos.xlsx'); - $pdfPath = storage_path('app/public/contactos.pdf'); - - Excel::store($export, 'public/contactos.xlsx'); - $pdf = Pdf::loadView('adminGen.contactos.contactos_pdf', ['contactos' => $export->collection()])->setPaper('A1', 'landscape'); - Storage::put('public/contactos.pdf', $pdf->output()); - - // Crear archivo ZIP - $zipPath = storage_path('app/public/contactos.zip'); - $zip = new ZipArchive; - if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) { - $zip->addFile($excelPath, 'contactos.xlsx'); - $zip->addFile($pdfPath, 'contactos.pdf'); - $zip->close(); + try{ + $export = new ContactosExport($contactIds, $extraFields, $filters); + if($request->archivo == 'excel'){ + return Excel::download($export, 'contactos.xlsx'); + }else if($request->archivo == 'pdf'){ + $pdf = Pdf::loadView('adminGen.contactos.contactos_pdf', ['contactos' => $export->collection()])->setPaper('A1', 'landscape'); + return $pdf->download('contactos.pdf'); + }else if($request->archivo == 'ambos'){ + $excelPath = storage_path('app/public/contactos.xlsx'); + $pdfPath = storage_path('app/public/contactos.pdf'); + + Excel::store($export, 'public/contactos.xlsx'); + $pdf = Pdf::loadView('adminGen.contactos.contactos_pdf', ['contactos' => $export->collection()])->setPaper('A1', 'landscape'); + Storage::put('public/contactos.pdf', $pdf->output()); + + // Crear archivo ZIP + $zipPath = storage_path('app/public/contactos.zip'); + $zip = new ZipArchive; + if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) { + $zip->addFile($excelPath, 'contactos.xlsx'); + $zip->addFile($pdfPath, 'contactos.pdf'); + $zip->close(); + } + + // Descargar archivo ZIP + return response()->download($zipPath)->deleteFileAfterSend(true); + }else{ + return response()->json(['Error, no seleccionaste un archivo de exportación valido.'], 400); } - - // Descargar archivo ZIP - return response()->download($zipPath)->deleteFileAfterSend(true); - }else{ - return response()->json(['Error, No seleccionaste un archivo de exportación valido.'], 400); + }catch(\Exception $e){ + return response()->json(['message'=> $e->getMessage()], 500); } + } public function getSubgrupos(Int $id) @@ -137,4 +150,48 @@ public function getSubgrupos(Int $id) $grupo = Grupos::find($id); return response()->json($grupo->subgrupos); } + + public function exportListas(Request $request) + { + try{ + if(is_null($request->archivo)){ + return response()->json(['message' => 'No seleccionaste un archivo de exportación valido.'], 400); + } + + $extraFields = $request->input('exportar', []); + if(!$extraFields){ + return response()->json(['message' => 'No seleccionaste campos a exportar.'], 400); + } + $lista_id = $request->input('id'); + + $export = new ListasExport($lista_id, $extraFields); + $uuid = Str::uuid()->toString(); + if($request->archivo == 'excel'){ + return Excel::download($export, $uuid . '.xlsx'); + }else if($request->archivo == 'pdf'){ + $pdf = Pdf::loadView('adminGen.contactos.contactos_pdf', ['contactos' => $export->collection()])->setPaper('A1', 'landscape'); + return $pdf->download($uuid.'.pdf'); + }else if($request->archivo == 'ambos'){ + $excelPath = storage_path('app/public/contactos.xlsx'); + $pdfPath = storage_path('app/public/contactos.pdf'); + + Excel::store($export, 'public/contactos.xlsx'); + $pdf = Pdf::loadView('adminGen.contactos.contactos_pdf', ['contactos' => $export->collection()])->setPaper('A1', 'landscape'); + Storage::put('public/contactos.pdf', $pdf->output()); + $zipPath = storage_path('app/public/'.$uuid.'.zip'); + $zip = new ZipArchive; + if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) { + $zip->addFile($excelPath, $uuid.'.xlsx'); + $zip->addFile($pdfPath, $uuid.'.pdf'); + $zip->close(); + } + + return response()->download($zipPath)->deleteFileAfterSend(true); + }else{ + return response()->json(['message' => 'no seleccionaste un archivo de exportación valido.'], 400); + } + }catch(\Exception $e){ + return response()->json(['message' => $e->getMessage()], 500); + } + } } diff --git a/app/Models/Subgrupo.php b/app/Models/Subgrupo.php index 0545c6ee742a9e7f73bdf84ef93bf2ad04d4c267..03b1ef21b783180b48bd90ff6b80a95b32885187 100644 --- a/app/Models/Subgrupo.php +++ b/app/Models/Subgrupo.php @@ -34,6 +34,6 @@ public function listas(): BelongsToMany public function contactos(): BelongsToMany { - return $this->belongsToMany(Contacto::class, 'contactos_subgrupos', 'contacto_id', 'subgrupo_id'); + return $this->belongsToMany(Contacto::class, 'contactos_subgrupos', 'subgrupo_id', 'contacto_id'); } } diff --git a/resources/views/adminGen/contactos/export.blade.php b/resources/views/adminGen/contactos/export.blade.php index 39c6d0cfde094a4c7a895604c65d8243c73a985c..2e41bce74d262ca4742f6c36e04ed2bb019bf004 100644 --- a/resources/views/adminGen/contactos/export.blade.php +++ b/resources/views/adminGen/contactos/export.blade.php @@ -1,6 +1,6 @@ - +
@@ -14,8 +14,8 @@

Nota: Este módulo aun se encuentra en desarrollo, por lo que podría haber errores.

-
-
+
+
@@ -31,9 +31,9 @@ class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md"
-
+
+
+
@@ -56,31 +59,16 @@ class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md"
-
+
- - -
-
+
@@ -125,11 +113,26 @@ class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md" + diff --git a/resources/views/adminGen/contactos/index.blade.php b/resources/views/adminGen/contactos/index.blade.php index 13e9910637bce8e251af442422e4b85cbf559a35..55eb066ee3d0786ec9d2767910660e7d67b73647 100644 --- a/resources/views/adminGen/contactos/index.blade.php +++ b/resources/views/adminGen/contactos/index.blade.php @@ -47,7 +47,10 @@ } else { nombreCompleto = contacto.nombre; } - return [nombreCompleto, renderParameter(contacto.ap_paterno), renderParameter(contacto.ap_materno), renderParameter(contacto.cargo?.nombre), renderActions(contacto.id)]; + + return [nombreCompleto, renderParameter(contacto.ap_paterno), renderParameter(contacto.ap_materno), renderParameter(contacto.cargo?.nombre), + renderParameter(contacto.cargo_desc), renderParameter(contacto.grupos.map(grupo => grupo.nombre).join(', ')), + renderParameter(contacto.subgrupos.map(subgrupo => subgrupo.nombre).join(', ')), renderActions(contacto.id)]; }); function renderActions(id) { @@ -64,7 +67,7 @@ function renderActions(id) { } function renderParameter(parametro) { - if(parametro === null || parametro === undefined){ + if(parametro === null || parametro === undefined || parametro === ""){ return `Sin información`; }else{ return parametro; @@ -74,7 +77,7 @@ function renderParameter(parametro) { document.addEventListener('DOMContentLoaded', () => { const datatable = new simpleDatatables.DataTable('#myTable', { data: { - headings: ['Nombre', 'Apellido paterno', 'Apellido materno', 'Cargo', 'Acciones'], + headings: ['Nombre', 'Apellido paterno', 'Apellido materno', 'Cargo', 'Descripción del cargo', 'Grupos', 'Subgrupos', 'Acciones'], data: data }, perPage: 10, diff --git a/resources/views/adminGen/listas/show.blade.php b/resources/views/adminGen/listas/show.blade.php index bc79f7aadbee4585324fa992cec354f118c48638..bf78bc4540d06bf544682a03e36c1ea07c02d032 100644 --- a/resources/views/adminGen/listas/show.blade.php +++ b/resources/views/adminGen/listas/show.blade.php @@ -14,6 +14,58 @@
+
+
+
Exportar datos
+
+
+
+ + +
+ + +
+ + +
+ + +
+ +
+ + +
+
+
+
+ + +
+ +
+ +
+
+
Grupos
@@ -93,5 +145,153 @@ class="btn btn-primary">
+
- + + + + + + + + + \ No newline at end of file diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 0be8d579d446225ca6d3c1c697cbacce23b39bd7..b7096fbeea19d68836e4d9d9b4530a0b8211870c 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -56,7 +56,14 @@ class="form-input" placeholder="Event Start Date" x-model="params.start"
- + + +
+
+
+
@@ -83,6 +90,7 @@ class="form-input" placeholder="Event Start Date" x-model="params.start" start: '', end: '', description: '', + cargo: '', type: 'primary' }), params: { @@ -91,6 +99,7 @@ class="form-input" placeholder="Event Start Date" x-model="params.start" start: '', end: '', description: '', + cargo: '', type: 'primary' }, isAddEventModal: false, @@ -157,6 +166,7 @@ class="form-input" placeholder="Event Start Date" x-model="params.start" end: obj.start, type: obj.classNames ? obj.classNames[0] : 'primary', description: obj.extendedProps ? obj.extendedProps.description : '', + cargo: obj.extendedProps ? obj.extendedProps.cargo : '', }; this.minStartDate = new Date(); this.minEndDate = new Date();