Skip to content

Commit

Permalink
[TASK] Listen to ProcessOrderCheckStock event
Browse files Browse the repository at this point in the history
Relates: #138
  • Loading branch information
extcode committed Oct 10, 2024
1 parent 616c955 commit 46b3369
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 0 deletions.
33 changes: 33 additions & 0 deletions Classes/Domain/DoctrineRepository/Product/BeVariantRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Extcode\CartProducts\Domain\DoctrineRepository\Product;

/*
* This file is part of the package extcode/cart-products.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

use TYPO3\CMS\Core\Database\ConnectionPool;

class BeVariantRepository
{
public function __construct(
private readonly ConnectionPool $connectionPool
) {}

public function getStock(int $uid): int
{
$productConnection = $this->connectionPool->getConnectionForTable('tx_cartproducts_domain_model_product_bevariant');

$productQueryBuilder = $productConnection->createQueryBuilder();

return $productQueryBuilder
->select('stock')
->from('tx_cartproducts_domain_model_product_bevariant')
->where(
$productQueryBuilder->expr()->eq('uid', $productQueryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
)->executeQuery()->fetchOne();
}
}
33 changes: 33 additions & 0 deletions Classes/Domain/DoctrineRepository/Product/ProductRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Extcode\CartProducts\Domain\DoctrineRepository\Product;

/*
* This file is part of the package extcode/cart-products.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

use TYPO3\CMS\Core\Database\ConnectionPool;

class ProductRepository
{
public function __construct(
private readonly ConnectionPool $connectionPool
) {}

public function getStock(int $uid): int
{
$productConnection = $this->connectionPool->getConnectionForTable('tx_cartproducts_domain_model_product_product');

$productQueryBuilder = $productConnection->createQueryBuilder();

return $productQueryBuilder
->select('stock')
->from('tx_cartproducts_domain_model_product_product')
->where(
$productQueryBuilder->expr()->eq('uid', $productQueryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
)->executeQuery()->fetchOne();
}
}
92 changes: 92 additions & 0 deletions Classes/EventListener/Order/Stock/CheckStock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

namespace Extcode\CartProducts\EventListener\Order\Stock;

/*
* This file is part of the package extcode/cart-products.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

use Extcode\Cart\Domain\Model\Cart\BeVariant as CartProductBeVariant;
use Extcode\Cart\Domain\Model\Cart\Product as CartProduct;
use Extcode\Cart\Event\ProcessOrderCheckStockEvent;
use Extcode\CartProducts\Domain\DoctrineRepository\Product\BeVariantRepository;
use Extcode\CartProducts\Domain\DoctrineRepository\Product\ProductRepository;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;

class CheckStock
{
private ProcessOrderCheckStockEvent $event;

public function __construct(
private readonly ProductRepository $productRepository,
private readonly BeVariantRepository $beVariantRepository,
) {}

public function __invoke(ProcessOrderCheckStockEvent $event): void
{
$this->event = $event;
$cart = $event->getCart();
$cartProducts = $cart->getProducts();

foreach ($cartProducts as $cartProduct) {
if ($cartProduct->getProductType() !== 'CartProducts' || $cartProduct->isHandleStock() === false) {
continue;
}

if ($cartProduct->isHandleStockInVariants()) {
foreach ($cartProduct->getBeVariants() as $cartProductBeVariant) {
$this->checkStockForBackendVariant($cartProductBeVariant, $cartProduct);
}
} else {
$this->checkStockForProduct($cartProduct);
}
}
}

private function checkStockForProduct(CartProduct $cartProduct): void
{
$quantityInStock = $this->productRepository->getStock($cartProduct->getProductId());

if ($quantityInStock < $cartProduct->getQuantity()) {
$this->falseAvailability($this->event, $cartProduct->getTitle(), $cartProduct->getSku(), $quantityInStock);
}
}

public function checkStockForBackendVariant(CartProductBeVariant $cartProductBeVariant, CartProduct $cartProduct): void
{
$quantityInStock = $this->beVariantRepository->getStock($cartProductBeVariant->getId());

if ($quantityInStock < $cartProductBeVariant->getQuantity()) {
$this->falseAvailability($this->event, $cartProduct->getTitle(), $cartProductBeVariant->getSku(), $quantityInStock);
}
}

private function falseAvailability(
ProcessOrderCheckStockEvent $event,
string $title,
string $sku,
int $quantityInStock
): void {
$event->setNotEveryProductAvailable();
$event->addInsufficientStockMessage(
GeneralUtility::makeInstance(
FlashMessage::class,
LocalizationUtility::translate(
'tx_cart.error.stock_handling.order',
'cart',
[$title, $sku, $quantityInStock]
),
'',
ContextualFeedbackSeverity::ERROR
)
);
}
}
6 changes: 6 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ services:
identifier: 'cart-products--check-product-availability'
event: Extcode\Cart\Event\CheckProductAvailabilityEvent

Extcode\CartProducts\EventListener\Order\Stock\CheckStock:
tags:
- name: event.listener
identifier: 'cart-products--order--stock-check-stock'
event: Extcode\Cart\Event\ProcessOrderCheckStockEvent

Extcode\CartProducts\Reaction\UpdateStockReaction:
tags: ['reactions.reaction']
public: true
Expand Down

0 comments on commit 46b3369

Please sign in to comment.