# Plan de implementación — Spec 008

**Feature:** Port funcionalidades `version2` → `develop_eneon`  
**Spec:** [spec.md](./spec.md)  
**Rama base:** `develop_eneon`  
**Rama referencia (origen lógico):** `version2`  
**Rama de trabajo propuesta:** `feature/008-port-version2`

---

## 1. Contexto técnico

| Aspecto | Valor |
|---------|-------|
| Stack | Laravel 10, PHP 8.2, Inertia v1, React 18, TypeScript, Vite 5 |
| BD | MySQL (`eneon`); esquema legacy + scripts `bdscripts/` |
| Integraciones | EnerSpain/AUDAX (token), ADX/MuleSoft (client_id/secret headers) |
| Patrón backend | Controllers delgados + Traits + Jobs + Services |
| Patrón frontend | Pages Inertia, hooks, CSS modules, componentes Shared Eneon |
| Autenticación rutas | `auth`, `user.active` |

### Fuentes de verdad

| Ámbito | Fuente |
|--------|--------|
| Código funcional ADX | Archivos actuales en `version2` (copiar/adaptar) |
| Arquitectura UX/a11y | `develop_eneon` (no revertir) |
| Contratos API | [contracts/api-adx-integracion.md](./contracts/api-adx-integracion.md) |
| Esquema BD | [data-model.md](./data-model.md) |
| Restricciones | [constraints-develop-eneon.md](./constraints-develop-eneon.md) |

---

## 2. Decisiones de arquitectura

### D-01 — Port selectivo, no merge git

**Decisión:** Crear rama desde `develop_eneon` e incorporar bloques de `version2` archivo a archivo.  
**Motivo:** Un merge traería ~80 eliminaciones (historial CUPS, a11y, tarjetas).  
**Alternativa descartada:** `git merge version2` → regresión masiva.

### D-02 — `AdxHttpClient` compartido SIPS + Tarifas

**Decisión:** Un cliente HTTP en `app/Services/Adx/AdxHttpClient.php` usado por `AdxSipsService` y `AdxTarifasService`.  
**Motivo:** Auth Salesforce idéntica (headers/basic/query).  
**Deuda aceptada:** `AdxSipsService` en version2 duplica algo de lógica; unificar en port.

### D-03 — Retrocompatibilidad `sips.consumo`

**Decisión:** `cod_com` opcional en backend; si falta, resolver primera comercializadora AUDAX activa o inferir desde comercializadora del contrato en frontend.  
**Motivo:** Hooks develop envían `{ cups, tipo }` sin romper flujos existentes.

### D-04 — SIPS UI sobre primitivas develop

**Decisión:** Paneles `AudaxSipsPanel` / `AdxSipsPanel` usan `EneonTabs` y conservan `validacionSips.ts`.  
**Motivo:** version2 eliminó a11y; develop la exige.

### D-05 — Scripts SQL fuera de migraciones Laravel

**Decisión:** Ejecutar `bdscripts/T_Propuesta_Comercial_CUPs_*.sql` manualmente con backup.  
**Motivo:** Convención Eneon; esquema principal no vive en migraciones.

### D-06 — Prompts SweetAlert modulares

**Decisión:** `promptComercialCanal.ts` y `promptCondicionesParticulares.ts` como módulos únicos; eliminar duplicados inline en `EditarContrato.tsx`.  
**Motivo:** version2 introdujo duplicación parcial.

---

## 3. Estructura de archivos objetivo

```
app/
├── Console/Commands/
│   ├── SipsAdxDebugCommand.php          [NUEVO — copiar version2]
│   └── TarifasAdxDebugCommand.php       [NUEVO — copiar version2]
├── DataTransferObjects/
│   └── AdxTarifaDto.php                 [NUEVO]
├── Http/Controllers/
│   ├── SipsController.php               [MOD — multi-proveedor + retrocompat]
│   ├── IntegracionController.php        [MOD — CodConCli]
│   ├── ContratosController.php          [MOD — OKCom, representantes]
│   └── AnexoProductoController.php      [MOD — CodConCli PDF]
├── Services/
│   ├── Adx/AdxHttpClient.php            [NUEVO]
│   ├── Sips/AdxSipsService.php          [NUEVO]
│   ├── Sips/SipsProviderRegistry.php    [NUEVO]
│   └── Tarifas/AdxTarifasService.php    [NUEVO]
├── Jobs/
│   ├── OkCommercialContractJob.php      [MOD — comercial, canal]
│   ├── EnvioDocumentoContratoIntegracionJob.php [MOD]
│   └── GenerarContratoIntegracionJob.php [MOD — codConCli]
├── Models/
│   └── PropuestaComercialCups.php       [MOD — fillable/casts]
└── Traits/
    ├── IntegracionTraits.php            [MOD — ADX tarifas, representante]
    ├── ContratoTraits.php               [MOD — servicios, ventana, canal]
    └── auxiliares/AuxiliarCondicionesParticularesTraits.php [MOD]

config/
├── sips.php                             [NUEVO]
└── services.php                         [MOD — bloque adx]

bdscripts/
├── T_Propuesta_Comercial_CUPs_ventana_adx.sql      [NUEVO]
└── T_Propuesta_Comercial_CUPs_servicios_contrato.sql [NUEVO]

resources/js/Pages/Eneon/
├── Sips/
│   ├── Index.tsx                        [MOD — orquestador]
│   ├── validacionSips.ts                [CONSERVAR develop]
│   ├── types.ts                         [NUEVO]
│   ├── hooks/useSipsConsulta.ts         [NUEVO]
│   ├── config/resolveProvider.ts        [NUEVO]
│   └── components/                      [NUEVO — 7 archivos]
└── Contratos/
    ├── promptComercialCanal.ts          [NUEVO]
    ├── promptCondicionesParticulares.ts [NUEVO]
    ├── ModalPrecios.tsx                 [MOD — rama ADX]
    ├── ComponentesComunes/
    │   ├── ventanaPreciosUtils.ts       [NUEVO]
    │   ├── serviciosContratoConfig.ts   [NUEVO]
    │   └── ServiciosContratoFields.tsx  [NUEVO]
    └── [tablas/hooks/edición según épica B,C,D]
```

**Invariante:** ningún archivo listado en `constraints-develop-eneon.md` §1–§9 se elimina.

---

## 4. Fases de implementación

### Fase 0 — Bootstrap (PR-0)

**Objetivo:** Rama lista, BD preparada, env documentado.

| # | Tarea | Archivos / acción |
|---|-------|-------------------|
| 0.1 | Crear `feature/008-port-version2` desde `develop_eneon` | git |
| 0.2 | Backup BD + ejecutar scripts SQL idempotentes | `bdscripts/*.sql` |
| 0.3 | Verificar `Servicio_Integracion` en `T_Comercializadora` | SQL SELECT |
| 0.4 | Documentar `.env` ADX en `.env.example` (sin secretos) | `.env.example` |
| 0.5 | Baseline manual: historial CUPS + tarjetas + contrato multipunto | checklist spec §8 |

**Gate:** columnas BD presentes; develop features intactas antes de código nuevo.

---

### Fase 1 — Infraestructura ADX backend (PR-1)

**Épicas:** A (parcial), B (parcial)  
**Depende de:** Fase 0

| # | Tarea | Origen version2 | Notas |
|---|-------|-----------------|-------|
| 1.1 | Copiar `AdxHttpClient` | `app/Services/Adx/` | Auth modes headers/basic/query |
| 1.2 | Copiar `AdxTarifaDto` | `app/DataTransferObjects/` | |
| 1.3 | Copiar `AdxTarifasService` | `app/Services/Tarifas/` | Usar AdxHttpClient |
| 1.4 | Copiar `AdxSipsService` + `SipsProviderRegistry` | `app/Services/Sips/` | Refactor auth → AdxHttpClient |
| 1.5 | Añadir `config/sips.php` | config | |
| 1.6 | Extender `config/services.php` bloque `adx` | diff version2 | |
| 1.7 | Copiar commands debug | `SipsAdxDebugCommand`, `TarifasAdxDebugCommand` | |
| 1.8 | Extender `IntegracionTraits::showTarifasIntegracion` rama `adx` | diff | Sin tocar rama audax |
| 1.9 | Smoke test CLI (manual, usuario ejecuta) | `sips:adx-debug`, `tarifas:adx-debug` | |

**Gate:** commands listan config; `--test` conecta en entorno dev.

---

### Fase 2 — SIPS multi-proveedor (PR-2)

**Épica:** A  
**Depende de:** Fase 1

| # | Tarea | Detalle |
|---|-------|---------|
| 2.1 | Reescribir `SipsController@index` | Props `comercializadoras` + `sipsProvidersByCodCom` |
| 2.2 | Reescribir `SipsController@consumirServicioSips` | Registry → audax/adx; **D-03 retrocompat `cod_com`** |
| 2.3 | Copiar frontend SIPS modular | `types`, `hooks`, `components/*`, `config/resolveProvider` |
| 2.4 | Adaptar `Index.tsx` | Orquestador + selector comercializadora |
| 2.5 | Integrar `EneonTabs` en paneles | Reemplazar Nav Bootstrap de version2 |
| 2.6 | Integrar `validacionSips.ts` en `useSipsConsulta` | Conservar develop |
| 2.7 | Actualizar hooks contratos SIPS | `useCupsElectrico`, `useCupsGas`, ReferenciasCodigo → enviar `cod_com` |
| 2.8 | Regresión AUDAX | Persistencia `T_ConsumosSIPSAudax*` |

**Gate:** `/sips` funciona AUDAX+ADX; contratos autocompletan consumo con comercializadora correcta.

---

### Fase 3 — Tarifas ADX + servicios contrato (PR-3)

**Épica:** B  
**Depende de:** Fase 1

| # | Tarea | Detalle |
|---|-------|---------|
| 3.1 | Extender `PropuestaComercialCups` | 10 campos nuevos fillable/casts |
| 3.2 | Portar `mapServiciosContrato`, `mapVentanaAdxFields` en `ContratoTraits` | create/update CUPS |
| 3.3 | Copiar utilidades frontend | `ventanaPreciosUtils`, `serviciosContratoConfig`, `ServiciosContratoFields` |
| 3.4 | Extender `ModalPrecios.tsx` | Rama ADX modal XL; conservar Audax legacy |
| 3.5 | Columnas servicios en tablas CUPS | MultiCliente + UniCliente + Edición |
| 3.6 | Tooltips accesibles columnas | `title` en `<th>` (CF, PP, …) |
| 3.7 | Bulk load: propagar servicios | `useBulkLoadCups` hooks |
| 3.8 | `CargaGlobalAudax.php` tarifas RL.1–RL.6 | diff version2 |
| 3.9 | Actualizar `Interfaces.ts` / `constants.ts` | Tipos TypeScript |

**Gate:** selección ventana ADX persiste; servicios contrato round-trip en save/edición.

---

### Fase 4 — Canal y comercial (PR-4)

**Épica:** C  
**Depende de:** Fase 0 (independiente de 2-3, paralelizable)

| # | Tarea | Detalle |
|---|-------|---------|
| 4.1 | Copiar `promptComercialCanal.ts` | localStorage keys |
| 4.2 | Validación backend OKCom | `ContratosController::okCommercialContract` |
| 4.3 | Extender `OkCommercialContractJob` | Props + body externo |
| 4.4 | Extender `documentContractTrait` + job envío docs | |
| 4.5 | Extender `GenerarContratoIntegracionJob` + trait | comercial/canal en body |
| 4.6 | Integrar prompt en `EnviarDocumentoComercializadoraModal` | |
| 4.7 | Integrar prompt en `EditarContrato*.tsx` | Eliminar inline duplicado |
| 4.8 | Actualizar `Utils.ts::saveContratoComercial` | TipProCom 3+ mantiene modal canal/comercial |

**Gate:** OKCom y documentos rechazan request sin canal/comercial; jobs registran campos en historial.

---

### Fase 5 — Representante legal TipProCom 1/2 (PR-5)

**Épica:** D  
**Depende de:** Fase 4 (prompts compartidos)

| # | Tarea | Detalle |
|---|-------|---------|
| 5.1 | Copiar `promptCondicionesParticulares.ts` | |
| 5.2 | Portar `getRepresentantesLegalesByCodCliTrait` | `ContratoTraits` |
| 5.3 | Prop Inertia `representantesLegales` en edición | `ContratosController` |
| 5.4 | `IntegracionTraits::resolverContactoRepresentanteTramitacion` | Body tramitación |
| 5.5 | `AuxiliarCondicionesParticularesTraits` representante PDF | |
| 5.6 | `AnexoProductoController` + hook PDF | Query `CodConCli` |
| 5.7 | `Utils.ts` tramitar Tip 1/2 | Modal condiciones particulares |
| 5.8 | Fusionar `RepresentanteLegalSection` | develop a11y + reglas version2 bulk guard |
| 5.9 | `filterClientesByRepresentanteLegal` + bulk guard | MultiCliente |

**Gate:** PDF y tramitación Tip 1/2 usan representante validado; Tip 3 sin regresión.

---

### Fase 6 — Regresión develop y cierre (PR-6)

| # | Tarea | Referencia |
|---|-------|------------|
| 6.1 | Historial CUPS lectura/escritura | EditarCups, EditarPunto |
| 6.2 | EneonTabs en SIPS y contratos | constraints §2 |
| 6.3 | Barra progreso carga masiva | constraints §3 |
| 6.4 | Vistas tarjetas listados | constraints §5 |
| 6.5 | Validación formularios multipunto | hooks develop |
| 6.6 | Revisión diff vs constraints checklist | constraints §11 |
| 6.7 | Actualizar spec criterios §5 | marcar completados |

---

## 5. Mapa de dependencias entre PRs

```mermaid
flowchart LR
    P0[Fase 0 Bootstrap] --> P1[Fase 1 ADX backend]
    P1 --> P2[Fase 2 SIPS]
    P1 --> P3[Fase 3 Tarifas]
    P0 --> P4[Fase 4 Canal]
    P4 --> P5[Fase 5 Representante]
    P2 --> P6[Fase 6 Regresión]
    P3 --> P6
    P5 --> P6
```

**Paralelismo posible:** Fase 4 puede iniciarse en paralelo con Fase 2-3 tras Fase 1.

---

## 6. Estrategia de extracción desde `version2`

Para cada archivo a portar:

```bash
# Ejemplo: extraer archivo de version2 sin cambiar de rama develop
git show version2:app/Services/Adx/AdxHttpClient.php > app/Services/Adx/AdxHttpClient.php
```

Para archivos **modificados** en ambas ramas:

1. Partir de versión `develop_eneon`.
2. Aplicar hunks funcionales de `git diff develop_eneon..version2 -- <file>`.
3. Resolver conflictos preservando bloques develop (a11y, historial).
4. Revisar contra `constraints-develop-eneon.md`.

**Commits version2 útiles para `git show` / cherry-pick parcial:**

| Commit | Ámbito |
|--------|--------|
| `72522fdb` | Canal/comercial jobs |
| `c2cb4142` | Representante legal |
| `d9440169`, `feada276` | SIPS ADX |
| `85666164`–`d460ae77` | Tarifas + servicios contrato |

---

## 7. Puntos de integración críticos

### Backend — no romper historial CUPS

Al tocar `CupsTraits`, `PuntoSuministroTraits`, `CupsController`:

- Mantener llamadas a `RegistrarHistorialCupsService`.
- No eliminar rutas `cups.historial.*`.

### Frontend — ModalPrecios

- Detectar provider: `Servicio_Integracion === 'adx'` OR `response.data.provider === 'adx'`.
- Audax: tabla 4 columnas (develop).
- ADX: tabla 15 columnas (version2).

### Frontend — RepresentanteLegalSection

```typescript
// Fusión: conservar props develop
interface Props {
  // develop: erroresRepresentante, TypeaheadClienteConLimpiar, ...
  // version2: onClearAll, filterClientesByRepresentanteLegal guard
}
```

---

## 8. Verificación

### Automática (solo si usuario lo solicita)

- Tests CupsHistorial existentes deben seguir pasando.
- No añadir tests ADX salvo solicitud explícita.

### Manual obligatoria (spec §8)

| # | Escenario | Fase |
|---|-----------|------|
| V1 | SIPS AUDAX persistencia | 2 |
| V2 | SIPS ADX sin BD | 2 |
| V3 | Tarifas modal ADX + save | 3 |
| V4 | Servicios contrato toggles | 3 |
| V5 | OKCom canal/comercial | 4 |
| V6 | Envío documentos | 4 |
| V7 | Tramitar Tip 1/2 + PDF | 5 |
| V8 | Historial CUPS + tarjetas + bulk progress | 6 |

### Comandos diagnóstico (ejecutar manualmente)

```bash
php artisan sips:adx-debug --test
php artisan tarifas:adx-debug --test --tarifa=2.0TD --subtarifa=T0
php artisan config:clear
npm run dev   # o build, según entorno
```

---

## 9. Riesgos y mitigaciones (plan operativo)

| ID | Riesgo | Mitigación en plan |
|----|--------|-------------------|
| R1 | Pérdida historial CUPS | PR-6.1; constraints §1; no merge git |
| R2 | Regresión a11y SIPS | D-04; Fase 2.5-2.6 |
| R3 | `cod_com` rompe contratos | D-03; Fase 2.7 |
| R4 | Columnas BD faltantes | Fase 0.2 gate |
| R5 | Conflictos traits grandes | Aplicar por método, no archivo entero |
| R6 | Duplicación prompt EditarContrato | Fase 4.7 |

---

## 10. Estimación

| Fase | PR | Esfuerzo relativo |
|------|-----|------------------|
| 0 Bootstrap | PR-0 | 0.5 d |
| 1 ADX backend | PR-1 | 1 d |
| 2 SIPS | PR-2 | 2 d |
| 3 Tarifas + servicios | PR-3 | 2.5 d |
| 4 Canal/comercial | PR-4 | 1.5 d |
| 5 Representante | PR-5 | 1.5 d |
| 6 Regresión | PR-6 | 1 d |
| **Total** | **7 PRs** | **~10 d** |

---

## 11. Artefactos del plan

| Documento | Estado |
|-----------|--------|
| [spec.md](./spec.md) | ✅ |
| [research.md](./research.md) | ✅ |
| [data-model.md](./data-model.md) | ✅ |
| [contracts/api-adx-integracion.md](./contracts/api-adx-integracion.md) | ✅ |
| [constraints-develop-eneon.md](./constraints-develop-eneon.md) | ✅ |
| [quickstart.md](./quickstart.md) | ✅ |
| [tasks.md](./tasks.md) | ✅ |

---

## 12. Siguiente paso

Ejecutar **`/speckit-implement`** para comenzar por **T001** (Fase 0), o iniciar manualmente creando la rama `feature/008-port-version2` desde `develop_eneon`.
