src/Controller/Api/OrganizationController.php line 138

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Api;
  3. use App\Enum\DocumentStatusEnum;
  4. use App\Enum\DocumentTypeOrganizationEnum;
  5. use App\Enum\InvoiceStatusEnum;
  6. use App\Enum\LetterTypeEnum;
  7. use App\Enum\OrganizationStatusEnum;
  8. use App\Enum\ProductKeyEnum;
  9. use App\Repository\OrganizationRepository;
  10. use App\Service\DocumentFilesService;
  11. use App\Service\DocumentUtils;
  12. use App\Service\EncryptorDataUtils;
  13. use App\Service\LegalRepresentativeUtils;
  14. use App\Service\Organization\OrganizationDiagnosticService;
  15. use App\Service\OrganizationUtils;
  16. use App\Service\SegmentAPI;
  17. use App\Service\SubscriptionUtils;
  18. use App\Traits\SentryNotifyTrait;
  19. use App\Utils\AppUtils;
  20. use App\Utils\InvoiceUtils;
  21. use Doctrine\ORM\EntityManagerInterface;
  22. use Evo\Domain\Core\SignatureServiceInterface;
  23. use Evo\Infrastructure\MappingORM\Document;
  24. use Evo\Infrastructure\MappingORM\Invoice;
  25. use Evo\Infrastructure\MappingORM\LegalRepresentative;
  26. use Evo\Infrastructure\MappingORM\Letter;
  27. use Evo\Infrastructure\MappingORM\Organization;
  28. use Evo\Infrastructure\MappingORM\PostalAddress;
  29. use Evo\Infrastructure\MappingORM\ProcessYousign;
  30. use Evo\Infrastructure\MappingORM\Quote;
  31. use Evo\Infrastructure\MappingORM\Subscription;
  32. use Evo\Infrastructure\MappingORM\User;
  33. use Evo\Infrastructure\PdfGenerator\PathGenerator;
  34. use Evo\Infrastructure\Repository\InvoiceRepository;
  35. use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
  36. use Knp\Snappy\Pdf;
  37. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  38. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  39. use Symfony\Component\HttpFoundation\JsonResponse;
  40. use Symfony\Component\HttpFoundation\Request;
  41. use Symfony\Component\HttpFoundation\Response;
  42. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  43. use Symfony\Component\HttpKernel\KernelInterface;
  44. use Symfony\Component\Routing\Annotation\Route;
  45. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  46. use Symfony\Component\Routing\RouterInterface;
  47. use Symfony\Component\Serializer\Exception\ExceptionInterface;
  48. use Symfony\Component\Serializer\SerializerInterface;
  49. use Symfony\Contracts\Translation\TranslatorInterface;
  50. use Twig\Environment;
  51. /**
  52.  * @Route("/organization")
  53.  */
  54. class OrganizationController extends AbstractController
  55. {
  56.     use SentryNotifyTrait;
  57.     public const DIGIDOM_SIREN '797978996';
  58.     public const DIGIDOM_COMPANY_NAME 'KOAH DIGIDOM';
  59.     public const DIGIDOM_STORE_STREET_ADDRESS '10 RUE DE PENTHIEVRE';
  60.     public const DIGIDOM_COMPANY_POSTAL_CODE '75008 PARIS';
  61.     private EntityManagerInterface $em;
  62.     private OrganizationUtils $organizationUtils;
  63.     private InvoiceUtils $invoiceUtils;
  64.     private EncryptorDataUtils $encryptor;
  65.     private ?Request $request null;
  66.     private UrlGeneratorInterface $router;
  67.     private SessionInterface $session;
  68.     private DocumentUtils $documentUtils;
  69.     private TranslatorInterface $translator;
  70.     private SegmentAPI $segmentAPI;
  71.     private OrganizationDiagnosticService $organizationDiagnosticService;
  72.     private AppUtils $appUtils;
  73.     private OrganizationRepository $organizationRepository;
  74.     private SerializerInterface $serializer;
  75.     private KernelInterface $kernel;
  76.     private Pdf $pdf;
  77.     private Environment $twig;
  78.     private LegalRepresentativeUtils $legalRepresentativeUtils;
  79.     private SignatureServiceInterface $yousignAPI;
  80.     private DocumentFilesService $documentFilesService;
  81.     private ParameterBagInterface $params;
  82.     public function __construct(
  83.         EntityManagerInterface $em,
  84.         InvoiceUtils $invoiceUtils,
  85.         DocumentUtils $documentUtils,
  86.         OrganizationUtils $organizationUtils,
  87.         LegalRepresentativeUtils $legalRepresentativeUtils,
  88.         SignatureServiceInterface $yousignAPI,
  89.         DocumentFilesService $documentFilesService,
  90.         ParameterBagInterface $params,
  91.         EncryptorDataUtils $encryptor,
  92.         RouterInterface $router,
  93.         SessionInterface $session,
  94.         TranslatorInterface $translator,
  95.         SegmentAPI $segmentAPI,
  96.         OrganizationDiagnosticService $organizationDiagnosticService,
  97.         AppUtils $appUtils,
  98.         OrganizationRepository $organizationRepository,
  99.         SerializerInterface $serializer,
  100.         KernelInterface $kernel,
  101.         Pdf $pdf,
  102.         Environment $twig
  103.     ) {
  104.         $this->em $em;
  105.         $this->documentUtils $documentUtils;
  106.         $this->organizationUtils $organizationUtils;
  107.         $this->invoiceUtils $invoiceUtils;
  108.         $this->legalRepresentativeUtils $legalRepresentativeUtils;
  109.         $this->yousignAPI $yousignAPI;
  110.         $this->documentFilesService $documentFilesService;
  111.         $this->params $params;
  112.         $this->encryptor $encryptor;
  113.         $this->router $router;
  114.         $this->session $session;
  115.         $this->translator $translator;
  116.         $this->segmentAPI $segmentAPI;
  117.         $this->organizationDiagnosticService $organizationDiagnosticService;
  118.         $this->appUtils $appUtils;
  119.         $this->organizationRepository $organizationRepository;
  120.         $this->serializer $serializer;
  121.         $this->kernel $kernel;
  122.         $this->pdf $pdf;
  123.         $this->twig $twig;
  124.     }
  125.     /**
  126.      * @Route("/{id}/get-dom-subscription", name="app_organization_get_dom_subscription", methods={"GET"})
  127.      */
  128.     public function getDomSubscription($id): JsonResponse
  129.     {
  130.         $organization $this->em->getRepository(Organization::class)->find($id);
  131.         if (!$organization instanceof Organization) {
  132.             return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
  133.         }
  134.         $data SubscriptionUtils::getDomSubscription($organization);
  135.         if (!$data instanceof Subscription) {
  136.             return $this->json(['message' => 'Subscription not found'], Response::HTTP_NOT_FOUND);
  137.         }
  138.         return $this->json($dataResponse::HTTP_OK);
  139.     }
  140.     /**
  141.      * @Route("/{id}/summary", name="app_organization_summary", methods={"GET"})
  142.      */
  143.     public function summary($idRequest $request)
  144.     {
  145.         $header $request->headers->get('Authorization');
  146.         $data explode(' '$header);
  147.         $token end($data);
  148.         $status $request->get('status');
  149.         if (!$token) {
  150.             return $this->json(['result' => 'Accès refusé'], Response::HTTP_FORBIDDEN);
  151.         }
  152.         $repository $this->em->getRepository(Organization::class);
  153.         /** @var Organization $organisation */
  154.         $organisation $repository->find($id);
  155.         if (!$organisation) {
  156.             return $this->json(['result' => 'Organization not found'], Response::HTTP_NOT_FOUND);
  157.         }
  158.         if (!$this->organizationUtils->checkPermission($organisation$token)) {
  159.             return $this->json(['result' => 'Accès refusé'], Response::HTTP_FORBIDDEN);
  160.         }
  161.         $result array_merge_recursive($organisation->getInvoices()->toArray(), $organisation->getQuotes()->toArray());
  162.         foreach ($result as $key => $data) {
  163.             /*
  164.              * Filter
  165.              */
  166.             if ($status && !in_array($data->getStatus(), $status)) {
  167.                 unset($result[$key]);
  168.                 continue;
  169.             }
  170.             if ($data instanceof Invoice) {
  171.                 $data->setType('Invoice');
  172.             } elseif ($data instanceof Quote) {
  173.                 $data->setType('Quote');
  174.             }
  175.             $result[$key] = $data;
  176.         }
  177.         $result array_values($result);
  178.         $this->invoiceUtils->sortByCreatedDate($result);
  179.         return $this->json($result);
  180.     }
  181.     /**
  182.      * @Route("/{id}/generate-link/{type}", name="app_generate_link_externe", methods={"GET"})
  183.      */
  184.     public function generateLinkYousign(int $idRequest $requeststring $type 'yousign'): JsonResponse
  185.     {
  186.         $repository $this->em->getRepository(Organization::class);
  187.         $organization $repository->find($id);
  188.         if (!$organization instanceof Organization) {
  189.             return $this->json(['result' => 'Organization not found'], Response::HTTP_NOT_FOUND);
  190.         }
  191.         if ('yousign' === $type) {
  192.             $organization $this->em->getRepository(Organization::class)->find($id);
  193.             if (!$organization) {
  194.                 return new JsonResponse(['error' => 'Organization not found'], Response::HTTP_NOT_FOUND);
  195.             }
  196.             $document $this->organizationUtils->getContratDomiciliation($organization);
  197.             if (!$document) {
  198.                 return new JsonResponse(['error' => 'Document not found'], Response::HTTP_NOT_FOUND);
  199.             }
  200.             $legalRepresentative $this->legalRepresentativeUtils->getFirstPhysicalRepresentative($organization);
  201.             if (!$legalRepresentative) {
  202.                 return new JsonResponse(['error' => 'Legal representative not found'], Response::HTTP_NOT_FOUND);
  203.             }
  204.             if (!in_array($organization->getStatus(), [
  205.                 OrganizationStatusEnum::NEW,
  206.                 OrganizationStatusEnum::NEW_PAYMENT,
  207.                 OrganizationStatusEnum::DOCS_MISSING,
  208.                 OrganizationStatusEnum::DOCS_EXPIRED,
  209.                 OrganizationStatusEnum::OK,
  210.             ], true)) {
  211.                 return new JsonResponse(['error' => 'Organization status not allowed'], Response::HTTP_BAD_REQUEST);
  212.             }
  213.             $processYousign $organization->getProcessYousign();
  214.             if (!$processYousign) {
  215.                 return new JsonResponse(['error' => 'Process Yousign not found'], Response::HTTP_NOT_FOUND);
  216.             }
  217.             $signatureRequestId $processYousign->getSignatureRequestId();
  218.             $signatureRequest $this->yousignAPI->getSignatureRequest($signatureRequestId);
  219.             if ('ongoing' === $signatureRequest['status']) {
  220.                 // update signer
  221.                 $signers $this->yousignAPI->getSigners($signatureRequestId);
  222.                 $signer $signers[1];
  223.                 $signerData $this->yousignAPI->getSignerData($legalRepresentative);
  224.                 try {
  225.                     $signerRequest $this->yousignAPI->updateSigner($signatureRequestId$signer['id'], ['info' => $signerData['info']]);
  226.                     $document->setYousignLink($signerRequest['signature_link']);
  227.                 } catch (\Exception $e) {
  228.                     // do nothing
  229.                 }
  230.                 return $this->json(['linkContratDomiciliation' => $document->getYousignLink()]);
  231.             }
  232.             $documentId $signatureRequest['documents'][0]['id'];
  233.             $path PathGenerator::generatePathForDocument($document);
  234.             // if status is draft, activate the signature request
  235.             if ('draft' === $signatureRequest['status']) {
  236.                 $newDocumentRequest $this->yousignAPI->replaceDocument(
  237.                     $signatureRequestId,
  238.                     $this->documentFilesService->read($path),
  239.                     $documentId
  240.                 );
  241.                 $processYousign->setLastUploadedFileAt(new \DateTime());
  242.                 $this->em->flush();
  243.                 $user $this->em->getRepository(User::class)->findOneBy(['email' => 'william@digidom.pro']);
  244.                 $signers = [];
  245.                 if ($user) {
  246.                     switch ($organization->getStatus()) {
  247.                         case OrganizationStatusEnum::NEW_PAYMENT:
  248.                             $status 'validation-client';
  249.                             break;
  250.                         case OrganizationStatusEnum::DOCS_MISSING:
  251.                             $status 'non-urgent-client';
  252.                             break;
  253.                         default:
  254.                             $status 'autres';
  255.                             break;
  256.                     }
  257.                     $redirectTo getenv('URL_NEW_ADMIN').'/kyc/'.$status;
  258.                     $signers[] = $this->yousignAPI->getSignerData($user, [
  259.                         'success' => $redirectTo,
  260.                         'error' => $redirectTo,
  261.                     ]);
  262.                 }
  263.                 $redirectToSuccess $this->params->get('uri_tunnel').'/contrat/'.$organization->getId().'?signed=true';
  264.                 $redirectToCancel $this->params->get('uri_tunnel').'/contrat/'.$organization->getId().'?signed=false';
  265.                 $signers[] = $this->yousignAPI->getSignerData($legalRepresentative, [
  266.                     'success' => $redirectToSuccess,
  267.                     'error' => $redirectToCancel,
  268.                 ]);
  269.                 foreach ($signers as $signerData) {
  270.                     $this->yousignAPI->addSigner($signatureRequestId$signerData);
  271.                 }
  272.                 if ($newDocumentRequest) {
  273.                     $processYousign->setExternalFileId($newDocumentRequest['id']);
  274.                     $this->em->flush();
  275.                 }
  276.                 $this->yousignAPI->activate($signatureRequestId);
  277.             }
  278.             $signers $this->yousignAPI->getSigners($signatureRequestId);
  279.             $signer $signers[1];
  280.             // get link to sign the document
  281.             $document->setYousignLink($signer['signature_link']);
  282.             $this->em->flush();
  283.             if ($document->getYousignLink()) {
  284.                 return $this->json(['linkContratDomiciliation' => $document->getYousignLink()]);
  285.             }
  286.             return $this->json(['message' => 'Domiciliation contract not found'], Response::HTTP_BAD_REQUEST);
  287.         } elseif ('gocardless' === $type) {
  288.             $linkGocardless null;
  289.             $sessionID null;
  290.             $source $request->get('source'); // 'TUNNEL' or 'DASHBOARD'
  291.             if (null === $source) {
  292.                 $source '';
  293.             }
  294.             if (null === $organization->getMandatID()) {
  295.                 $linkGocardless $this->organizationUtils->generateURLGocardLess($organization$source);
  296.             }
  297.             $params = [
  298.                 'linkGocardless' => $linkGocardless,
  299.                 'sessionID' => $sessionID,
  300.             ];
  301.             return $this->json($params);
  302.         }
  303.         return $this->json(['message' => 'Type not found'], Response::HTTP_NOT_FOUND);
  304.     }
  305.     /**
  306.      * @Route("/{organizationID}/doc-to-validate-number", name="app_organization_doc_to_validate_number", methods={"GET"})
  307.      */
  308.     public function docToValidateNumbers(string $organizationID): JsonResponse
  309.     {
  310.         /** @var ?Organization $organization */
  311.         $organization $this->em->getRepository(Organization::class)->find($organizationID);
  312.         $organizationDocs $organization && $organization->getDocuments() ? $organization->getDocuments() : [];
  313.         $topLegalRepresentatives null !== $organization $organization->getLegalRepresentatives() : [];
  314.         $legalRepresentativeDocs = [];
  315.         foreach ($topLegalRepresentatives as $legalRepresentative) {
  316.             $legalRepresentativeDocs[] = $this->documentUtils->getLegalRepresentativeWithChildrenDocuments($legalRepresentative);
  317.         }
  318.         $dispatchedLrDocs = [];
  319.         foreach ($legalRepresentativeDocs as $docs) {
  320.             foreach ($docs as $doc) {
  321.                 $dispatchedLrDocs[] = $doc;
  322.             }
  323.         }
  324.         $allDocs array_merge_recursive($organizationDocs$dispatchedLrDocs);
  325.         $toApproveDoc array_filter($allDocs, function ($document) {
  326.             if (DocumentStatusEnum::TO_APPROVE === $document->getStatus()) {
  327.                 return $document;
  328.             }
  329.         });
  330.         return new JsonResponse(count($toApproveDoc), Response::HTTP_OK);
  331.     }
  332.     /**
  333.      * @Route("/{id}/regenerate-certificate", name="app_organization_regenerate_certificate", methods={"GET"})
  334.      */
  335.     public function regenerateCertificateDomiciliation(Request $request$id): JsonResponse
  336.     {
  337.         /** @var ?Organization $organization */
  338.         $organization $this->em->getRepository(Organization::class)->find($id);
  339.         if (null !== $organization) {
  340.             try {
  341.                 $this->organizationUtils->generateDocs(
  342.                     $organization,
  343.                     false,
  344.                     [DocumentTypeOrganizationEnum::DOMICILIATION_CERTIFICATE]
  345.                 );
  346.                 $this->em->refresh($organization);
  347.                 foreach ($organization->getDocuments() as $document) {
  348.                     if (DocumentTypeOrganizationEnum::DOMICILIATION_CERTIFICATE === $document->getType()) {
  349.                         $urlAPI $this->router->generate(
  350.                             'app_document_view',
  351.                             ['id' => $this->encryptor->encrypt($document->getId())]
  352.                         );
  353.                         $url $request->getSchemeAndHttpHost().$urlAPI;
  354.                         $url str_replace('http://''https://'$url);
  355.                         return $this->json(['url' => $url]);
  356.                     }
  357.                 }
  358.                 return $this->json(['message' => 'Domiciliation certificate not found'], Response::HTTP_NOT_FOUND);
  359.             } catch (\Exception $e) {
  360.                 return $this->json(['message' => 'Error'], Response::HTTP_INTERNAL_SERVER_ERROR);
  361.             }
  362.         }
  363.         return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
  364.     }
  365.     /**
  366.      * @Route("/account-statement/{id}/download", requirements={"id"="\d+"}, name="app_organization_account_statement_download", methods={"GET"})
  367.      */
  368.     public function downloadAccountStatementForOrganization(Request $requeststring $id): PdfResponse
  369.     {
  370.         $organizationRepository $this->em->getRepository(Organization::class);
  371.         $startDate $request->query->get('startDate');
  372.         $endDate $request->query->get('endDate');
  373.         $startDate = !strtotime($startDate) ? date('Y-m-01') : $startDate;
  374.         $endDate = !strtotime($endDate) ? date('Y-m-t'strtotime('-6 months')) : $endDate;
  375.         $accountDataForTemplate $organizationRepository->getOrganizationAccountStatementQuery(
  376.             $startDate,
  377.             $endDate,
  378.             $id
  379.         );
  380.         $organization $organizationRepository->getOrganizationInformationForAccountStatement($id)[0] ?? null;
  381.         if ([] === $organization) {
  382.             throw $this->createNotFoundException('Organization not found');
  383.         }
  384.         $organization['CountryTranslation'] = PostalAddress::getCountryName($organization['addressCountry'] ?? 'FR');
  385.         $legalName $organization['legalName'] ?? '';
  386.         $publicDir $this->kernel->getProjectDir().'/public/';
  387.         $filename iconv('UTF-8''ASCII//TRANSLIT''Releve-de-compte-'.$legalName.'-'.$startDate.'&'.$endDate.'.pdf');
  388.         $toPay array_reduce($accountDataForTemplate, static function ($carry$item) {
  389.             return $carry + (float) $item['toPay'];
  390.         }, 0);
  391.         $paid array_reduce($accountDataForTemplate, static function ($carry$item) {
  392.             return $carry + (float) $item['paid'];
  393.         }, 0);
  394.         $twigData = [
  395.             'startDate' => $startDate,
  396.             'endDate' => $endDate,
  397.             'accountStatements' => $accountDataForTemplate,
  398.             'publicDir' => $publicDir,
  399.             'organization' => $organization,
  400.             'toPay' => number_format($toPay2),
  401.             'paid' => number_format($paid2),
  402.             'due' => number_format($toPay $paid2),
  403.         ];
  404.         try {
  405.             return new PdfResponse(
  406.                 $this->pdf->getOutputFromHtml(
  407.                     $this->twig->render('billing/account_statement.html.twig'$twigData)
  408.                 ),
  409.                 $filename
  410.             );
  411.         } catch (\Exception $e) {
  412.             throw $this->createNotFoundException('Error while generating PDF');
  413.         }
  414.     }
  415.     /**
  416.      * @Route("/postal-power/{id}/download", requirements={"id"="\d+"}, name="app_organization_postal_power_download", methods={"GET"})
  417.      */
  418.     public function downloadPostalPowerOfAttorney(Request $requeststring $id)
  419.     {
  420.         $siren $request->query->get('siren');
  421.         $companyName $request->query->get('companyName');
  422.         $storeStreetAddress $request->query->get('storeStreetAddress');
  423.         $companyPostalCode $request->query->get('companyPostalCode');
  424.         $lrName $request->query->get('lrName');
  425.         $lrQuality $request->query->get('lrQuality');
  426.         $missingParams $this->checkParamsForPostalAttorneyDownload($siren$companyName$storeStreetAddress$companyPostalCode$lrName$lrQuality);
  427.         if (!empty($missingParams)) {
  428.             $missingParamsList implode(', '$missingParams);
  429.             $message "Les paramètres suivants sont manquants : $missingParamsList";
  430.             return new JsonResponse(['message' => $message], Response::HTTP_BAD_REQUEST);
  431.         }
  432.         $digidomData = [
  433.             'siren' => $this->appUtils->stringToArray(self::DIGIDOM_SIREN14),
  434.             'companyName' => $this->appUtils->stringToArray(self::DIGIDOM_COMPANY_NAME38),
  435.             'storeStreetAddress' => $this->appUtils->stringToArray(self::DIGIDOM_STORE_STREET_ADDRESS38),
  436.             'companyPostalCode' => $this->appUtils->stringToArray(self::DIGIDOM_COMPANY_POSTAL_CODE38),
  437.         ];
  438.         $twigData = [
  439.             'siren' => $this->appUtils->stringToArray($siren14),
  440.             'companyName' => $this->appUtils->stringToArray($companyName38),
  441.             'storeStreetAddress' => $this->appUtils->stringToArray($storeStreetAddress38),
  442.             'companyPostalCode' => $this->appUtils->stringToArray($companyPostalCode38),
  443.             'lrData' => [
  444.                 'name' => $lrName,
  445.                 'quality' => $lrQuality,
  446.             ],
  447.             'digidomData' => $digidomData,
  448.         ];
  449.         $options = [
  450.             'orientation' => 'Landscape',
  451.             'margin-bottom' => '0',
  452.             'margin-top' => '0',
  453.             'margin-right' => '1',
  454.             'margin-left' => '1',
  455.         ];
  456.         try {
  457.             return new PdfResponse(
  458.                 $this->pdf->getOutputFromHtml(
  459.                     $this->twig->render('documents/annexes/procuration/procuration_postal.html.twig'$twigData),
  460.                     $options
  461.                 ),
  462.             );
  463.         } catch (\Exception $e) {
  464.             throw $this->createNotFoundException('Error while generating PDF');
  465.         }
  466.     }
  467.     private function checkParamsForPostalAttorneyDownload($siren$legalName$agency$postalCode$lrName$lrQuality): array
  468.     {
  469.         $requiredParams = [
  470.             'siren' => $siren,
  471.             'legalName' => $legalName,
  472.             'agency' => $agency,
  473.             'postalCode' => $postalCode,
  474.             'lrName' => $lrName,
  475.             'lrQuality' => $lrQuality,
  476.         ];
  477.         $missingParams = [];
  478.         foreach ($requiredParams as $paramName => $paramValue) {
  479.             if (null === $paramValue) {
  480.                 $missingParams[] = $paramName;
  481.             }
  482.         }
  483.         return $missingParams;
  484.     }
  485.     /**
  486.      * @param string $documentType
  487.      *
  488.      * @return JsonResponse
  489.      *
  490.      * @Route("/{id}/generate-status", name="app_generate_organization_doc_status", methods={"GET"})
  491.      */
  492.     public function generateStatusDocument($id)
  493.     {
  494.         /** @var Organization $organization */
  495.         $organization $this->em->getRepository(Organization::class)->find($id);
  496.         if ($organization && $this->documentUtils->checkGenerateStatus($organization)) {
  497.             $trans DocumentTypeOrganizationEnum::getReadableValue(DocumentTypeOrganizationEnum::STATUS);
  498.             $document = new Document();
  499.             $document
  500.                 ->setType(DocumentTypeOrganizationEnum::STATUS)
  501.                 ->setStatus(DocumentStatusEnum::APPROVED)
  502.                 ->setOrganization($organization)
  503.                 ->setName($this->translator->trans($trans));
  504.             $organization->addDocument($document);
  505.             $this->em->persist($organization);
  506.             $this->em->flush();
  507.             return $this->json(['message' => 'Document generated'], Response::HTTP_OK);
  508.         }
  509.         return $this->json(['message' => 'Organization not found'], Response::HTTP_BAD_REQUEST);
  510.     }
  511.     /**
  512.      * @Route("/{id}/regenerate", name="app_organization_regenerate_contrat", methods={"GET"})
  513.      */
  514.     public function regenerateContratDomiciliation($id): JsonResponse
  515.     {
  516.         /** @var Organization $organization */
  517.         $organization $this->em->getRepository(Organization::class)->find($id);
  518.         if (!$organization) {
  519.             return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
  520.         }
  521.         $processYousignRepo $this->em->getRepository(ProcessYousign::class);
  522.         // delete procedure yousign for the subscriber can regenerate the request signature
  523.         $processYousign $processYousignRepo->findOneBy(['organization' => $organization]);
  524.         // delete signature request
  525.         if ($processYousign) {
  526.             try {
  527.                 foreach ($processYousign->getSignatures() as $signature) {
  528.                     $this->em->remove($signature);
  529.                 }
  530.                 $this->em->remove($processYousign);
  531.                 $organization->setProcessYousign(null);
  532.                 $this->em->flush();
  533.             } catch (\Exception $e) {
  534.                 // nothing to do
  535.             }
  536.         }
  537.         try {
  538.             $this->organizationUtils->generateDocs(
  539.                 $organization,
  540.                 false,
  541.                 [DocumentTypeOrganizationEnum::DOMICILIATION_CONTRACT]
  542.             );
  543.             return $this->json(['message' => 'Contrat regénéré']);
  544.         } catch (\Exception $e) {
  545.             return $this->json(['message' => 'Error'], Response::HTTP_INTERNAL_SERVER_ERROR);
  546.         }
  547.     }
  548.     /**
  549.      * @Route("/{id}/potential-case", name="app_organization_potential_case", methods={"GET"})
  550.      */
  551.     public function getOrganizationPotentialCase(string $id): JsonResponse
  552.     {
  553.         $potentialCase $this->em->getRepository(Organization::class)->getOrganizationPotentialCase($id);
  554.         if (null === $potentialCase[0]['id']) {
  555.             $potentialCase null;
  556.         }
  557.         return new JsonResponse($potentialCaseResponse::HTTP_OK);
  558.     }
  559.     /**
  560.      * @Route("/{id}/update-mandate", name="app_organization_update_mandate", methods={"GET"})
  561.      */
  562.     public function updateMandate($id)
  563.     {
  564.         $repository $this->em->getRepository(Organization::class);
  565.         /** @var Organization $organization */
  566.         $organization $repository->find($id);
  567.         if ($organization) {
  568.             $linkGocardless $this->organizationUtils->generateURLGocardLess($organization'DASHBOARD');
  569.             if ($linkGocardless) {
  570.                 $data = [
  571.                     'linkGocardless' => $linkGocardless,
  572.                     'sessionID' => $this->session->get('session_id'),
  573.                 ];
  574.                 return $this->json($dataResponse::HTTP_OK);
  575.             }
  576.             return $this->json(
  577.                 ['message' => 'Error gocardless'],
  578.                 Response::HTTP_INTERNAL_SERVER_ERROR
  579.             );
  580.         }
  581.         return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
  582.     }
  583.     /**
  584.      * @Route("/checked", name="app_organization_checked", methods={"GET"})
  585.      */
  586.     public function checkedLost()
  587.     {
  588.         /** @var OrganizationRepository $repository */
  589.         $repository $this->em->getRepository(Organization::class);
  590.         $aOrganizations $repository->getOrganizationWithStatus([OrganizationStatusEnum::NEW]);
  591.         $now time();
  592.         $expiration $now 30 86400;
  593.         $count 0;
  594.         /** @var Organization $organization */
  595.         foreach ($aOrganizations as $organization) {
  596.             $startingDate $organization->getDomiciliationStartDate();
  597.             if (null !== $startingDate) {
  598.                 $startingDate $startingDate->getTimestamp();
  599.             } elseif (null !== $organization->getCreatedAt()) {
  600.                 $startingDate $organization->getCreatedAt()->getTimestamp();
  601.             }
  602.             if ($expiration $startingDate
  603.                 && null !== $startingDate) {
  604.                 $organization->setStatus(OrganizationStatusEnum::LOST);
  605.                 $this->em->persist($organization);
  606.                 ++$count;
  607.             }
  608.         }
  609.         $this->em->flush();
  610.         return $this->json(['result' => 'success''count' => $count]);
  611.     }
  612.     /**
  613.      * @Route(
  614.      *     name="organization_document_to_check",
  615.      *     path="/{id}/documents_to_checked",
  616.      *     methods={"GET"},
  617.      *     defaults={"_api_item_operation_name"="get_document_to_checked"}
  618.      * )
  619.      */
  620.     public function documentsToCheck($id)
  621.     {
  622.         $repository $this->em->getRepository(Organization::class);
  623.         $organization $repository->find($id);
  624.         if (!$organization instanceof Organization) {
  625.             return $this->json([]);
  626.         }
  627.         $aDocuments $organization->getDocuments();
  628.         $aDocs = [];
  629.         foreach ($aDocuments as $document) {
  630.             if (DocumentStatusEnum::TO_APPROVE == $document->getStatus()) {
  631.                 $aDocs[] = $document;
  632.             }
  633.         }
  634.         if (null !== $organization->getLegalRepresentatives()) {
  635.             /** @var LegalRepresentative $legalRepresentative */
  636.             foreach ($organization->getLegalRepresentatives()->toArray() as $legalRepresentative) {
  637.                 /** @var Document $document */
  638.                 foreach ($legalRepresentative->getPerson()->getDocuments()->toArray() as $document) {
  639.                     if (DocumentStatusEnum::TO_APPROVE === $document->getStatus()) {
  640.                         $aDocs[] = $document;
  641.                     }
  642.                 }
  643.                 /*
  644.                  * Get document of parent where LegalRepresentative = LEGAL
  645.                  */
  646.                 if (null !== $legalRepresentative->getParent()) {
  647.                     /** @var Document $document */
  648.                     foreach ($legalRepresentative->getParent()->getPerson()->getDocuments()->toArray() as $document) {
  649.                         if (DocumentStatusEnum::TO_APPROVE === $document->getStatus()) {
  650.                             $aDocs[] = $document;
  651.                         }
  652.                     }
  653.                 }
  654.             }
  655.         }
  656.         return $this->json($aDocs);
  657.     }
  658.     /**
  659.      * @Route("/{id}/missing-documents", name="app_organization_missing_documents", methods={"GET"})
  660.      *
  661.      * @param EntityManagerInterface $em
  662.      *
  663.      * @return JsonResponse
  664.      */
  665.     public function getMissingDocuments(
  666.         $id,
  667.         OrganizationUtils $organizationUtils,
  668.         LegalRepresentativeUtils $legalRepresentativeUtils
  669.     ) {
  670.         $repository $this->em->getRepository(Organization::class);
  671.         /** @var Organization $organization */
  672.         $organization $repository->findOneBy(['id' => (int) $id]);
  673.         $missingDocuments = [];
  674.         if ($organization) {
  675.             foreach ($organization->getLegalRepresentatives() as $legalRepresentative) {
  676.                 $mandatoryDocuments $legalRepresentativeUtils->getMandatoryDocuments($legalRepresentative);
  677.                 foreach ($legalRepresentative->getPerson()->getDocuments() as $document) {
  678.                     if (DocumentStatusEnum::NOT_APPROVED != $document->getStatus()
  679.                         && isset($mandatoryDocuments[$document->getType()])) {
  680.                         unset($mandatoryDocuments[$document->getType()]);
  681.                     }
  682.                 }
  683.                 $missingDocuments['LR'][$legalRepresentative->getId()] = [
  684.                     'person' => [
  685.                         'id' => $legalRepresentative->getPerson()->getId(),
  686.                         'familyName' => $legalRepresentative->getPerson()->getFamilyName(),
  687.                         'givenName' => $legalRepresentative->getPerson()->getGivenName(),
  688.                         'legalName' => $legalRepresentative->getPerson()->getLegalName(),
  689.                         'type' => $legalRepresentative->getPerson()->getType(),
  690.                     ],
  691.                     'missingDocuments' => $mandatoryDocuments,
  692.                 ];
  693.             }
  694.             $mandatoryDocuments $organizationUtils->getMandatoryDocuments($organization);
  695.             foreach ($organization->getDocuments() as $document) {
  696.                 if (DocumentStatusEnum::NOT_APPROVED != $document->getStatus()
  697.                     && isset($mandatoryDocuments[$document->getType()])) {
  698.                     unset($mandatoryDocuments[$document->getType()]);
  699.                 }
  700.             }
  701.             $missingDocuments['Organization']['missingDocuments'] = $mandatoryDocuments;
  702.         }
  703.         return $this->json($missingDocuments);
  704.     }
  705.     /**
  706.      * @Route("/{id}/ordered-documents", name="app_organization_ordered_documents", methods={"GET"})
  707.      *
  708.      * @param EntityManagerInterface $em
  709.      *
  710.      * @return JsonResponse
  711.      */
  712.     public function getOrderedDocuments($id)
  713.     {
  714.         $repository $this->em->getRepository(Organization::class);
  715.         /** @var Organization $organization */
  716.         $organization $repository->findOneBy(['id' => (int) $id]);
  717.         if (!$organization) {
  718.             return $this->json(['error' => 'No organization found']);
  719.         }
  720.         $orgInvoices $organization->getInvoices()->filter(fn (Invoice $invoice) => InvoiceStatusEnum::DRAFT != $invoice->getStatus());
  721.         $orderedInvoices = [];
  722.         /** @var Invoice $invoice */
  723.         foreach ($orgInvoices as $invoice) {
  724.             $createdAt $invoice->getCreatedAt();
  725.             $url $this->generateUrl('app_invoice_view', [
  726.                 'id' => $this->encryptor->encrypt($invoice->getId()),
  727.             ]);
  728.             $orderedInvoices[$createdAt->format('Y')][$createdAt->format('m')][] = [
  729.                 'id' => $invoice->getId(),
  730.                 'createdAt' => $invoice->getCreatedAt(),
  731.                 'status' => $invoice->getStatus(),
  732.                 'path' => $url,
  733.                 'name' => $invoice->getName(),
  734.             ];
  735.         }
  736.         $orgLetters $organization->getLetters()->filter(fn (Letter $letter) => LetterTypeEnum::NOTICE != $letter->getType());
  737.         $isMailScanning SubscriptionUtils::hasAccessTo($organization->getSubscriptions(), ProductKeyEnum::NUMERISATION_COURRIER);
  738.         $orderedLetters = [];
  739.         $loopId 1;
  740.         /** @var Letter $letter */
  741.         foreach ($orgLetters as $letter) {
  742.             $createdAt $letter->getCreatedAt();
  743.             $urlRecto $this->generateUrl('app_letter_view', [
  744.                 'id' => $this->encryptor->encrypt($letter->getId()),
  745.                 'type' => 'recto',
  746.             ]);
  747.             $urlVerso $this->generateUrl('app_letter_view', [
  748.                 'id' => $this->encryptor->encrypt($letter->getId()),
  749.                 'type' => 'verso',
  750.             ]);
  751.             $urlContent $this->generateUrl('app_letter_view', [
  752.                 'id' => $this->encryptor->encrypt($letter->getId()),
  753.                 'type' => 'content',
  754.             ]);
  755.             if ($isMailScanning && null === $letter->getContentPathAWS()) {
  756.                 continue;
  757.             }
  758.             $orderedLetters[$createdAt->format('Y')][$createdAt->format('m')][] = [
  759.                 'id' => $letter->getId(),
  760.                 'createdAt' => $letter->getCreatedAt(),
  761.                 'status' => $letter->getStatus(),
  762.                 'path_recto' => $urlRecto,
  763.                 'path_verso' => $urlVerso,
  764.                 'path_content' => $urlContent,
  765.                 'name' => 'COURRIER-'.$loopId,
  766.             ];
  767.             ++$loopId;
  768.         }
  769.         $orgDocuments = [];
  770.         foreach ($organization->getDocuments() as $document) {
  771.             if (DocumentStatusEnum::APPROVED == $document->getStatus()) {
  772.                 $orgDocuments[] = $document;
  773.             }
  774.         }
  775.         $orderedOrgDocuments = [];
  776.         /** @var Document $document */
  777.         foreach ($orgDocuments as $document) {
  778.             $url $this->generateUrl('app_document_view', [
  779.                 'id' => $this->encryptor->encrypt($document->getId()),
  780.             ]);
  781.             $orderedOrgDocuments[] = [
  782.                 'id' => $document->getId(),
  783.                 'createdAt' => $document->getCreatedAt(),
  784.                 'status' => $document->getStatus(),
  785.                 'extension' => $document->getExtension(),
  786.                 'type' => $document->getType(),
  787.                 'path' => $url,
  788.                 'name' => $document->getName(),
  789.             ];
  790.         }
  791.         return $this->json([
  792.             'invoices' => $orderedInvoices,
  793.             'letters' => $orderedLetters,
  794.             'documents' => [
  795.                 'organization' => $orderedOrgDocuments,
  796.             ],
  797.         ]);
  798.     }
  799.     /**
  800.      * @Route("/{id}/prescribed", name="app_organization_prescribed", methods={"GET"})
  801.      *
  802.      * @return JsonResponse
  803.      */
  804.     public function getOrganizationPerscribed(Request $request$id)
  805.     {
  806.         $page $request->query->get('page');
  807.         $max $request->query->get('max-result');
  808.         $name $request->query->get('legal-name');
  809.         $isAuthorizePrescriber $request->query->get('authorize-prescriber');
  810.         if (null === $max) {
  811.             $max 30;
  812.         }
  813.         $repository $this->em->getRepository(Organization::class);
  814.         /** @var Organization $organizations */
  815.         $organizations $repository->getOrganizationPrescribed($id$page$max$name$isAuthorizePrescriber);
  816.         $data $organizations['data'];
  817.         $total $organizations['total'];
  818.         return $this->json(['data' => $data'total' => $total]);
  819.     }
  820.     /**
  821.      * @Route("/{id}/facturation", name="app_organization_prescribed_facturation", methods={"GET"})
  822.      *
  823.      * @return JsonResponse
  824.      */
  825.     public function getOrganizationPrecribedFacturation(Request $request$id)
  826.     {
  827.         $page $request->query->get('page');
  828.         $max $request->query->get('max-result');
  829.         $name $request->query->get('legal-name');
  830.         if (null === $max) {
  831.             $max 30;
  832.         }
  833.         $repository $this->em->getRepository(Organization::class);
  834.         /** @var Organization $organizations */
  835.         $organizations $repository->getPrescribedOrganizationId($id$name);
  836.         /** @var InvoiceRepository $invoiceRepository */
  837.         $invoiceRepository $this->em->getRepository(Invoice::class);
  838.         $quoteRepository $this->em->getRepository(Quote::class);
  839.         /** @var Invoice $invoices */
  840.         $invoices $invoiceRepository->getPrescribedInvoices($organizations$page$max);
  841.         /** @var Quote $quotes */
  842.         $quotes $quoteRepository->getPrescribedQuotes($organizations$page$max);
  843.         return $this->json([
  844.             'invoices' => $invoices['data'],
  845.             'quotes' => $quotes['data'],
  846.             'total_invoice' => $invoices['total'],
  847.             'total_quote' => $quotes['total'],
  848.         ]);
  849.     }
  850.     /**
  851.      * @Route("/{id}/letters", name="app_organization_letter", methods={"GET"})
  852.      *
  853.      * @return JsonResponse
  854.      */
  855.     public function getOrganizationLetters(Request $request$id)
  856.     {
  857.         $page $request->query->get('page');
  858.         $max $request->query->get('max-result');
  859.         $prescriberId = (int) $request->query->get('prescriber-id');
  860.         $data = [];
  861.         $total 0;
  862.         if (null === $max) {
  863.             $max 30;
  864.         }
  865.         if (null === $prescriberId) {
  866.             return $this->json([
  867.                 'message' => 'Letter not found',
  868.             ], Response::HTTP_NOT_FOUND);
  869.         }
  870.         $repository $this->em->getRepository(Organization::class);
  871.         /** @var Organization $organization */
  872.         $organization $repository->find($id);
  873.         if ($organization) {
  874.             if ($prescriberId !== $organization->getPrescriber()->getId()) {
  875.                 return $this->json([
  876.                     'message' => 'Letter not found',
  877.                 ], Response::HTTP_NOT_FOUND);
  878.             }
  879.             $letterRepository $this->em->getRepository(Letter::class);
  880.             /** @var Letter $letters */
  881.             $letters $letterRepository->getOrganizationLetters($id$page$max);
  882.             $data $letters['data'];
  883.             $total $letters['total'];
  884.         }
  885.         return $this->json(['data' => $data'total' => $total]);
  886.     }
  887.     /**
  888.      * @Route("/{id}/details", name="app_organization_details", methods={"GET"})
  889.      *
  890.      * @return JsonResponse
  891.      */
  892.     public function getOrganizationDetails(Request $request$id)
  893.     {
  894.         $prescriberId = (int) $request->query->get('prescriber-id');
  895.         $organizationDetails = [];
  896.         if (null === $prescriberId) {
  897.             return $this->json([
  898.                 'message' => 'Organization not found',
  899.             ], Response::HTTP_NOT_FOUND);
  900.         }
  901.         $repository $this->em->getRepository(Organization::class);
  902.         /** @var Organization $organization */
  903.         $organization $repository->find($id);
  904.         if ($organization && $organization->getPrescriber()) {
  905.             $organizationPrescriber $organization->getPrescriber();
  906.             if ($organizationPrescriber->getId() === $prescriberId) {
  907.                 $organizationDetails $organization;
  908.             } else {
  909.                 return $this->json([
  910.                     'message' => 'Organization not found',
  911.                 ], Response::HTTP_NOT_FOUND);
  912.             }
  913.         } else {
  914.             return $this->json([
  915.                 'message' => 'Organization not found',
  916.             ], Response::HTTP_NOT_FOUND);
  917.         }
  918.         return $this->json(['organization' => $organizationDetails]);
  919.     }
  920.     /**
  921.      * @Route("/{id}/balEmpty/{isEmpty}", name="app_organization_bal_empty", methods={"GET"})
  922.      *
  923.      * @return JsonResponse
  924.      */
  925.     public function setOrganizationEmptyBal(int $idbool $isEmpty)
  926.     {
  927.         $repository $this->em->getRepository(Organization::class);
  928.         /** @var Organization $organization */
  929.         $organization $repository->findOneBy(['id' => $id]);
  930.         if (!$organization) {
  931.             return $this->json(['error' => 'No organization found']);
  932.         }
  933.         $organization->setIsEmptybal($isEmpty);
  934.         $this->segmentAPI->trackNewLetterSignature(null$organization);
  935.         return $this->json(['message' => 'ok']);
  936.     }
  937.     /**
  938.      * @Route("/diagnostic/{id}", name="app_organization_diagnostic", methods={"GET"})
  939.      */
  940.     public function diagnosticOrganization(int $id): JsonResponse
  941.     {
  942.         $organization $this->em->getRepository(Organization::class)->find($id);
  943.         if (!$organization instanceof Organization) {
  944.             return $this->json(['error' => 'No organization found']);
  945.         }
  946.         return $this->json($this->organizationDiagnosticService->diagnosticOrganization($organization));
  947.     }
  948.     /**
  949.      * @Route("/filleul/{orgaId}", name="app_organization_filleul", methods={"GET"})
  950.      */
  951.     public function getFilleul(int $orgaIdOrganizationRepository $organizationRepository): JsonResponse
  952.     {
  953.         $encryptedParentId 'DIGIPAR'.$orgaId;
  954.         $allOrga $organizationRepository->findBy(['encryptedParentId' => $encryptedParentId]);
  955.         $aData = [];
  956.         foreach ($allOrga as $organization) {
  957.             $aData[] = [
  958.                 'id' => $organization->getId(),
  959.                 'legalName' => $organization->getLegalName(),
  960.                 'stores' => null !== $organization->getStore() ? $this->storeObject($organization->getStore()) : null,
  961.             ];
  962.         }
  963.         return new JsonResponse($aDataResponse::HTTP_OK);
  964.     }
  965.     private function storeObject($store): ?object
  966.     {
  967.         if ($store) {
  968.             return (object) [
  969.                 'id' => $store->getId(),
  970.                 'name' => $store->getName(),
  971.                 'postalAddress' => [
  972.                     'id' => $store->getPostalAddress()->getId(),
  973.                     'addressCountry' => $store->getPostalAddress()->getAddressCountry(),
  974.                     'addressLocality' => $store->getPostalAddress()->getAddressLocality(),
  975.                     'addressRegion' => $store->getPostalAddress()->getAddressRegion(),
  976.                     'postalCode' => $store->getPostalAddress()->getPostalCode(),
  977.                     'streetAddress' => $store->getPostalAddress()->getStreetAddress(),
  978.                 ],
  979.             ];
  980.         }
  981.         return null;
  982.     }
  983.     /**
  984.      * @Route("/with-same-name", name="app_organization_with_sameName", methods={"POST"})
  985.      *
  986.      * @throws ExceptionInterface
  987.      */
  988.     public function organizationWithSameName(Request $request): JsonResponse
  989.     {
  990.         $params json_decode($request->getContent() ?: '{}'true512JSON_THROW_ON_ERROR);
  991.         $data $this->organizationRepository->getOrganizationWithSameName(null$params);
  992.         return new JsonResponse(
  993.             $this->serializer->normalize($data'jsonld', ['groups' => 'read_comparisonkyc']),
  994.             Response::HTTP_OK
  995.         );
  996.     }
  997. }