<?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\SuppliersOrdersBundle;
use App\Services\CheckBundleInstall;
use Doctrine\ORM\EntityManagerInterface;
use Bluue\StocksBundle\Entity\StockProduct;
use Bluue\StocksBundle\Entity\StockLocation;
use Bluue\StocksBundle\Entity\StockQuantity;
use Bluue\StocksBundle\Services\StockService;
use Symfony\Component\HttpFoundation\RequestStack;
use Bluue\StocksBundle\Repository\StockProductRepository;
use Bluue\StocksBundle\Repository\StockLocationRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ReceiptNoteSubscriber implements EventSubscriberInterface
{
/**
* @var RequestStack $requestStack
*/
protected RequestStack $requestStack;
/**
* @var EntityManagerInterface $em
*/
private EntityManagerInterface $em;
/**
* @var StockService $stockService
*/
private StockService $stockService;
/**
* @var StockProductRepository $stockProductRepo
*/
private StockProductRepository $stockProductRepo;
/**
* @var StockLocationRepository $stockLocationRepo
*/
private StockLocationRepository $stockLocationRepo;
public function __construct(
RequestStack $requestStack,
EntityManagerInterface $em,
StockService $stockService,
StockProductRepository $stockProductRepo,
StockLocationRepository $stockLocationRepo
) {
$this->requestStack = $requestStack;
$this->em = $em;
$this->stockService = $stockService;
$this->stockProductRepo = $stockProductRepo;
$this->stockLocationRepo = $stockLocationRepo;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
if (CheckBundleInstall::exist('suppliers-orders-bundle')) {
$reflectionClass = new \ReflectionClass('Bluue\SuppliersOrdersBundle\Event\ReceiptNoteEvent');
return [
$reflectionClass->getConstant('POST_VALIDATE') => 'validateReceipt'
];
}
return [];
}
public function validateReceipt(object $event)
{
$receiptNote = $event->getReceiptNote();
$eventReceiptNoteLine = $event->getReceiptNoteLine();
$user = $eventReceiptNoteLine ? $eventReceiptNoteLine->getUpdatedBy() : $receiptNote->getValidatedBy();
if ($receiptNote->getLines()->count()) {
$receiptNoteLineClassName = 'Bluue\SuppliersOrdersBundle\Entity\ReceiptNoteLine';
foreach ($receiptNote->getLines() as $receiptNoteLine) {
if ($eventReceiptNoteLine && $eventReceiptNoteLine != $receiptNoteLine) {
continue;
}
if (!$eventReceiptNoteLine && $receiptNoteLine->getQuantityRemaining() == 0) {
continue;
}
$quantity = (int) $receiptNoteLine->getQuantityReceived();
if (
$quantity === 0 ||
(
!$receiptNoteLine->getStockLocation() &&
!$receiptNoteLine->getLocation() &&
!$receiptNoteLine->getSubLocation()
)
) {
continue;
}
if ($stockLoc = $receiptNoteLine->getStockLocation()) {
$stockQuantity = (new StockQuantity())
->setQuantityEntry($quantity)
->setWholesalePrice($receiptNoteLine->getWholesalePrice())
->addOptions([$receiptNoteLineClassName => $receiptNoteLine->getId()])
->setCreatedBy($user)
->setUpdatedBy($user)
;
$stockLoc->addStockQuantity($stockQuantity);
$this->em->persist($stockQuantity);
} else {
// Get product and declination.
$supplierOrderLine = $receiptNoteLine->getSupplierOrderLine();
$product = $supplierOrderLine->getProduct() ?? $supplierOrderLine->getDeclination()->getProduct();
$declination = $supplierOrderLine->getDeclination();
if ($receiptNoteLine->getSubLocation()) {
$location = $receiptNoteLine->getSubLocation()->getLocation();
$subLoc = $receiptNoteLine->getSubLocation();
// Assign automatic-location by width comparaison
if ($subLoc->getLocation()->getIsDefaultForEmptySubLocation()) {
$autoAssignLocation = $this->stockService->foundLocationByEmptyVolumeForSubLocation(
$subLoc
);
if ($autoAssignLocation) {
$subLoc->setLocation($autoAssignLocation);
$location = $subLoc->getLocation();
}
}
} else {
$location = $receiptNoteLine->getLocation();
}
$warehouse = $location->getWarehouse();
// Check stock product
$reqStockProduct = $this->stockProductRepo->createQueryBuilder('sp')
->andWhere('sp.warehouse = :warehouse')
->andWhere('sp.product = :product')
->setParameter('warehouse', $warehouse->getId()->toBinary())
->setParameter('product', $product->getId()->toBinary());
if ($declination) {
$reqStockProduct = $reqStockProduct
->andWhere('sp.declination = :declination')
->setParameter('declination', $declination->getId()->toBinary());
} else {
$reqStockProduct = $reqStockProduct
->andWhere('sp.declination IS NULL');
}
$stockProduct = $reqStockProduct->setMaxResults(1)->getQuery()->getOneOrNullResult();
if (!$stockProduct) {
$stockProduct = (new StockProduct())
->setProduct($product)
->setDeclination($declination)
->setWarehouse($warehouse)
->setCreatedBy($user)
->setUpdatedBy($user)
;
$this->em->persist($stockProduct);
}
// Check stock location
$stockLocsQueryBuilder = $this->stockLocationRepo->createQueryBuilder('sl')
->join('sl.stockProduct', 'sp')
->andWhere('sp.warehouse = :warehouse')
->andWhere('sp.product = :product')
->setParameter('product', $product->getId()->toBinary())
->setParameter('warehouse', $warehouse->getId()->toBinary())
;
if ($supplierOrderLine->getDeclination()) {
$stockLocsQueryBuilder->andWhere('sp.declination = :declination')
->setParameter('declination', $supplierOrderLine->getDeclination()->getId()->toBinary());
} else {
$stockLocsQueryBuilder->andWhere('sp.declination IS NULL');
}
if ($receiptNoteLine->getLocation()) {
$stockLocsQueryBuilder->andWhere('sl.location = :location')
->setParameter('location', $receiptNoteLine->getLocation()->getId()->toBinary());
} else {
$stockLocsQueryBuilder->andWhere('sl.location IS NULL');
}
if ($receiptNoteLine->getSubLocation()) {
$stockLocsQueryBuilder->andWhere('sl.subLocation = :sub_location')
->setParameter('sub_location', $receiptNoteLine->getSubLocation()->getId()->toBinary());
} else {
$stockLocsQueryBuilder->andWhere('sl.subLocation IS NULL');
}
if ($receiptNoteLine->getBatchNumber()) {
$stockLocsQueryBuilder->andWhere('sl.batch_number = :batchNumber')
->setParameter('batchNumber', $receiptNoteLine->getBatchNumber());
} else {
$stockLocsQueryBuilder->andWhere('sl.batch_number IS NULL');
}
if ($receiptNoteLine->getDateType()) {
$stockLocsQueryBuilder->andWhere('sl.dateType = :dateType')
->setParameter('dateType', $receiptNoteLine->getDateType()->getId()->toBinary());
} else {
$stockLocsQueryBuilder->andWhere('sl.dateType IS NULL');
}
if ($receiptNoteLine->getDate()) {
$stockLocsQueryBuilder->andWhere('sl.date = :date')
->setParameter('date', $receiptNoteLine->getDate());
} else {
$stockLocsQueryBuilder->andWhere('sl.date IS NULL');
}
$stockLoc = $stockLocsQueryBuilder->setMaxResults(1)->getQuery()->getOneOrNullResult();
if (!$stockLoc) {
$stockLoc = (new StockLocation())
->setLocation($receiptNoteLine->getLocation())
->setSubLocation($receiptNoteLine->getSubLocation())
->setDateType($receiptNoteLine->getDateType())
->setDate($receiptNoteLine->getDate())
->setBatchNumber($receiptNoteLine->getBatchNumber())
->setStockProduct($stockProduct)
->setCreatedBy($user)
->setUpdatedBy($user)
;
$this->em->persist($stockLoc);
}
$stockQuantity = (new StockQuantity())
->setQuantityEntry($quantity)
->setStockLocation($stockLoc)
->setWholesalePrice($receiptNoteLine->getWholesalePrice())
->addOptions([$receiptNoteLineClassName => $receiptNoteLine->getId()])
->setCreatedBy($user)
->setUpdatedBy($user)
;
$this->em->persist($stockQuantity);
$stockLoc->addStockQuantity($stockQuantity);
$stockProduct->addStockLocation($stockLoc);
// Search existing stock with same parameters
}
$this->em->flush();
}
}
}
}