# 7. Parsers de Balanzas ## Arquitectura ``` Upload archivo │ ▼ ┌─────────────────┐ │ DetectorFormato │ ← Detecta el sistema origen └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Parser Específico│ │ - ContpaqiParser│ │ - GenericoParser│ │ - (futuro: Aspel)│ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Formato Standard│ ← Estructura normalizada └────────┬────────┘ │ ▼ ┌─────────────────┐ │ ClasificadorCtas│ ← Aplica reglas de mapeo └─────────────────┘ ``` --- ## Interface ParserInterface Todos los parsers deben implementar: ```php interface ParserInterface { /** * Parsea archivo y retorna array de cuentas normalizadas */ public function parsear(string $filePath): array; /** * Verifica si puede manejar el archivo */ public function puedeManej(string $filePath): bool; /** * Retorna identificador del sistema */ public function getSistema(): string; } ``` ### Estructura de cuenta normalizada: ```php [ 'codigo' => '001-100-000', 'nombre' => 'ACTIVO CIRCULANTE', 'nivel' => 1, 'saldo_inicial_deudor' => 1500000.00, 'saldo_inicial_acreedor' => 0.00, 'cargos' => 500000.00, 'abonos' => 200000.00, 'saldo_final_deudor' => 1800000.00, 'saldo_final_acreedor' => 0.00, 'es_cuenta_padre' => true, 'cuenta_padre_codigo' => null, // opcional ] ``` --- ## DetectorFormato Detecta automáticamente el sistema origen del archivo. ```php class DetectorFormato { private array $parsers = [ new ContpaqiParser(), // new AspelParser(), // new SapParser(), new GenericoParser(), // Fallback ]; public function detectar(string $filePath): array { foreach ($this->parsers as $parser) { if ($parser->puedeManej($filePath)) { return [ 'sistema' => $parser->getSistema(), 'parser' => $parser, ]; } } throw new Exception('Formato no reconocido'); } } ``` --- ## ContpaqiParser Parser para balanzas de CONTPAQi. ### Detección Busca patrones característicos en el PDF: - Texto "CONTPAQ" o "CONTPAQi" - Patrón de códigos: `\d{3}-\d{3}-\d{3}` - Encabezados típicos: "Saldo Inicial", "Debe", "Haber" ### Formato de código CONTPAQi ``` XXX-XXX-XXX │ │ │ │ │ └── Detalle (000 = padre) │ └────── Subcuenta (000 = padre) └────────── Mayor ``` Ejemplos: - `001-100-000` → Nivel 1 (Mayor: Activo Circulante) - `101-000-000` → Nivel 2 (Subcuenta: Caja) - `101-001-000` → Nivel 3 (Detalle) ### Reglas de mapeo CONTPAQi | Cuenta Padre | Rango Hijos | Categoría | |--------------|-------------|-----------| | 001-100-000 | 101-000-000 a 154-999-999 | Activos Circulantes | | 001-200-000 | 155-000-000 a 199-999-999 | Activos No Circulantes | | 002-100-000 | 200-000-000 a 209-999-999 | Pasivo Circulante | | 002-200-000 | 210-000-000 a 220-999-999 | Pasivo No Circulante | | 30X-XXX-XXX | - | Capital Social | | 310-XXX-XXX | - | Pérdidas Anteriores | | 311-XXX-XXX | - | Utilidades Anteriores | | 40X-XXX-XXX | - | Ingresos | | 5XX-XXX-XXX | - | Gastos Operativos | | 6XX-XXX-XXX | - | Otros Gastos | | 7XX-XXX-XXX | - | Gastos Financieros | --- ## GenericoParser Parser para archivos Excel/CSV genéricos. ### Formatos soportados - `.xlsx` - Excel 2007+ - `.xls` - Excel 97-2003 - `.csv` - Valores separados por coma/punto y coma ### Detección de columnas Busca headers similares a: | Campo | Aliases aceptados | |-------|-------------------| | codigo | codigo, cuenta, code, account, cta, numero | | nombre | nombre, descripcion, name, description, concepto | | saldo_inicial_deudor | saldo_inicial_deudor, inicial_debe, opening_debit | | cargos | cargos, debe, debit, debits, movs_deudor | | abonos | abonos, haber, credit, credits, movs_acreedor | | saldo_final_deudor | saldo_final_deudor, final_debe, closing_debit | ### Detección de delimitador CSV Detecta automáticamente: `,`, `;`, `\t`, `|` --- ## Agregar Nuevo Parser 1. **Crear clase** en `app/Services/Parsers/`: ```php parsers = [ new ContpaqiParser(), new AspelParser(), // ← Agregar antes de GenericoParser new GenericoParser(), ]; ``` 3. **Agregar reglas de mapeo** en seeder: ```php // Crear nuevo seeder: ReglasMapeeoAspelSeeder.php ReglaMapeo::create([ 'sistema_origen' => 'aspel', 'patron_regex' => '/^1\d{3}/', 'reporte_contable_id' => $balance->id, 'categoria_contable_id' => $activosCirc->id, 'prioridad' => 10, ]); ``` --- ## ClasificadorCuentas Aplica reglas de mapeo a las cuentas importadas. ### Proceso: 1. Buscar mapeo específico del cliente 2. Si no existe, buscar regla del sistema 3. Si no existe regla, marcar para revisión ### Detección de anomalías: - Cuentas 45X (normalmente pasivo) usadas como gasto - Cuentas 8XX-9XX (cuentas de orden) - Códigos sin regla de mapeo ```php // Ejemplo de nota de revisión automática "Código 45X normalmente es pasivo pero podría ser gasto. Verificar clasificación." ```