src/Controller/SocietyController.php line 80

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Associes;
  4. use App\Entity\ClauseScoiety;
  5. use App\Entity\Client;
  6. use App\Entity\DomiciliationAddress;
  7. use App\Entity\DocumentSociety;
  8. use App\Entity\Files;
  9. use App\Entity\President;
  10. use App\Entity\Signatures;
  11. use App\Entity\SirenEnterprise;
  12. use App\Entity\Society;
  13. use App\Entity\UserClauseSelection;
  14. use App\Entity\UserSocietyActivities;
  15. use App\Events\DocumentEvent;
  16. use App\Form\AssociesType;
  17. use App\Form\PresidentType;
  18. use App\Form\SocietyConditionsType;
  19. use App\Form\SocietyIndicatorType;
  20. use App\Form\SocietyType;
  21. use App\Manager\InpiManager;
  22. use App\Repository\ClauseScoietyRepository;
  23. use App\Repository\ClientRepository;
  24. use App\Repository\DocumentSocietyRepository;
  25. use App\Repository\FilesRepository;
  26. use App\Repository\IbanRepository;
  27. use App\Repository\SirenEnterpriseRepository;
  28. use App\Repository\SocietyRepository;
  29. use App\Repository\UserClauseSelectionRepository;
  30. use App\Repository\UserRepository;
  31. use App\Service\MailService;
  32. use App\Service\S3Service;
  33. use Doctrine\ORM\EntityManagerInterface;
  34. use Knp\Component\Pager\PaginatorInterface;
  35. use Psr\EventDispatcher\EventDispatcherInterface;
  36. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  37. use Symfony\Component\EventDispatcher\GenericEvent;
  38. use Symfony\Component\HttpClient\HttpClient;
  39. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  40. use Symfony\Component\HttpFoundation\JsonResponse;
  41. use Symfony\Component\HttpFoundation\RedirectResponse;
  42. use Symfony\Component\HttpFoundation\Request;
  43. use Symfony\Component\HttpFoundation\RequestStack;
  44. use Symfony\Component\HttpFoundation\Response;
  45. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  46. use Symfony\Component\Routing\Annotation\Route;
  47. use PhpOffice\PhpWord\Shared\ZipArchive;
  48. use Symfony\Component\Security\Core\Security;
  49. use Symfony\Contracts\HttpClient\HttpClientInterface;
  50. /**
  51.  * @Route("/society")
  52.  */
  53. class SocietyController extends AbstractController
  54. {
  55.     private $mailService;
  56.     private $documentSocietyRepository;
  57.     private $entityManager;
  58.     private $s3Service;
  59.     private $httpClient;
  60.     public function __construct(MailService $mailServiceDocumentSocietyRepository $documentSocietyRepositoryEntityManagerInterface $entityManagerS3Service $s3Service HttpClientInterface $httpClient)
  61.     {
  62.         $this->mailService $mailService;
  63.         $this->documentSocietyRepository $documentSocietyRepository;
  64.         $this->entityManager $entityManager;
  65.         $this->s3Service $s3Service;
  66.         $this->httpClient $httpClient;    }
  67.     /**
  68.      * @Route("/", name="society_index", methods={"GET"})
  69.      */
  70.     public function index(Request $requestPaginatorInterface $paginatorSocietyRepository $societyRepositoryUserRepository $userRepository)
  71.     {
  72.         $connectedUser $this->getUser();
  73.         if (!$connectedUser) {
  74.             throw $this->createAccessDeniedException('Vous devez être connecté pour accéder à cette page.');
  75.         }
  76.         $collaborator $request->query->getInt('collaborator') ?: null;
  77.         $postalCode   trim(strip_tags((string) $request->query->get('postal_code'''))) ?: null;
  78.         $address      trim(strip_tags((string) $request->query->get('address'''))) ?: null;
  79.         $name         trim(strip_tags((string) $request->query->get('name'''))) ?: null;
  80.         $number       trim(strip_tags((string) $request->query->get('number'''))) ?: null;
  81.         $created      trim(strip_tags((string) $request->query->get('created'''))) ?: null;
  82.         $users = [];
  83.         $collaborators = [];
  84.         $isClient false;
  85.         $isCollaborator false;
  86.         if ($this->isGranted('ROLE_ADMIN')) {
  87.             $users $userRepository->findAll();
  88.         } elseif ($this->isGranted('ROLE_CLIENT')) {
  89.             $users $userRepository->findCollaboratorsByClient($connectedUser);
  90.             $collaborators array_map(function ($user) {
  91.                 return $user->getId();
  92.             }, $users);
  93.             $isClient true;
  94.         } elseif ($this->isGranted('ROLE_COLLABORATEUR')) {
  95.             // If the user is a collaborator, show only their own societies
  96.             $collaborators = [$connectedUser->getId()];
  97.             $isCollaborator true;
  98.         }
  99.         $queryBuilder $societyRepository->findByFiltersQueryBuilder(
  100.             $collaborator$postalCode$address$name$number$connectedUser->getClient(), $collaborators$isClient$isCollaborator$created
  101.         );
  102.         // Pagination côté serveur avec Knp Paginator
  103.         $pagination $paginator->paginate(
  104.             $queryBuilder,
  105.             $request->query->getInt('page'1),
  106.             12 // Nombre d'items par page
  107.         );
  108.         // Calcul des statistiques significatives
  109.         $allSocieties $queryBuilder->getQuery()->getResult();
  110.         // Sociétés créées ce mois
  111.         $startOfMonth = new \DateTime('first day of this month 00:00:00');
  112.         $createdThisMonth array_filter($allSocieties, function($society) use ($startOfMonth) {
  113.             return $society->getCreated() && $society->getCreated() >= $startOfMonth;
  114.         });
  115.         // Sociétés modifiées dans les 7 derniers jours
  116.         $sevenDaysAgo = new \DateTime('-7 days');
  117.         $recentlyUpdated array_filter($allSocieties, function($society) use ($sevenDaysAgo) {
  118.             return $society->getUpdated() && $society->getUpdated() >= $sevenDaysAgo;
  119.         });
  120.         // Sociétés en attente (status = 'created')
  121.         $pendingSocieties array_filter($allSocieties, function($society) {
  122.             return $society->getStatus() === Society::STATUS_CREATED;
  123.         });
  124.         return $this->render('society/index.html.twig', [
  125.             'pagination' => $pagination,
  126.             'users' => $users,
  127.             'stats' => [
  128.                 'createdThisMonth' => count($createdThisMonth),
  129.                 'recentlyUpdated' => count($recentlyUpdated),
  130.                 'pending' => count($pendingSocieties),
  131.             ],
  132.         ]);
  133.     }
  134.     /**
  135.      * @Route("/new", name="society_new", methods={"GET", "POST"})
  136.      */
  137.     public
  138.     function new(Request $requestEntityManagerInterface $entityManagerRequestStack $requestStack): Response
  139.     {
  140.         $society = new Society();
  141.         $user $this->getUser();
  142.         /**
  143.          * @var Client $client
  144.          */
  145.         $client $user->getClient();
  146.         // Pré-remplir les infos de domiciliation depuis le client existant
  147.         if ($client) {
  148.             $domClient = new \App\Entity\Client();
  149.             $domClient->setName($client->getName());
  150.             $domClient->setSocietyForme($client->getSocietyForme());
  151.             $domClient->setSiren($client->getSiren());
  152.             $domClient->setAgreementNumber($client->getAgreementNumber());
  153.             $domClient->setSocietySiege($client->getSocietySiege());
  154.             $domClient->setCp($client->getCp());
  155.             $domClient->setVille($client->getVille());
  156.             $domClient->setSocietyCapitalChiffre($client->getSocietyCapitalChiffre());
  157.             $domClient->setSocietyCapitalLettre($client->getSocietyCapitalLettre());
  158.             $domClient->setQualityRepresentant($client->getQualityRepresentant());
  159.             $domClient->setCivility($client->getCivility());
  160.             $domClient->setRepresantantLastName($client->getRepresantantLastName());
  161.             $domClient->setRepresantantFirstName($client->getRepresantantFirstName());
  162.             $domClient->setDescriptionService($client->getDescriptionService());
  163.             $domClient->setImmeubleDescription($client->getImmeubleDescription());
  164.             $domClient->setEquipment($client->getEquipment());
  165.             $domClient->setSurfaceOffice($client->getSurfaceOffice());
  166.             $domClient->setPieceNumber($client->getPieceNumber());
  167.             $domClient->setMontantRedevance($client->getMontantRedevance());
  168.             $domClient->setDureeContrat($client->getDureeContrat());
  169.             $domClient->setDelaiDay($client->getDelaiDay());
  170.             $society->setClient($domClient);
  171.         }
  172.         $form $this->createForm(SocietyType::class, $society);
  173.         $form->handleRequest($request);
  174.         $formAssocy $this->createForm(AssociesType::class);
  175.         $client->getSociety()->count();
  176.         if ($form->isSubmitted() && $form->isValid()) {
  177.             $number sprintf("%08d"$client->getSociety()->count() + 1);
  178.             $society->setCreated(new \DateTime("now"));
  179.             $society->setClient($user->getClient());
  180.             $society->setStatus(Society::STATUS_CREATED);
  181.             $society->setNumber(sprintf('%08d'$number));
  182.             $society->setUser($user);
  183.             $society->setFreeOrder(true);
  184.             // Store the selected domiciliation address reference
  185.             $domiciliationAddressId $request->request->get('domiciliation_address_id');
  186.             if ($domiciliationAddressId) {
  187.                 $domiciliationAddress $entityManager->getRepository(DomiciliationAddress::class)->find($domiciliationAddressId);
  188.                 if ($domiciliationAddress && $domiciliationAddress->getClient() === $client) {
  189.                     $society->setDomiciliationAddress($domiciliationAddress);
  190.                 }
  191.             }
  192.             $entityManager->persist($society);
  193.             $entityManager->flush();
  194.             $publicDirectory $this->getParameter('pdf_directory');
  195.             $filepath $publicDirectory "/" $society->getId() . "/";
  196.             if (!file_exists($filepath)) {
  197.                 mkdir($filepath0777true);
  198.             }
  199.             $requestStack->getSession()->set('tab''society');
  200.             $entityManager->flush();
  201.             return $this->redirectToRoute('society_show', ['id' => $society->getId()], Response::HTTP_SEE_OTHER);
  202.         }
  203.         $domiciliationAddresses $client->getDomiciliationAddresses();
  204.         $yearEnd date('j/m'strtotime('12/31'));
  205.         $now = new \DateTime();
  206.         return $this->renderForm('society/new.html.twig', [
  207.             'society' => $society,
  208.             'endDate' => $yearEnd,
  209.             'now' => date('j/m/Y'),
  210.             'form' => $form,
  211.             'formAssocy' => $formAssocy,
  212.             'client' => $user,
  213.             'domiciliationAddresses' => $domiciliationAddresses,
  214.         ]);
  215.     }
  216.     /**
  217.      * @Route("/api/domiciliation-address/{id}", name="api_domiciliation_address", methods={"GET"})
  218.      */
  219.     public function getDomiciliationAddress(int $idEntityManagerInterface $entityManager): JsonResponse
  220.     {
  221.         $user $this->getUser();
  222.         $client $user->getClient();
  223.         $address $entityManager->getRepository(DomiciliationAddress::class)->find($id);
  224.         if (!$address || $address->getClient() !== $client) {
  225.             return new JsonResponse(['error' => 'Adresse non trouvée'], Response::HTTP_NOT_FOUND);
  226.         }
  227.         return new JsonResponse([
  228.             'id' => $address->getId(),
  229.             'label' => $address->getLabel(),
  230.             'name' => $address->getName(),
  231.             'societyForme' => $address->getSocietyForme(),
  232.             'siren' => $address->getSiren(),
  233.             'agreementNumber' => $address->getAgreementNumber(),
  234.             'societySiege' => $address->getSocietySiege(),
  235.             'cp' => $address->getCp(),
  236.             'ville' => $address->getVille(),
  237.             'societyCapitalChiffre' => $address->getSocietyCapitalChiffre(),
  238.             'societyCapitalLettre' => $address->getSocietyCapitalLettre(),
  239.             'qualityRepresentant' => $address->getQualityRepresentant(),
  240.             'civility' => $address->getCivility(),
  241.             'represantantLastName' => $address->getRepresantantLastName(),
  242.             'represantantFirstName' => $address->getRepresantantFirstName(),
  243.             'descriptionService' => $address->getDescriptionService(),
  244.             'immeubleDescription' => $address->getImmeubleDescription(),
  245.             'equipment' => $address->getEquipment(),
  246.             'surfaceOffice' => $address->getSurfaceOffice(),
  247.             'pieceNumber' => $address->getPieceNumber(),
  248.             'montantRedevance' => $address->getMontantRedevance(),
  249.             'domiciliationDate' => $address->getDomiciliationDate() ? $address->getDomiciliationDate()->format('Y-m-d') : null,
  250.             'dureeContrat' => $address->getDureeContrat(),
  251.             'delaiDay' => $address->getDelaiDay(),
  252.         ]);
  253.     }
  254.     /**
  255.      * @Route("/searchSiren", name="society_siren_info")
  256.      */
  257.     public function fetchEnterpriseData(SirenEnterpriseRepository $sirenEnterpriseRepositoryEntityManagerInterface $entityManagerRequest $request)
  258.     {
  259.         $siren $request->request->get('siren');
  260.         $enterprise $sirenEnterpriseRepository->findOneBy(['siren' => $siren]);
  261.         if ($enterprise) {
  262.             $html $this->renderView('society/enterpriseInfo.html.twig', ['data' => $enterprise->getData(), 'siren' => $siren]);
  263.             return new Response($html);
  264.         }
  265.         $apiToken 'fa81590fc90352718e3dd057c27a9f34cd57188d83fd002f';
  266.         $url "https://api.pappers.fr/v2/entreprise?api_token=$apiToken&siren=$siren";
  267.         $httpClient HttpClient::create();
  268.         $response $httpClient->request('GET'$url);
  269.         $data = [];
  270.         $apiError null;
  271.         $statusCode $response->getStatusCode();
  272.         if ($statusCode === 200) {
  273.             $content $response->getContent();
  274.             $data json_decode($contenttrue);
  275.             $enterprise = new SirenEnterprise();
  276.             $enterprise->setSiren($siren);
  277.             $enterprise->setData($data);
  278.             $entityManager->persist($enterprise);
  279.             $entityManager->flush();
  280.         } else {
  281.             $content $response->getContent(false);
  282.             $errorData json_decode($contenttrue);
  283.             if (isset($errorData['error'])) {
  284.                 $apiError $errorData['error'];
  285.             }
  286.         }
  287.         //normalement data hna fil edit njib associe ou bien dirigent -> getRepresentantData mech donnés mta3 l api, 5ater badel fihom
  288.         $html $this->renderView('society/enterpriseInfo.html.twig', ['data' => $data'siren' => $siren'apiError' => $apiError]);
  289.         return new Response($html);
  290.     }
  291.     /**
  292.      * @Route("/{id}", name="society_show", methods={"GET"})
  293.      */
  294.     public function show(Society $societyClauseScoietyRepository $clauseScoietyRepositoryIbanRepository $ibanRepositoryFilesRepository $filesRepositoryEntityManagerInterface $entityManagerRequest $requestInpiManager $inpiManagerSecurity $securityUserClauseSelectionRepository $userClauseSelectionRepositoryRequestStack $requestStack): Response
  295.     {
  296.         $user $security->getUser();
  297.         if ($society->getUser() !== $user) {
  298.             return $this->render('redirection/AccessDenied.html.twig');
  299.         }
  300.         $selectedProfile null;
  301.         $statutsBySocietyType null;
  302.         if ($society->getType()) {
  303.             $statutsBySocietyType $userClauseSelectionRepository->StatusSociety($user->getId(), $society->getType()->getId());
  304.             if ($society->getSelectedProfil()) {
  305.                 $selectedProfile $society->getSelectedProfil()->getClauses();
  306.             }
  307.         }
  308.         $actifTabParam $request->query->get('actifTab');
  309.         if ($actifTabParam === 'signature') {
  310.             $actifTab 'signature';
  311.         } else {
  312.             $tab $requestStack->getSession()->get('tab');
  313.             if ($tab && $tab == 'society') {
  314.                 $actifTab 'society';
  315.             } else
  316.                 $actifTab 'document';
  317.             if (count($society->getDocumentSocieties()) > 0) {
  318.                 $requestStack->getSession()->remove('tab');
  319.             }else{
  320.                 $actifTab 'society';
  321.             }
  322.         }
  323.         $form $this->createForm(SocietyType::class, $society);
  324.         $formSocietyIndicator $this->createForm(SocietyIndicatorType::class);
  325.         // Formulaire "Nouvel associé" : doit être vide pour saisir un nouvel associé.
  326.         // (Auparavant lié au 1er associé existant -> le formulaire s'affichait pré-rempli.)
  327.         $formAssocy $this->createForm(AssociesType::class, new Associes(), ['pourcentageMax' => $society->getTotalPourcentageAssocies()]);
  328.         $formPresident $this->createForm(PresidentType::class,new President());
  329.         //dd($formPresident);
  330.         $SocietyConditions $society->getSocietyConditions() ? $society->getSocietyConditions() : null;
  331.         $formSocietyConditions $this->createForm(SocietyConditionsType::class, $SocietyConditions);
  332.         $form->handleRequest($request);
  333.         $files $filesRepository->findBy(['society' => $society->getId()]);
  334.         $documents $society->getDocumentSocieties();
  335.         //$signatairesByDocument = [];
  336.         //foreach ($documents as $document) {
  337.         //$signatairesByDocument[$document->getId()] = $document->getSociety()->getSignataires() ?? [];
  338.         //}
  339.         mb_internal_encoding("UTF-8"); // Assurez-vous que l'encodage interne est défini sur UTF-8
  340.         $societyTypeName $society->getType() ? $society->getType()->getName() : "NC";
  341.         $decodedName mb_convert_case($societyTypeNameMB_CASE_LOWER"UTF-8");
  342.         $includeCommon = !str_contains($decodedName'sasu');
  343.         $statuts $clauseScoietyRepository->findBySocietyType(trim($decodedName), $includeCommon);
  344.         $recipients $society->getAssociesEmails();
  345.         //b$documentsSigned = $entityManager->getRepository(Signatures::class)->findBy(['status' => $society->getId(), 'si' => ['!=' => null]]);
  346.         // Aligne la BDD sur les auto-checks visuels de helpers.html.twig (lignes ~391-396) et
  347.         // _formEdit.html.twig (ligne ~1446). Sans ça, certaines conditions sont cochées à l'écran
  348.         // (parfois masquées en display:none) mais absentes de societyStatus, ce qui empêche les
  349.         // sous-champs AJAX (AGE LIMITE, DELAI PREAVIS, etc.) d'apparaître.
  350.         $status $society->getSocietyStatus() ?? [];
  351.         $changed false;
  352.         // Cas 1 : au moins un président enregistré → PRESIDENT_DE_LA_SOCIETE_SASU + organe_dirigeant_unique_president
  353.         $hasPresidentQuality = !$society->getPresidents()->isEmpty();
  354.         if ($hasPresidentQuality) {
  355.             foreach (['PRESIDENT_DE_LA_SOCIETE_SASU''organe_dirigeant_unique_president'] as $ref) {
  356.                 if (!in_array($ref$statustrue)) {
  357.                     $status[] = $ref;
  358.                     $changed true;
  359.                 }
  360.             }
  361.         }
  362.         // Cas 2 : DIRECTEURS_GENERAL_AUX_SASU coché → dispositions_statutaires_designation_dg
  363.         // (condition masquée display:none par helpers.html.twig:385 mais auto-cochée par le hack 394-396)
  364.         if (in_array('DIRECTEURS_GENERAL_AUX_SASU'$statustrue)
  365.             && !in_array('dispositions_statutaires_designation_dg'$statustrue)) {
  366.             $status[] = 'dispositions_statutaires_designation_dg';
  367.             $changed true;
  368.         }
  369.         // Cas 3 : au moins un président avec isRepresanteSociety=true → dg_pouvoir_representer_societe
  370.         $hasPresidentRepresenting false;
  371.         foreach ($society->getPresidents() as $p) {
  372.             if ($p->getIsRepresanteSociety()) {
  373.                 $hasPresidentRepresenting true;
  374.                 break;
  375.             }
  376.         }
  377.         if ($hasPresidentRepresenting
  378.             && !in_array('dg_pouvoir_representer_societe'$statustrue)) {
  379.             $status[] = 'dg_pouvoir_representer_societe';
  380.             $changed true;
  381.         }
  382.         if ($changed) {
  383.             $society->setSocietyStatus(array_values($status));
  384.             $entityManager->persist($society);
  385.             $entityManager->flush();
  386.         }
  387.         return $this->render('society/show.html.twig', [
  388.             'society' => $society,
  389.             'recipients' => $recipients,
  390.             'documents' => $documents,
  391.             'signataires' => $society->getSignataires(),
  392.             'form' => $form->createView(),
  393.             'formAssocy' => $formAssocy->createView(),
  394.             'formSocietyConditions' => $formSocietyConditions->createView(),
  395.             'formPresident' => $formPresident->createView(),
  396.             'formSocietyIndicator' => $formSocietyIndicator->createView(),
  397.             'associes' => $society->getAssocies(),
  398.             'presidents' => $society->getPresidents(),
  399.             'society_indicators' => $society->getSocietyIndicators(),
  400.             'files' => $files,
  401.             'directory' => "uploads/societyDocuments/",
  402.             'statuts' => $statuts,
  403.             'statutsBySocietyType' => $statutsBySocietyType,
  404.             'selectedProfile' => $selectedProfile,
  405.             'actifTab' => $actifTab,
  406.             'domiciliationAddresses' => $user->getClient() ? $user->getClient()->getDomiciliationAddresses() : [],
  407.         ]);
  408.     }
  409.     /**
  410.      * @Route("/api/society/{id}/can-update", name="api_society_can_update", methods={"GET"})
  411.      */
  412.     public function canUpdateSocietyApi(int $idEntityManagerInterface $em): JsonResponse
  413.     {
  414.         $society $em->getRepository(Society::class)->find($id);
  415.         if (!$society) {
  416.             return new JsonResponse(['error' => 'Société introuvable'], 404);
  417.         }
  418.         $associes count($society->getAssocies());
  419.         $dirigeants count($society->getPresidents());
  420.         $canUpdate $associes && $dirigeants 0;
  421.         return new JsonResponse(['canUpdate' => $canUpdate]);
  422.     }
  423.     /**
  424.      * @Route("/{id}/edit", name="society_edit", methods={"GET", "POST"})
  425.      */
  426.     public function edit(Request $requestSociety $societyEntityManagerInterface $entityManagerFilesRepository $filesRepositoryEventDispatcherInterface $dispatcher): Response
  427.     {
  428.         $form $this->createForm(SocietyType::class, $society);
  429.         $form->handleRequest($request);
  430.         $publicDirectory $this->getParameter('pdf_directory');
  431.         $filepath $publicDirectory "/" $society->getId() . "/";
  432.         if (!file_exists($filepath)) {
  433.             mkdir($filepath0777true);
  434.         }
  435.         if ($form->isSubmitted()) {
  436.             // Sauvegarder les champs condition_* des formulaires AJAX dans societyStatus
  437.             $allParams $request->request->all();
  438.             $societyStatus $society->getSocietyStatus() ?? [];
  439.             foreach ($allParams as $key => $value) {
  440.                 if (strpos($key'condition_') === && !empty($value)) {
  441.                     $societyStatus[$key] = $value;
  442.                 }
  443.             }
  444.             // Filtrer les Commissaire vides (aucun champ significatif rempli) avant flush
  445.             foreach ($society->getCommissaires() as $commissaire) {
  446.                 if (empty($commissaire->getType())
  447.                     && empty($commissaire->getNom())
  448.                     && empty($commissaire->getPrenom())
  449.                     && empty($commissaire->getSiren())
  450.                     && empty($commissaire->getDenomination())
  451.                     && empty($commissaire->getDescription())) {
  452.                     $society->removeCommissaire($commissaire);
  453.                     $entityManager->remove($commissaire);
  454.                 }
  455.             }
  456.             // Auto-cocher COMMISSAIRES_AUX_COMPTES_SASU si au moins un commissaire reste apres filtrage
  457.             $hasCommissaire false;
  458.             foreach ($society->getCommissaires() as $commissaire) {
  459.                 if (!empty($commissaire->getType())) {
  460.                     $hasCommissaire true;
  461.                     break;
  462.                 }
  463.             }
  464.             if ($hasCommissaire && !in_array('COMMISSAIRES_AUX_COMPTES_SASU'$societyStatustrue)) {
  465.                 $societyStatus[] = 'COMMISSAIRES_AUX_COMPTES_SASU';
  466.             }
  467.             $society->setSocietyStatus($societyStatus);
  468.             // Sauvegarder les champs capitalVariable / capitalMontantMin / capitalMontantMax sur le premier associé
  469.             $associesPostData $request->request->all('associes');
  470.             if (!empty($associesPostData)) {
  471.                 $firstAssocy $society->getAssocies()->first();
  472.                 if ($firstAssocy) {
  473.                     $firstAssocy->setCapitalVariable(!empty($associesPostData['capitalVariable']));
  474.                     $firstAssocy->setCapitalMontantMin($associesPostData['capitalMontantMin'] ?? null);
  475.                     $firstAssocy->setCapitalMontantMax($associesPostData['capitalMontantMax'] ?? null);
  476.                     if (!empty($associesPostData['Periodicite'])) {
  477.                         $firstAssocy->setPeriodicite($associesPostData['Periodicite']);
  478.                     }
  479.                     $entityManager->persist($firstAssocy);
  480.                 }
  481.             } else {
  482.                 // Checkbox non cochée = décochée
  483.                 $firstAssocy $society->getAssocies()->first();
  484.                 if ($firstAssocy) {
  485.                     $firstAssocy->setCapitalVariable(false);
  486.                     $entityManager->persist($firstAssocy);
  487.                 }
  488.             }
  489.             // Store the selected domiciliation address reference
  490.             $domiciliationAddressId $request->request->get('domiciliation_address_id');
  491.             if ($domiciliationAddressId) {
  492.                 $domiciliationAddress $entityManager->getRepository(DomiciliationAddress::class)->find($domiciliationAddressId);
  493.                 if ($domiciliationAddress && $domiciliationAddress->getClient() === $society->getClient()) {
  494.                     $society->setDomiciliationAddress($domiciliationAddress);
  495.                 }
  496.             } else {
  497.                 $society->setDomiciliationAddress(null);
  498.             }
  499.             $society->setUpdated(new \DateTime("now"));
  500.             $userSocietyAcitvities = new UserSocietyActivities();
  501.             $userSocietyAcitvities->setSociety($society);
  502.             $userSocietyAcitvities->setUser($this->getUser());
  503.             $userSocietyAcitvities->setClient($society->getClient());
  504.             $userSocietyAcitvities->setUpdatedAt(new \DateTime());
  505.             $entityManager->persist($userSocietyAcitvities);
  506.             $entityManager->flush();
  507.             $dispatcher->dispatch(new GenericEvent($society, [$filepath]), DocumentEvent::SOCIETY_REMOVE_DOCUMENTS);
  508.             $dispatcher->dispatch(new GenericEvent($society, [$filepath]), DocumentEvent::SOCIETY_CREATE);
  509.             //$dispatcher->dispatch(new GenericEvent($society, [$filepath]), DocumentEvent::SOCIETY_UPDATE);
  510.             $entityManager->flush();
  511.             return $this->redirectToRoute('society_show', ['id' => $society->getId()], Response::HTTP_SEE_OTHER);
  512.         }
  513.         $user $this->getUser();
  514.         $client $user->getClient();
  515.         $domiciliationAddresses $client $client->getDomiciliationAddresses() : [];
  516.         $files $filesRepository->findBy(['society' => $society->getId()]);
  517.         $publicDirectory $this->getParameter('file_directory');
  518.         return $this->renderForm('society/edit.html.twig', [
  519.             'society' => $society,
  520.             'form' => $form,
  521.             'associes' => $society->getAssocies(),
  522.             'presidents' => $society->getPresidents(),
  523.             'files' => $files,
  524.             'directory' => "uploads/societyDocuments/",
  525.             'domiciliationAddresses' => $domiciliationAddresses,
  526.         ]);
  527.     }
  528. //    *****************************************************edit button ************************************************************************
  529.     /**
  530.      * @Route("/{id}/generate-documents", name="society_generate_documents", methods={"GET", "POST"})
  531.      */
  532.     public function generate(Request $requestSociety $societyEntityManagerInterface $entityManagerEventDispatcherInterface $dispatcher): Response
  533.     {
  534.         if ($society->getDocumentSocieties()) {
  535.             foreach ($society->getDocumentSocieties() as $documentSociety) {
  536.                 if ($documentSociety->getSignatures()) {
  537.                     foreach ($documentSociety->getSignatures() as $signature) {
  538.                         $entityManager->remove($signature);
  539.                     }
  540.                 }
  541.                 $entityManager->flush();
  542.             }
  543.         }
  544.         $publicDirectory $this->getParameter('pdf_directory');
  545.         $filepath $publicDirectory "/" $society->getId() . "/";
  546.         if (!file_exists($filepath)) {
  547.             mkdir($filepath0777true);
  548.         }
  549.         //hna n3adi fil path li houwa ploads/societyPdf/
  550.         $dispatcher->dispatch(new GenericEvent($society, [$filepath]), DocumentEvent::SOCIETY_REMOVE_DOCUMENTS);
  551.         $dispatcher->dispatch(new GenericEvent($society, [$filepath]), DocumentEvent::SOCIETY_CREATE);
  552.         $dispatcher->dispatch(new GenericEvent($society, [$filepath]), DocumentEvent::SOCIETY_REMOVE_DOCUMENTS_FOLDER);
  553.         $entityManager->flush();
  554.         // Rediriger après modification
  555.         return $this->redirectToRoute('society_show', ['id' => $society->getId()], Response::HTTP_SEE_OTHER);
  556.     }
  557. //    *****************************************************edit button ************************************************************************
  558.     /**
  559.      * @Route("/{id}", name="society_delete", methods={"POST"})
  560.      */
  561.     public function delete(Request $requestSociety $societyEntityManagerInterface $entityManager): Response
  562.     {
  563.         if ($this->isCsrfTokenValid('delete' $society->getId(), $request->request->get('_token'))) {
  564.             try {
  565.                 $societyName $society->getName();
  566.                 $entityManager->remove($society);
  567.                 $entityManager->flush();
  568.                 $this->addFlash('success''La société "' $societyName '" a été supprimée avec succès.');
  569.             } catch (\Exception $e) {
  570.                 $this->addFlash('error''Impossible de supprimer cette société : ' $e->getMessage());
  571.             }
  572.         }
  573.         return $this->redirectToRoute('society_index', [], Response::HTTP_SEE_OTHER);
  574.     }
  575.     /**
  576.      * @Route("/upload/{id}", name="society_upload", methods={"POST"})
  577.      */
  578.     public function uploadDocuments(Request $requestSociety $societyFilesRepository $filesRepository)
  579.     {
  580.         if ($request->getMethod() == "POST") {
  581.             $entityManager $this->getDoctrine()->getManager();
  582.             $file $request->files->get('file');
  583.             $fileName $file->getClientOriginalName();
  584.             $publicDirectory $this->getParameter('file_directory');
  585.             $filepath $publicDirectory "/" $society->getId();
  586.             if (!file_exists($filepath)) {
  587.                 mkdir($filepath0777true);
  588.             }
  589.             $fileName $file->getClientOriginalName();
  590.             $file->move(
  591.                 $filepath,
  592.                 $fileName
  593.             );
  594.             $fileEntity = new Files();
  595.             $fileEntity->setName($fileName);
  596.             $fileEntity->setPath($society->getId() . '/' $fileName);
  597.             $fileEntity->setSociety($society);
  598.             $entityManager->persist($fileEntity);
  599.             $entityManager->flush();
  600.             $html $this->renderView('society/_document_ajax.html.twig', [
  601.                 'files' => $filesRepository->findBy(['society' => $society->getId()]),
  602.                 'directory' => "uploads/societyDocuments/",
  603.                 'society' => $society
  604.             ]);
  605.             return new Response($html);
  606.         }
  607.     }
  608.     /**
  609.      * @Route("/deleteFile/{id}/{file}", name="delete_file")
  610.      */
  611.     public function refreshDocuments(Request $requestSociety $society$fileFilesRepository $filesRepository)
  612.     {
  613.         $entityManager $this->getDoctrine()->getManager();
  614.         $fileEntity $filesRepository->find($file);
  615.         $publicDirectory $this->getParameter('file_directory');
  616.         $filepath $publicDirectory "/" $fileEntity->getPath();
  617.         if (file_exists($filepath)) unlink($filepath);
  618.         $entityManager->remove($fileEntity);
  619.         $entityManager->flush();
  620.         $referer $request->headers->get('referer');
  621.         return new RedirectResponse($referer);
  622.     }
  623.     /**
  624.      * @Route("/new/{id}", name="app_society_update_Clauses", methods={"GET", "POST"})
  625.      */
  626.     public function updateStatus(Request $requestSociety $societyEntityManagerInterface $entityManager): Response
  627.     {
  628.         if ($request->isXmlHttpRequest()) {
  629.             $data $request->request->all();
  630.             $result $selectedClauses = [];
  631.             $profilName = !empty($data['profil-name']) ? $data['profil-name'] : null;
  632.             $profilId   = !empty($data['profil-id'])   ? (int)$data['profil-id']   : null;
  633.             // Keys posted by the form that are NOT clause refs — must not pollute societyStatus
  634.             $nonClauseKeys = ['profil-name''profil-id''profile''_token''save-mode'];
  635.             foreach ($data as $key => $value) {
  636.                 if (in_array($key$nonClauseKeystrue)) {
  637.                     continue;
  638.                 }
  639.                 if (strpos($key'condition_') === 0) {
  640.                     $result[$key] = $value;
  641.                 } else {
  642.                     $result[] = $key;
  643.                     if ($profilName || $profilId) {
  644.                         $clause $entityManager->getRepository(ClauseScoiety::class)->findOneBy(['ref' => $key]);
  645.                         if ($clause) {
  646.                             $selectedClauses[] = $clause->getId();
  647.                         }
  648.                     }
  649.                 }
  650.             }
  651.             if ($profilName && $selectedClauses) {
  652.                 // Créer un nouveau profil
  653.                 $selection = new UserClauseSelection();
  654.                 $selection->setUser($this->getUser());
  655.                 $selection->setSocietyType($society->getType());
  656.                 $selection->setName($profilName);
  657.                 $selection->setCreatedAt(new \DateTime());
  658.                 $selection->setClauses($selectedClauses);
  659.                 $entityManager->persist($selection);
  660.                 $entityManager->flush();
  661.                 $society->setSelectedProfil($selection);
  662.                 $entityManager->flush();
  663.             } elseif ($profilId && $selectedClauses) {
  664.                 // Mettre à jour un profil existant
  665.                 $selection $entityManager->getRepository(UserClauseSelection::class)->find($profilId);
  666.                 if ($selection) {
  667.                     $selection->setClauses($selectedClauses);
  668.                     $entityManager->flush();
  669.                     $society->setSelectedProfil($selection);
  670.                     $entityManager->flush();
  671.                 }
  672.             } else {
  673.                 // Pas d'action profil : la sélection de la société ne correspond plus à un profil sauvegardé
  674.                 $society->setSelectedProfil(null);
  675.             }
  676.             $society->setSocietyStatus($result);
  677.             $entityManager->persist($society);
  678.             $entityManager->flush();
  679.             return new Response('succes'Response::HTTP_OK);
  680.         }
  681.         return new Response('failed'Response::HTTP_BAD_REQUEST);
  682.     }
  683.     /**
  684.      * @Route("/preview-statuts/{id}", name="app_society_preview_statuts", methods={"POST"})
  685.      */
  686.     public function previewStatuts(Request $requestSociety $societyEntityManagerInterface $entityManager): Response
  687.     {
  688.         if (!$request->isXmlHttpRequest()) {
  689.             return new JsonResponse(['error' => 'Invalid request'], Response::HTTP_BAD_REQUEST);
  690.         }
  691.         $data $request->request->all();
  692.         
  693.         // Traitement des clauses similaire à updateStatus
  694.         $result = [];
  695.         foreach ($data as $key => $value) {
  696.             if (strpos($key'condition_') === 0) {
  697.                 $result[$key] = $value;
  698.             } else {
  699.                 $result[] = $key;
  700.             }
  701.         }
  702.         
  703.         // Récupération des clauses/statuts pour le type de société
  704.         mb_internal_encoding("UTF-8");
  705.         $societyTypeName $society->getType()->getName();
  706.         $decodedName mb_convert_case($societyTypeNameMB_CASE_LOWER"UTF-8");
  707.         $includeCommon = !str_contains($decodedName'sasu');
  708.         $allStatuts $entityManager->getRepository(ClauseScoiety::class)->findBySocietyType($decodedName$includeCommon);
  709.         $checkedRefs array_values(array_filter(array_keys($result), 'is_int'));
  710.         $checkedRefs array_map(function($k) use ($result) { return $result[$k]; }, $checkedRefs);
  711.         $statuts array_values(array_filter($allStatuts, function($s) use ($checkedRefs) {
  712.             return in_array($s->getRef(), $checkedRefs);
  713.         }));
  714.         
  715.         // Simulation de la mise à jour temporaire pour la preview
  716.         $conditionData = [];
  717.         foreach ($result as $key => $value) {
  718.             if (is_string($key) && strpos($key'condition_') === 0) {
  719.                 $conditionData[$key] = $value;
  720.             }
  721.         }
  722.         $tempSociety = clone $society;
  723.         $tempSociety->setSocietyStatus($result);
  724.         // Override DB clauseConditionsArray with live form data so preview reflects current state
  725.         $tempSociety->setClauseConditionsArray($conditionData);
  726.         
  727.         // Génération du PDF en mémoire
  728.         $pdfOptions = new \Dompdf\Options();
  729.         $pdfOptions->set('defaultFont''Arial');
  730.         $pdfOptions->set('isRemoteEnabled'true);
  731.         
  732.         $dompdf = new \Dompdf\Dompdf($pdfOptions);
  733.         
  734.         // Template du document statuts
  735.         $template 'documentsPdf/statuts.html.twig';
  736.         if (!$this->container->get('twig')->getLoader()->exists($template)) {
  737.             return new JsonResponse(['error' => 'Template not found'], Response::HTTP_NOT_FOUND);
  738.         }
  739.         try {
  740.             $html $this->container->get('twig')->render($template, [
  741.                 'society' => $tempSociety,
  742.                 'statuts' => $statuts,
  743.                 'data' => $result
  744.             ]);
  745.             
  746.             $dompdf->loadHtml($html);
  747.             $dompdf->setPaper('A4''portrait');
  748.             $dompdf->render();
  749.             
  750.             // Ajout du footer
  751.             $canvas $dompdf->get_canvas();
  752.             $w $canvas->get_width();
  753.             $h $canvas->get_height();
  754.             // Résolution correcte du font via FontMetrics (évite arial.afm introuvable sur Linux)
  755.             $fontMetrics $dompdf->getFontMetrics();
  756.             $footerFont $fontMetrics->getFont('Helvetica''normal')
  757.                 ?? $fontMetrics->getFont('helvetica''normal')
  758.                 ?? $fontMetrics->getFont('Times''normal');
  759.             // Footer personnalisé ou par défaut
  760.             $customFooter null;
  761.             if ($society->getClient() && $society->getClient()->getLogo()) {
  762.                 $customFooter $society->getClient()->getLogo()->getPiedDePage();
  763.             }
  764.             if ($customFooter) {
  765.                 $canvas->page_text(30$h 30$customFooter$footerFont9, [000]);
  766.             } else {
  767.                 $canvas->page_text(30$h 30$society->getName(), $footerFont9, [000]);
  768.                 $canvas->page_text($w 60$h 30"Généré le " date('d/m/Y'), $footerFont9, [000]);
  769.             }
  770.             $canvas->page_text($w 120$h 30"Page {PAGE_NUM} de {PAGE_COUNT}"$footerFont9, [000]);
  771.             $canvas->line(30$h 45$w 30$h 45, [0.50.50.5], 0.5);
  772.             
  773.             $output $dompdf->output();
  774.             
  775.             // Retourner le PDF en base64 pour affichage dans l'iframe
  776.             return new JsonResponse([
  777.                 'success' => true,
  778.                 'pdf' => base64_encode($output),
  779.                 'mime' => 'data:application/pdf;base64,'
  780.             ]);
  781.             
  782.         } catch (\Exception $e) {
  783.             error_log('[previewStatuts] Exception: ' $e->getMessage() . ' in ' $e->getFile() . ':' $e->getLine());
  784.             return new JsonResponse(['error' => 'Erreur: ' $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
  785.         }
  786.     }
  787.     /**
  788.      * @Route("/sendMail/{id}", name="app_society_send_document", methods={"GET", "POST"})
  789.      */
  790.     public function sendDocumentByMail(Request $requestint $id): Response
  791.     {
  792.         // Récupère le document en utilisant son ID
  793.         $documentSociety $this->documentSocietyRepository->find($id);
  794.         if (!$documentSociety) {
  795.             throw $this->createNotFoundException('Le document n\'existe pas');
  796.         }
  797.         // Récupère la société associée au document
  798.         $society $documentSociety->getSociety();
  799.         if ($request->isMethod('POST')) {
  800.             $recipients $request->request->get('emails', []);
  801.             $content $request->request->get('content''');
  802.             // Récupère le chemin S3 du fichier PDF
  803.             $s3Key $this->s3Service->extractKeyFromUrl($documentSociety->getPath());
  804.             // Utilise le service S3 pour récupérer le contenu du fichier
  805.             $fileContent $this->s3Service->downloadDocument($s3Key);
  806.             if (!$fileContent) {
  807.                 throw $this->createNotFoundException('Impossible de récupérer le fichier PDF depuis AWS S3');
  808.             }
  809.             // Convertit le flux en contenu lisible
  810.             if ($fileContent instanceof \Psr\Http\Message\StreamInterface) {
  811.                 $fileContent $fileContent->getContents();
  812.             }
  813.             // Détermine le nom du fichier
  814.             $filename $documentSociety->getNameFormated() . '.pdf';
  815.             // Envoie un email avec le fichier PDF en pièce jointe à chaque destinataire
  816.             foreach ($recipients as $recipient) {
  817.                 $this->mailService->sendEmailWithAttachment($recipient'MacsSolution.fr (Nouveau document)'$content$fileContent$filename);
  818.             }
  819.             $this->addFlash('success''Le mail a été envoyé avec succès.');
  820.             return $this->redirectToRoute('society_show', ['id' => $society->getId()]);
  821.         }
  822.         return $this->redirectToRoute('society_show', ['id' => $society->getId()]);
  823.     }
  824.     /**
  825.      * @Route("/society/update-signataires-by-document", name="app_society_update_signataires_document", methods={"POST"})
  826.      */
  827.     public function updateSignataires(Request $requestEntityManagerInterface $entityManagerDocumentSocietyRepository $documentSocietyRepository): Response
  828.     {
  829.         if ($request->isXmlHttpRequest()) {
  830.             $data $request->request->all();
  831.             $document $documentSocietyRepository->find($data['documentId']);
  832.             $signataires $data['selectedSignataires'];
  833.             $document->setSignataires($signataires);
  834.             $entityManager->persist($document);
  835.             $entityManager->flush();
  836.             return new Response('succes'Response::HTTP_OK);
  837.         }
  838.         return new Response('failed'Response::HTTP_BAD_REQUEST);
  839.     }
  840.     /**
  841.      * @Route("/society/sendMailMultiple/{id}", name="app_society_send_document_multiple", methods={"POST"})
  842.      */
  843.     public function sendDocumentMultipleByMail(Request $requestSociety $societyEntityManagerInterface $entityManager): Response
  844.     {
  845.         $action      $request->request->get('action');
  846.         $documentIds $request->request->get('documents', []);
  847.         $documents   $this->documentSocietyRepository->findBy(['id' => $documentIds]);
  848.         if (empty($documents)) {
  849.             return $this->json(['error' => 'Aucun document sélectionné.'], 400);
  850.         }
  851.         // Crée un fichier ZIP temporaire
  852.         $zipName sys_get_temp_dir() . '/' uniqid() . '.zip';
  853.         $zip = new \ZipArchive();
  854.         $zip->open($zipName, \ZipArchive::CREATE);
  855.         $tempFiles = [];
  856.         foreach ($documents as $documentSociety) {
  857.             $key         $this->s3Service->extractKeyFromUrl($documentSociety->getPath());
  858.             $fileContent $this->s3Service->downloadDocument($key);
  859.             if ($fileContent && strlen($fileContent) > 0) {
  860.                 $tempFilePath sys_get_temp_dir() . '/' uniqid() . '.pdf';
  861.                 file_put_contents($tempFilePath$fileContent);
  862.                 $tempFiles[] = $tempFilePath;
  863.                 $zip->addFile($tempFilePath, ($documentSociety->getNameFormated() ?: $documentSociety->getName()) . '.pdf');
  864.             }
  865.             if ($action === 'download') {
  866.                 $documentSociety->setIsDownload(true);
  867.             } elseif ($action === 'send') {
  868.                 $documentSociety->setIsSend(true);
  869.             }
  870.             $entityManager->persist($documentSociety);
  871.         }
  872.         $zip->close();
  873.         $entityManager->flush();
  874.         // Nettoyer les fichiers temporaires PDF
  875.         foreach ($tempFiles as $tmp) {
  876.             @unlink($tmp);
  877.         }
  878.         if ($action === 'download') {
  879.             $response = new BinaryFileResponse($zipName);
  880.             $response->headers->set('Content-Type''application/zip');
  881.             $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT'documents.zip');
  882.             $response->deleteFileAfterSend(true);
  883.             return $response;
  884.         }
  885.         if ($action === 'send') {
  886.             // Destinataires choisis dans le modal
  887.             $emailsParam $request->request->get('emails', []);
  888.             $recipients  array_unique(array_filter((array)$emailsParam));
  889.             if (empty($recipients)) {
  890.                 @unlink($zipName);
  891.                 return $this->json(['error' => 'Aucun destinataire sélectionné.'], 400);
  892.             }
  893.             $message $request->request->get('message''Veuillez trouver en pièce jointe les documents de la société ' $society->getName() . '.');
  894.             try {
  895.                 $zipContent file_get_contents($zipName);
  896.                 foreach ($recipients as $recipient) {
  897.                     $this->mailService->sendEmailWithAttachment(
  898.                         $recipient,
  899.                         'MacsSolution.fr – Documents société ' $society->getName(),
  900.                         $message,
  901.                         $zipContent,
  902.                         'documents.zip'
  903.                     );
  904.                 }
  905.                 @unlink($zipName);
  906.                 return $this->json(['success' => true'recipients' => count($recipients)]);
  907.             } catch (\Exception $e) {
  908.                 @unlink($zipName);
  909.                 return $this->json(['error' => 'Erreur lors de l\'envoi : ' $e->getMessage()], 500);
  910.             }
  911.         }
  912.         return $this->json(['error' => 'Action invalide.'], 400);
  913.     }
  914.     /**
  915.      * @Route("/activity/reformulate", name="app_activity_reformulate")
  916.      */
  917.     public function reformulateActivity(Request $request): JsonResponse
  918.     {
  919.         $data json_decode($request->getContent(), true);
  920.         $text $data['text'] ?? '';
  921.         try {
  922.             $response $this->httpClient->request('POST''https://api.openai.com/v1/chat/completions', [
  923.                 'headers' => [
  924.                     'Authorization' => 'Bearer ' . ($_ENV['OPENAI_API_KEY'] ?? ''),
  925.                     'Content-Type' => 'application/json',
  926.                 ],
  927.                 'json' => [
  928.                     'model' => 'gpt-4o',
  929.                     'messages' => [
  930.                         ['role' => 'system''content' => 'Tu es un assistant juridique. Génère un objet social clair à partir de mots-clés. Réponds uniquement avec le texte de l\'objet social, sans titre, sans introduction, sans mise en forme Markdown, sans astérisques, sans gras. Le texte doit commencer directement par "La société a pour objet" ou par une liste numérotée.'],
  931.                         ['role' => 'user''content' => $text],
  932.                     ],
  933.                     'temperature' => 0.7,
  934.                 ]
  935.             ]);
  936.             $statusCode $response->getStatusCode();
  937.             if ($statusCode === 401) {
  938.                 return new JsonResponse(['error' => 'Clé API OpenAI invalide ou expirée. Veuillez la renouveler.'], 200);
  939.             }
  940.             $result $response->toArray();
  941.             $reformulated $result['choices'][0]['message']['content'] ?? '';
  942.             return new JsonResponse(['reformulated' => $reformulated]);
  943.         } catch (\Exception $e) {
  944.             $message str_contains($e->getMessage(), '401')
  945.                 ? 'Clé API OpenAI invalide ou expirée. Veuillez la renouveler.'
  946.                 'Erreur lors de la génération : ' $e->getMessage();
  947.             return new JsonResponse(['error' => $message], 200);
  948.         }
  949.     }
  950.     /**
  951.      * @param EntityManagerInterface $entityManager
  952.      * @return null
  953.      */
  954.     public function getFlush(EntityManagerInterface $entityManager)
  955.     {
  956.         return $entityManager->flush();
  957.     }
  958. }