<?php class LegalController { private $modelo; public function __construct() { require_once 'models/LegalModel.php'; $this->modelo = new LegalModel(); } public function cargaMasiva() { $this->verificarSesion(); $resultados = []; $procesados = 0; $errores = []; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['archivo_csv'])) { $file = $_FILES['archivo_csv']; if ($file['error'] !== UPLOAD_ERR_OK) { $errores[] = 'Error al subir el archivo.'; } else { $handle = fopen($file['tmp_name'], 'r'); $bom = fread($handle, 3); if ($bom !== "\xEF\xBB\xBF") rewind($handle); $header = fgetcsv($handle, 0, ','); $header = array_map(fn($h) => strtolower(trim($h)), $header); // ═══════════════════════════════════════════════════════════ // PASO 1: AGRUPAR POR CÉDULA // ═══════════════════════════════════════════════════════════ $empleados_agrupados = []; while (($row = fgetcsv($handle, 0, ',')) !== false) { if (count($row) < 2) continue; $data = @array_combine($header, $row); if (!$data) continue; // Validar cédula (requerido) $cedula = strtoupper(trim($data['cedula'] ?? '')); if (empty($cedula)) { $errores[] = "Fila omitida: cédula vacía"; continue; } // Si es la primera vez que vemos esta cédula, guardamos datos del empleado if (!isset($empleados_agrupados[$cedula])) { $empleados_agrupados[$cedula] = [ 'datos_empleado' => [ 'fingreso' => $data['fingreso'] ?? date('Y-m-d'), 'ident' => $cedula, 'nombre' => strtoupper(trim($data['nombre'] ?? '')), 'ccosto' => $data['ccosto'] ?? '', 'area' => $data['area'] ?? '', 'cargo' => $data['cargo'] ?? '', 'tallaPant' => strtoupper(trim($data['tallapant'] ?? 'NO APLICA')), 'tallaCami' => strtoupper(trim($data['tallacami'] ?? 'NO APLICA')), 'tallaBot' => strtoupper(trim($data['tallabot'] ?? 'NO APLICA')), 'tallaChaq' => strtoupper(trim($data['tallachaq'] ?? 'NO APLICA')), 'tallaImp' => strtoupper(trim($data['tallaimp'] ?? 'NO APLICA')), 'tpEntrega' => $data['tpentrega'] ?? 'Primera Entrega', 'tpContrato' => $data['tpcontrato'] ?? 'DIRECTO', ], 'codigos_epp' => [] ]; } // Agregar códigos EPP de esta fila (CON LIMPIEZA) if (!empty($data['codigo_epp'])) { // ✅ LIMPIAR pipes problemáticos $codigo_epp_limpio = $this->limpiarPipes($data['codigo_epp']); $cantidad_limpia = $this->limpiarPipes($data['cantidad'] ?? '1'); // Solo procesar si quedó algo después de limpiar if (!empty($codigo_epp_limpio)) { $codigos = array_map('trim', explode('|', $codigo_epp_limpio)); $cantidades = array_map('trim', explode('|', $cantidad_limpia)); // Si solo hay una cantidad, aplicarla a todos los códigos if (count($cantidades) == 1 && count($codigos) > 1) { $cantidades = array_fill(0, count($codigos), $cantidades[0]); } foreach ($codigos as $idx => $codigo) { if (!empty($codigo)) { $empleados_agrupados[$cedula]['codigos_epp'][] = [ 'codigo' => strtoupper($codigo), 'cantidad' => intval($cantidades[$idx] ?? 1) ]; } } } } } fclose($handle); // ═══════════════════════════════════════════════════════════ // PASO 2: PROCESAR EMPLEADOS AGRUPADOS // ═══════════════════════════════════════════════════════════ foreach ($empleados_agrupados as $cedula => $data) { $emp = $data['datos_empleado']; $dotaciones = $data['codigos_epp']; // Validar que haya al menos un EPP if (empty($dotaciones)) { $resultados[] = [ 'cedula' => $cedula, 'nombre' => $emp['nombre'], 'ok' => false, 'error' => 'No se especificó ningún código EPP válido' ]; continue; } // Inserción dual (Empleado + Dotación) $res = $this->modelo->insertarEmpleadoConDotacion($emp, $dotaciones); if ($res['success']) { $procesados++; $resultados[] = [ 'cedula' => $cedula, 'nombre' => $emp['nombre'], 'ok' => true, 'epp_count' => count($dotaciones) ]; } else { $resultados[] = [ 'cedula' => $cedula, 'nombre' => $emp['nombre'], 'ok' => false, 'error' => $res['error'] ]; } } } } include 'views/legal/masiva_legal.php'; } /** * Limpia pipes problemáticos de strings generados desde Excel * Elimina: pipes al inicio, pipes al final, pipes duplicados */ private function limpiarPipes($texto) { if (empty($texto)) return ''; // 1. Reemplazar múltiples pipes consecutivos por uno solo $texto = preg_replace('/\|+/', '|', $texto); // 2. Eliminar pipe al inicio $texto = ltrim($texto, '|'); // 3. Eliminar pipe al final $texto = rtrim($texto, '|'); // 4. Trim general $texto = trim($texto); return $texto; } public function descargarPlantilla() { header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=plantilla_legal_dotacion.csv'); $out = fopen('php://output', 'w'); fputs($out, "\xEF\xBB\xBF"); // Cabecera: ahora usa codigo_epp en lugar de nombre_epp fputcsv($out, ['fingreso','cedula','nombre','ccosto','area','cargo', 'tallaPant','tallaCami','tallaBot','tallaChaq','tallaImp', 'tpEntrega','tpContrato','codigo_epp','cantidad']); // Ejemplo 1: Un solo EPP fputcsv($out, ['2026-02-19','10203040','JUAN PEREZ','ADMINISTRACION','LEGAL', 'AUXILIAR','M','M','40','M','M','Primera Entrega','DIRECTO', '40001','2']); // Ejemplo 2: Múltiples EPP en una sola fila (separados por pipe |) fputcsv($out, ['2026-02-20','20304050','MARIA LOPEZ','ADMINISTRACION','LEGAL', 'ASISTENTE','S','S','38','S','S','Primera Entrega','DIRECTO', '40001|40002|40003','2|1|3']); // Ejemplo 3: Múltiples EPP con la misma cantidad fputcsv($out, ['2026-02-21','30405060','CARLOS GOMEZ','ADMINISTRACION','LEGAL', 'COORDINADOR','L','L','42','L','L','Primera Entrega','DIRECTO', '40001|40002','1']); // Ejemplo 4: MISMO EMPLEADO en múltiples filas (se agruparán automáticamente) fputcsv($out, ['2026-02-19','10203040','JUAN PEREZ','ADMINISTRACION','LEGAL', 'AUXILIAR','M','M','40','M','M','Primera Entrega','DIRECTO', '40006','2']); fputcsv($out, ['2026-02-19','10203040','JUAN PEREZ','ADMINISTRACION','LEGAL', 'AUXILIAR','M','M','40','M','M','Primera Entrega','DIRECTO', '40008|40007','1|3']); fclose($out); exit(); } private function verificarSesion() { if (!isset($_SESSION['DIGITA'])) { header('Location: index.php'); exit(); } } }