['codigo', 'cuenta', 'code', 'account', 'cta', 'numero'], 'nombre' => ['nombre', 'descripcion', 'name', 'description', 'concepto'], 'saldo_inicial_deudor' => ['saldo_inicial_deudor', 'inicial_debe', 'opening_debit', 'si_deudor'], 'saldo_inicial_acreedor' => ['saldo_inicial_acreedor', 'inicial_haber', 'opening_credit', 'si_acreedor'], 'cargos' => ['cargos', 'debe', 'debit', 'debits', 'movs_deudor'], 'abonos' => ['abonos', 'haber', 'credit', 'credits', 'movs_acreedor'], 'saldo_final_deudor' => ['saldo_final_deudor', 'final_debe', 'closing_debit', 'sf_deudor'], 'saldo_final_acreedor' => ['saldo_final_acreedor', 'final_haber', 'closing_credit', 'sf_acreedor'], ]; public function getSistema(): string { return 'generico'; } public function puedeManej(string $filePath): bool { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); return in_array($extension, ['xlsx', 'xls', 'csv']); } public function parsear(string $filePath): array { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if ($extension === 'csv') { return $this->parsearCsv($filePath); } return $this->parsearExcel($filePath); } private function parsearExcel(string $filePath): array { $spreadsheet = IOFactory::load($filePath); $worksheet = $spreadsheet->getActiveSheet(); $rows = $worksheet->toArray(); if (empty($rows)) { return []; } // Primera fila son headers $headers = array_map(fn($h) => $this->normalizarHeader($h), $rows[0]); $mapeo = $this->mapearColumnas($headers); $cuentas = []; for ($i = 1; $i < count($rows); $i++) { $cuenta = $this->parsearFila($rows[$i], $mapeo); if ($cuenta) { $cuentas[] = $cuenta; } } return $cuentas; } private function parsearCsv(string $filePath): array { $handle = fopen($filePath, 'r'); if (!$handle) { throw new \Exception('No se pudo abrir el archivo CSV'); } // Detectar delimitador $primeraLinea = fgets($handle); rewind($handle); $delimitador = $this->detectarDelimitador($primeraLinea); // Primera fila son headers $headers = fgetcsv($handle, 0, $delimitador); $headers = array_map(fn($h) => $this->normalizarHeader($h), $headers); $mapeo = $this->mapearColumnas($headers); $cuentas = []; while (($row = fgetcsv($handle, 0, $delimitador)) !== false) { $cuenta = $this->parsearFila($row, $mapeo); if ($cuenta) { $cuentas[] = $cuenta; } } fclose($handle); return $cuentas; } private function normalizarHeader(?string $header): string { if ($header === null) { return ''; } return strtolower(trim(preg_replace('/[^a-zA-Z0-9]/', '_', $header))); } private function detectarDelimitador(string $linea): string { $delimitadores = [',', ';', "\t", '|']; $conteos = []; foreach ($delimitadores as $d) { $conteos[$d] = substr_count($linea, $d); } return array_keys($conteos, max($conteos))[0]; } private function mapearColumnas(array $headers): array { $mapeo = []; foreach ($this->mapeoColumnas as $campo => $aliases) { foreach ($headers as $index => $header) { if (in_array($header, $aliases)) { $mapeo[$campo] = $index; break; } } } return $mapeo; } private function parsearFila(array $row, array $mapeo): ?array { // Verificar que tenemos código y nombre if (!isset($mapeo['codigo']) || !isset($mapeo['nombre'])) { return null; } $codigo = trim($row[$mapeo['codigo']] ?? ''); $nombre = trim($row[$mapeo['nombre']] ?? ''); if (empty($codigo) || empty($nombre)) { return null; } // Determinar nivel basado en la estructura del código $nivel = $this->determinarNivel($codigo); $esCuentaPadre = $nivel <= 2; return [ 'codigo' => $codigo, 'nombre' => $nombre, 'nivel' => $nivel, 'saldo_inicial_deudor' => $this->obtenerNumero($row, $mapeo, 'saldo_inicial_deudor'), 'saldo_inicial_acreedor' => $this->obtenerNumero($row, $mapeo, 'saldo_inicial_acreedor'), 'cargos' => $this->obtenerNumero($row, $mapeo, 'cargos'), 'abonos' => $this->obtenerNumero($row, $mapeo, 'abonos'), 'saldo_final_deudor' => $this->obtenerNumero($row, $mapeo, 'saldo_final_deudor'), 'saldo_final_acreedor' => $this->obtenerNumero($row, $mapeo, 'saldo_final_acreedor'), 'es_cuenta_padre' => $esCuentaPadre, ]; } private function determinarNivel(string $codigo): int { // Contar separadores para determinar nivel $separadores = preg_match_all('/[-.\s]/', $codigo); return min(3, $separadores + 1); } private function obtenerNumero(array $row, array $mapeo, string $campo): float { if (!isset($mapeo[$campo])) { return 0.0; } $valor = $row[$mapeo[$campo]] ?? 0; return (float) str_replace([',', '$', ' '], '', $valor); } }