EMPRESA_JOSESAID · reportes-ejecutivos-ms

Uso de IA · Reportes ejecutivos

Indicadores y reportes para dirección.

Cómo se usa la IA aquí. Los fragmentos son código real del repositorio.

Usuario a ser usado: direccion@demo.empresa.mx (contraseña Demo2026!)

Herramientas que expone a la IA (3):

consultar_indicadoresconsultar_reporteregistrar_indicador

Ruta base en Nexus: /reportes-ejecutivos-ms/v1

01 Herramienta de lectura: consulta el servicio y devuelve datos

Herramienta de lectura: consulta el servicio y devuelve datos.

HerramientasReportes.java
    @Tool(name = "consultar_indicadores",
          description = "Devuelve los indicadores consolidados de un periodo. El periodo es AAAA-MM, AAAA-Qn o AAAA.")
    public String consultarIndicadores(
            @ToolParam(description = "Periodo: AAAA-MM, AAAA-Q1..Q4 o AAAA", required = true) String periodo,
            @ToolParam(description = "Área opcional. Valores válidos: VENTAS_ATENCION_CLIENTES, FINANZAS_CONTABILIDAD, OPERACIONES, COMPRAS_PROVEEDORES, ADMINISTRACION_LEGAL, DIRECCION_GENERAL. Vacío para todas.",
                       required = false) String area) {
        RegistroHerramientasUsadas.registrar("consultar_indicadores");
        String cuerpo = gateway.get()
                .uri(constructor -> {
                    var uri = constructor.path(RUTA_BASE + "/indicadores").queryParam("periodo", periodo);
                    if (area != null && !area.isBlank()) {
                        uri.queryParam("area", area.trim().toUpperCase());
                    }
                    return uri.build();
                })
                .retrieve()
                .body(String.class);
        return FiltroDatosSensibles.redactar(cuerpo).texto();
    }
Qué hace: Llama al gateway con la ruta del servicio y devuelve el resultado al modelo.

02 Herramienta de escritura: prepara la acción y NO la ejecuta

Herramienta de escritura: prepara la acción y NO la ejecuta.

HerramientasReportes.java
    @Tool(name = "registrar_indicador",
          description = "Prepara el registro de un indicador de un área para un periodo. NO lo registra: devuelve "
                  + "un resumen y un accion_id. El usuario debe confirmarlo en la aplicación. Solo DIRECCION puede usarla.")
    public String registrarIndicador(
            @ToolParam(description = "Área. Valores válidos: VENTAS_ATENCION_CLIENTES, FINANZAS_CONTABILIDAD, OPERACIONES, COMPRAS_PROVEEDORES, ADMINISTRACION_LEGAL, DIRECCION_GENERAL",
                       required = true) String area,
            @ToolParam(description = "Nombre del indicador", required = true) String nombre,
            @ToolParam(description = "Periodo: AAAA-MM, AAAA-Q1..Q4 o AAAA", required = true) String periodo,
            @ToolParam(description = "Valor numérico del indicador", required = true) String valor,
            @ToolParam(description = "Momento en que se actualizó la fuente, en ISO-8601 UTC, por ejemplo 2026-11-08T00:00:00Z",
                       required = true) String fuenteActualizadaUtc) {
        RegistroHerramientasUsadas.registrar("registrar_indicador");
        if (acciones == null) {
            return NO_DISPONIBLE;
        }
        String areaLimpia = area == null ? "" : area.trim().toUpperCase();
        if (!AREAS.contains(areaLimpia)) {
            return "El área no es válida. Valores: " + String.join(", ", AREAS) + ".";
        }
        if (nombre == null || nombre.isBlank()) {
            return "El nombre del indicador es obligatorio.";
        }
        String periodoLimpio = periodo == null ? "" : periodo.trim();
        if (!PERIODO.matcher(periodoLimpio).matches()) {
            return "El periodo debe ser AAAA-MM, AAAA-Qn o AAAA.";
        }
        BigDecimal numero;
        try {
            numero = new BigDecimal(valor.trim());
        } catch (NumberFormatException | NullPointerException e) {
            return "El valor debe ser numérico.";
        }
        Instant fuente;
        try {
            fuente = Instant.parse(fuenteActualizadaUtc.trim());
        } catch (DateTimeParseException | NullPointerException e) {
            return "La fecha de actualización debe estar en ISO-8601 UTC, por ejemplo 2026-11-08T00:00:00Z.";
        }
        Map<String, Object> cuerpo = new LinkedHashMap<>();
        cuerpo.put("area", areaLimpia);
        cuerpo.put("nombre", nombre.trim());
        cuerpo.put("periodo", periodoLimpio);
        cuerpo.put("valor", numero);
        cuerpo.put("fuenteActualizadaUtc", fuente.toString());
        String resumen = "Registrar indicador " + nombre.trim() + " de " + areaLimpia + " (" + periodoLimpio
                + ") = " + numero.toPlainString();
        AccionPendiente accion = acciones.preparar(usuarioActual(), AccionesPendientes.TIPO_INDICADOR_REGISTRAR,
                aJson(cuerpo), resumen);
        return FiltroDatosSensibles.redactar("Registro preparado, no ejecutado. " + resumen
                + ". accion_id: " + accion.id() + ". Vence en 10 minutos; el usuario debe confirmarlo en la aplicación.")
                .texto();
    }
Qué hace: La acción queda pendiente hasta que la persona confirma con el código.

03 Ruta base del servicio dentro de Nexus

Ruta base del servicio dentro de Nexus.

HerramientasReportes.java
    static final String RUTA_BASE = "/reportes-ejecutivos-ms/v1";
Qué hace: Todas las herramientas de este módulo se construyen sobre esta ruta.
Regla del proyecto: la IA propone o prepara; la persona confirma con el código de 8 dígitos. Ninguna herramienta de escritura cambia datos por sí sola.