<?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;
public function __construct(
RequestStack $requestStack,
EntityManagerInterface $em,
StockService $stockService
) {
$this->requestStack = $requestStack;
$this->em = $em;
$this->stockService = $stockService;
}
/**
* @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();
if ($receiptNote->getLines()->count()) {
$receiptNoteLineClassName = 'Bluue\SuppliersOrdersBundle\Entity\ReceiptNoteLine';
foreach ($receiptNote->getLines() as $receiptNoteLine) {
$quantity = (int) $receiptNoteLine->getQuantityReceived();
if (
$quantity === 0 ||
(
!$receiptNoteLine->getStockLocation() &&
!$receiptNoteLine->getLocation() &&
!$receiptNoteLine->getSubLocation()
)
) {
continue;
}
if ($stockLoc = $receiptNoteLine->getStockLocation()) {
$stockQuantity = new StockQuantity();
$stockQuantity->setQuantityEntry($quantity);
$stockQuantity->setWholesalePrice($receiptNoteLine->getWholesalePrice());
$stockQuantity->addOptions([$receiptNoteLineClassName => $receiptNoteLine->getId()]);
$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
/** @var StockProductRepository $stockProductRepo */
$stockProductRepo = $this->em->getRepository(StockProduct::class);
$reqStockProduct = $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();
$stockProduct->setProduct($product);
$stockProduct->setDeclination($declination);
$stockProduct->setWarehouse($warehouse);
$this->em->persist($stockProduct);
}
// Check stock location
/** @var StockLocationRepository $stockLocRepo */
$stockLocRepo = $this->em->getRepository(StockLocation::class);
$stockLocsQueryBuilder = $stockLocRepo->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();
$stockLoc->setLocation($receiptNoteLine->getLocation());
$stockLoc->setSubLocation($receiptNoteLine->getSubLocation());
$stockLoc->setDateType($receiptNoteLine->getDateType());
$stockLoc->setDate($receiptNoteLine->getDate());
$stockLoc->setBatchNumber($receiptNoteLine->getBatchNumber());
$stockLoc->setStockProduct($stockProduct);
$this->em->persist($stockLoc);
}
$stockQuantity = new StockQuantity();
$stockQuantity->setQuantityEntry($quantity);
$stockQuantity->setStockLocation($stockLoc);
$stockQuantity->setWholesalePrice($receiptNoteLine->getWholesalePrice());
$stockQuantity->addOptions([$receiptNoteLineClassName => $receiptNoteLine->getId()]);
$this->em->persist($stockQuantity);
$stockLoc->addStockQuantity($stockQuantity);
$stockProduct->addStockLocation($stockLoc);
// Search existing stock with same parameters
}
$this->em->flush();
}
}
}
}