custom/plugins/PickwareErpStarter/src/Stock/ProductAvailableUpdater.php line 43

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright (c) Pickware GmbH. All rights reserved.
  4.  * This file is part of software that is released under a proprietary license.
  5.  * You must not copy, modify, distribute, make publicly available, or execute
  6.  * its contents or parts thereof without express permission by the copyright
  7.  * holder, unless otherwise permitted by law.
  8.  */
  9. declare(strict_types=1);
  10. namespace Pickware\PickwareErpStarter\Stock;
  11. use Doctrine\DBAL\Connection;
  12. use Pickware\DalBundle\RetryableTransaction;
  13. use Shopware\Core\Content\Product\ProductEvents;
  14. use Shopware\Core\Defaults;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. class ProductAvailableUpdater implements EventSubscriberInterface
  18. {
  19.     private Connection $db;
  20.     public function __construct(Connection $db)
  21.     {
  22.         $this->db $db;
  23.     }
  24.     public static function getSubscribedEvents(): array
  25.     {
  26.         return [
  27.             ProductAvailableStockUpdatedEvent::class => 'productAvailableStockUpdated',
  28.             ProductEvents::PRODUCT_WRITTEN_EVENT => 'productWritten',
  29.         ];
  30.     }
  31.     public function productAvailableStockUpdated(ProductAvailableStockUpdatedEvent $event): void
  32.     {
  33.         $this->recalculateProductAvailable($event->getProductIds());
  34.     }
  35.     public function productWritten(EntityWrittenEvent $event): void
  36.     {
  37.         if ($event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  38.             return;
  39.         }
  40.         $productIds = [];
  41.         foreach ($event->getWriteResults() as $writeResult) {
  42.             $payload $writeResult->getPayload();
  43.             if (isset($payload['parentId'])
  44.                 || isset($payload['versionId'])
  45.                 || isset($payload['isCloseout'])
  46.                 || isset($payload['minPurchase'])
  47.             ) {
  48.                 $productIds[] = $payload['id'];
  49.             }
  50.         }
  51.         $this->recalculateProductAvailable($productIds);
  52.     }
  53.     public function recalculateProductAvailable(array $productIds): void
  54.     {
  55.         if (count($productIds) === 0) {
  56.             return;
  57.         }
  58.         RetryableTransaction::retryable($this->db, function () use ($productIds): void {
  59.             $this->db->executeStatement(
  60.                 'UPDATE `product`
  61.                 LEFT JOIN `product` AS `parent`
  62.                     ON `parent`.`id` = `product`.`parent_id` AND `parent`.`version_id` = `product`.`version_id`
  63.                 SET `product`.`available` =
  64.                     IF(
  65.                         -- If product is in closeout ...
  66.                         COALESCE(`product`.`is_closeout`, `parent`.`is_closeout`, 0),
  67.                         -- ... it is available if more stock is available than the minimum purchase ...
  68.                         `product`.`available_stock` >= COALESCE(`product`.`min_purchase`, `parent`.`min_purchase`, 1),
  69.                         -- ... else it is available always
  70.                         1
  71.                     )
  72.                 WHERE `product`.`version_id` = :liveVersionId
  73.                     AND (`product`.`id` IN (:productIds) OR `product`.`parent_id` IN (:productIds))',
  74.                 [
  75.                     'liveVersionId' => hex2bin(Defaults::LIVE_VERSION),
  76.                     'productIds' => array_map('hex2bin'$productIds),
  77.                 ],
  78.                 [
  79.                     'productIds' => Connection::PARAM_STR_ARRAY,
  80.                 ],
  81.             );
  82.         });
  83.     }
  84. }