diff --git a/config/packages/vich_uploader.yaml b/config/packages/vich_uploader.yaml index b9bc551..a877357 100644 --- a/config/packages/vich_uploader.yaml +++ b/config/packages/vich_uploader.yaml @@ -46,6 +46,18 @@ vich_uploader: uri_prefix: /uploads/eflex/audit upload_destination: '%kernel.project_dir%/public/uploads/eflex/audit' namer: Vich\UploaderBundle\Naming\SmartUniqueNamer + contrat_pdf: + uri_prefix: /uploads/contrats + upload_destination: '%kernel.project_dir%/public/uploads/contrats' + namer: Vich\UploaderBundle\Naming\SmartUniqueNamer + contrat_signed_pdf: + uri_prefix: /uploads/contrats/signed + upload_destination: '%kernel.project_dir%/public/uploads/contrats/signed' + namer: Vich\UploaderBundle\Naming\SmartUniqueNamer + contrat_audit_pdf: + uri_prefix: /uploads/contrats/audit + upload_destination: '%kernel.project_dir%/public/uploads/contrats/audit' + namer: Vich\UploaderBundle\Naming\SmartUniqueNamer attestation_custom_pdf: uri_prefix: /uploads/attestations upload_destination: '%kernel.project_dir%/public/uploads/attestations' diff --git a/src/Controller/Admin/ContratController.php b/src/Controller/Admin/ContratController.php index a258ad8..aa9d183 100644 --- a/src/Controller/Admin/ContratController.php +++ b/src/Controller/Admin/ContratController.php @@ -2,7 +2,10 @@ namespace App\Controller\Admin; +use App\Entity\Contrat; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; @@ -11,9 +14,75 @@ use Symfony\Component\Security\Http\Attribute\IsGranted; #[IsGranted('ROLE_EMPLOYE')] class ContratController extends AbstractController { + public function __construct( + private EntityManagerInterface $em, + ) { + } + #[Route('', name: 'index')] public function index(): Response { - return $this->render('admin/contrats/index.html.twig'); + $contrats = $this->em->getRepository(Contrat::class)->findBy([], ['createdAt' => 'DESC']); + + return $this->render('admin/contrats/index.html.twig', [ + 'contrats' => $contrats, + ]); + } + + #[Route('/create', name: 'create', methods: ['POST'])] + public function create(Request $request): Response + { + $email = trim($request->request->getString('email')); + $raisonSociale = trim($request->request->getString('raisonSociale')); + $type = $request->request->getString('type'); + + if ('' === $email || '' === $raisonSociale || '' === $type) { + $this->addFlash('error', 'Tous les champs sont requis.'); + + return $this->redirectToRoute('app_admin_contrats_index'); + } + + if (!isset(Contrat::TYPE_LABELS[$type])) { + $this->addFlash('error', 'Type de contrat invalide.'); + + return $this->redirectToRoute('app_admin_contrats_index'); + } + + $contrat = new Contrat($email, $raisonSociale, $type); + $this->em->persist($contrat); + $this->em->flush(); + + $this->addFlash('success', 'Contrat '.$contrat->getReference().' cree.'); + + return $this->redirectToRoute('app_admin_contrats_show', ['id' => $contrat->getId()]); + } + + #[Route('/{id}', name: 'show', requirements: ['id' => '\d+'])] + public function show(int $id): Response + { + $contrat = $this->em->getRepository(Contrat::class)->find($id); + if (null === $contrat) { + throw $this->createNotFoundException('Contrat introuvable'); + } + + return $this->render('admin/contrats/show.html.twig', [ + 'contrat' => $contrat, + ]); + } + + #[Route('/{id}/cancel', name: 'cancel', requirements: ['id' => '\d+'], methods: ['POST'])] + public function cancel(int $id): Response + { + $contrat = $this->em->getRepository(Contrat::class)->find($id); + if (null === $contrat) { + throw $this->createNotFoundException('Contrat introuvable'); + } + + $contrat->setState(Contrat::STATE_CANCELLED); + $this->em->flush(); + + $this->addFlash('success', 'Contrat annule.'); + + return $this->redirectToRoute('app_admin_contrats_index'); } } diff --git a/src/Entity/Contrat.php b/src/Entity/Contrat.php new file mode 100644 index 0000000..cf0ecc7 --- /dev/null +++ b/src/Entity/Contrat.php @@ -0,0 +1,312 @@ + 'Contrat Migration SARL SITECONSEIL', + ]; + + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column] + private ?int $id = null; + + #[ORM\Column(length: 255)] + private string $email; + + #[ORM\Column(length: 255)] + private string $raisonSociale; + + #[ORM\Column(length: 50)] + private string $type; + + #[ORM\Column(length: 20, options: ['default' => 'draft'])] + private string $state = self::STATE_DRAFT; + + #[ORM\Column(nullable: true)] + private ?string $submissionId = null; + + #[ORM\Column(nullable: true)] + private ?int $submitterCompanyId = null; + + #[ORM\Column(nullable: true)] + private ?int $submitterCustomerId = null; + + // ── PDF Unsigned ── + #[ORM\Column(length: 255, nullable: true)] + private ?string $pdfUnsigned = null; + + #[Vich\UploadableField(mapping: 'contrat_pdf', fileNameProperty: 'pdfUnsigned')] + private ?File $pdfUnsignedFile = null; + + // ── PDF Signed ── + #[ORM\Column(length: 255, nullable: true)] + private ?string $pdfSigned = null; + + #[Vich\UploadableField(mapping: 'contrat_signed_pdf', fileNameProperty: 'pdfSigned')] + private ?File $pdfSignedFile = null; + + // ── PDF Audit ── + #[ORM\Column(length: 255, nullable: true)] + private ?string $pdfAudit = null; + + #[Vich\UploadableField(mapping: 'contrat_audit_pdf', fileNameProperty: 'pdfAudit')] + private ?File $pdfAuditFile = null; + + #[ORM\ManyToOne(targetEntity: Customer::class)] + #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')] + private ?Customer $customer = null; + + #[ORM\Column] + private \DateTimeImmutable $createdAt; + + #[ORM\Column(nullable: true)] + private ?\DateTimeImmutable $signedAt = null; + + #[ORM\Column(nullable: true)] + private ?\DateTimeImmutable $updatedAt = null; + + public function __construct(string $email, string $raisonSociale, string $type) + { + $this->email = $email; + $this->raisonSociale = $raisonSociale; + $this->type = $type; + $this->createdAt = new \DateTimeImmutable(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getReference(): string + { + return 'CTR_'.str_pad((string) ($this->id ?? 0), 5, '0', \STR_PAD_LEFT); + } + + public function getEmail(): string + { + return $this->email; + } + + public function setEmail(string $email): static + { + $this->email = $email; + + return $this; + } + + public function getRaisonSociale(): string + { + return $this->raisonSociale; + } + + public function setRaisonSociale(string $raisonSociale): static + { + $this->raisonSociale = $raisonSociale; + + return $this; + } + + public function getType(): string + { + return $this->type; + } + + public function getTypeLabel(): string + { + return self::TYPE_LABELS[$this->type] ?? $this->type; + } + + public function setType(string $type): static + { + $this->type = $type; + + return $this; + } + + public function getState(): string + { + return $this->state; + } + + public function setState(string $state): static + { + $this->state = $state; + + return $this; + } + + public function getSubmissionId(): ?string + { + return $this->submissionId; + } + + public function setSubmissionId(?string $submissionId): static + { + $this->submissionId = $submissionId; + + return $this; + } + + public function getSubmitterCompanyId(): ?int + { + return $this->submitterCompanyId; + } + + public function setSubmitterCompanyId(?int $submitterCompanyId): static + { + $this->submitterCompanyId = $submitterCompanyId; + + return $this; + } + + public function getSubmitterCustomerId(): ?int + { + return $this->submitterCustomerId; + } + + public function setSubmitterCustomerId(?int $submitterCustomerId): static + { + $this->submitterCustomerId = $submitterCustomerId; + + return $this; + } + + public function getPdfUnsigned(): ?string + { + return $this->pdfUnsigned; + } + + public function setPdfUnsigned(?string $pdfUnsigned): static + { + $this->pdfUnsigned = $pdfUnsigned; + + return $this; + } + + public function getPdfUnsignedFile(): ?File + { + return $this->pdfUnsignedFile; + } + + public function setPdfUnsignedFile(?File $file): static + { + $this->pdfUnsignedFile = $file; + if (null !== $file) { + $this->updatedAt = new \DateTimeImmutable(); + } + + return $this; + } + + public function getPdfSigned(): ?string + { + return $this->pdfSigned; + } + + public function setPdfSigned(?string $pdfSigned): static + { + $this->pdfSigned = $pdfSigned; + + return $this; + } + + public function getPdfSignedFile(): ?File + { + return $this->pdfSignedFile; + } + + public function setPdfSignedFile(?File $file): static + { + $this->pdfSignedFile = $file; + if (null !== $file) { + $this->updatedAt = new \DateTimeImmutable(); + } + + return $this; + } + + public function getPdfAudit(): ?string + { + return $this->pdfAudit; + } + + public function setPdfAudit(?string $pdfAudit): static + { + $this->pdfAudit = $pdfAudit; + + return $this; + } + + public function getPdfAuditFile(): ?File + { + return $this->pdfAuditFile; + } + + public function setPdfAuditFile(?File $file): static + { + $this->pdfAuditFile = $file; + if (null !== $file) { + $this->updatedAt = new \DateTimeImmutable(); + } + + return $this; + } + + public function getCustomer(): ?Customer + { + return $this->customer; + } + + public function setCustomer(?Customer $customer): static + { + $this->customer = $customer; + + return $this; + } + + public function getCreatedAt(): \DateTimeImmutable + { + return $this->createdAt; + } + + public function getSignedAt(): ?\DateTimeImmutable + { + return $this->signedAt; + } + + public function setSignedAt(?\DateTimeImmutable $signedAt): static + { + $this->signedAt = $signedAt; + + return $this; + } + + public function getUpdatedAt(): ?\DateTimeImmutable + { + return $this->updatedAt; + } + + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): static + { + $this->updatedAt = $updatedAt; + + return $this; + } +} diff --git a/templates/admin/contrats/index.html.twig b/templates/admin/contrats/index.html.twig index 730f42f..3154980 100644 --- a/templates/admin/contrats/index.html.twig +++ b/templates/admin/contrats/index.html.twig @@ -6,6 +6,7 @@

Contrats

+
{% for type, messages in app.flashes %} @@ -14,13 +15,79 @@ {% endfor %} {% endfor %} -
- - - -

Contrats

-

Cette section sera disponible prochainement.

-

Creez un contrat, faites-le signer, puis l'espace client sera cree automatiquement.

+ {% if contrats|length > 0 %} +
+ + + + + + + + + + + + + + {% for c in contrats %} + + + + + + + + + + {% endfor %} + +
ReferenceClientEmailTypeStatutDateActions
{{ c.reference }}{{ c.raisonSociale }}{{ c.email }}{{ c.typeLabel }} + {% if c.state == 'signed' %} + Signe + {% elseif c.state == 'send' %} + Envoye + {% elseif c.state == 'cancelled' %} + Annule + {% else %} + Brouillon + {% endif %} + {{ c.createdAt|date('d/m/Y') }} + Voir +
+
+ {% else %} +
Aucun contrat.
+ {% endif %} + + {# Modal creation #} +
{% endblock %} diff --git a/templates/admin/contrats/show.html.twig b/templates/admin/contrats/show.html.twig new file mode 100644 index 0000000..1ab3c40 --- /dev/null +++ b/templates/admin/contrats/show.html.twig @@ -0,0 +1,84 @@ +{% extends 'admin/_layout.html.twig' %} + +{% block title %}Contrat {{ contrat.reference }} - Association E-Cosplay{% endblock %} + +{% block admin_content %} +
+
+
+

{{ contrat.reference }}

+

{{ contrat.typeLabel }} - {{ contrat.raisonSociale }}

+
+
+ {% if contrat.state == 'signed' %} + Signe + {% elseif contrat.state == 'send' %} + Envoye + {% elseif contrat.state == 'cancelled' %} + Annule + {% else %} + Brouillon + {% endif %} + Retour +
+
+ + {% for type, messages in app.flashes %} + {% for message in messages %} +
{{ message }}
+ {% endfor %} + {% endfor %} + + {# Informations #} +
+
+

Client

+
+

Raison sociale : {{ contrat.raisonSociale }}

+

Email : {{ contrat.email }}

+ {% if contrat.customer %} +

Compte client : {{ contrat.customer.fullName }}

+ {% endif %} +
+
+
+

Contrat

+
+

Reference : {{ contrat.reference }}

+

Type : {{ contrat.typeLabel }}

+

Cree le : {{ contrat.createdAt|date('d/m/Y H:i') }}

+ {% if contrat.signedAt %} +

Signe le : {{ contrat.signedAt|date('d/m/Y H:i') }}

+ {% endif %} +
+
+
+ + {# Actions #} +
+ {% if contrat.pdfUnsigned %} + + Voir PDF + + {% endif %} + {% if contrat.pdfSigned %} + + Contrat signe + + {% endif %} + {% if contrat.pdfAudit %} + + Audit signature + + {% endif %} + {% if contrat.state in ['draft', 'send'] %} +
+ +
+ {% endif %} +
+
+{% endblock %}