<?php
/**
* @author Léo BANNHOLTZER (contact@scaledev.fr)
* @copyright 2021 - ScaleDEV SAS, 12 RUE CHARLES MORET, 10120 ST ANDRE LES VERGERS
* @license commercial
*/
declare(strict_types=1);
namespace Bluue\StocksBundle\EventSubscriber\SalesBundle;
use ReflectionClass;
use App\Services\Configuration;
use Symfony\Component\Uid\UuidV6;
use App\Services\SoftdeleteFilter;
use App\Services\CheckBundleInstall;
use Bluue\SalesBundle\Entity\DeliveryNote;
use Bluue\SalesBundle\Entity\DeliveryNoteLine;
use Bluue\StocksBundle\Entity\Location;
use Doctrine\ORM\EntityManagerInterface;
use Bluue\StocksBundle\Entity\SubLocation;
use Bluue\StocksBundle\Entity\StockProduct;
use Bluue\StocksBundle\Entity\StockLocation;
use Bluue\StocksBundle\Entity\StockQuantity;
use Bluue\StocksBundle\Services\StockService;
use Bluue\StocksBundle\Entity\StockProductRoot;
use Symfony\Component\HttpFoundation\RequestStack;
use Bluue\StocksBundle\Repository\StockMovementRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Bluue\StocksBundle\Repository\StockMovementReasonRepository;
class DeliveryNoteSubscriber implements EventSubscriberInterface
{
protected RequestStack $requestStack;
private StockMovementRepository $stockMovementRepo;
private Configuration $configuration;
private StockMovementReasonRepository $stockMovementReasonRepo;
private StockService $stockService;
private EntityManagerInterface $em;
public function __construct(
RequestStack $requestStack,
StockMovementRepository $stockMovementRepo,
StockMovementReasonRepository $stockMovementReasonRepo,
Configuration $configuration,
StockService $stockService,
EntityManagerInterface $em
) {
$this->requestStack = $requestStack;
$this->stockMovementRepo = $stockMovementRepo;
$this->stockMovementReasonRepo = $stockMovementReasonRepo;
$this->configuration = $configuration;
$this->stockService = $stockService;
$this->em = $em;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
if (CheckBundleInstall::exist('sales-bundle')) {
$reflectionClass = new ReflectionClass('Bluue\SalesBundle\Event\DeliveryNoteMovementsEvent');
return [
$reflectionClass->getConstant('VALIDATE_DELIVERY') => 'validateDelivery',
$reflectionClass->getConstant('CANCEL_DELIVERY') => 'cancelDelivery'
];
}
return [];
}
/**
* @param object $event
* @return void
*/
public function validateDelivery(object $event): void
{
/** @var DeliveryNote $deliveryNote */
$deliveryNote = $event->getDeliveryNote();
if ($deliveryNote->getProductLines()->count()) {
$stockMovementReason = $this->configuration
->get('stocks_bundle__default_stock_movement_reason__delivery_note_validate');
if ($stockMovementReason) {
$stockMovementReason = $this->stockMovementReasonRepo->find($stockMovementReason);
}
foreach ($deliveryNote->getProductLines() as $productLine) {
$options = $productLine->getOptions();
if (
(array_key_exists('no_remove_stock', $options) && $options['no_remove_stock'])
|| $productLine->getIsPack()
) {
continue;
}
$quantity = intval($productLine->getQuantity());
if (!empty($options['product']['virtual_quantity'])) {
$quantity *= intval($options['product']['virtual_quantity']);
}
$this->stockService->processStockOut(
new UuidV6($options['product']['id']),
($productLine->isDeclination() ? new UuidV6($options['product']['declination_id']) : null),
$quantity,
$stockMovementReason,
$deliveryNote->getContext()->getId(),
[
'deliveryNote' => $deliveryNote,
'deliveryNoteLine' => $productLine
],
null,
$deliveryNote->getEstablishment() ? $deliveryNote->getEstablishment()->getId()->toRfc4122() : null
);
}
$this->stockService->dispatchMessageRemainingQuantityOrdered($deliveryNote->getOrder());
}
}
/**
* @param object $event
* @return void
*/
public function cancelDelivery(object $event): void
{
$productLines = $event->getDeliveryNote()->getProductLines();
if ($productLines->count()) {
SoftdeleteFilter::disable($this->em, [
StockQuantity::class,
StockLocation::class,
StockProduct::class,
StockProductRoot::class,
Location::class,
SubLocation::class
]);
$stockMovementReason = $this->configuration
->get('stocks_bundle__default_stock_movement_reason__delivery_note_cancel');
if ($stockMovementReason) {
$stockMovementReason = $this->stockMovementReasonRepo->find($stockMovementReason);
}
$stockMovements = [];
foreach ($productLines as $productLine) {
$stockMovements = array_merge(
$stockMovements,
$this->stockMovementRepo->findBy(['entityId' => $productLine->getId()])
);
}
foreach ($stockMovements as $stockMovement) {
$sq = $stockMovement->getStockQuantity();
if ($sq->isDeleted()) {
$stockQuantity = new StockQuantity();
$stockQuantity->setQuantityEntry(intval($stockMovement->getQuantity()));
$stockQuantity->setReason($stockMovementReason);
$stockQuantity->setOptions([
DeliveryNote::class => $event->getDeliveryNote()->getId(),
DeliveryNoteLine::class => $stockMovement->getEntityId()
]);
$mvStockQuantity = $sq;
$stockLocation = $sq->getStockLocation();
$stockProduct = $stockLocation->getStockProduct();
if ($stockProduct->isDeleted()) {
$stockProduct->setDeletedAt();
$stockProduct->setDeletedBy();
$stockLocation->setStockProduct($stockProduct);
}
if ($stockLocation->isDeleted()) {
$stockLocation->setDeletedAt();
$stockLocation->setDeletedBy();
$mvStockQuantity->setStockLocation($stockLocation);
}
$location = $stockLocation->getLocation();
$subLoc = $stockLocation->getSubLocation();
if ($location && $location->isDeleted()) {
$location->setDeletedAt();
$location->setDeletedBy();
$stockLocation->setLocation($location);
}
if ($subLoc && $subLoc->isDeleted()) {
$subLoc->setDeletedAt();
$subLoc->setDeletedBy();
$stockLocation->setSubLocation($subLoc);
}
$stockMovement->setStockQuantity($mvStockQuantity);
$stockQuantity->setStockLocation($sq->getStockLocation());
$stockQuantity->setWholesalePrice($sq->getWholesalePrice());
$stockQuantity->setDateEntry($sq->getDateEntry());
$stockQuantity->setCurrencyChangeRate($sq->getCurrencyChangeRate());
$stockQuantity->setCurrency($sq->getCurrency());
$this->em->flush();
$this->em->persist($stockQuantity);
} else {
$this->stockService->updateStockQuantity(
$sq,
intval($stockMovement->getQuantity()),
$stockMovementReason,
[
DeliveryNote::class => $event->getDeliveryNote()->getId(),
DeliveryNoteLine::class => $stockMovement->getEntityId()
]
);
}
}
$this->em->flush();
$this->stockService->dispatchMessageRemainingQuantityOrdered($event->getDeliveryNote()->getOrder());
}
}
}