Actualiza el inventario de Búsqueda de venta minorista

Si bien los métodos Product de creación, lectura, actualización y eliminación (CRUD) se usan para modificar de forma amplia los atributos de un Product, hay un conjunto de métodos Product que se pueden usar para actualizar campos específicos del inventario con diferentes niveles de detalle. Los siguientes campos Product se consideran campos de inventario:

  • Product.price_info
  • Product.availability
  • Product.available_quantity
  • Product.fulfillment_info

Métodos de actualización de inventario

Los cambios en la información de inventario de un producto pueden ocurrir con mucha más frecuencia que los cambios en la información de su catálogo. Como tal, se proporciona un conjunto especializado de métodos para controlar grandes volúmenes de actualizaciones específicas del inventario. Estos métodos son asíncronos debido a las optimizaciones posteriores que admiten cientos de actualizaciones simultáneas por producto, sin sacrificar el rendimiento.

Actualizaciones incrementales

fulfillment_info se usa a menudo con el fin de codificar la disponibilidad de entrega a nivel de lugar para un Product. En algunos casos, la disponibilidad de la entrega de algunos lugares específicos puede cambiar, y puedes decidir emitir actualizaciones que describan este cambio en lugar de usar el método UpdateProduct para volver a especificar la información de entrega de todo el producto.

En esos casos, se pueden usar los métodos AddFulfillmentPlaces y RemoveFulfillmentPlaces para actualizar de forma gradual los cambios de entrega de un producto según los ID de lugar que se agregan o quitan para un tipo de entrega determinado.

Java

Si deseas obtener información sobre cómo instalar y usar la biblioteca cliente de venta minorista, consulta Bibliotecas cliente de venta minorista. Si deseas obtener más información, consulta la documentación de referencia de la API de venta minorista para Java.

public static AddFulfillmentPlacesResponse addFulfillmentPlaces(
    Product productToUpdate, String fulfillmentInfoType, ImmutableList<String> placeIds)
    throws IOException, InterruptedException, ExecutionException {
  ProductServiceClient productClient = getProductServiceClient();

  AddFulfillmentPlacesRequest request = AddFulfillmentPlacesRequest.newBuilder()
      .setProduct(productToUpdate.getName())
      .setType(fulfillmentInfoType)
      .addAllPlaceIds(placeIds)
      .setAddTime(Timestamps.fromMillis(System.currentTimeMillis()))
      .build();

  AddFulfillmentPlacesResponse response = productClient
      .addFulfillmentPlacesAsync(request).get();

  productClient.shutdownNow();
  productClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

Proto

  {
    product: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    type: "pickup-in-store"
    place_ids: "store0"
    place_ids: "store1"
    add_time: {
      seconds: 100
      nanos: 100
    }
    allow_missing: true
  }
  

Este AddFulfillmentPlacesRequest de muestra agrega el tipo de entrega "pickup-in- store" a los ID de lugares "store0" y "store1" para el producto especificado. Dado que AddFulfillmentPlacesRequest.allow_missing se establece como verdadero, incluso si el producto aún no existe, la información del inventario actualizada se almacenará cuando se cree el producto. La actualización tiene una marca de tiempo con AddFulfillmentPlacesRequest.add_time para evitar que las actualizaciones inactivas anulen el estado de entrega de estos ID de lugar. En las siguientes secciones, se analizan estas funciones con más detalle.

El comportamiento es idéntico para RemoveFulfillmentPlacesRequest y el esquema es muy similar.

Actualizaciones no incrementales

price_info, availability y available_quantity no se pueden actualizar de forma incremental porque representan el inventario a nivel del producto, a diferencia de la información a nivel del lugar. Además, puede ser conveniente emitir actualizaciones no incrementales a fulfillment_info en lugar de solo cambios incrementales. En esos casos, se recomienda el método SetInventory.

Java

Si deseas obtener información sobre cómo instalar y usar la biblioteca cliente de venta minorista, consulta Bibliotecas cliente de venta minorista. Si deseas obtener más información, consulta la documentación de referencia de la API de venta minorista para Java.

public static SetInventoryResponse setInventoryWithMask(Product productToUpdate,
    FieldMask updateMask)
    throws IOException, ExecutionException, InterruptedException {
  ProductServiceClient productClient = getProductServiceClient();

  SetInventoryRequest request = SetInventoryRequest.newBuilder()
      .setInventory(productToUpdate)
      .setSetMask(updateMask)
      .setSetTime(Timestamps.fromMillis(System.currentTimeMillis()))
      .setAllowMissing(true)
      .build();

  SetInventoryResponse response = productClient.setInventoryAsync(request).get();

  productClient.shutdownNow();
  productClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

Proto

  {
    product: {
      name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
      availability: IN_STOCK
      fulfillment_info: {
        type: "pickup-in-store"
        place_ids: "store0"
        place_ids: "store1"
        place_ids: "store2"
        place_ids: "store3"
      }
      fulfillment_info: {
        type: "same-day-delivery"
      }
    }
    set_time: {
      seconds: 100
      nanos: 100
    }
    set_mask: {
      paths: "availability"
      paths: "fulfillment_info"
    }
    allow_missing: true
  }
  

En esta solicitud en particular, los campos SetInventoryRequest.product.fulfillment_info son descripciones completas de los ID de lugares aptos de cada tipo de entrega, a diferencia de las especificaciones incrementales. La actualización a "same-day-delivery" indica que ningún ID de lugar es apto para este tipo de entrega en este producto. Todos los demás tipos de entregas no se actualizan en esta solicitud.

De forma predeterminada,SetInventory actualizará todos los campos de inventario si SetInventory.set_mask no se configura o está vacío. Si la máscara no está vacía o si un campo de inventario no aparece de forma explícita en SetInventoryRequest.set_mask, se ignorará cualquier valor especificado para ese campo de inventario en la solicitud de actualización.

Al igual que con las actualizaciones incrementales, el campo SetInventoryRequest.set_time se puede usar para establecer una hora de actualización que se comparará con la última hora de actualización registrada de todos los campos de inventario actualizados.

Protecciones de marca de tiempo para actualizaciones de inventario

Hay varias rutas diferentes para actualizar los campos de inventario de un producto y, a fin de protegerte contra las actualizaciones desordenadas, cada campo de inventario está asociado con una última actualización.

Se registra la hora de actualización más reciente de price_info, availability, available_quantity y cada par de (fulfillment_info.place_ids, fulfillment_info.type).

Los métodos AddFulfillmentPlaces, RemoveFulfillmentPlaces y SetInventory permiten que el emisor especifique una hora de actualización cuando se emite la solicitud. Esta hora de actualización se compara con la última hora de actualización registrada para los campos de inventario relevantes y la actualización se confirma solo si la hora de actualización es posterior a la última actualización.

Por ejemplo, supongamos que el ID de lugar "store1" tiene habilitado el tipo de entrega "pickup-in- store" y la última hora de actualización registrada se establece en la hora T. Si RemoveFulfillmentPlacesRequest.type = "pickup-in-store" y RemoveFulfillmentPlacesRequest.place_ids contienen "store1", la solicitud borrará "pickup-in-store" de "store1" solo si RemoveFulfillmentPlacesRequest.remove_time es posterior a la hora T. Lo mismo sucede con AddFulfillmentPlacesRequests.

SetInventory opera de forma similar para actualizar price_info, availability y available_quantity. Cuando se actualiza fulfillment_info, SetInventoryRequest solicita, de manera implícita, agregar todos los ID de lugar especificados para un tipo de entrega determinado y quitar todos los ID de lugar existentes no especificados.

Por lo tanto, cuando se procesa SetInventoryRequest, la actualización fulfillment_info se convierte de forma implícita en una AddFulfillmentPlacesRequest y una RemoveFulfillmentPlacesRequest para cada tipo de entrega especificado. Esto significa que si cualquier lugar existente "store1" con entrega "pickup-in-store" tiene una hora de última actualización T que es más reciente que SetInventoryRequest.set_time, entonces el agregar/quitar implícito en "store1" y "pickup-in-store" no se aplicarán.

Carga previa de la información de inventario

Cada uno de los métodos de actualización de inventario permite que el emisor configure allow_missing en la solicitud. Cuando allow_missing se establece como verdadero, una actualización del inventario a un Product inexistente se procesará como si el Product existiera según las especificaciones del método. La información del inventario se conservará durante un máximo de dos días si el Product correspondiente no se crea a través de CreateProduct dentro de este período.

Java

public static SetInventoryResponse setInventory(Product productToUpdate)
    throws IOException, ExecutionException, InterruptedException {
  ProductServiceClient productClient = getProductServiceClient();

  SetInventoryRequest request = SetInventoryRequest.newBuilder()
      .setInventory(productToUpdate)
      .setSetTime(Timestamps.fromMillis(System.currentTimeMillis()))
      .setAllowMissing(true)
      .build();

  SetInventoryResponse response = productClient.setInventoryAsync(request).get();

  productClient.shutdownNow();
  productClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

Cuándo usar los métodos Product

Si bien es posible actualizar los campos de inventario con los métodos de CRUD del producto, el emisor debe conocer de forma explícita los efectos en la información de inventario existente o preexistente.

Estos son métodos síncronos, lo que significa que no se aplican las optimizaciones posteriores que se usan para los métodos de inventario y puede volverse costoso depender de estos métodos para actualizaciones de inventario frecuentes. Siempre que sea posible, prefiere usar los métodos de actualización de inventario mencionados antes.

CreateProduct

Cuando se invoca CreateProduct con cualquier campo de inventario configurado, los valores proporcionados en CreateProductRequest.product anularán cualquier valor precargado de esos campos respectivos. Si no se configuran campos de inventario, se usará de forma automática cualquier información de inventario preexistente.

Además, la hora de actualización más reciente de los campos de inventario anulados se restablecerá al momento de la llamada al método.

CreateProduct con inventario precargado

PROTO

{
  parent: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch"
  product_id: "p123"
  product: {
    name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    title: "some product"
    type: VARIANT
  }
}

En este ejemplo, el producto creado no tiene ningún campo de inventario establecido, lo que significa que cualquier información de inventario precargada se usará de forma automática si se actualiza con los métodos de actualización de inventario. Esto puede ser útil cuando las actualizaciones de inventario se separan de las actualizaciones del catálogo y deseas que un Product recién creado se sincronice con cualquier información de inventario preexistente.

CreateProduct con inventario explícito

PROTO

{
  parent: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch"
  product_id: "p123"
  product: {
    name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    title: "some product"
    type: VARIANT
    availability: OUT_OF_STOCK
    fulfillment_info: {
      type: "pickup-in-store"
    }
    fulfillment_info: {
      type: "same-day-delivery"
    }
  }
}

En este ejemplo, se crea un Product con campos de inventario configurados explícitamente. Estos campos anularán cualquier valor preexistente, sin importar la hora de actualización más reciente de los campos correspondientes. Por lo tanto, se garantiza que la Product recién creada tiene disponibilidad establecida en OUT_OF_STOCK y ningún ID de lugar admitirá los tipos de entrega "pickup-in-store" y "same-day-delivery".

CreateProduct con información de inventario puede ser útil si no estás seguro de que toda la información de inventario precargada sea precisa y prefieras configurar de forma explícita el inventario en el momento de la creación de Product para sincronizar por completo el catálogo y el inventario.

UpdateProduct

Cuando se invoca UpdateProduct y la máscara de campo UpdateProductRequest.update_mask contiene algún campo de inventario, los valores proporcionados en UpdateProductRequest.product anularán cualquier valor precargado. para esos campos respectivos.

Además, la hora de actualización más reciente de los campos de inventario anulados se restablecerá al momento de la llamada al método.

PROTO

{
  product: {
    name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    availability: IN_STOCK
    fulfillment_info: {
      type: "pickup-in-store"
      place_ids: "store0"
      place_ids: "store1"
      place_ids: "store2"
      place_ids: "store3"
    }
    fulfillment_info: {
      type: "same-day-delivery"
    }
  }
  update_mask: {
    paths: "availability"
    paths: "fulfillment_info"
  }
}

Este ejemplo es muy similar al ejemplo SetInventory, excepto que se garantiza que la actualización se aplique sin importar la hora de actualización más reciente de cada campo de inventario.

UpdateProduct para el inventario puede ser útil cuando se necesita una sincronización completa en la información de inventario mientras se ignoran las protecciones de marca de tiempo.

Si bien es posible precargar la información del inventario mediante UpdateProduct si se configura UpdateProductRequest.allow_missing en true para realizar una inserción de Product, el método requiere establecer campos de catálogo específicos, como UpdateProductRequest.product.title. Por lo tanto, se recomienda usar los métodos de actualización de inventario para precargar casos prácticos.

DeleteProduct

Cuándo DeleteProduct se invoca, toda la información del inventario existente para el producto especificado en DeleteProductRequest.name se borrará, incluidos todos los registros de la última hora de actualización de cada campo de inventario.