<?php
namespace App\EventSubscriber;
use App\Entity\CommandeChantier;
use App\Entity\LivraisonChantier;
use App\Entity\ProductCommande;
use App\Event\Chantier\CommandeChantierCreatedEvent;
use App\Event\Chantier\CommandeChantierDeletedEvent;
use App\Event\Chantier\CommandeChantierUpdatedEvent;
use App\Event\Chantier\LigneCommandeProductChantierCreatedEvent;
use App\Event\Produit\ProductCommandeEvent;
use App\Repository\LivraisonChantierRepository;
use App\Service\ProductHelper;
use Doctrine\ORM\EntityManagerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
class CommandeChantierSubscriber implements EventSubscriberInterface
{
private LivraisonChantierRepository $livraisonChantierRepository;
private EventDispatcherInterface $eventDispatcher;
private ProductHelper $productHelper;
private EntityManagerInterface $entityManager;
public function __construct(LivraisonChantierRepository $livraisonChantierRepository,
EventDispatcherInterface $eventDispatcher,
ProductHelper $productHelper,
EntityManagerInterface $entityManager)
{
$this->livraisonChantierRepository = $livraisonChantierRepository;
$this->eventDispatcher = $eventDispatcher;
$this->productHelper = $productHelper;
$this->entityManager = $entityManager;
}
public static function getSubscribedEvents(): array
{
return [
CommandeChantierCreatedEvent::class => ['onCommandeCreated', 100],
CommandeChantierUpdatedEvent::class => ['onCommandeUpdated', 100],
CommandeChantierDeletedEvent::class => ['onCommandeDeleted', 100],
LigneCommandeProductChantierCreatedEvent::class => ['onLigneCreated', 100]
];
}
public function onCommandeCreated(CommandeChantierCreatedEvent $event)
{
// Ajout de l'année en DB
$commande = $event->getCommande();
$this->setAnnee($commande);
$this->addToBl($commande);
}
public function onCommandeUpdated(CommandeChantierUpdatedEvent $event)
{
// Ajout de l'année en DB
$commande = $event->getCommande();
$this->setAnnee($commande);
}
public function onCommandeDeleted(CommandeChantierUpdatedEvent $event)
{
// On recalcule le ttc du BL
$commande = $event->getCommande();
$bl = $commande->getBonLivraison();
$bl->setTotalTtc($bl->getTotalTtc() - $commande->getMontantCommandeTtc());
}
private function setAnnee (CommandeChantier $commande) {
$semaineEncours = Date('W');
$annee = Date('Y');
if ($commande->getDateEnlevement() <= $semaineEncours) {
$annee++;
}
$commande->setAnneeEnlevement($annee);
}
/**
* Ajoute une commande à son BL
* Créé le BL si besoin
*
* @param CommandeChantier $commande
* @throws \Doctrine\ORM\NonUniqueResultException
*/
private function addToBl (CommandeChantier $commande) {
if (!$commande->getBonLivraison()) {
// On l'ajoute au BL
/** @var LivraisonChantier $bl */
$bl = $this->livraisonChantierRepository->findBl($commande->getStructure(), $commande->getDateEnlevement(), $commande->getAnneeEnlevement());
if ($bl) {
$bl->setTotalTtc($bl->getTotalTtc() + $commande->getMontantCommandeTtc());
} else {
// On créé le BL
// On prend le premier jour de la semaine
$date_enlevement = date_isodate_set(date_create(), $commande->getAnneeEnlevement(), $commande->getDateEnlevement());
$bl = new LivraisonChantier();
$bl->setStructure($commande->getStructure())
->setAnnee($commande->getAnneeEnlevement())
->setSemaine($commande->getDateEnlevement())
->setTotalTtc($commande->getMontantCommandeTtc())
->setDateEnlevement($date_enlevement);
}
$commande->setBonLivraison($bl);
}
}
public function onLigneCreated (LigneCommandeProductChantierCreatedEvent $event) {
$ligne = $event->getLigne();
$livraison = $event->getLivraison();
$tarif = $this->productHelper->getBestTarif($ligne->getProduct());
if (!$tarif) {
throw new \Exception("Ce produit ne possède pas de tarif");
}
$ligne->setTotalHt($tarif->getHt() * $ligne->getQuantite())
->setTotalTtc($tarif->getTtc() * $ligne->getQuantite())
->setTtc($tarif->getTtc())
->setHt($tarif->getHt())
->setTaxe($tarif->getTva())
->setReference($tarif->getReference());
if ($livraison->getProductCommandes()->isEmpty()) {
// On créé la commande
$commande = new ProductCommande();
$commande->setLivraisonChantier($livraison)
->setStructure($livraison->getStructure())
->setFournisseur($tarif->getFournisseur())
->setDateLivraison($livraison->getDateEnlevement());
$commande->addLigne($ligne);
$this->entityManager->persist($commande);
$ligne->setCommande($commande);
$livraison->addProductCommande($commande);
} else {
$commande = $livraison->getProductCommandes()->first();
$ligne->setCommande($commande);
$commande->addLigne($ligne);
}
// On met à jour le montant du camion
$livraison->setTotalTtc($livraison->getTotalTtc() + $tarif->getTtc() * $ligne->getQuantite());
$this->entityManager->flush();
$this->eventDispatcher->dispatch(new ProductCommandeEvent($commande, new Request()));
}
}