custom/plugins/PickwareErpStarter/src/Stock/WarehouseStockUpdater.php line 38

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\PickwareErpStarter\Stock\Model\StockMovementDefinition;
  13. use Shopware\Core\Defaults;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  15. use Shopware\Core\Framework\Uuid\Uuid;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. class WarehouseStockUpdater implements EventSubscriberInterface
  18. {
  19.     /**
  20.      * @var Connection
  21.      */
  22.     private $db;
  23.     public function __construct(Connection $db)
  24.     {
  25.         $this->db $db;
  26.     }
  27.     public static function getSubscribedEvents(): array
  28.     {
  29.         return [StockMovementDefinition::ENTITY_WRITTEN_EVENT => 'stockMovementWritten'];
  30.     }
  31.     public function stockMovementWritten(EntityWrittenEvent $entityWrittenEvent): void
  32.     {
  33.         if ($entityWrittenEvent->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  34.             return;
  35.         }
  36.         $stockMovementIds = [];
  37.         foreach ($entityWrittenEvent->getWriteResults() as $writeResult) {
  38.             if ($writeResult->getExistence()->exists()) {
  39.                 // Updating stock movements is not supported yet
  40.                 // In case a stock location is deleted, this code path is also reached. This is because an
  41.                 // EntityWrittenEvent is triggered when an entity field gets null-ed because of a SET NULL constraint
  42.                 // of a FK.
  43.                 continue;
  44.             }
  45.             $payload $writeResult->getPayload();
  46.             $stockMovementIds[] = $payload['id'];
  47.         }
  48.         $this->indexStockMovements($stockMovementIds);
  49.     }
  50.     public function indexStockMovements(array $stockMovementIds): void
  51.     {
  52.         $stockMovementIds array_values(array_unique($stockMovementIds));
  53.         $stockMovements $this->db->fetchAllAssociative(
  54.             'SELECT
  55.                 LOWER(HEX(product_id)) AS productId,
  56.                 LOWER(HEX(product_version_id)) AS productVersionId,
  57.                 quantity,
  58.                 LOWER(HEX(COALESCE(
  59.                     source_warehouse_id,
  60.                     sourceStockContainer.warehouse_id,
  61.                     sourceBinLocation.warehouse_id
  62.                 ))) AS sourceWarehouseId,
  63.                 LOWER(HEX(COALESCE(
  64.                     destination_warehouse_id,
  65.                     destinationStockContainer.warehouse_id,
  66.                     destinationBinLocation.warehouse_id
  67.                 ))) AS destinationWarehouseId
  68.             FROM pickware_erp_stock_movement stockMovement
  69.             LEFT JOIN pickware_erp_stock_container sourceStockContainer ON sourceStockContainer.id = stockMovement.source_stock_container_id
  70.             LEFT JOIN pickware_erp_bin_location sourceBinLocation ON sourceBinLocation.id = stockMovement.source_bin_location_id
  71.             LEFT JOIN pickware_erp_stock_container destinationStockContainer ON destinationStockContainer.id = stockMovement.destination_stock_container_id
  72.             LEFT JOIN pickware_erp_bin_location destinationBinLocation ON destinationBinLocation.id = stockMovement.destination_bin_location_id
  73.             WHERE stockMovement.id IN (:stockMovementIds) AND product_version_id = :liveVersionId',
  74.             [
  75.                 'stockMovementIds' => array_map('hex2bin'$stockMovementIds),
  76.                 'liveVersionId' => hex2bin(Defaults::LIVE_VERSION),
  77.             ],
  78.             [
  79.                 'stockMovementIds' => Connection::PARAM_STR_ARRAY,
  80.             ],
  81.         );
  82.         // Update warehouse stocks if stock was moved to or from a warehouse or bin location (in that warehouse) or
  83.         // stock container (in that warehouse).
  84.         foreach ($stockMovements as $stockMovement) {
  85.             if ($stockMovement['sourceWarehouseId']) {
  86.                 $this->persistWarehouseStockChange([
  87.                     'productId' => $stockMovement['productId'],
  88.                     'productVersionId' => $stockMovement['productVersionId'],
  89.                     'warehouseId' => $stockMovement['sourceWarehouseId'],
  90.                     'changeAmount' => -$stockMovement['quantity'],
  91.                 ]);
  92.             }
  93.             if ($stockMovement['destinationWarehouseId']) {
  94.                 $this->persistWarehouseStockChange([
  95.                     'productId' => $stockMovement['productId'],
  96.                     'productVersionId' => $stockMovement['productVersionId'],
  97.                     'warehouseId' => $stockMovement['destinationWarehouseId'],
  98.                     'changeAmount' => $stockMovement['quantity'],
  99.                 ]);
  100.             }
  101.         }
  102.     }
  103.     private function persistWarehouseStockChange(array $payload): void
  104.     {
  105.         $this->db->executeStatement(
  106.             'INSERT INTO pickware_erp_warehouse_stock (
  107.                 id,
  108.                 product_id,
  109.                 product_version_id,
  110.                 quantity,
  111.                 warehouse_id,
  112.                 created_at
  113.             ) VALUES (
  114.                 :id,
  115.                 :productId,
  116.                 :productVersionId,
  117.                 :changeAmount,
  118.                 :warehouseId,
  119.                 NOW(3)
  120.             ) ON DUPLICATE KEY UPDATE
  121.                 quantity = quantity + VALUES(quantity),
  122.                 updated_at = NOW(3)',
  123.             [
  124.                 'id' => Uuid::randomBytes(),
  125.                 'productId' => hex2bin($payload['productId']),
  126.                 'productVersionId' => hex2bin($payload['productVersionId']),
  127.                 'warehouseId' => hex2bin($payload['warehouseId']),
  128.                 'changeAmount' => $payload['changeAmount'],
  129.             ],
  130.         );
  131.     }
  132. }