<?php
namespace App\Controller\Api;
use App\Enum\DocumentStatusEnum;
use App\Enum\DocumentTypeOrganizationEnum;
use App\Enum\InvoiceStatusEnum;
use App\Enum\LetterTypeEnum;
use App\Enum\OrganizationStatusEnum;
use App\Enum\ProductKeyEnum;
use App\Repository\OrganizationRepository;
use App\Service\DocumentFilesService;
use App\Service\DocumentUtils;
use App\Service\EncryptorDataUtils;
use App\Service\LegalRepresentativeUtils;
use App\Service\Organization\OrganizationDiagnosticService;
use App\Service\OrganizationUtils;
use App\Service\SegmentAPI;
use App\Service\SubscriptionUtils;
use App\Traits\SentryNotifyTrait;
use App\Utils\AppUtils;
use App\Utils\InvoiceUtils;
use Doctrine\ORM\EntityManagerInterface;
use Evo\Domain\Core\SignatureServiceInterface;
use Evo\Infrastructure\MappingORM\Document;
use Evo\Infrastructure\MappingORM\Invoice;
use Evo\Infrastructure\MappingORM\LegalRepresentative;
use Evo\Infrastructure\MappingORM\Letter;
use Evo\Infrastructure\MappingORM\Organization;
use Evo\Infrastructure\MappingORM\PostalAddress;
use Evo\Infrastructure\MappingORM\ProcessYousign;
use Evo\Infrastructure\MappingORM\Quote;
use Evo\Infrastructure\MappingORM\Subscription;
use Evo\Infrastructure\MappingORM\User;
use Evo\Infrastructure\PdfGenerator\PathGenerator;
use Evo\Infrastructure\Repository\InvoiceRepository;
use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
use Knp\Snappy\Pdf;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Environment;
/**
* @Route("/organization")
*/
class OrganizationController extends AbstractController
{
use SentryNotifyTrait;
public const DIGIDOM_SIREN = '797978996';
public const DIGIDOM_COMPANY_NAME = 'KOAH DIGIDOM';
public const DIGIDOM_STORE_STREET_ADDRESS = '10 RUE DE PENTHIEVRE';
public const DIGIDOM_COMPANY_POSTAL_CODE = '75008 PARIS';
private EntityManagerInterface $em;
private OrganizationUtils $organizationUtils;
private InvoiceUtils $invoiceUtils;
private EncryptorDataUtils $encryptor;
private ?Request $request = null;
private UrlGeneratorInterface $router;
private SessionInterface $session;
private DocumentUtils $documentUtils;
private TranslatorInterface $translator;
private SegmentAPI $segmentAPI;
private OrganizationDiagnosticService $organizationDiagnosticService;
private AppUtils $appUtils;
private OrganizationRepository $organizationRepository;
private SerializerInterface $serializer;
private KernelInterface $kernel;
private Pdf $pdf;
private Environment $twig;
private LegalRepresentativeUtils $legalRepresentativeUtils;
private SignatureServiceInterface $yousignAPI;
private DocumentFilesService $documentFilesService;
private ParameterBagInterface $params;
public function __construct(
EntityManagerInterface $em,
InvoiceUtils $invoiceUtils,
DocumentUtils $documentUtils,
OrganizationUtils $organizationUtils,
LegalRepresentativeUtils $legalRepresentativeUtils,
SignatureServiceInterface $yousignAPI,
DocumentFilesService $documentFilesService,
ParameterBagInterface $params,
EncryptorDataUtils $encryptor,
RouterInterface $router,
SessionInterface $session,
TranslatorInterface $translator,
SegmentAPI $segmentAPI,
OrganizationDiagnosticService $organizationDiagnosticService,
AppUtils $appUtils,
OrganizationRepository $organizationRepository,
SerializerInterface $serializer,
KernelInterface $kernel,
Pdf $pdf,
Environment $twig
) {
$this->em = $em;
$this->documentUtils = $documentUtils;
$this->organizationUtils = $organizationUtils;
$this->invoiceUtils = $invoiceUtils;
$this->legalRepresentativeUtils = $legalRepresentativeUtils;
$this->yousignAPI = $yousignAPI;
$this->documentFilesService = $documentFilesService;
$this->params = $params;
$this->encryptor = $encryptor;
$this->router = $router;
$this->session = $session;
$this->translator = $translator;
$this->segmentAPI = $segmentAPI;
$this->organizationDiagnosticService = $organizationDiagnosticService;
$this->appUtils = $appUtils;
$this->organizationRepository = $organizationRepository;
$this->serializer = $serializer;
$this->kernel = $kernel;
$this->pdf = $pdf;
$this->twig = $twig;
}
/**
* @Route("/{id}/get-dom-subscription", name="app_organization_get_dom_subscription", methods={"GET"})
*/
public function getDomSubscription($id): JsonResponse
{
$organization = $this->em->getRepository(Organization::class)->find($id);
if (!$organization instanceof Organization) {
return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
$data = SubscriptionUtils::getDomSubscription($organization);
if (!$data instanceof Subscription) {
return $this->json(['message' => 'Subscription not found'], Response::HTTP_NOT_FOUND);
}
return $this->json($data, Response::HTTP_OK);
}
/**
* @Route("/{id}/summary", name="app_organization_summary", methods={"GET"})
*/
public function summary($id, Request $request)
{
$header = $request->headers->get('Authorization');
$data = explode(' ', $header);
$token = end($data);
$status = $request->get('status');
if (!$token) {
return $this->json(['result' => 'Accès refusé'], Response::HTTP_FORBIDDEN);
}
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organisation */
$organisation = $repository->find($id);
if (!$organisation) {
return $this->json(['result' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
if (!$this->organizationUtils->checkPermission($organisation, $token)) {
return $this->json(['result' => 'Accès refusé'], Response::HTTP_FORBIDDEN);
}
$result = array_merge_recursive($organisation->getInvoices()->toArray(), $organisation->getQuotes()->toArray());
foreach ($result as $key => $data) {
/*
* Filter
*/
if ($status && !in_array($data->getStatus(), $status)) {
unset($result[$key]);
continue;
}
if ($data instanceof Invoice) {
$data->setType('Invoice');
} elseif ($data instanceof Quote) {
$data->setType('Quote');
}
$result[$key] = $data;
}
$result = array_values($result);
$this->invoiceUtils->sortByCreatedDate($result);
return $this->json($result);
}
/**
* @Route("/{id}/generate-link/{type}", name="app_generate_link_externe", methods={"GET"})
*/
public function generateLinkYousign(int $id, Request $request, string $type = 'yousign'): JsonResponse
{
$repository = $this->em->getRepository(Organization::class);
$organization = $repository->find($id);
if (!$organization instanceof Organization) {
return $this->json(['result' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
if ('yousign' === $type) {
$organization = $this->em->getRepository(Organization::class)->find($id);
if (!$organization) {
return new JsonResponse(['error' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
$document = $this->organizationUtils->getContratDomiciliation($organization);
if (!$document) {
return new JsonResponse(['error' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
$legalRepresentative = $this->legalRepresentativeUtils->getFirstPhysicalRepresentative($organization);
if (!$legalRepresentative) {
return new JsonResponse(['error' => 'Legal representative not found'], Response::HTTP_NOT_FOUND);
}
if (!in_array($organization->getStatus(), [
OrganizationStatusEnum::NEW,
OrganizationStatusEnum::NEW_PAYMENT,
OrganizationStatusEnum::DOCS_MISSING,
OrganizationStatusEnum::DOCS_EXPIRED,
OrganizationStatusEnum::OK,
], true)) {
return new JsonResponse(['error' => 'Organization status not allowed'], Response::HTTP_BAD_REQUEST);
}
$processYousign = $organization->getProcessYousign();
if (!$processYousign) {
return new JsonResponse(['error' => 'Process Yousign not found'], Response::HTTP_NOT_FOUND);
}
$signatureRequestId = $processYousign->getSignatureRequestId();
$signatureRequest = $this->yousignAPI->getSignatureRequest($signatureRequestId);
if ('ongoing' === $signatureRequest['status']) {
// update signer
$signers = $this->yousignAPI->getSigners($signatureRequestId);
$signer = $signers[1];
$signerData = $this->yousignAPI->getSignerData($legalRepresentative);
try {
$signerRequest = $this->yousignAPI->updateSigner($signatureRequestId, $signer['id'], ['info' => $signerData['info']]);
$document->setYousignLink($signerRequest['signature_link']);
} catch (\Exception $e) {
// do nothing
}
return $this->json(['linkContratDomiciliation' => $document->getYousignLink()]);
}
$documentId = $signatureRequest['documents'][0]['id'];
$path = PathGenerator::generatePathForDocument($document);
// if status is draft, activate the signature request
if ('draft' === $signatureRequest['status']) {
$newDocumentRequest = $this->yousignAPI->replaceDocument(
$signatureRequestId,
$this->documentFilesService->read($path),
$documentId
);
$processYousign->setLastUploadedFileAt(new \DateTime());
$this->em->flush();
$user = $this->em->getRepository(User::class)->findOneBy(['email' => 'william@digidom.pro']);
$signers = [];
if ($user) {
switch ($organization->getStatus()) {
case OrganizationStatusEnum::NEW_PAYMENT:
$status = 'validation-client';
break;
case OrganizationStatusEnum::DOCS_MISSING:
$status = 'non-urgent-client';
break;
default:
$status = 'autres';
break;
}
$redirectTo = getenv('URL_NEW_ADMIN').'/kyc/'.$status;
$signers[] = $this->yousignAPI->getSignerData($user, [
'success' => $redirectTo,
'error' => $redirectTo,
]);
}
$redirectToSuccess = $this->params->get('uri_tunnel').'/contrat/'.$organization->getId().'?signed=true';
$redirectToCancel = $this->params->get('uri_tunnel').'/contrat/'.$organization->getId().'?signed=false';
$signers[] = $this->yousignAPI->getSignerData($legalRepresentative, [
'success' => $redirectToSuccess,
'error' => $redirectToCancel,
]);
foreach ($signers as $signerData) {
$this->yousignAPI->addSigner($signatureRequestId, $signerData);
}
if ($newDocumentRequest) {
$processYousign->setExternalFileId($newDocumentRequest['id']);
$this->em->flush();
}
$this->yousignAPI->activate($signatureRequestId);
}
$signers = $this->yousignAPI->getSigners($signatureRequestId);
$signer = $signers[1];
// get link to sign the document
$document->setYousignLink($signer['signature_link']);
$this->em->flush();
if ($document->getYousignLink()) {
return $this->json(['linkContratDomiciliation' => $document->getYousignLink()]);
}
return $this->json(['message' => 'Domiciliation contract not found'], Response::HTTP_BAD_REQUEST);
} elseif ('gocardless' === $type) {
$linkGocardless = null;
$sessionID = null;
$source = $request->get('source'); // 'TUNNEL' or 'DASHBOARD'
if (null === $source) {
$source = '';
}
if (null === $organization->getMandatID()) {
$linkGocardless = $this->organizationUtils->generateURLGocardLess($organization, $source);
}
$params = [
'linkGocardless' => $linkGocardless,
'sessionID' => $sessionID,
];
return $this->json($params);
}
return $this->json(['message' => 'Type not found'], Response::HTTP_NOT_FOUND);
}
/**
* @Route("/{organizationID}/doc-to-validate-number", name="app_organization_doc_to_validate_number", methods={"GET"})
*/
public function docToValidateNumbers(string $organizationID): JsonResponse
{
/** @var ?Organization $organization */
$organization = $this->em->getRepository(Organization::class)->find($organizationID);
$organizationDocs = $organization && $organization->getDocuments() ? $organization->getDocuments() : [];
$topLegalRepresentatives = null !== $organization ? $organization->getLegalRepresentatives() : [];
$legalRepresentativeDocs = [];
foreach ($topLegalRepresentatives as $legalRepresentative) {
$legalRepresentativeDocs[] = $this->documentUtils->getLegalRepresentativeWithChildrenDocuments($legalRepresentative);
}
$dispatchedLrDocs = [];
foreach ($legalRepresentativeDocs as $docs) {
foreach ($docs as $doc) {
$dispatchedLrDocs[] = $doc;
}
}
$allDocs = array_merge_recursive($organizationDocs, $dispatchedLrDocs);
$toApproveDoc = array_filter($allDocs, function ($document) {
if (DocumentStatusEnum::TO_APPROVE === $document->getStatus()) {
return $document;
}
});
return new JsonResponse(count($toApproveDoc), Response::HTTP_OK);
}
/**
* @Route("/{id}/regenerate-certificate", name="app_organization_regenerate_certificate", methods={"GET"})
*/
public function regenerateCertificateDomiciliation(Request $request, $id): JsonResponse
{
/** @var ?Organization $organization */
$organization = $this->em->getRepository(Organization::class)->find($id);
if (null !== $organization) {
try {
$this->organizationUtils->generateDocs(
$organization,
false,
[DocumentTypeOrganizationEnum::DOMICILIATION_CERTIFICATE]
);
$this->em->refresh($organization);
foreach ($organization->getDocuments() as $document) {
if (DocumentTypeOrganizationEnum::DOMICILIATION_CERTIFICATE === $document->getType()) {
$urlAPI = $this->router->generate(
'app_document_view',
['id' => $this->encryptor->encrypt($document->getId())]
);
$url = $request->getSchemeAndHttpHost().$urlAPI;
$url = str_replace('http://', 'https://', $url);
return $this->json(['url' => $url]);
}
}
return $this->json(['message' => 'Domiciliation certificate not found'], Response::HTTP_NOT_FOUND);
} catch (\Exception $e) {
return $this->json(['message' => 'Error'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
/**
* @Route("/account-statement/{id}/download", requirements={"id"="\d+"}, name="app_organization_account_statement_download", methods={"GET"})
*/
public function downloadAccountStatementForOrganization(Request $request, string $id): PdfResponse
{
$organizationRepository = $this->em->getRepository(Organization::class);
$startDate = $request->query->get('startDate');
$endDate = $request->query->get('endDate');
$startDate = !strtotime($startDate) ? date('Y-m-01') : $startDate;
$endDate = !strtotime($endDate) ? date('Y-m-t', strtotime('-6 months')) : $endDate;
$accountDataForTemplate = $organizationRepository->getOrganizationAccountStatementQuery(
$startDate,
$endDate,
$id
);
$organization = $organizationRepository->getOrganizationInformationForAccountStatement($id)[0] ?? null;
if ([] === $organization) {
throw $this->createNotFoundException('Organization not found');
}
$organization['CountryTranslation'] = PostalAddress::getCountryName($organization['addressCountry'] ?? 'FR');
$legalName = $organization['legalName'] ?? '';
$publicDir = $this->kernel->getProjectDir().'/public/';
$filename = iconv('UTF-8', 'ASCII//TRANSLIT', 'Releve-de-compte-'.$legalName.'-'.$startDate.'&'.$endDate.'.pdf');
$toPay = array_reduce($accountDataForTemplate, static function ($carry, $item) {
return $carry + (float) $item['toPay'];
}, 0);
$paid = array_reduce($accountDataForTemplate, static function ($carry, $item) {
return $carry + (float) $item['paid'];
}, 0);
$twigData = [
'startDate' => $startDate,
'endDate' => $endDate,
'accountStatements' => $accountDataForTemplate,
'publicDir' => $publicDir,
'organization' => $organization,
'toPay' => number_format($toPay, 2),
'paid' => number_format($paid, 2),
'due' => number_format($toPay - $paid, 2),
];
try {
return new PdfResponse(
$this->pdf->getOutputFromHtml(
$this->twig->render('billing/account_statement.html.twig', $twigData)
),
$filename
);
} catch (\Exception $e) {
throw $this->createNotFoundException('Error while generating PDF');
}
}
/**
* @Route("/postal-power/{id}/download", requirements={"id"="\d+"}, name="app_organization_postal_power_download", methods={"GET"})
*/
public function downloadPostalPowerOfAttorney(Request $request, string $id)
{
$siren = $request->query->get('siren');
$companyName = $request->query->get('companyName');
$storeStreetAddress = $request->query->get('storeStreetAddress');
$companyPostalCode = $request->query->get('companyPostalCode');
$lrName = $request->query->get('lrName');
$lrQuality = $request->query->get('lrQuality');
$missingParams = $this->checkParamsForPostalAttorneyDownload($siren, $companyName, $storeStreetAddress, $companyPostalCode, $lrName, $lrQuality);
if (!empty($missingParams)) {
$missingParamsList = implode(', ', $missingParams);
$message = "Les paramètres suivants sont manquants : $missingParamsList";
return new JsonResponse(['message' => $message], Response::HTTP_BAD_REQUEST);
}
$digidomData = [
'siren' => $this->appUtils->stringToArray(self::DIGIDOM_SIREN, 14),
'companyName' => $this->appUtils->stringToArray(self::DIGIDOM_COMPANY_NAME, 38),
'storeStreetAddress' => $this->appUtils->stringToArray(self::DIGIDOM_STORE_STREET_ADDRESS, 38),
'companyPostalCode' => $this->appUtils->stringToArray(self::DIGIDOM_COMPANY_POSTAL_CODE, 38),
];
$twigData = [
'siren' => $this->appUtils->stringToArray($siren, 14),
'companyName' => $this->appUtils->stringToArray($companyName, 38),
'storeStreetAddress' => $this->appUtils->stringToArray($storeStreetAddress, 38),
'companyPostalCode' => $this->appUtils->stringToArray($companyPostalCode, 38),
'lrData' => [
'name' => $lrName,
'quality' => $lrQuality,
],
'digidomData' => $digidomData,
];
$options = [
'orientation' => 'Landscape',
'margin-bottom' => '0',
'margin-top' => '0',
'margin-right' => '1',
'margin-left' => '1',
];
try {
return new PdfResponse(
$this->pdf->getOutputFromHtml(
$this->twig->render('documents/annexes/procuration/procuration_postal.html.twig', $twigData),
$options
),
);
} catch (\Exception $e) {
throw $this->createNotFoundException('Error while generating PDF');
}
}
private function checkParamsForPostalAttorneyDownload($siren, $legalName, $agency, $postalCode, $lrName, $lrQuality): array
{
$requiredParams = [
'siren' => $siren,
'legalName' => $legalName,
'agency' => $agency,
'postalCode' => $postalCode,
'lrName' => $lrName,
'lrQuality' => $lrQuality,
];
$missingParams = [];
foreach ($requiredParams as $paramName => $paramValue) {
if (null === $paramValue) {
$missingParams[] = $paramName;
}
}
return $missingParams;
}
/**
* @param string $documentType
*
* @return JsonResponse
*
* @Route("/{id}/generate-status", name="app_generate_organization_doc_status", methods={"GET"})
*/
public function generateStatusDocument($id)
{
/** @var Organization $organization */
$organization = $this->em->getRepository(Organization::class)->find($id);
if ($organization && $this->documentUtils->checkGenerateStatus($organization)) {
$trans = DocumentTypeOrganizationEnum::getReadableValue(DocumentTypeOrganizationEnum::STATUS);
$document = new Document();
$document
->setType(DocumentTypeOrganizationEnum::STATUS)
->setStatus(DocumentStatusEnum::APPROVED)
->setOrganization($organization)
->setName($this->translator->trans($trans));
$organization->addDocument($document);
$this->em->persist($organization);
$this->em->flush();
return $this->json(['message' => 'Document generated'], Response::HTTP_OK);
}
return $this->json(['message' => 'Organization not found'], Response::HTTP_BAD_REQUEST);
}
/**
* @Route("/{id}/regenerate", name="app_organization_regenerate_contrat", methods={"GET"})
*/
public function regenerateContratDomiciliation($id): JsonResponse
{
/** @var Organization $organization */
$organization = $this->em->getRepository(Organization::class)->find($id);
if (!$organization) {
return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
$processYousignRepo = $this->em->getRepository(ProcessYousign::class);
// delete procedure yousign for the subscriber can regenerate the request signature
$processYousign = $processYousignRepo->findOneBy(['organization' => $organization]);
// delete signature request
if ($processYousign) {
try {
foreach ($processYousign->getSignatures() as $signature) {
$this->em->remove($signature);
}
$this->em->remove($processYousign);
$organization->setProcessYousign(null);
$this->em->flush();
} catch (\Exception $e) {
// nothing to do
}
}
try {
$this->organizationUtils->generateDocs(
$organization,
false,
[DocumentTypeOrganizationEnum::DOMICILIATION_CONTRACT]
);
return $this->json(['message' => 'Contrat regénéré']);
} catch (\Exception $e) {
return $this->json(['message' => 'Error'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* @Route("/{id}/potential-case", name="app_organization_potential_case", methods={"GET"})
*/
public function getOrganizationPotentialCase(string $id): JsonResponse
{
$potentialCase = $this->em->getRepository(Organization::class)->getOrganizationPotentialCase($id);
if (null === $potentialCase[0]['id']) {
$potentialCase = null;
}
return new JsonResponse($potentialCase, Response::HTTP_OK);
}
/**
* @Route("/{id}/update-mandate", name="app_organization_update_mandate", methods={"GET"})
*/
public function updateMandate($id)
{
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organization */
$organization = $repository->find($id);
if ($organization) {
$linkGocardless = $this->organizationUtils->generateURLGocardLess($organization, 'DASHBOARD');
if ($linkGocardless) {
$data = [
'linkGocardless' => $linkGocardless,
'sessionID' => $this->session->get('session_id'),
];
return $this->json($data, Response::HTTP_OK);
}
return $this->json(
['message' => 'Error gocardless'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
/**
* @Route("/checked", name="app_organization_checked", methods={"GET"})
*/
public function checkedLost()
{
/** @var OrganizationRepository $repository */
$repository = $this->em->getRepository(Organization::class);
$aOrganizations = $repository->getOrganizationWithStatus([OrganizationStatusEnum::NEW]);
$now = time();
$expiration = $now - 30 * 86400;
$count = 0;
/** @var Organization $organization */
foreach ($aOrganizations as $organization) {
$startingDate = $organization->getDomiciliationStartDate();
if (null !== $startingDate) {
$startingDate = $startingDate->getTimestamp();
} elseif (null !== $organization->getCreatedAt()) {
$startingDate = $organization->getCreatedAt()->getTimestamp();
}
if ($expiration > $startingDate
&& null !== $startingDate) {
$organization->setStatus(OrganizationStatusEnum::LOST);
$this->em->persist($organization);
++$count;
}
}
$this->em->flush();
return $this->json(['result' => 'success', 'count' => $count]);
}
/**
* @Route(
* name="organization_document_to_check",
* path="/{id}/documents_to_checked",
* methods={"GET"},
* defaults={"_api_item_operation_name"="get_document_to_checked"}
* )
*/
public function documentsToCheck($id)
{
$repository = $this->em->getRepository(Organization::class);
$organization = $repository->find($id);
if (!$organization instanceof Organization) {
return $this->json([]);
}
$aDocuments = $organization->getDocuments();
$aDocs = [];
foreach ($aDocuments as $document) {
if (DocumentStatusEnum::TO_APPROVE == $document->getStatus()) {
$aDocs[] = $document;
}
}
if (null !== $organization->getLegalRepresentatives()) {
/** @var LegalRepresentative $legalRepresentative */
foreach ($organization->getLegalRepresentatives()->toArray() as $legalRepresentative) {
/** @var Document $document */
foreach ($legalRepresentative->getPerson()->getDocuments()->toArray() as $document) {
if (DocumentStatusEnum::TO_APPROVE === $document->getStatus()) {
$aDocs[] = $document;
}
}
/*
* Get document of parent where LegalRepresentative = LEGAL
*/
if (null !== $legalRepresentative->getParent()) {
/** @var Document $document */
foreach ($legalRepresentative->getParent()->getPerson()->getDocuments()->toArray() as $document) {
if (DocumentStatusEnum::TO_APPROVE === $document->getStatus()) {
$aDocs[] = $document;
}
}
}
}
}
return $this->json($aDocs);
}
/**
* @Route("/{id}/missing-documents", name="app_organization_missing_documents", methods={"GET"})
*
* @param EntityManagerInterface $em
*
* @return JsonResponse
*/
public function getMissingDocuments(
$id,
OrganizationUtils $organizationUtils,
LegalRepresentativeUtils $legalRepresentativeUtils
) {
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organization */
$organization = $repository->findOneBy(['id' => (int) $id]);
$missingDocuments = [];
if ($organization) {
foreach ($organization->getLegalRepresentatives() as $legalRepresentative) {
$mandatoryDocuments = $legalRepresentativeUtils->getMandatoryDocuments($legalRepresentative);
foreach ($legalRepresentative->getPerson()->getDocuments() as $document) {
if (DocumentStatusEnum::NOT_APPROVED != $document->getStatus()
&& isset($mandatoryDocuments[$document->getType()])) {
unset($mandatoryDocuments[$document->getType()]);
}
}
$missingDocuments['LR'][$legalRepresentative->getId()] = [
'person' => [
'id' => $legalRepresentative->getPerson()->getId(),
'familyName' => $legalRepresentative->getPerson()->getFamilyName(),
'givenName' => $legalRepresentative->getPerson()->getGivenName(),
'legalName' => $legalRepresentative->getPerson()->getLegalName(),
'type' => $legalRepresentative->getPerson()->getType(),
],
'missingDocuments' => $mandatoryDocuments,
];
}
$mandatoryDocuments = $organizationUtils->getMandatoryDocuments($organization);
foreach ($organization->getDocuments() as $document) {
if (DocumentStatusEnum::NOT_APPROVED != $document->getStatus()
&& isset($mandatoryDocuments[$document->getType()])) {
unset($mandatoryDocuments[$document->getType()]);
}
}
$missingDocuments['Organization']['missingDocuments'] = $mandatoryDocuments;
}
return $this->json($missingDocuments);
}
/**
* @Route("/{id}/ordered-documents", name="app_organization_ordered_documents", methods={"GET"})
*
* @param EntityManagerInterface $em
*
* @return JsonResponse
*/
public function getOrderedDocuments($id)
{
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organization */
$organization = $repository->findOneBy(['id' => (int) $id]);
if (!$organization) {
return $this->json(['error' => 'No organization found']);
}
$orgInvoices = $organization->getInvoices()->filter(fn (Invoice $invoice) => InvoiceStatusEnum::DRAFT != $invoice->getStatus());
$orderedInvoices = [];
/** @var Invoice $invoice */
foreach ($orgInvoices as $invoice) {
$createdAt = $invoice->getCreatedAt();
$url = $this->generateUrl('app_invoice_view', [
'id' => $this->encryptor->encrypt($invoice->getId()),
]);
$orderedInvoices[$createdAt->format('Y')][$createdAt->format('m')][] = [
'id' => $invoice->getId(),
'createdAt' => $invoice->getCreatedAt(),
'status' => $invoice->getStatus(),
'path' => $url,
'name' => $invoice->getName(),
];
}
$orgLetters = $organization->getLetters()->filter(fn (Letter $letter) => LetterTypeEnum::NOTICE != $letter->getType());
$isMailScanning = SubscriptionUtils::hasAccessTo($organization->getSubscriptions(), ProductKeyEnum::NUMERISATION_COURRIER);
$orderedLetters = [];
$loopId = 1;
/** @var Letter $letter */
foreach ($orgLetters as $letter) {
$createdAt = $letter->getCreatedAt();
$urlRecto = $this->generateUrl('app_letter_view', [
'id' => $this->encryptor->encrypt($letter->getId()),
'type' => 'recto',
]);
$urlVerso = $this->generateUrl('app_letter_view', [
'id' => $this->encryptor->encrypt($letter->getId()),
'type' => 'verso',
]);
$urlContent = $this->generateUrl('app_letter_view', [
'id' => $this->encryptor->encrypt($letter->getId()),
'type' => 'content',
]);
if ($isMailScanning && null === $letter->getContentPathAWS()) {
continue;
}
$orderedLetters[$createdAt->format('Y')][$createdAt->format('m')][] = [
'id' => $letter->getId(),
'createdAt' => $letter->getCreatedAt(),
'status' => $letter->getStatus(),
'path_recto' => $urlRecto,
'path_verso' => $urlVerso,
'path_content' => $urlContent,
'name' => 'COURRIER-'.$loopId,
];
++$loopId;
}
$orgDocuments = [];
foreach ($organization->getDocuments() as $document) {
if (DocumentStatusEnum::APPROVED == $document->getStatus()) {
$orgDocuments[] = $document;
}
}
$orderedOrgDocuments = [];
/** @var Document $document */
foreach ($orgDocuments as $document) {
$url = $this->generateUrl('app_document_view', [
'id' => $this->encryptor->encrypt($document->getId()),
]);
$orderedOrgDocuments[] = [
'id' => $document->getId(),
'createdAt' => $document->getCreatedAt(),
'status' => $document->getStatus(),
'extension' => $document->getExtension(),
'type' => $document->getType(),
'path' => $url,
'name' => $document->getName(),
];
}
return $this->json([
'invoices' => $orderedInvoices,
'letters' => $orderedLetters,
'documents' => [
'organization' => $orderedOrgDocuments,
],
]);
}
/**
* @Route("/{id}/prescribed", name="app_organization_prescribed", methods={"GET"})
*
* @return JsonResponse
*/
public function getOrganizationPerscribed(Request $request, $id)
{
$page = $request->query->get('page');
$max = $request->query->get('max-result');
$name = $request->query->get('legal-name');
$isAuthorizePrescriber = $request->query->get('authorize-prescriber');
if (null === $max) {
$max = 30;
}
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organizations */
$organizations = $repository->getOrganizationPrescribed($id, $page, $max, $name, $isAuthorizePrescriber);
$data = $organizations['data'];
$total = $organizations['total'];
return $this->json(['data' => $data, 'total' => $total]);
}
/**
* @Route("/{id}/facturation", name="app_organization_prescribed_facturation", methods={"GET"})
*
* @return JsonResponse
*/
public function getOrganizationPrecribedFacturation(Request $request, $id)
{
$page = $request->query->get('page');
$max = $request->query->get('max-result');
$name = $request->query->get('legal-name');
if (null === $max) {
$max = 30;
}
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organizations */
$organizations = $repository->getPrescribedOrganizationId($id, $name);
/** @var InvoiceRepository $invoiceRepository */
$invoiceRepository = $this->em->getRepository(Invoice::class);
$quoteRepository = $this->em->getRepository(Quote::class);
/** @var Invoice $invoices */
$invoices = $invoiceRepository->getPrescribedInvoices($organizations, $page, $max);
/** @var Quote $quotes */
$quotes = $quoteRepository->getPrescribedQuotes($organizations, $page, $max);
return $this->json([
'invoices' => $invoices['data'],
'quotes' => $quotes['data'],
'total_invoice' => $invoices['total'],
'total_quote' => $quotes['total'],
]);
}
/**
* @Route("/{id}/letters", name="app_organization_letter", methods={"GET"})
*
* @return JsonResponse
*/
public function getOrganizationLetters(Request $request, $id)
{
$page = $request->query->get('page');
$max = $request->query->get('max-result');
$prescriberId = (int) $request->query->get('prescriber-id');
$data = [];
$total = 0;
if (null === $max) {
$max = 30;
}
if (null === $prescriberId) {
return $this->json([
'message' => 'Letter not found',
], Response::HTTP_NOT_FOUND);
}
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organization */
$organization = $repository->find($id);
if ($organization) {
if ($prescriberId !== $organization->getPrescriber()->getId()) {
return $this->json([
'message' => 'Letter not found',
], Response::HTTP_NOT_FOUND);
}
$letterRepository = $this->em->getRepository(Letter::class);
/** @var Letter $letters */
$letters = $letterRepository->getOrganizationLetters($id, $page, $max);
$data = $letters['data'];
$total = $letters['total'];
}
return $this->json(['data' => $data, 'total' => $total]);
}
/**
* @Route("/{id}/details", name="app_organization_details", methods={"GET"})
*
* @return JsonResponse
*/
public function getOrganizationDetails(Request $request, $id)
{
$prescriberId = (int) $request->query->get('prescriber-id');
$organizationDetails = [];
if (null === $prescriberId) {
return $this->json([
'message' => 'Organization not found',
], Response::HTTP_NOT_FOUND);
}
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organization */
$organization = $repository->find($id);
if ($organization && $organization->getPrescriber()) {
$organizationPrescriber = $organization->getPrescriber();
if ($organizationPrescriber->getId() === $prescriberId) {
$organizationDetails = $organization;
} else {
return $this->json([
'message' => 'Organization not found',
], Response::HTTP_NOT_FOUND);
}
} else {
return $this->json([
'message' => 'Organization not found',
], Response::HTTP_NOT_FOUND);
}
return $this->json(['organization' => $organizationDetails]);
}
/**
* @Route("/{id}/balEmpty/{isEmpty}", name="app_organization_bal_empty", methods={"GET"})
*
* @return JsonResponse
*/
public function setOrganizationEmptyBal(int $id, bool $isEmpty)
{
$repository = $this->em->getRepository(Organization::class);
/** @var Organization $organization */
$organization = $repository->findOneBy(['id' => $id]);
if (!$organization) {
return $this->json(['error' => 'No organization found']);
}
$organization->setIsEmptybal($isEmpty);
$this->segmentAPI->trackNewLetterSignature(null, $organization);
return $this->json(['message' => 'ok']);
}
/**
* @Route("/diagnostic/{id}", name="app_organization_diagnostic", methods={"GET"})
*/
public function diagnosticOrganization(int $id): JsonResponse
{
$organization = $this->em->getRepository(Organization::class)->find($id);
if (!$organization instanceof Organization) {
return $this->json(['error' => 'No organization found']);
}
return $this->json($this->organizationDiagnosticService->diagnosticOrganization($organization));
}
/**
* @Route("/filleul/{orgaId}", name="app_organization_filleul", methods={"GET"})
*/
public function getFilleul(int $orgaId, OrganizationRepository $organizationRepository): JsonResponse
{
$encryptedParentId = 'DIGIPAR'.$orgaId;
$allOrga = $organizationRepository->findBy(['encryptedParentId' => $encryptedParentId]);
$aData = [];
foreach ($allOrga as $organization) {
$aData[] = [
'id' => $organization->getId(),
'legalName' => $organization->getLegalName(),
'stores' => null !== $organization->getStore() ? $this->storeObject($organization->getStore()) : null,
];
}
return new JsonResponse($aData, Response::HTTP_OK);
}
private function storeObject($store): ?object
{
if ($store) {
return (object) [
'id' => $store->getId(),
'name' => $store->getName(),
'postalAddress' => [
'id' => $store->getPostalAddress()->getId(),
'addressCountry' => $store->getPostalAddress()->getAddressCountry(),
'addressLocality' => $store->getPostalAddress()->getAddressLocality(),
'addressRegion' => $store->getPostalAddress()->getAddressRegion(),
'postalCode' => $store->getPostalAddress()->getPostalCode(),
'streetAddress' => $store->getPostalAddress()->getStreetAddress(),
],
];
}
return null;
}
/**
* @Route("/with-same-name", name="app_organization_with_sameName", methods={"POST"})
*
* @throws ExceptionInterface
*/
public function organizationWithSameName(Request $request): JsonResponse
{
$params = json_decode($request->getContent() ?: '{}', true, 512, JSON_THROW_ON_ERROR);
$data = $this->organizationRepository->getOrganizationWithSameName(null, $params);
return new JsonResponse(
$this->serializer->normalize($data, 'jsonld', ['groups' => 'read_comparisonkyc']),
Response::HTTP_OK
);
}
}