/** {@inheritDoc} */
  public boolean isManageable(final Object object, final Class objectType) {

    if (!hasAccessRole()) {
      return false;
    }

    final Product product = (Product) object;
    if (isTransientEntity(product) && CollectionUtils.isEmpty(product.getProductCategory())) {
      return true; // skip this until sub import has finished
    }

    for (final ProductCategory category : product.getProductCategory()) {
      if (categoryFederationFilter.isManageable(category.getCategory(), Category.class)) {
        return true;
      }
    }
    return false;
  }
  @Test
  public void testRun() throws Exception {

    final WarehouseService warehouseService =
        ctx().getBean("warehouseService", WarehouseService.class);
    final ProductService productService = ctx().getBean("productService", ProductService.class);
    final SkuWarehouseService skuWarehouseService =
        ctx().getBean("skuWarehouseService", SkuWarehouseService.class);
    final LuceneQueryFactory luceneQueryFactory =
        ctx().getBean("luceneQueryFactory", LuceneQueryFactory.class);

    final List<Warehouse> warehouses = warehouseService.getByShopId(10L);

    Product product = productService.findById(9998L);
    assertEquals(Product.AVAILABILITY_STANDARD, product.getAvailability());

    final String skuCode = product.getDefaultSku().getCode();
    Pair<BigDecimal, BigDecimal> quantity =
        skuWarehouseService.findQuantity(warehouses, product.getDefaultSku().getCode());
    assertTrue(quantity.getFirst().compareTo(BigDecimal.ZERO) > 0);
    assertTrue(quantity.getFirst().compareTo(quantity.getSecond()) > 0);

    final BigDecimal oldQuantity = quantity.getFirst();

    productService.reindexProduct(product.getId());

    final NavigationContext context =
        luceneQueryFactory.getFilteredNavigationQueryChain(
            10L,
            null,
            Collections.singletonMap(
                ProductSearchQueryBuilder.PRODUCT_ID_FIELD, (List) Arrays.asList("9998")));

    List<ProductSearchResultDTO> rez =
        productService
            .getProductSearchResultDTOByQuery(context.getProductQuery(), 0, 1, null, false)
            .getResults();
    assertNotNull(rez);
    assertEquals(1, rez.size());

    getTx()
        .execute(
            new TransactionCallbackWithoutResult() {
              @Override
              protected void doInTransactionWithoutResult(
                  final TransactionStatus transactionStatus) {
                // native update to bypass indexing on save!!
                for (final Warehouse warehouse : warehouses) {
                  productService
                      .getGenericDao()
                      .executeNativeUpdate(
                          "update TSKUWAREHOUSE set QUANTITY = 0"
                              + ", UPDATED_TIMESTAMP = '2099-01-01 00:00:00' where WAREHOUSE_ID = "
                              + warehouse.getWarehouseId()
                              + " and SKU_CODE = '"
                              + skuCode
                              + "'");
                }
              }
            });

    product = productService.findById(9998L);

    quantity =
        skuWarehouseService.findQuantity(
            warehouseService.getByShopId(10L), product.getDefaultSku().getCode());
    assertTrue(quantity.getFirst().compareTo(BigDecimal.ZERO) == 0);
    assertTrue(quantity.getFirst().compareTo(quantity.getSecond()) <= 0);

    getTx()
        .execute(
            new TransactionCallbackWithoutResult() {
              @Override
              protected void doInTransactionWithoutResult(
                  final TransactionStatus transactionStatus) {
                new ProductInventoryChangedProcessorImpl(
                    skuWarehouseService, productService, null, null, null) {
                  @Override
                  protected String getNodeId() {
                    return "TEST";
                  }

                  @Override
                  protected Boolean isLuceneIndexDisabled() {
                    return false;
                  }
                }.doRun(
                    new Date()); // this should reindex product and it will be removed as there is
                                 // no inventory
              }
            });

    final CacheManager mgr = ctx().getBean("cacheManager", CacheManager.class);

    mgr.getCache("productService-productSearchResultDTOByQuery").clear();
    mgr.getCache("productSkuService-productSkuSearchResultDTOByQuery").clear();

    rez =
        productService
            .getProductSearchResultDTOByQuery(context.getProductQuery(), 0, 1, null, false)
            .getResults();
    assertNotNull(rez);
    assertEquals(0, rez.size());

    getTx()
        .execute(
            new TransactionCallbackWithoutResult() {
              @Override
              protected void doInTransactionWithoutResult(
                  final TransactionStatus transactionStatus) {
                // native update to bypass indexing on save!!
                for (final Warehouse warehouse : warehouses) {
                  productService
                      .getGenericDao()
                      .executeNativeUpdate(
                          "update TSKUWAREHOUSE set QUANTITY = "
                              + oldQuantity.toPlainString()
                              + ", UPDATED_TIMESTAMP = '2099-01-01 00:00:00' where WAREHOUSE_ID = "
                              + warehouse.getWarehouseId()
                              + " and SKU_CODE = '"
                              + skuCode
                              + "'");
                }
              }
            });

    product = productService.findById(9998L);

    quantity =
        skuWarehouseService.findQuantity(
            warehouseService.getByShopId(10L), product.getDefaultSku().getCode());
    assertTrue(quantity.getFirst().compareTo(BigDecimal.ZERO) > 0);
    assertTrue(quantity.getFirst().compareTo(quantity.getSecond()) > 0);

    getTx()
        .execute(
            new TransactionCallbackWithoutResult() {
              @Override
              protected void doInTransactionWithoutResult(
                  final TransactionStatus transactionStatus) {
                new ProductInventoryChangedProcessorImpl(
                    skuWarehouseService, productService, null, null, null) {
                  @Override
                  protected String getNodeId() {
                    return "TEST";
                  }

                  @Override
                  protected Boolean isLuceneIndexDisabled() {
                    return false;
                  }
                }.doRun(
                    new Date()); // this should reindex product and it will be removed as there is
                                 // no inventory
              }
            });

    mgr.getCache("productService-productSearchResultDTOByQuery").clear();
    mgr.getCache("productSkuService-productSkuSearchResultDTOByQuery").clear();

    rez =
        productService
            .getProductSearchResultDTOByQuery(context.getProductQuery(), 0, 1, null, false)
            .getResults();
    assertNotNull(rez);
    assertEquals(1, rez.size());
  }