EMPRESA_JOSESAID · facturacion-pagos-ms

Uso de IA · Facturación y pagos

Comprobantes, cobros y pagos a proveedores.

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

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

Herramientas que expone a la IA (6):

consultar_comprobantebuscar_comprobante_por_foliolistar_pagos_proveedorlistar_comprobantes_pendientes_cobroconsultar_cuenta_por_pagarregistrar_pago_comprobante

Ruta base en Nexus: /facturacion-pagos-ms/v1

01 Herramienta de lectura: consulta el servicio y devuelve datos

Herramienta de lectura: consulta el servicio y devuelve datos.

HerramientasFinanzas.java
    @Tool(name = "consultar_comprobante",
          description = "Devuelve un comprobante por su identificador UUID: folio, subtotal, IVA, total, estatus, "
                  + "estatus de cobro, monto pagado, saldo y lista de pagos.")
    public String consultarComprobante(
            @ToolParam(description = "Identificador UUID del comprobante", required = true) String comprobanteId) {
        RegistroHerramientasUsadas.registrar("consultar_comprobante");
        String cuerpo = gateway.get()
                .uri(constructor -> constructor.path(RUTA_BASE + "/comprobantes/{id}")
                        .build(UUID.fromString(comprobanteId.trim())))
                .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.

HerramientasFinanzas.java
    @Tool(name = "registrar_pago_comprobante",
          description = "Prepara el registro de un cobro sobre un comprobante. NO lo registra: devuelve un resumen y un "
                  + "accion_id. El usuario debe confirmarlo en la aplicación. Solo FINANZAS puede usarla.")
    public String registrarPagoComprobante(
            @ToolParam(description = "Identificador UUID del comprobante", required = true) String comprobanteId,
            @ToolParam(description = "Monto mayor a cero, hasta 2 decimales", required = true) String monto,
            @ToolParam(description = "Fecha del pago en formato AAAA-MM-DD; vacío para hoy", required = false) String fechaPago,
            @ToolParam(description = "Referencia bancaria o de transferencia, de hasta 100 caracteres", required = false) String referencia) {
        RegistroHerramientasUsadas.registrar("registrar_pago_comprobante");
        if (acciones == null) {
            return NO_DISPONIBLE;
        }
        UUID id = identificador(comprobanteId);
        if (id == null) {
            return "El identificador del comprobante no es válido.";
        }
        BigDecimal cantidad = decimal(monto);
        if (cantidad == null || cantidad.signum() <= 0) {
            return "El monto debe ser mayor a cero, con hasta 2 decimales.";
        }
        LocalDate fecha = null;
        if (fechaPago != null && !fechaPago.isBlank()) {
            try {
                fecha = LocalDate.parse(fechaPago.trim());
            } catch (DateTimeParseException e) {
                return "La fecha debe tener formato AAAA-MM-DD.";
            }
        }
        if (referencia != null && referencia.trim().length() > 100) {
            return "La referencia no puede tener más de 100 caracteres.";
        }
        try {
            gateway.get().uri(RUTA_BASE + "/comprobantes/{id}", id).retrieve().body(String.class);
        } catch (HttpClientErrorException.NotFound e) {
            return "No encontré ese comprobante.";
        }
        Map<String, Object> cuerpo = new LinkedHashMap<>();
        cuerpo.put("comprobanteId", id.toString());
        cuerpo.put("monto", cantidad);
        if (fecha != null) {
            cuerpo.put("fechaPago", fecha.toString());
        }
        if (referencia != null && !referencia.isBlank()) {
            cuerpo.put("referencia", referencia.trim());
        }
        // Clave única por acción: si el cobro se reintenta, facturación no lo aplica dos veces.
        cuerpo.put("idempotencyKey", java.util.UUID.randomUUID().toString());
        String resumen = "Registrar un cobro de " + cantidad.toPlainString() + " sobre el comprobante " + id
                + (fecha == null ? "" : " con fecha " + fecha);
        AccionPendiente accion = acciones.preparar(usuarioActual(), AccionesPendientes.TIPO_COMPROBANTE_PAGO_REGISTRAR,
                aJson(cuerpo), resumen);
        return FiltroDatosSensibles.redactar("Cobro preparado, no registrado. " + 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.

HerramientasFinanzas.java
    static final String RUTA_BASE = "/facturacion-pagos-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.