1

I have set up a cron job in a custom module in which reads from a XML file, search the product by Sku and then update prices. The problem is that even when i catch the exception of Magento\Catalog\Model\ProductRepository::get which is Magento\Framework\Exception\NoSuchEntityException in my module's try/catch block, when the cronjob runs automatically it throws the error and stops the cronjob

For example, if i stop the crontab jobs of Magento and manually run a php bin/magento cron:run the code just works.

Function code is:

public function processXML($xmlPath){
    $xml = $this->xmlParser;
    $coreRootPath = $this->directoryList->getRoot();
    $xml->load($coreRootPath.'/'.$xmlPath);
    $elements = $xml->xmlToArray();
    $this->logger->info('Total: '.count($elements['PRODUCTOS']['items']['PRODUCTO']));
    $currencyConverter = $this->currencyFactory->create();
    $currencyConverter->load(self::CURRENCY_FROM);
    $productRepository = $this->productRepo;
    foreach($elements['PRODUCTOS']['items']['PRODUCTO'] as $product){
      $sku = $product['CODI'];
      $qty = $product['UNIDS'];
      $price = $product['WPVP'];
      $pvenPrice = $product['PVEN'];
      $this->logger->info('$sku: '.$sku);

      //WPVP
      $convertedPricePounds = $currencyConverter->convert($price, self::CURRENCY_TO);
      $newPricePounds = round(($convertedPricePounds + 5 / 2) / 5) * 5;

      //PVEN
      $convertedPricePoundsPVEN = $currencyConverter->convert($pvenPrice, self::CURRENCY_TO);
      $newPricePoundsPVEN = round(($convertedPricePoundsPVEN + 5 / 2) / 5) * 5;

      try{
          $product = $productRepository->get($sku);
          if(is_object($product)){
            $stockData = ['qty' => $qty, 'is_in_stock' => 1];
            $product->setStockData($stockData);

            $resourceModelProduct = $this->resourceModelProduct->load($product, $product->getId());
            //EUR EN
            $this->logger->info('----- EN -----');
            $this->logger->info('$price: '.$price);
            $this->logger->info('$pvenPrice: '.$pvenPrice);
            $product->setStoreId(self::EUR_EN_STORE_ID);
            $product->setPrice($price);
            $product->setPvenPrice($pvenPrice);
            $resourceModelProduct->saveAttribute($product, 'price');
            $resourceModelProduct->saveAttribute($product, 'pven_price');

            //EUR ES
            $this->logger->info('----- ES -----');
            $this->logger->info('$price: '.$price);
            $this->logger->info('$pvenPrice: '.$pvenPrice);
            $product->setStoreId(self::EUR_ES_STORE_ID);
            $product->setPrice($price);
            $product->setPvenPrice($pvenPrice);
            $resourceModelProduct->saveAttribute($product, 'price');
            $resourceModelProduct->saveAttribute($product, 'pven_price');

            //GBP EN
            $this->logger->info('----- GB -----');
            $this->logger->info('$newPricePounds: '.$newPricePounds);
            $this->logger->info('$newPricePoundsPVEN: '.$newPricePoundsPVEN);
            $product->setStoreId(self::GBP_EN_STORE_ID);
            $product->setPrice($newPricePounds);
            $product->setPvenPrice($newPricePoundsPVEN);
            $resourceModelProduct->saveAttribute($product, 'price');
            $resourceModelProduct->saveAttribute($product, 'pven_price');

            $productRepository->save($product);
          }
      }catch(\Magento\Framework\Exception\NoSuchEntityException $e){
          $this->logger->info('SKU no existe: '.$sku);
        }
    }
  }

Looking at Magento\Catalog\Model\ProductRepository::232 i see that the NoSuchEntityException is the one thrown by the ProductRepository when the loaded Product by sku has no entity_id (Because there is no product with that sku) and see that in the XML i know that certain SKUs are non-existent in the catalog

  $productId = $this->resourceModel->getIdBySku($sku);
            if (!$productId) {
                throw new NoSuchEntityException(__('Requested product doesn\'t exist'));
            }

In the cron_schedule table shows this: {{{El producto solicitado no existe}}{{El producto solicitado no existe}}{{Requested product doesn't exist}}{{theme}}}

4
  • Try to have less code in your try/catch just for read purposes. How sure are you that it is that certain get() that throws the exception? Oct 19, 2018 at 12:05
  • Ok, ty! I'll take that in mind, please see the update Oct 19, 2018 at 12:18
  • Well you are loading the product 2 times. First with the get and then with the $this->resourceModelProduct. ResourceModelProduct Load function will load it into $product and not in $resourceModelProduct. So that is a weird thing to do. Oct 21, 2018 at 14:51
  • That was the way i was able to save prices in a different website. Loading a product from the repository and setting its store_id did not worked for me. Well, maybe i just have to use the saveAttribute from the resource model and not filll a model product again. But the thing is, that when i execute the cron manually it just works! When then set up the automatic cron then it fails.... super strange Oct 22, 2018 at 14:52

2 Answers 2

0

Any uncaught exception should end up in the var/log/exception.log with a stack trace that could help locate the source.

Debugging with Xdebug is my preferred way to track down issues when logging isn't enough.

Without debugging I might try catching all exceptions with \Exception or PHP 7 \Throwable and the log detail to see if another error could be in play.

0

Try this code (quickly editted):

public function processXML($xmlPath){
    $xml = $this->xmlParser;
    $coreRootPath = $this->directoryList->getRoot();
    $xml->load($coreRootPath.'/'.$xmlPath);
    $elements = $xml->xmlToArray();
    $this->logger->info('Total: '.count($elements['PRODUCTOS']['items']['PRODUCTO']));
    $currencyConverter = $this->currencyFactory->create();
    $currencyConverter->load(self::CURRENCY_FROM);
    $productRepository = $this->productRepo;
    foreach($elements['PRODUCTOS']['items']['PRODUCTO'] as $product){
      $sku = $product['CODI'];
      $qty = $product['UNIDS'];
      $price = $product['WPVP'];
      $pvenPrice = $product['PVEN'];
      $this->logger->info('$sku: '.$sku);

      //WPVP
      $convertedPricePounds = $currencyConverter->convert($price, self::CURRENCY_TO);
      $newPricePounds = round(($convertedPricePounds + 5 / 2) / 5) * 5;

      //PVEN
      $convertedPricePoundsPVEN = $currencyConverter->convert($pvenPrice, self::CURRENCY_TO);
      $newPricePoundsPVEN = round(($convertedPricePoundsPVEN + 5 / 2) / 5) * 5;

      try{
          $product = $productRepository->get($sku);
      }catch(\Magento\Framework\Exception\NoSuchEntityException $e){
$product = null;
          $this->logger->info('SKU no existe: '.$sku);
        }
          if(isset($product){
            $stockData = ['qty' => $qty, 'is_in_stock' => 1];
            $product->setStockData($stockData);
            //EUR EN
            $this->logger->info('----- EN -----');
            $this->logger->info('$price: '.$price);
            $this->logger->info('$pvenPrice: '.$pvenPrice);
            $product->setStoreId(self::EUR_EN_STORE_ID);
            $product->setPrice($price);
            $product->setPvenPrice($pvenPrice);
try {
$productRepository->save($product);
}catch(...){
//exception here
}

            //EUR ES
            $this->logger->info('----- ES -----');
            $this->logger->info('$price: '.$price);
            $this->logger->info('$pvenPrice: '.$pvenPrice);
            $product->setStoreId(self::EUR_ES_STORE_ID);
            $product->setPrice($price);
            $product->setPvenPrice($pvenPrice);
try {
$productRepository->save($product);
}catch(...){
//exception here
}

            //GBP EN
            $this->logger->info('----- GB -----');
            $this->logger->info('$newPricePounds: '.$newPricePounds);
            $this->logger->info('$newPricePoundsPVEN: '.$newPricePoundsPVEN);
            $product->setStoreId(self::GBP_EN_STORE_ID);
            $product->setPrice($newPricePounds);
            $product->setPvenPrice($newPricePoundsPVEN);
try {
$productRepository->save($product);
}catch(...){
//exception here
}
          }
    }
  }

You can load products by doing 2 things:

1.Using a resourceModel to load() it into a Model (note that the resourceModel->load() will not return the model but it will fill the data in the model that your provide, you can just keep using that model). This is often used to create new products and fill it with data.

  1. Use the repository to get() it. This will return the model of the product. You need to put that into a new variable
1
  • Hmmm did not know that, about differences between the resourceModel Load and the repository get, thank you! Oct 22, 2018 at 14:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.