EMPRESA_JOSESAID · inventario-operaciones-ms

Uso de IA · Inventario y operaciones

Existencias, lotes, movimientos y órdenes de operación.

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

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

Herramientas que expone a la IA (8):

consultar_existenciasconsultar_trazabilidad_lotelistar_articulos_bajo_minimolistar_movimientos_articulocrear_articuloregistrar_movimiento_inventariocrear_orden_operacioncrear_almacen

Ruta base en Nexus: /inventario-operaciones-ms/v1

01 Herramienta de lectura: consulta el servicio y devuelve datos

Herramienta de lectura: consulta el servicio y devuelve datos.

HerramientasInventario.java
    @Tool(name = "consultar_existencias",
          description = "Devuelve las existencias de un artículo por almacén: cantidad, reservado y disponible. Requiere el identificador UUID del artículo.")
    public String consultarExistencias(
            @ToolParam(description = "Identificador UUID del artículo", required = true) String articuloId) {
        RegistroHerramientasUsadas.registrar("consultar_existencias");
        String cuerpo = gateway.get()
                .uri(constructor -> constructor.path(RUTA_BASE + "/existencias")
                        .queryParam("articulo", UUID.fromString(articuloId.trim()))
                        .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.

HerramientasInventario.java
    @Tool(name = "registrar_movimiento_inventario",
          description = "Prepara un movimiento de inventario: entrada, salida, ajuste o reserva. NO lo registra: devuelve "
                  + "un resumen y un accion_id. El usuario debe confirmarlo en la aplicación. Solo ALMACEN puede usarla.")
    public String registrarMovimientoInventario(
            @ToolParam(description = "Identificador UUID del artículo", required = true) String articuloId,
            @ToolParam(description = "Identificador UUID del almacén", required = true) String almacenId,
            @ToolParam(description = "Tipo: ENTRADA, SALIDA, AJUSTE o RESERVA", required = true) String tipo,
            @ToolParam(description = "Cantidad mayor a cero, hasta 3 decimales", required = true) String cantidad,
            @ToolParam(description = "Lote, opcional, de hasta 60 caracteres", required = false) String lote,
            @ToolParam(description = "Referencia, opcional, de hasta 100 caracteres", required = false) String referencia) {
        RegistroHerramientasUsadas.registrar("registrar_movimiento_inventario");
        if (acciones == null) {
            return NO_DISPONIBLE;
        }
        UUID articulo = identificador(articuloId);
        UUID almacen = identificador(almacenId);
        if (articulo == null || almacen == null) {
            return "El identificador del artículo y del almacén deben ser UUID válidos.";
        }
        String tipoNormalizado = normalizar(tipo);
        if (!TIPOS_MOVIMIENTO.contains(tipoNormalizado)) {
            return "El tipo debe ser ENTRADA, SALIDA, AJUSTE o RESERVA.";
        }
        BigDecimal cant = decimal(cantidad, 3, 9);
        if (cant == null || cant.signum() <= 0) {
            return "La cantidad debe ser mayor a cero, con hasta 3 decimales y 9 dígitos enteros.";
        }
        if (!vacio(lote) && lote.trim().length() > 60) {
            return "El lote no puede tener más de 60 caracteres.";
        }
        if (!vacio(referencia) && referencia.trim().length() > 100) {
            return "La referencia no puede tener más de 100 caracteres.";
        }
        Map<String, Object> cuerpo = new LinkedHashMap<>();
        cuerpo.put("articuloId", articulo.toString());
        cuerpo.put("almacenId", almacen.toString());
        cuerpo.put("tipo", tipoNormalizado);
        cuerpo.put("cantidad", cant);
        if (!vacio(lote)) {
            cuerpo.put("lote", lote.trim());
        }
        if (!vacio(referencia)) {
            cuerpo.put("referencia", referencia.trim());
        }
        // Clave única por acción: si el movimiento se reintenta, inventario no lo aplica dos veces.
        cuerpo.put("idempotencyKey", java.util.UUID.randomUUID().toString());
        String resumen = "Movimiento " + tipoNormalizado + " de " + cant.stripTrailingZeros().toPlainString()
                + " del artículo " + articulo + " en el almacén " + almacen;
        return guardar(AccionesPendientes.TIPO_MOVIMIENTO_REGISTRAR, cuerpo, resumen, "Movimiento preparado, no registrado.");
    }
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.

HerramientasInventario.java
    static final String RUTA_BASE = "/inventario-operaciones-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.