# Análisis Técnico y Operativo: Carga Masiva de Clientes desde Excel y Actualización Automática

**Proyecto:** Dev-ISP (Sistema de Gestión y Facturación ISP SaaS)  
**Fecha de Análisis:** Octubre 2026  
**Documento:** `cargamasiva.md`  
**Estado:** Funcionalidad Totalmente Implementada y Operativa  

---

## 1. Resumen Ejecutivo y Respuestas Directas

| Pregunta Clave | Respuesta | Detalle Técnico |
| :--- | :---: | :--- |
| **¿Se puede subir un archivo Excel para la carga masiva de clientes?** | **SÍ, TOTALMENTE** | El sistema cuenta con un módulo dedicado en **Ajustes > Clientes desde Excel** (`/app/ajustes/clientes-excel`) con soporte nativo para archivos `.xlsx`, `.xls` y `.csv` de hasta 20 MB, procesados mediante la biblioteca `PhpSpreadsheet`. |
| **¿Los clientes existentes se actualizarán si ya están registrados?** | **SÍ, AUTOMÁTICAMENTE** | El sistema implementa la lógica de **Upsert (Update or Insert)**. Comprueba la identificación única (`DNI / Cédula / RUC / Pasaporte`) en la base de datos de la empresa: si el cliente ya existe, **no se duplica** y se actualizan sus nombres, apellidos, razón social, zona y estado de servicio. Si no existe, se crea como nuevo cliente. |

---

## 2. Dónde se Encuentra y Cómo Funciona en el Sistema

### 2.1. Ruta y Menú de Acceso
* **Menú Lateral:** Ajustes $\rightarrow$ Herramientas $\rightarrow$ **Clientes desde Excel**.
* **Ruta Web:** `http://[dominio-isp]/app/ajustes/clientes-excel`
* **Controlador Principal:** [`App\Http\Controllers\App\AjustesController.php`](file:///c:/laragon/www/devisp/app/Http/Controllers/App/AjustesController.php) (métodos `clientesExcel`, `descargarPlantillaClientesExcel`, `importarClientesExcel`).
* **Servicio de Procesamiento:** [`App\Services\ClienteExcelImportService.php`](file:///c:/laragon/www/devisp/app/Services/ClienteExcelImportService.php).
* **Interfaz de Usuario:** [`resources/js/Pages/App/Ajustes/Index.jsx`](file:///c:/laragon/www/devisp/resources/js/Pages/App/Ajustes/Index.jsx).

### 2.2. Botón "Descargar Plantilla Oficial"
El sistema incluye la descarga directa de un archivo Excel estilizado (`plantilla_oficial_clientes_devisp.xlsx`):
1. **Hoja 1 (`Plantilla_Clientes`):** Contiene la cabecera oficial en verde esmeralda con anchos automáticos, bordes y 5 filas de ejemplos reales (clientes pagados, pendientes, suspendidos y con transferencias).
2. **Hoja 2 (`Instrucciones_Uso`):** Tabla de referencia técnica con el detalle de obligatoriedad, tipos de datos, valores admitidos y ejemplos para cada columna.

---

## 3. Estructura Oficial de los 11 Campos del Archivo Excel

El procesador analiza inteligentemente las cabeceras de la hoja de cálculo respetando el orden oficial o detectándolas por nombre:

| # | Columna Oficial | Obligatorio | Tipo de Dato | Función en el Sistema |
| :-: | :--- | :-: | :-: | :--- |
| **1** | `#Factura` | Opcional | Texto | Número del comprobante (ej: `FAC-001-001-000101`). Si viene vacío, se autogenera con formato `FAC-EXCEL-YYYYMM-ID`. |
| **2** | `Fecha Emisión` | Opcional | Fecha | Fecha de emisión de la factura (`YYYY-MM-DD` o formato Excel). Si está vacía, toma la fecha actual. |
| **3** | `Cliente` | **SÍ** | Texto | Nombre y apellido completo del cliente o razón social (ej: `Carlos Andres Mendoza Perez`). |
| **4** | `DNI/C.I./C.C.` | **SÍ** | Texto / Numérico | **Llave única de identificación**. Cédula, DNI, RUC o pasaporte. Con este campo se evalúa si el cliente ya existe o es nuevo. |
| **5** | `Fecha Pago` | Opcional | Fecha | Fecha en que el abonado realizó el pago. Obligatorio si *Total Cobrado* es mayor a 0. |
| **6** | `Estado` | Opcional | Texto | Estado de la factura: `Pagada`, `Pendiente`, `Parcial`, `Vencida`, `Anulada`. |
| **7** | `Zona` | Opcional | Texto | Sector o cobertura geográfica (ej: `Zona Norte`, `Centro`). Si la zona no existe en el sistema, se crea automáticamente. |
| **8** | `Total Cobrado` | Opcional | Moneda / Número | Monto efectivamente pagado. Si es $> 0$, se registra el cobro en la tabla de pagos. |
| **9** | `Forma de Pago` | Opcional | Texto | Medio de recaudación: `Efectivo`, `Transferencia`, `Tarjeta`, `PayPhone`, etc. |
| **10** | `Estado Servicio` | Opcional | Texto | Estado operativo del abonado: `Activo`, `Suspendido`, `Cortado`, `Retirado`. |
| **11** | `Total` | Opcional | Moneda / Número | Valor total facturado del servicio o mensualidad (ej: `25.00`). |

---

## 4. Análisis Detallado: ¿Cómo se Actualizan los Clientes Existentes?

### 4.1. Criterio de Búsqueda y Unicidad
En el servicio [`ClienteExcelImportService.php`](file:///c:/laragon/www/devisp/app/Services/ClienteExcelImportService.php#L425-L430), cada fila leída ejecuta la siguiente consulta filtrada por la empresa activa (`empresa_id`):

```php
$cliente = Cliente::where('empresa_id', $empresaId)
    ->where(function($q) use ($dni) {
        $q->where('identificacion', $dni)
          ->orWhere('dni_ci_facturacion', $dni);
    })->first();
```

### 4.2. Comportamiento Si el Cliente YA EXISTE (Actualización)
Cuando se encuentra una coincidencia por Cédula/DNI/RUC:
1. **No se crea un registro duplicado:** El ID del cliente se mantiene intacto, protegiendo su historial previo (tickets, contratos, asignaciones).
2. **Actualización de Identidad:**
   - Se separan inteligentemente los nombres y apellidos:
     ```php
     [$nombres, $apellidos] = $this->separarNombresApellidos($clienteNombre);
     $cliente->nombres = $nombres;
     $cliente->apellidos = $apellidos;
     $cliente->razon_social = $clienteNombre;
     ```
3. **Actualización de Zona:**
   - Si se especifica una zona en el Excel, se vincula al nuevo `zona_id`.
   - Si la zona no existía previamente en la base de datos, el sistema la da de alta automáticamente con estado activo y la asocia al cliente.
4. **Actualización del Estado del Servicio:**
   - Se normaliza el texto de la columna `Estado Servicio` (`Activo` $\rightarrow$ `activo`, `Mora/Suspendido` $\rightarrow$ `suspendido`, `Cortado` $\rightarrow$ `cortado`, `Retirado` $\rightarrow$ `retirado`).
   - Se actualiza `$cliente->estado = $estadoServicio;`
5. **Guardado:** Se ejecuta `$cliente->save();` y se incrementa el contador de `clientes_actualizados`.

### 4.3. Comportamiento Si el Cliente NO EXISTE (Creación)
Si el DNI/Cédula no está registrado en esa empresa:
1. Se instancia un nuevo modelo `Cliente`.
2. Se asignan los valores por defecto del sistema ISP:
   - `empresa_id = $empresaId`
   - `identificacion = $dni`
   - `dni_ci_facturacion = $dni`
   - `fecha_registro = Carbon::now()->toDateString()`
   - `tipo_facturacion = 'mensual_adelantado'`
   - `dia_pago = 5`
   - `dia_corte = 15`
   - `auto_activar_pago = true`
3. Se asignan nombres, zona y estado de servicio.
4. Se guarda en la BD y se incrementa el contador de `clientes_creados`.

---

## 5. Gestión Concurrente de Facturas, Pagos y Recálculo de Saldos

El proceso no solo actualiza la ficha del cliente, sino que sincroniza su estado de cuenta:

```mermaid
flowchart TD
    A[Fila del Archivo Excel] --> B[Leer DNI/C.I. y Datos]
    B --> C{¿Existe Cliente con ese DNI?}
    C -- SÍ --> D[Actualizar Nombres, Apellidos, Razón Social, Zona y Estado]
    C -- NO --> E[Crear Nuevo Cliente con Configuración Base ISP]
    D --> F[Procesar Factura #Factura]
    E --> F
    F --> G{¿Factura Ya Existe?}
    G -- SÍ --> H[Actualizar Totales, IVA y Estado de Factura]
    G -- NO --> I[Crear Nueva Factura vinculada al Cliente]
    H --> J{¿Total Cobrado > 0?}
    I --> J
    J -- SÍ --> K[Registrar Pago si no existe previamente]
    J -- NO --> L[Omitir Registro de Pago]
    K --> M[Ejecutar recalcularValoresPendientes]
    L --> M
    M --> N[Actualizar facturas_pagadas y saldo pendiente del Cliente]
```

1. **Facturas Existentes vs Nuevas:**
   - Si el número de factura ya existe en la empresa, actualiza montos e impuestos para evitar comprobantes duplicados.
   - Si no existe, genera la factura con vencimiento a 15 días.
2. **Control Anti-Duplicación de Pagos:**
   - Si `Total Cobrado > 0`, antes de insertar verifica si ya existe un pago asociado a esa factura con el mismo monto.
3. **Recálculo Financiero en Tiempo Real:**
   - Se invoca `$cliente->recalcularValoresPendientes()`.
   - Evalúa si el total de pagos cubre el total adeudado. Si el saldo restante es $\le 0$, marca la factura como `pagada` y la propiedad `facturas_pagadas` del cliente en `true`.

---

## 6. Seguridad, Transaccionalidad y Tolerancia a Fallos

1. **Aislamiento Multi-Empresa (SaaS Multi-tenant):**
   - Todas las búsquedas e inserciones están limitadas al `empresa_id` de la sesión activa del usuario autenticado. Una empresa nunca sobreescribirá clientes de otro tenant.
2. **Transacciones ACID (`DB::beginTransaction` / `DB::commit` / `DB::rollBack`):**
   - La importación se procesa en un bloque protegido. Si el archivo sufre un error crítico irrecuperable en mitad del procesamiento, la base de datos revierte los cambios para evitar datos corruptos o incompletos.
3. **Mapeo Flexible de Encabezados:**
   - El sistema es tolerante a variaciones en las cabeceras (mayúsculas, minúsculas, tildes, guiones). Reconoce encabezados como:
     - `DNI/C.I./C.C.` $\rightarrow$ `cedula`, `identificacion`, `c_i`, `dni`, `ruc`.
     - `Cliente` $\rightarrow$ `abonado`, `nombre`, `nombres`, `razon_social`.
     - `Total Cobrado` $\rightarrow$ `abono`, `pagado`, `monto_pagado`.
     - `Estado Servicio` $\rightarrow$ `servicio`, `estado_servicio`.
4. **Resumen de Resultados y Auditoría Visual:**
   - Al finalizar, la interfaz gráfica muestra estadísticas inmediatas:
     - Cantidad de clientes nuevos creados (`+X`).
     - Cantidad de clientes actualizados (`X`).
     - Facturas emitidas.
     - Pagos ingresados.
     - Zonas creadas.
     - Tabla con los primeros registros procesados y lista de advertencias si hubo filas omitidas.
5. **Requisito del Entorno PHP (`ZipArchive`):**
   - Para descomprimir y procesar hojas de cálculo modernas en formato `.xlsx`, el servidor requiere la extensión `zip` activa en `php.ini` (`extension=zip`). En Laragon (`php-8.3`), esto se encuentra habilitado y operativo.

---

## 7. Conclusión y Recomendaciones de Uso

### Conclusión
La carga masiva mediante archivo Excel **está completamente desarrollada, probada y lista para su uso en producción**. Permite tanto la **migración inicial** de carteras de clientes desde otros sistemas, como la **actualización masiva periódica** de estados de servicio, zonas y cobranzas de abonados ya existentes sin peligro de duplicación.

### Recomendaciones Prácticas
1. **Descargar siempre la plantilla oficial:** Utilizar el botón *"Descargar Plantilla Oficial"* desde `/app/ajustes/clientes-excel` para contar con el formato exacto.
2. **Cédula / DNI como dato maestro:** Asegurarse de que las cédulas o identificaciones no tengan espacios accidentales al inicio o final (el importador aplica `trim()` automáticamente).
3. **Para actualizar solo estados o zonas:** Basta con subir el Excel con la columna `DNI/C.I./C.C.`, el `Cliente`, la `Zona` y el `Estado Servicio`; el sistema actualizará los clientes existentes manteniendo su historial de red y facturación.
