Files
ludikevent_crm/src/Controller/Dashboard/DevisController.php

328 lines
14 KiB
PHP
Raw Normal View History

<?php
namespace App\Controller\Dashboard;
use App\Entity\CustomerAddress;
use App\Entity\Devis;
2026-01-17 22:29:04 +01:00
use App\Entity\DevisLine;
use App\Entity\DevisOptions;
use App\Event\Signature\DevisSend;
use App\Form\NewDevisType;
use App\Logger\AppLogger;
use App\Repository\AccountRepository;
use App\Repository\CustomerAddressRepository;
2026-01-17 22:29:04 +01:00
use App\Repository\CustomerRepository;
use App\Repository\DevisLineRepository;
use App\Repository\DevisOptionsRepository;
use App\Repository\DevisRepository;
use App\Repository\OptionsRepository;
use App\Repository\ProductRepository;
2026-01-17 22:29:04 +01:00
use App\Service\Pdf\DevisPdfService;
use App\Service\Signature\Client;
use DateTimeImmutable;
2026-01-17 22:29:04 +01:00
use Doctrine\ORM\EntityManagerInterface;
use Knp\Bundle\PaginatorBundle\KnpPaginatorBundle;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
2026-01-17 22:29:04 +01:00
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Attribute\Route;
class DevisController extends AbstractController
{
/**
* Liste des administrateurs
*/
#[Route(path: '/crm/devis', name: 'app_crm_devis', options: ['sitemap' => false], methods: ['GET', 'POST'])]
public function devis(
EventDispatcherInterface $eventDispatcher,
EntityManagerInterface $entityManager,
DevisRepository $devisRepository,
AppLogger $appLogger,
PaginatorInterface $paginator,
Request $request,
KernelInterface $kernel,
): Response
{
// Gestion du renvoi de la signature
if ($request->query->has('resend')) {
$quoteId = $request->query->get('resend');
$quote = $devisRepository->find($quoteId);
if ($quote instanceof Devis) {
// Déclenchement de l'événement de renvoi
$event = new DevisSend($quote);
$eventDispatcher->dispatch($event);
// Journalisation et notification
$appLogger->record('RESEND', 'Relance signature pour le devis ' . $quote->getNum());
$this->addFlash("success", "Le lien de signature pour le devis " . $quote->getNum() . " a été renvoyé au client.");
return $this->redirectToRoute('app_crm_devis');
}
$this->addFlash("error", "Devis introuvable.");
}
$appLogger->record('VIEW', 'Consultation de la liste des devis');
// Pagination (Tri décroissant sur la date de création pour voir les plus récents en premier)
$pagination = $paginator->paginate(
$devisRepository->findBy([], ['createA' => 'DESC']),
$request->query->getInt('page', 1),
20
);
return $this->render('dashboard/devis/list.twig', [
'quotes' => $pagination,
]);
}
#[Route(path: '/crm/devis/delete/{id}', name: 'app_crm_devis_delete', options: ['sitemap' => false], methods: ['GET', 'POST'])]
public function devisDelete(string $id, AppLogger $appLogger, Client $client, Request $request, DevisRepository $devisRepository, EntityManagerInterface $entityManager): Response
{
$customer = $devisRepository->find($id);
if (!$customer) {
$this->addFlash('error', 'Le devis demandé n\'existe pas.');
return $this->redirectToRoute('app_crm_devis');
}
$token = $request->query->get('_token');
if ($this->isCsrfTokenValid('delete' . $customer->getId(), $token)) {
$appLogger->record('DELETE', sprintf('Suppression définitive du devis : %s', $customer->getNum()));
if ($customer->getSignatureId() != "") {
$client->cancelSign($customer->getSignatureId());
}
foreach ($customer->getDevisLines() as $devisLine) {
$entityManager->remove($devisLine);
}
foreach ($customer->getDevisOptions() as $devisOption) {
$entityManager->remove($devisOption);
}
$entityManager->remove($customer);
$entityManager->flush();
$this->addFlash('success', sprintf('Le devis %s a été supprimé définitivement.', $customer->getNum()));
} else {
$this->addFlash('error', 'Jeton de sécurité invalide. La suppression a été annulée.');
}
return $this->redirectToRoute('app_crm_devis');
}
#[Route(path: '/crm/devis/add', name: 'app_crm_devis_add', options: ['sitemap' => false], methods: ['GET', 'POST'])]
public function devisAdd(Client $client, OptionsRepository $optionsRepository, EventDispatcherInterface $eventDispatcher, KernelInterface $kernel, CustomerAddressRepository $customerAddress, ProductRepository $productRepository, EntityManagerInterface $entityManager, CustomerRepository $customerRepository, DevisRepository $devisRepository, AppLogger $appLogger, Request $request): Response
{
$devisNumber = "DEVIS-" . sprintf('%05d', $devisRepository->count() + 1);
$appLogger->record('VIEW', 'Consultation de la création d\'un devis');
$devis = new Devis();
$devis->setNum($devisNumber);
$devis->setState("draft");
$devis->setCreateA(new \DateTimeImmutable());
$devis->setUpdateAt(new \DateTimeImmutable());
$form = $this->createForm(NewDevisType::class, $devis);
if ($request->isMethod('POST')) {
$devis->setStartAt(new DateTimeImmutable($_POST['new_devis']['startAt']));
$devis->setEndAt(new DateTimeImmutable($_POST['new_devis']['endAt']));
$interval = $devis->getStartAt()->diff($devis->getEndAt());
$day = $interval->days;
$devis->setBillAddress($customerAddress->find($_POST['devis']['bill_address']));
$devis->setAddressShip($customerAddress->find($_POST['devis']['ship_address']));
$devis->setCustomer($customerRepository->find($_POST['new_devis']['customer']));
foreach ($_POST['lines'] as $cd => $line) {
$rLine = new DevisLine();
$rLine->setDevi($devis);
$rLine->setPos($cd);
$rLine->setProduct($productRepository->find($line['product_id']));
$rLine->setDay($day);
$rLine->setPriceHt(floatval($line['price_ht']));
$rLine->setPriceHtSup(floatval($line['price_sup_ht']));
$entityManager->persist($rLine);
}
foreach ($_POST['options'] as $line) {
$rLineOptions = new DevisOptions();
$rLineOptions->setDevis($devis);
$rLineOptions->setOption($optionsRepository->find($line['product_id']));
$rLineOptions->setPriceHt(floatval($line['price_ht']));
$entityManager->persist($rLineOptions);
}
$entityManager->persist($devis);
$entityManager->flush();
$docusealService = new DevisPdfService($kernel, $devis, true);
$contentDocuseal = $docusealService->generate();
$tmpPathDocuseal = sys_get_temp_dir() . '/docuseal_' . uniqid() . '.pdf';
file_put_contents($tmpPathDocuseal, $contentDocuseal);
$fileDocuseal = new UploadedFile($tmpPathDocuseal, 'dc_' . $devis->getNum() . '.pdf', 'application/pdf', 0, true);
$devis->setDevisDocuSealFile($fileDocuseal);
$devisService = new DevisPdfService($kernel, $devis, false);
$contentDevis = $devisService->generate();
$tmpPathDevis = sys_get_temp_dir() . '/devis_' . uniqid() . '.pdf';
file_put_contents($tmpPathDevis, $contentDevis);
$fileDevis = new UploadedFile($tmpPathDevis, 'devis_' . $devis->getNum() . '.pdf', 'application/pdf', 0, true);
$devis->setDevisFile($fileDevis);
$devis->setState("created_waitsign");
$devis->setUpdateAt(new \DateTimeImmutable());
$entityManager->flush();
$client->createSubmissionDevis($devis);
$event = new DevisSend($devis);
$eventDispatcher->dispatch($event);
$this->addFlash('success', sprintf('Le devis %s a été crée.', $devis->getNum()));
return $this->redirectToRoute('app_crm_devis');
2026-01-17 22:29:04 +01:00
}
return $this->render('dashboard/devis/add.twig', [
'form' => $form->createView(),
'lines' => [
[
'product_id' => '',
'days'=>'',
'price_ht' => '',
'price_sup_ht' =>''
],
],
'options' => [
[
'product_id' => '',
'price_ht' => '',
]
]
]);
}
#[Route(path: '/crm/devis/{id}', name: 'app_crm_devis_edit', options: ['sitemap' => false], methods: ['GET', 'POST'])]
public function devisEdit(?Devis $devis,Client $client,DevisLineRepository $devisLineRepository,DevisOptionsRepository $devisOptionsRepository, OptionsRepository $optionsRepository, EventDispatcherInterface $eventDispatcher, KernelInterface $kernel, CustomerAddressRepository $customerAddress, ProductRepository $productRepository, EntityManagerInterface $entityManager, CustomerRepository $customerRepository, DevisRepository $devisRepository, AppLogger $appLogger, Request $request): Response
{
$appLogger->record('VIEW', 'Consultation pour modifier le devis '.$devis->getNum());
$form = $this->createForm(NewDevisType::class, $devis);
if ($request->isMethod('POST')) {
$devis->setStartAt(new DateTimeImmutable($_POST['new_devis']['startAt']));
$devis->setEndAt(new DateTimeImmutable($_POST['new_devis']['endAt']));
$devis->setBillAddress($customerAddress->find($_POST['devis']['bill_address']));
$devis->setAddressShip($customerAddress->find($_POST['devis']['ship_address']));
$devis->setCustomer($customerRepository->find($_POST['new_devis']['customer']));
foreach ($_POST['lines'] as $cd => $line) {
$rLine = $devisLineRepository->find($line['id']);
$rLine->setDevi($devis);
$rLine->setPos($cd);
$rLine->setProduct($productRepository->find($line['product_id']));
$rLine->setDay($line['days']);
$rLine->setPriceHt(floatval($line['price_ht']));
$rLine->setPriceHtSup(floatval($line['price_sup_ht']));
$entityManager->persist($rLine);
}
foreach ($_POST['options'] as $line) {
$rLineOptions = $devisOptionsRepository->find($line['id']);
$rLineOptions->setOption($optionsRepository->find($line['product_id']));
$rLineOptions->setPriceHt(floatval($line['price_ht']));
$entityManager->persist($rLineOptions);
}
$entityManager->persist($devis);
$entityManager->flush();
$docusealService = new DevisPdfService($kernel, $devis, true);
$contentDocuseal = $docusealService->generate();
$tmpPathDocuseal = sys_get_temp_dir() . '/docuseal_' . uniqid() . '.pdf';
file_put_contents($tmpPathDocuseal, $contentDocuseal);
$fileDocuseal = new UploadedFile($tmpPathDocuseal, 'dc_' . $devis->getNum() . '.pdf', 'application/pdf', 0, true);
$devis->setDevisDocuSealFile($fileDocuseal);
$devisService = new DevisPdfService($kernel, $devis, false);
$contentDevis = $devisService->generate();
$tmpPathDevis = sys_get_temp_dir() . '/devis_' . uniqid() . '.pdf';
file_put_contents($tmpPathDevis, $contentDevis);
$fileDevis = new UploadedFile($tmpPathDevis, 'devis_' . $devis->getNum() . '.pdf', 'application/pdf', 0, true);
$devis->setDevisFile($fileDevis);
$devis->setUpdateAt(new \DateTimeImmutable());
$entityManager->flush();
$client->createSubmissionDevis($devis);
$event = new DevisSend($devis);
$eventDispatcher->dispatch($event);
$this->addFlash('success', sprintf('Le devis %s a été modifiée.', $devis->getNum()));
return $this->redirectToRoute('app_crm_devis');
}
$lines =[
[
'id' => '',
'product_id' => '',
'days'=>'',
'price_ht' => '',
'price_sup_ht' =>''
]
];
$options = [
[
'id' => '',
'product_id' => '',
'price_ht' => '',
]
];
$shipAddress = [];
$billAddress =[];
foreach ($devis->getDevisLines() as $key => $line) {
$lines[$key] = [
'id' => $line->getId(),
'product_id' => $line->getProduct()->getId(),
'days' => $line->getDay(),
'price_ht' => $line->getPriceHt(),
'price_sup_ht' => $line->getPriceHtSup()
];
}
foreach ($devis->getDevisOptions() as $key => $line) {
$options[$key] = [
'id' => $line->getId(),
'product_id' => $line->getOption()->getId(),
'price_ht' => $line->getPriceHt(),
];
}
foreach ($devis->getCustomer()->getCustomerAddresses() as $customerAddress) {
$shipAddress[$customerAddress->getId()] = $customerAddress->getAddress()." ".$customerAddress->getZipcode()." ".$customerAddress->getCity();
$billAddress[$customerAddress->getId()] = $customerAddress->getAddress()." ".$customerAddress->getZipcode()." ".$customerAddress->getCity();
}
return $this->render('dashboard/devis/add.twig', [
'form' => $form->createView(),
'devis' => $devis,
'lines' => $lines,
'options' => $options,
'products' => $productRepository->findAll(),
'optionsList' => $optionsRepository->findAll(),
'shipAddress' => $shipAddress,
'billAddress' => $billAddress,
]);
}
}