# Feature Specification: Herramienta de contratos Unicliente (UniPunto y MultiPuntos) con detalle de suministro

**Feature Branch**: `005-contratos-unicliente-detalle`

**Created**: 2026-05-28

**Status**: Draft

**Input**: User description: "Dar al agente una herramienta que use una consulta específica cuando se pregunte por contratos, especialmente contratos Unicliente y UniCliente MultiPuntos. El agente debe listar los contratos ordenados por fecha de propuesta comercial (= fecha de contrato), responder cualquier pregunta sobre las columnas de salida de la consulta, y filtrar por cliente, dirección, teléfono, correo, punto de suministro o cualquier columna del resultado, procesando los datos para dar una respuesta inteligente."

> **Constitution (I. Spec-First)**: Este spec MUST ser agnóstico de stack.
> No mencionar Laravel, Angular ni rutas de código. El CÓMO va en `plan.md`.

> **Término de dominio**: «contrato» = **propuesta comercial**. El tipo de contrato se discrimina por `TipProCom`:
> - `TipProCom = 1` → **Unicliente UniPunto** (un cliente, un punto de suministro).
> - `TipProCom = 2` → **UniCliente MultiPuntos** (un cliente, varios puntos de suministro).
> - `TipProCom = 3` → **MultiCliente MultiPunto** → **FUERA DE ALCANCE** en esta feature (consulta distinta, feature futura).
>
> Esta feature cubre exclusivamente los contratos con `TipProCom` distinto de 3 (es decir, valores 1 y 2), cuyo titular se resuelve siempre contra el catálogo de **clientes empresa**.

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Listar contratos Unicliente ordenados por fecha de contrato (Priority: P1)

Como operador autenticado en el asistente, quiero pedir el listado de contratos **Unicliente UniPunto** y **UniCliente MultiPuntos** ordenados por **fecha de la propuesta comercial (= fecha de contrato)**, de más reciente a más antiguo, para revisar la cartera contractual sin abrir la base de datos manualmente.

**Why this priority**: Es el flujo principal de valor de la herramienta: obtener la lista contractual de este tipo de contratos con sus datos clave de cliente y suministro.

**Independent Test**: El operador pregunta "lista los contratos Unicliente" (o equivalente) y recibe un listado con los contratos de tipo 1 y 2, ordenado por fecha de contrato descendente, con datos verificables existentes en la base de datos.

**Acceptance Scenarios**:

1. **Given** existen contratos de tipo Unicliente UniPunto (TipProCom=1) y UniCliente MultiPuntos (TipProCom=2), **When** el operador pide listar contratos Unicliente, **Then** el asistente devuelve ambos tipos, **excluyendo** los de tipo MultiCliente MultiPunto (TipProCom=3), ordenados por fecha de contrato (más reciente primero).
2. **Given** el operador especifica un tipo concreto ("solo Unicliente UniPunto" o "solo MultiPuntos"), **When** lo solicita, **Then** el asistente devuelve únicamente los contratos del tipo indicado.
3. **Given** no existen contratos que cumplan el criterio, **When** el operador pregunta, **Then** el asistente indica claramente que no encontró resultados, sin inventar datos.

---

### User Story 2 - Filtrar contratos por cualquier dato del resultado (Priority: P1)

Como operador, quiero filtrar estos contratos por **cliente, NIF/CIF, dirección, teléfono, correo, punto de suministro, código CUPS o tarifa** (cualquier columna del resultado), para localizar rápidamente contratos concretos en lenguaje natural.

**Why this priority**: Sin capacidad de filtrado, el listado completo tiene poco valor operativo; el operador casi siempre busca por un criterio.

**Independent Test**: El operador pregunta "contratos del cliente [nombre/NIF]", "contratos en la dirección [X]", "contrato con el CUPS [código]" o "contratos con tarifa [nombre]" y recibe solo los registros que coinciden con ese criterio.

**Acceptance Scenarios**:

1. **Given** un cliente con contratos Unicliente, **When** el operador filtra por su nombre, NIF/CIF, teléfono o correo, **Then** el asistente devuelve solo los contratos de ese cliente.
2. **Given** un punto de suministro o dirección concreta, **When** el operador filtra por ella, **Then** el asistente devuelve los contratos/líneas asociados a ese suministro.
3. **Given** un código CUPS (eléctrico o de gas) o un nombre de tarifa, **When** el operador filtra por ese valor, **Then** el asistente devuelve las coincidencias correspondientes.
4. **Given** un filtro sin coincidencias, **When** el operador pregunta, **Then** el asistente indica que no hay resultados y sugiere revisar el criterio.

---

### User Story 3 - Consultar el detalle energético de un contrato o punto de suministro (Priority: P2)

Como operador, quiero consultar el **detalle de suministro** de un contrato (códigos CUPS eléctrico/gas, tarifas eléctrica y de gas, potencias contratadas P1–P6, consumo eléctrico y consumo de gas, fechas de activación y vencimiento del CUPS, dirección y localidad del punto de suministro y del cliente), para responder dudas técnicas/comerciales en una sola interacción.

**Why this priority**: Complementa el listado y el filtrado; muchas consultas requieren los datos de suministro y no solo la cabecera del contrato.

**Independent Test**: El operador pregunta por las potencias, consumos o tarifas de un contrato/punto de suministro concreto y recibe esos valores tomados de la base de datos.

**Acceptance Scenarios**:

1. **Given** un contrato UniCliente MultiPuntos con varios puntos de suministro, **When** el operador pide su detalle, **Then** el asistente presenta cada punto de suministro con su CUPS, tarifa, potencias y consumos.
2. **Given** una línea de suministro eléctrica, **When** el operador pregunta por sus potencias o consumo, **Then** el asistente devuelve P1–P6 y el consumo eléctrico; para una línea de gas devuelve el consumo de gas y la tarifa de gas.
3. **Given** un dato no disponible para esa línea (p. ej. tarifa de gas en un suministro eléctrico), **When** el operador pregunta, **Then** el asistente indica que ese dato no aplica/está vacío, sin inventarlo.

---

### User Story 4 - Respuestas completas y fiables sin tope artificial de filas (Priority: P2)

Como operador, quiero que el asistente base sus respuestas exclusivamente en los datos consultados y que **no recorte arbitrariamente los resultados a un máximo fijo de filas**, para no perder contratos relevantes en listados extensos.

**Why this priority**: El catálogo de herramientas existente impone un tope de 50 filas pensado para consultas resumidas; para esta herramienta de listado/detalle contractual ese tope sería una limitación que ocultaría información válida.

**Independent Test**: Con un volumen de contratos superior a 50 que cumplen el criterio, el asistente devuelve el conjunto completo de resultados relevantes (no truncado a 50), manteniendo la respuesta legible.

**Acceptance Scenarios**:

1. **Given** más de 50 contratos/líneas que cumplen el filtro, **When** el operador consulta, **Then** el asistente **no** limita el resultado a 50 filas; presenta todos los resultados relevantes (resumiendo o agrupando para mantener legibilidad si el volumen es muy alto).
2. **Given** un error de acceso a la base de datos, **When** el operador consulta, **Then** recibe un mensaje claro de error sin datos ficticios.
3. **Given** un volumen muy elevado de filas, **When** el asistente responde, **Then** puede agrupar por contrato y/o resumir, pero MUST NOT descartar silenciosamente contratos por un límite fijo.

---

### Edge Cases

- Contrato UniCliente MultiPuntos con múltiples puntos de suministro: el resultado debe poder verse **por contrato** (puntos anidados) o **por punto de suministro** (una fila por CUPS) según la pregunta.
- Línea de suministro eléctrica vs. de gas: los datos eléctricos (potencias P1–P6, consumo eléctrico, CUPS eléctrico, tarifa eléctrica) y de gas (consumo de gas, CUPS de gas, tarifa de gas) se rellenan según el tipo de CUPS; los no aplicables quedan vacíos.
- Contrato sin punto de suministro o sin tarifa asociada: mostrar la cabecera del contrato e indicar los datos ausentes sin inventarlos.
- Término de búsqueda ambiguo (coincide con varios clientes/contratos): pedir concreción o mostrar las coincidencias claramente separadas.
- Solicitud sobre contratos MultiCliente MultiPunto (TipProCom=3): el asistente indica que ese tipo se consulta de otra forma (fuera de alcance de esta herramienta).
- Volumen muy alto de resultados: agrupar o resumir conceptualmente manteniendo legibilidad, sin aplicar un tope fijo de filas.
- Caracteres especiales o términos muy cortos (< 3 caracteres): manejo seguro sin errores opacos.
- Operador sin sesión válida: no debe acceder a la consulta (reutiliza la autenticación existente del producto).

## Requirements *(mandatory)*

### Functional Requirements

- **FR-001**: El sistema MUST ofrecer una herramienta de consulta para **contratos Unicliente UniPunto (`TipProCom=1`)** y **UniCliente MultiPuntos (`TipProCom=2`)**, y MUST **excluir** los contratos MultiCliente MultiPunto (`TipProCom=3`).
- **FR-002**: El asistente MUST enrutar hacia esta herramienta las preguntas sobre contratos Unicliente/UniPunto/MultiPuntos y sobre las columnas de salida descritas en esta spec.
- **FR-003**: El listado MUST ordenarse por **fecha de la propuesta comercial (= fecha de contrato)** de forma descendente por defecto (más reciente primero).
- **FR-004**: El sistema MUST permitir **filtrar por cualquier columna del resultado**: cliente (nombre/razón social), NIF/CIF, dirección del cliente, teléfono, correo, dirección/punto de suministro, localidad, código CUPS (eléctrico o de gas) y nombre de tarifa (eléctrica o de gas).
- **FR-005**: El sistema MUST permitir distinguir y filtrar por **tipo de contrato** (Unicliente UniPunto vs. UniCliente MultiPuntos) cuando el operador lo solicite.
- **FR-006**: El sistema MUST devolver, por cada contrato/línea de suministro, las siguientes columnas de salida cuando existan en la base de datos:
  - Datos de contrato: código de propuesta comercial, **fecha de contrato** (fecha de propuesta comercial).
  - Datos de cliente: NIF/CIF, nombre comercial, correo, teléfono fijo, dirección del cliente, localidad del cliente.
  - Datos del punto de suministro: dirección del punto de suministro, localidad del punto de suministro, fecha de inicio y fecha de vencimiento del CUPS.
  - Datos de energía: código CUPS eléctrico, código CUPS de gas, nombre de tarifa eléctrica, nombre de tarifa de gas, consumo de gas, potencias contratadas P1, P2, P3, P4, P5 y P6, y consumo eléctrico.
- **FR-007**: El sistema MUST poder presentar los resultados **agrupados por contrato** (puntos de suministro anidados) o **por punto de suministro** (una fila por CUPS), según la naturaleza de la pregunta.
- **FR-008**: El sistema MUST NOT aplicar a esta herramienta el **tope fijo de 50 filas** del catálogo general; MUST devolver el conjunto completo de resultados relevantes para el criterio consultado.
- **FR-009**: Para mantener la legibilidad ante volúmenes altos, el asistente MAY agrupar o resumir resultados, pero MUST NOT descartar silenciosamente contratos por un límite fijo; si resume, MUST indicarlo.
- **FR-010**: Las respuestas MUST basarse exclusivamente en los datos consultados; el asistente MUST NOT inventar contratos, clientes, CUPS, tarifas, potencias ni consumos.
- **FR-011**: Cuando no haya resultados, el asistente MUST informarlo claramente y sugerir criterios alternativos de búsqueda.
- **FR-012**: El sistema MUST operar en modo **solo lectura**; MUST NOT modificar, insertar ni eliminar registros de negocio.
- **FR-013**: El asistente MUST poder usar el **contexto de la conversación** para interpretar seguimientos sobre un listado o contrato previamente mostrado (p. ej. "¿y el segundo de la lista?", "¿cuál es su tarifa de gas?").
- **FR-014**: La consulta de esta herramienta MUST derivarse del **mapa de relaciones del dominio comercial** (cliente → propuesta comercial → línea de suministro/CUPS → punto de suministro, tarifas y códigos CUPS); MUST NOT definirse fuera de ese mapa relacional.
- **FR-015**: El asistente MUST NOT exponer al operador detalles técnicos internos (nombres de herramientas, consultas o estructura de datos).

### Key Entities

- **Contrato** (= propuesta comercial): entidad central; cada registro es un contrato. Atributos clave: código de propuesta comercial, tipo de contrato (`TipProCom`: 1 Unicliente UniPunto, 2 UniCliente MultiPuntos, 3 fuera de alcance), fecha de contrato (fecha de propuesta comercial).
- **Cliente titular**: cliente empresa titular del contrato. Para `TipProCom` 1 y 2 el titular se resuelve siempre contra el catálogo de clientes. Atributos: NIF/CIF, nombre comercial, correo, teléfono fijo, dirección y localidad.
- **Línea de suministro / CUPS de la propuesta**: detalle contractual por punto de suministro. Atributos: fechas de activación y vencimiento del CUPS, potencias P1–P6, consumo eléctrico, consumo de gas, tipo de CUPS (eléctrico/gas), tarifa y código CUPS asociados.
- **Punto de suministro**: ubicación física del suministro. Atributos: dirección y localidad.
- **CUPS eléctrico / CUPS de gas**: código identificador del punto de suministro según tipo de energía.
- **Tarifa eléctrica / Tarifa de gas**: nombre de la tarifa aplicada según tipo de energía.
- **Localidad**: descripción de la localidad, usada tanto para el punto de suministro como para el cliente.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: En pruebas con al menos 10 preguntas representativas (listado, filtro por cliente/dirección/CUPS/tarifa, detalle de suministro), al menos el **90%** devuelven información correcta verificable contra la base de datos.
- **SC-002**: El **100%** de las respuestas sobre estos contratos incluyen solo datos presentes en los resultados de la consulta (cero invención en escenarios de prueba documentados).
- **SC-003**: El **100%** de los listados de contratos Unicliente aparecen ordenados por fecha de contrato descendente.
- **SC-004**: En un escenario con más de 50 contratos/líneas que cumplen el criterio, el **100%** de los resultados relevantes se devuelven sin truncado a 50 filas.
- **SC-005**: Las preguntas sobre contratos Unicliente/UniPunto/MultiPuntos se enrutan a esta herramienta en al menos el **95%** de los casos de prueba definidos.
- **SC-006**: Cuando la base de datos no está disponible, el **100%** de los intentos muestran un mensaje claro de error sin datos ficticios.

## Assumptions

- La base de datos operativa ya está conectada y accesible (conexión secundaria del producto), con datos de clientes, contratos, puntos de suministro, CUPS y tarifas poblados para pruebas.
- Para `TipProCom` 1 y 2 el **titular siempre es un cliente empresa** (no contacto/representante); la resolución de titular vía contacto aplica solo a `TipProCom=3`, fuera de alcance.
- **MultiCliente MultiPunto (`TipProCom=3`)** queda **fuera de alcance**; usa una consulta distinta que se especificará en una feature futura.
- Esta herramienta **no aplica el tope de 50 filas** del catálogo general de consultas comerciales; el límite/agrupación para volúmenes altos se define en `plan.md` priorizando no perder contratos relevantes.
- Solo operadores autenticados del panel pueden usar esta capacidad (misma política de acceso que el chat actual).
- La respuesta al operador es en español, en lenguaje natural, sin exponer detalles técnicos de herramientas o consultas internas.
- Escritura en base de datos (altas, bajas, actualizaciones) queda fuera de alcance; solo consultas de lectura.

## Dependencies

- Feature `002-agent-db-clients-contracts`: catálogo de herramientas de consulta comercial, orquestación del agente y clasificación de intención; esta herramienta amplía dicho catálogo.
- Feature `004-chat-conversations`: contexto conversacional para interpretar seguimientos sobre listados o contratos previamente mostrados.
- Modelo relacional del dominio comercial (cliente, propuesta comercial, líneas de suministro/CUPS, punto de suministro, tarifas y códigos CUPS) como fuente de verdad para construir la consulta.
- Base de datos secundaria con datos de contratos Unicliente UniPunto y UniCliente MultiPuntos poblados para pruebas de aceptación.
