# Reporte de Arquitectura y Normalización de Calles (2026-05-20)

Este documento detalla la nueva arquitectura backend implementada para las secciones de la Ficha de Inventario y el esquema de normalización dinámica para el catálogo de calles del Centro Histórico.

---

## 1. Nueva Arquitectura del Módulo de Inventario

Para desacoplar el HTTP del dominio y evitar controladores monolíticos con match-statements gigantescos, implementamos un diseño basado en **Factory Pattern** y **Template Method Pattern**.

### Diagrama de Flujo del Proceso

```mermaid
graph TD
    A[Cliente / HTTP Request] -->|GET / POST| B[SectionController]
    B -->|relation name| C[SectionServiceFactory]
    C -->|Instancia| D[SeccionServiceBase]
    D -->|template-method| E[Ejecución de Lógica]
    E -->|1. validate| D
    E -->|2. prepareData| D
    E -->|3. persist| D
    D -->|Retorno| B
    B -->|Inertia / JSON| A
```

### Componentes Clave

1. **`SectionController` (Capa HTTP):**
   - Recibe la petición HTTP, delega la resolución al Factory, y gestiona los fallos de dominio.
   - Si la sección no existe en la fábrica, se lanza una `InvalidArgumentException` que el controlador captura para retornar un `abort(404, 'Sección no encontrada.')` limpio.

2. **`SectionServiceFactory` (Creador):**
   - Resuelve dinámicamente el nombre de la relación (ej. `seccion1`) a su clase de servicio correspondiente (ej. `Seccion1Service`).
   - Mapea nombres especiales (como `usosFuncionales`) y utiliza `studly()` para convenciones automáticas.

3. **`BaseSectionService` (Template Pattern & Reglas de Negocio):**
   - Clase base abstracta que unifica el ciclo de vida de la sección:
     - `validate(array $data)`: Valida la entrada contra las reglas de la sección.
     - `prepareData(array $data)`: Hook opcional para mutaciones previas a guardar.
     - `persist(Inventario $inventario, array $data)`: Guarda/actualiza el registro hijo en la relación correspondiente y marca la sección como completada en `$inventario->sections_completed`.
     - `catalogs(Inventario $inventario)`: Retorna un array con catálogos y sugerencias para la vista.

---

## 2. Catálogo de Calles e Inserción Dinámica (Sección 1)

Para evitar la polución de datos por errores ortográficos y mejorar el rendimiento de la base de datos (eliminando consultas `DISTINCT` pesadas), normalizamos el almacenamiento de calles del Centro Histórico de Potosí.

### Esquema de la Base de Datos

*   **Tabla `calles` (Nueva):**
    *   `id`: Autoincremental.
    *   `nombre`: String único (con índice).
*   **Tabla `f_inv_seccion_1` (Modificada):**
    *   Se eliminaron las columnas de texto `calle` y `esq_entre`.
    *   Se añadieron las llaves foráneas `calle_id` (obligatoria, apunta a `calles`) y `esq_calle_id` (nullable, apunta a `calles`).

### Funcionamiento e Inserción Dinámica

El brigadista sigue teniendo libertad de escribir cualquier calle (incluso si no existe en el catálogo) en el frontend.

1. **Guardado Dinámico (`Seccion1Service::prepareData`):**
   Antes de guardar en la base de datos, el servicio intercepta el texto de la calle y la esquina, ejecutando `firstOrCreate` sobre el modelo `Calle`:
   ```php
   if (! empty($data['calle'])) {
       $calle = Calle::firstOrCreate(['nombre' => trim($data['calle'])]);
       $data['calle_id'] = $calle->id;
   }
   unset($data['calle'], $data['esq_entre']); // Limpiamos campos temporales de texto
   ```

2. **Compatibilidad con Frontend (Sin Cambios en el Cliente):**
   El modelo `InvSeccion1` utiliza la funcionalidad `$appends` de Laravel para seguir devolviendo los strings `calle` y `esq_entre` directamente al frontend.
   ```php
   protected $with = ['calleRelation', 'esqCalleRelation'];
   protected $appends = ['calle', 'esq_entre'];

   public function getCalleAttribute(): ?string {
       return $this->calleRelation?->nombre;
   }
   ```
   *Nota: Eager-loading (`$with`) está activado por defecto para prevenir consultas N+1.*

3. **Sugerencias de Autocomplete:**
   Las sugerencias de autocompletado en `catalogs()` ahora se leen directamente de la tabla `calles` de forma ultrarrápida, eliminando consultas costosas en la tabla de inventario.
