custom/plugins/UandiEfbErpSynchronization/src/Subscriber/ProductSubscriber.php line 66

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Uandi\UandiEfbErpSynchronization\Subscriber;
  3. use Monolog\Logger;
  4. use Shopware\Core\Checkout\Customer\CustomerEntity;
  5. use Shopware\Core\Content\Product\ProductDefinition;
  6. use Shopware\Core\Content\Product\ProductEntity;
  7. use Shopware\Core\Content\Product\ProductEvents;
  8. use Shopware\Core\Framework\Api\Context\SalesChannelApiSource;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  14. use Shopware\Core\PlatformRequest;
  15. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\RequestStack;
  19. use Uandi\UandiEfbErpSynchronization\Service\ApiConnectionServiceInterface;
  20. use Uandi\UandiEfbErpSynchronization\Service\Price\Import as PriceImportService;
  21. class ProductSubscriber implements EventSubscriberInterface
  22. {
  23.     /**
  24.      * Entity updated
  25.      */
  26.     const REQUEST_NAME 'PriceRequest';
  27.     private RequestStack $requestStack;
  28.     private EntityRepository $customerPriceRepository;
  29.     private ApiConnectionServiceInterface $soapService;
  30.     private PriceImportService $priceImportService;
  31.     private Logger $logger;
  32.     public function __construct(
  33.         RequestStack $requestStack,
  34.         EntityRepository $customerPriceRepository,
  35.         ApiConnectionServiceInterface $soapService,
  36.         PriceImportService $priceImportService,
  37.         Logger $logger
  38.     ) {
  39.         $this->requestStack $requestStack;
  40.         $this->customerPriceRepository $customerPriceRepository;
  41.         $this->soapService $soapService;
  42.         $this->priceImportService $priceImportService;
  43.         $this->logger $logger;
  44.     }
  45.     /**
  46.      * @return string[]
  47.      */
  48.     public static function getSubscribedEvents(): array
  49.     {
  50.         return [
  51.             ProductEvents::PRODUCT_LOADED_EVENT => 'onProductLoaded'
  52.         ];
  53.     }
  54.     /**
  55.      * Updates prices per customer on product load
  56.      *
  57.      * @param EntityLoadedEvent $event
  58.      */
  59.     public function onProductLoaded(EntityLoadedEvent $event): void
  60.     {
  61.         if ($event->getDefinition() instanceof ProductDefinition
  62.             && $this->requestStack->getCurrentRequest() instanceof Request
  63.         ) {
  64.             $source $event->getContext()->getSource();
  65.             if ($source instanceof SalesChannelApiSource) {
  66.                 /** @var SalesChannelContext $salesChannelContext */
  67.                 $salesChannelContext $this->requestStack->getCurrentRequest()->attributes->get(
  68.                     PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT
  69.                 );
  70.                 // check if customer is logged in
  71.                 if ($salesChannelContext instanceof SalesChannelContext
  72.                     && $salesChannelContext->getCustomer() instanceof CustomerEntity
  73.                 ) {
  74.                     $currentCustomer $salesChannelContext->getCustomer();
  75.                     $customerPricesResult $this->customerPriceRepository
  76.                         ->search(
  77.                             (new Criteria())
  78.                                 ->addFilter(
  79.                                     new EqualsFilter('customerId'$currentCustomer->getId()),
  80.                                     new EqualsAnyFilter('productId'$event->getIds())
  81.                                 ),
  82.                             $event->getContext()
  83.                         );
  84.                     // get products which needs to be updated
  85.                     $productsToUpdate $this->getProductsToUpdate($customerPricesResult$event->getEntities());
  86.                     if ($productsToUpdate === []) {
  87.                         return;
  88.                     }
  89.                     // create request array
  90.                     $priceRequestArray $this->createPriceRequestArray($productsToUpdate$currentCustomer->getCustomerNumber());
  91.                     // request prices from the ERP
  92.                     $newCustomerPrices $this->requestErpPrice($priceRequestArray$salesChannelContext->getSalesChannelId());
  93.                     //import prices to CustomerPriceEntity
  94.                     $this->priceImportService->execute($newCustomerPrices$currentCustomer->getId(), $productsToUpdate$event->getContext());
  95.                     /**
  96.                      * @see \VioCustomerPrice\Subscriber\ProductSubscriber
  97.                      */
  98.                     $customerPricesResult $this->customerPriceRepository
  99.                         ->search(
  100.                             (new Criteria())
  101.                                 ->addFilter(
  102.                                     new EqualsFilter('customerId'$salesChannelContext->getCustomer()->getId()),
  103.                                     new EqualsAnyFilter('productId'array_keys($productsToUpdate))
  104.                                 ),
  105.                             $event->getContext()
  106.                         );
  107.                     /** @var ProductEntity $product */
  108.                     foreach ($event->getEntities() as $product) {
  109.                         if (!array_key_exists($product->getId(), $productsToUpdate)) {
  110.                             continue;
  111.                         }
  112.                         $customerPrices $customerPricesResult->filterByProperty('productId'$product->getId());
  113.                         if ($product->hasExtension('customerPrices')) {
  114.                             $product->removeExtension('customerPrices');
  115.                         }
  116.                         $product->addExtension('customerPrices'$customerPrices->getEntities());
  117.                     }
  118.                 }
  119.             }
  120.         }
  121.     }
  122.     /**
  123.      * Returns an array of products needs to be updated
  124.      * productId=>productNumber
  125.      *
  126.      * @param $customerPricesResult
  127.      * @param $productsLoaded
  128.      *
  129.      * @return array
  130.      */
  131.     private function getProductsToUpdate($customerPricesResult$productsLoaded): array
  132.     {
  133.         $productNumbersToUpdate = [];
  134.         $customerPrices $customerPricesResult->getElements();
  135.         $customerPriceProductIds = [];
  136.         foreach ($customerPrices as $customerPrice) {
  137.             $customerPriceProductIds[] = $customerPrice->getProductId();
  138.         }
  139.         // products with graduated prices
  140.         $customerPriceProductIds array_unique($customerPriceProductIds);
  141.         foreach ($productsLoaded as $product) {
  142.             //request price only for variants
  143.             if (null === $product->getParentId()) {
  144.                 continue;
  145.             }
  146.             if (!in_array($product->getId(), $customerPriceProductIds)) {
  147.                 $productNumbersToUpdate[$product->getId()] = $product->getProductNumber();
  148.             }
  149.         }
  150.         return $productNumbersToUpdate;
  151.     }
  152.     /**
  153.      * Creates price request array
  154.      *
  155.      *     $value =[
  156.      *          "customer_number" => 11129100,
  157.      *          "product_list" => [
  158.      *              'K5510.2',
  159.      *              'K5510.10',
  160.      *              'E-20071'
  161.      *          ]
  162.      *      ];
  163.      *
  164.      * @param $productNumbers
  165.      * @param $customerNumber
  166.      *
  167.      * @return array
  168.      */
  169.     public function createPriceRequestArray($productNumbers$customerNumber): array
  170.     {
  171.         if (empty($productNumbers) || empty($customerNumber)) {
  172.             return [];
  173.         }
  174.         $requestArray['customer_number'] = $customerNumber;
  175.         foreach ($productNumbers as $productNumber) {
  176.             $requestArray['product_list'][] = $productNumber;
  177.         }
  178.         return $requestArray;
  179.     }
  180.     /**
  181.      * Request price from the ERP
  182.      *
  183.      * @param array $requestArray
  184.      * @param string $salesChannelId
  185.      * @return array
  186.      */
  187.     public function requestErpPrice(array $requestArraystring $salesChannelId): array
  188.     {
  189.         return $this->soapService->execute($requestArrayself::REQUEST_NAME$salesChannelId);
  190.     }
  191. }