<?php
namespace App\Controller\Api;
use App\Enum\DocumentTypeOrganizationEnum;
use App\Enum\DocumentTypeUserEnum;
use App\Enum\OrganizationStatusEnum;
use App\Enum\PappersDocumentTypeOrganizationEnum;
use App\Service\DocumentUtils;
use App\Service\EncryptorDataUtils;
use App\Service\Organization\GetOrganizationFromUserAccess;
use App\Service\OrganizationUtils;
use App\Service\UserChecker;
use App\Traits\SentryNotifyTrait;
use App\Utils\UserUtils;
use Doctrine\ORM\EntityManagerInterface;
use Evo\Domain\Core\SignatureServiceInterface;
use Evo\Infrastructure\MappingORM\Document;
use Evo\Infrastructure\MappingORM\Organization;
use Evo\Infrastructure\MappingORM\User;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/document")
*/
class DocumentController extends AbstractController
{
use SentryNotifyTrait;
private SignatureServiceInterface $yousignAPI;
private EncryptorDataUtils $encryptor;
private KernelInterface $kernel;
private EntityManagerInterface $entityManager;
private UserChecker $userChecker;
private UserUtils $userUtils;
private DocumentUtils $documentUtils;
private OrganizationUtils $organizationUtils;
public function __construct(
SignatureServiceInterface $yousignAPI,
EncryptorDataUtils $encryptor,
EntityManagerInterface $entityManager,
UserChecker $userChecker,
UserUtils $userUtils,
DocumentUtils $documentUtils,
OrganizationUtils $organizationUtils
) {
$this->yousignAPI = $yousignAPI;
$this->encryptor = $encryptor;
$this->entityManager = $entityManager;
$this->userChecker = $userChecker;
$this->userUtils = $userUtils;
$this->documentUtils = $documentUtils;
$this->organizationUtils = $organizationUtils;
}
/**
* @Route("/get-all-types", name="app_document_get_all_types", methods={"GET"})
*/
public function getAllTypes(TranslatorInterface $translator)
{
$documentTypes = [];
$documentUserEnums = DocumentTypeUserEnum::getChoices();
$documentOrgaEnums = DocumentTypeOrganizationEnum::getChoices();
$documentEnums = array_merge($documentUserEnums, $documentOrgaEnums);
foreach ($documentEnums as $key => $value) {
$documentTypes[$translator->trans($key)] = $value;
}
return $this->json($documentTypes);
}
/**
* @Route("/checked", name="app_document_checked", methods={"GET"})
*/
public function checked(EntityManagerInterface $em)
{
$repository = $em->getRepository(Document::class);
$repositoryOrganization = $em->getRepository(Organization::class);
$aDocuments = $repository->findBy(['organization' => null]);
$aDocsType = DocumentTypeUserEnum::DOCUMENT_WITH_VALIDITY;
$aOrganizationStatus = [
OrganizationStatusEnum::NEW,
OrganizationStatusEnum::PRE_CANCELLATION,
OrganizationStatusEnum::CANCELLED,
OrganizationStatusEnum::LOST,
];
$now = strtotime(date('Y-m-d H:s:i'));
$count = 0;
/** @var Document $document */
foreach ($aDocuments as $document) {
$aOrganizations = $document->getPerson()->getLegalRepresentative()->getOrganizations()->toArray();
/** @var Organization $organization */
foreach ($aOrganizations as $organization) {
if (in_array($document->getType(), $aDocsType) && !in_array($organization->getStatus(), $aOrganizationStatus, true)) {
$expirationDate = $document->getExpirationDate();
if (null !== $expirationDate) {
$expirationDate = $expirationDate->getTimestamp();
if ($expirationDate < $now) {
$organization = $repositoryOrganization->find($organization->getId());
$organization->setStatus(OrganizationStatusEnum::DOCS_EXPIRED);
$em->persist($organization);
++$count;
}
}
}
}
}
$em->flush();
return $this->json(['result' => 'successs', 'count' => $count]);
}
/**
* @Route("/view/{id}/{token}", name="app_document_view", methods={"GET"})
*/
public function viewDocument(string $id, ?string $token = null): Response
{
$repository = $this->entityManager->getRepository(Document::class);
/** @var ?User $user */
$user = $this->userChecker->checkUserByToken($token);
$decryptedId = $this->encryptor->decrypt($id);
/** @var ?Document $document */
$document = $repository->find($decryptedId);
if (!$user || !$document) {
return $this->json(['result' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
if (in_array('ROLE_ADMIN', $user->getRoles(), true)) {
$this->documentUtils->viewDocument($document);
}
$organization = $document->getOrganization();
$person = $document->getPerson();
if (!$organization && null !== $person) {
$organization = GetOrganizationFromUserAccess::process($person, $user);
if (!$organization instanceof Organization) {
return $this->json(['result' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
}
$prescriberOrganizations = $this->userUtils->getOrganizationPrescribersID($user);
if ($organization ||
($organization->getPrescriber() && in_array($organization->getPrescriber()->getId(), $prescriberOrganizations, true))) {
$this->documentUtils->viewDocument($document);
}
return $this->json(['message' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
/**
* @Route("/download/{id}/{token}", name="app_document_dowload", methods={"GET"})
*/
public function downloadDocument(string $id, ?string $token = null): Response
{
$repository = $this->entityManager->getRepository(Document::class);
/** @var ?User $user */
$user = $this->userChecker->checkUserByToken($token);
$decryptedId = $this->encryptor->decrypt($id);
/** @var ?Document $document */
$document = $repository->find($decryptedId);
if (!$user || !$document) {
return $this->json(['result' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
if (in_array('ROLE_ADMIN', $user->getRoles(), true)) {
$this->documentUtils->downloadDocument($document);
}
$organization = $document->getOrganization();
$person = $document->getPerson();
if (!$organization && null !== $person) {
$organization = GetOrganizationFromUserAccess::process($person, $user);
if (!$organization instanceof Organization) {
return $this->json(['result' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
}
$prescriberOrganizations = $this->userUtils->getOrganizationPrescribersID($user);
if ($organization ||
($organization->getPrescriber() && in_array($organization->getPrescriber()->getId(), $prescriberOrganizations, true))) {
$this->documentUtils->downloadDocument($document);
}
return $this->json(['message' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
/**
* @Route("/download/{id}", name="app_document_download_aws_file", methods={"GET"})
*/
public function downloadAWSFile($id, EntityManagerInterface $em, DocumentUtils $documentUtils): JsonResponse
{
// @TODO: use flysystem and dynamic path
$repository = $em->getRepository(Document::class);
$id = $this->encryptor->decrypt($id);
$document = $repository->find($id);
if (null !== $document) {
return $this->json(['result' => $documentUtils->downloadAWSDocument($document)], Response::HTTP_OK);
}
return $this->json(['result' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
/**
* Check if is api can generate document.
*
* @Route("/{id}/is-able-to-generate", name="document_is_able_to_generate", methods={"GET"})
*/
public function isAbleToGenerateDocument(Request $request, int $id): JsonResponse
{
$documentToGenerate = $request->query->get('documentToGenerate');
$organization = $this->entityManager->getRepository(Organization::class)->find($id);
$isAble = false;
if ($organization && $documentToGenerate) {
$generateContract = DocumentTypeOrganizationEnum::DOMICILIATION_CONTRACT === $documentToGenerate;
$documentsOtherToGenerate = $this->organizationUtils->getDocsToGenerate($organization, $generateContract);
if ($this->documentUtils->checkGenerateStatus($organization)) {
$documentsOtherToGenerate[] = DocumentTypeOrganizationEnum::STATUS;
}
$isAble = in_array($documentToGenerate, $documentsOtherToGenerate);
}
return new JsonResponse(['isAble' => $isAble], Response::HTTP_OK);
}
/**
* Check if is PAPPERS can generate document.
*
* @Route("/{id}/is-pappers-able-to-generate", name="document_is_pappers_able_to_generate", methods={"GET"})
*
* @throws GuzzleException
*/
public function isPappersAbleToGenerateDocument(Request $request, int $id): JsonResponse
{
$documentToGenerate = $request->query->get('documentToGenerate');
$organization = $this->entityManager->getRepository(Organization::class)->find($id);
$isDocumentCanBeGenerated = false;
if ($organization && $organization->getSIRET() && $documentToGenerate) {
$isDocumentCanBeGenerated = array_search($documentToGenerate, PappersDocumentTypeOrganizationEnum::DOCUMENT_PAPPERS_ABLE_TO_GENERATE, true);
}
return new JsonResponse(
[
'isAble' => (bool) $isDocumentCanBeGenerated,
],
Response::HTTP_OK
);
}
/**
* @Route("/{documentId}/get-link-sign", name="document_get_link_sign", methods={"GET"})
*/
public function getLinkSign(string $documentId): JsonResponse
{
$docRepo = $this->entityManager->getRepository(Document::class);
$document = $docRepo->find($documentId);
if (!$document) {
return $this->json(['message' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
$organization = $document->getOrganization();
if (!$organization) {
return $this->json(['message' => 'Organization not found'], Response::HTTP_NOT_FOUND);
}
if (!$organization->getProcessYousign()) {
return $this->json(['message' => 'Process not found'], Response::HTTP_NOT_FOUND);
}
$signatureRequested = $this->yousignAPI->getSignatureRequest($document->getProcessYousigns()->first()->getUniqueKey());
if (!$this->yousignAPI->isResponseValid($signatureRequested)) {
return $this->json(['message' => 'Link not found'], Response::HTTP_NOT_FOUND);
}
$signer = $this->yousignAPI->getSigner($signatureRequested['id'], $signatureRequested['signers'][1]['id'] ?? $signatureRequested['signers'][0]['id']);
if (!$this->yousignAPI->isResponseValid($signer)) {
return $this->json(['message' => 'Link not found'], Response::HTTP_NOT_FOUND);
}
return $this->json(['link' => $signer['signature_link']]);
}
/**
* @Route("/{id}/is-exist", name="app_document_is_exist", methods={"GET"})
*/
public function isDocumentExist(string $id): JsonResponse
{
$repository = $this->entityManager->getRepository(Document::class);
$document = $repository->find($id);
if (!$document) {
return $this->json(['result' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
if (!$this->documentUtils->isDocumentExist($document)) {
return $this->json(['result' => 'Document not found'], Response::HTTP_NOT_FOUND);
}
return $this->json(['result' => true], Response::HTTP_OK);
}
}