Skip to content

Commit

Permalink
Referrals reports
Browse files Browse the repository at this point in the history
  • Loading branch information
Rémi authored and Rémi committed Feb 26, 2025
1 parent 79d9b79 commit 9ea77e2
Show file tree
Hide file tree
Showing 20 changed files with 266 additions and 66 deletions.
39 changes: 39 additions & 0 deletions features/api/referrals.feature
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,45 @@ Feature:
"status": "invitation_sent"
}
"""
And I should have 1 email "ReferralAdhesionCreatedMessage" for "[email protected]" with payload:
"""
{
"template_name": "referral-adhesion-created",
"template_content": [],
"message": {
"subject": "Nouveau parrainage",
"from_email": "[email protected]",
"html": null,
"merge_vars": [
{
"rcpt": "[email protected]",
"vars": [
{
"content": "Jane",
"name": "first_name"
},
{
"content": "http://test.renaissance.code/invitation/adhesion/@string@",
"name": "adhesion_link"
},
{
"content": "http://test.renaissance.code/invitation/@string@/signaler",
"name": "report_link"
}
]
}
],
"from_name": "Renaissance",
"to": [
{
"email": "[email protected]",
"type": "to",
"name": "Jane"
}
]
}
}
"""

Scenario: As an logged in user, I can create a new referral with all informations
Given I am logged with "[email protected]" via OAuth client "JeMengage Mobile" with scope "jemarche_app"
Expand Down
19 changes: 19 additions & 0 deletions migrations/2025/Version20250220155540.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20250220155540 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql('CREATE UNIQUE INDEX UNIQ_73079D00772E836A ON referral (identifier)');
}

public function down(Schema $schema): void
{
$this->addSql('DROP INDEX UNIQ_73079D00772E836A ON referral');
}
}
46 changes: 46 additions & 0 deletions src/Adherent/Referral/Notifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace App\Adherent\Referral;

use App\Controller\Renaissance\Referral\AdhesionController;
use App\Controller\Renaissance\Referral\Report\FormController;
use App\Entity\Referral;
use App\Mailer\MailerService;
use App\Mailer\Message\Renaissance\Referral\ReferralAdhesionCreatedMessage;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class Notifier
{
public function __construct(
private readonly MailerService $transactionalMailer,
private readonly UrlGeneratorInterface $urlGenerator,
) {
}

public function sendAdhesionMessage(Referral $referral): void
{
$this->transactionalMailer->sendMessage(
ReferralAdhesionCreatedMessage::create(
$referral->emailAddress,
$referral->firstName,
$this->generateUrl(
AdhesionController::ROUTE_NAME,
[
'identifier' => $referral->identifier,
]
),
$this->generateUrl(
FormController::ROUTE_NAME,
[
'identifier' => $referral->identifier,
]
)
)
);
}

private function generateUrl(string $routeName, array $parameters = []): string
{
return $this->urlGenerator->generate($routeName, $parameters, UrlGeneratorInterface::ABSOLUTE_URL);
}
}
31 changes: 0 additions & 31 deletions src/Adherent/Referral/ReferralNotifier.php

This file was deleted.

20 changes: 20 additions & 0 deletions src/Adherent/Referral/ReportHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Adherent\Referral;

use App\Entity\Referral;
use Doctrine\ORM\EntityManagerInterface;

class ReportHandler
{
public function __construct(private readonly EntityManagerInterface $entityManager)
{
}

public function report(Referral $referral): void
{
$referral->report();

$this->entityManager->flush();
}
}
1 change: 1 addition & 0 deletions src/Adherent/Referral/StatusEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ enum StatusEnum: string
case ACCOUNT_CREATED = 'account_created';
case ADHESION_FINISHED = 'adhesion_finished';
case ADHESION_VIA_OTHER_LINK = 'adhesion_via_other_link';
case REPORTED = 'reported';
}
6 changes: 3 additions & 3 deletions src/Api/Listener/PostReferralCreateListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
namespace App\Api\Listener;

use ApiPlatform\Symfony\EventListener\EventPriorities;
use App\Adherent\Referral\ReferralNotifier;
use App\Adherent\Referral\Notifier;
use App\Entity\Referral;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class PostReferralCreateListener implements EventSubscriberInterface
{
public function __construct(private readonly ReferralNotifier $referralNotifier)
public function __construct(private readonly Notifier $notifier)
{
}

Expand All @@ -29,7 +29,7 @@ public function onSubscribe(ViewEvent $viewEvent): void
}

if ($referral->isAdhesion()) {
$this->referralNotifier->sendAdhesionMessage($referral);
$this->notifier->sendAdhesionMessage($referral);
}
}
}
25 changes: 25 additions & 0 deletions src/Controller/Renaissance/Referral/AdhesionController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Controller\Renaissance\Referral;

use App\Entity\Referral;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/invitation/adhesion/{identifier}', name: self::ROUTE_NAME, requirements: ['uuid' => '%pattern_uuid%'], methods: ['GET', 'POST'])]
class AdhesionController extends AbstractController
{
public const ROUTE_NAME = 'app_referral_adhesion';

public function __invoke(Referral $referral): Response
{
if (!$referral->isAdhesion()) {
throw $this->createNotFoundException();
}

return $this->render('renaissance/referral/adhesion.html.twig', [
'referral' => $referral,
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Controller\Renaissance\Referral\Report;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/referral/report/confirmation', name: self::ROUTE_NAME, methods: ['GET'])]
class ConfirmationController extends AbstractController
{
public const ROUTE_NAME = 'app_referral_report_confirmation';

public function __invoke(): Response
{
return $this->render('renaissance/referral/report/confirmation.html.twig');
}
}
45 changes: 45 additions & 0 deletions src/Controller/Renaissance/Referral/Report/FormController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace App\Controller\Renaissance\Referral\Report;

use App\Adherent\Referral\ReportHandler;
use App\Entity\Referral;
use App\Form\ConfirmActionType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/invitation/{identifier}/signaler', name: self::ROUTE_NAME, requirements: ['uuid' => '%pattern_uuid%'], methods: ['GET', 'POST'])]
class FormController extends AbstractController
{
public const ROUTE_NAME = 'app_referral_report';

public function __construct(private readonly ReportHandler $reportHandler)
{
}

public function __invoke(Request $request, Referral $referral): Response
{
if ($referral->isReported()) {
return $this->render('renaissance/referral/report/already_reported.html.twig');
}

$form = $this
->createForm(ConfirmActionType::class, null, [
'with_deny' => false,
])
->handleRequest($request)
;

if ($form->isSubmitted() && $form->isValid()) {
$this->reportHandler->report($referral);

return $this->redirectToRoute('app_referral_report_confirmation');
}

return $this->render('renaissance/referral/report/form.html.twig', [
'form' => $form->createView(),
]);
}
}
20 changes: 0 additions & 20 deletions src/Controller/Renaissance/Referral/ReportController.php

This file was deleted.

16 changes: 7 additions & 9 deletions src/DataFixtures/ORM/LoadReferralData.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace App\DataFixtures\ORM;

use App\Adherent\Referral\IdentifierGenerator;
use App\Adherent\Referral\ModeEnum;
use App\Adherent\Referral\StatusEnum;
use App\Adherent\Referral\TypeEnum;
Expand All @@ -19,24 +18,22 @@ class LoadReferralData extends Fixture implements DependentFixtureInterface
public const UUID_1 = 'abeb6804-a88b-478a-8859-0c5e2f549d17';
public const UUID_2 = '2055b072-73f4-46c3-a9ab-1fb617c464f1';

public function __construct(private readonly IdentifierGenerator $referralIdentifierGenerator)
{
}

public function load(ObjectManager $manager): void
{
$manager->persist($this->createReferral(
Uuid::fromString(self::UUID_1),
'[email protected]',
'Jean',
$this->getReference('adherent-1', Adherent::class)
$this->getReference('adherent-1', Adherent::class),
'PAB123'
));

$manager->persist($this->createReferral(
Uuid::fromString(self::UUID_2),
'[email protected]',
'John',
$this->getReference('adherent-1', Adherent::class)
$this->getReference('adherent-1', Adherent::class),
'P789YZ'
));

$manager->flush();
Expand All @@ -46,15 +43,16 @@ private function createReferral(
UuidInterface $uuid,
string $emailAddress,
string $firstName,
?Adherent $referrer = null,
Adherent $referrer,
string $identifier,
): Referral {
$referral = new Referral($uuid);

$referral->emailAddress = $emailAddress;
$referral->firstName = $firstName;
$referral->referrer = $referrer;

$referral->identifier = $this->referralIdentifierGenerator->generate();
$referral->identifier = $identifier;
$referral->type = TypeEnum::INVITATION;
$referral->mode = ModeEnum::EMAIL;
$referral->status = StatusEnum::INVITATION_SENT;
Expand Down
14 changes: 12 additions & 2 deletions src/Entity/Referral.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class Referral
public ?Adherent $referred = null;

#[Groups(['referral_read'])]
#[ORM\Column(length: 6)]
#[ORM\Column(length: 6, unique: true)]
public ?string $identifier = null;

#[Groups(['referral_read'])]
Expand Down Expand Up @@ -122,9 +122,19 @@ public function hasFullInformations(): bool

public function isAdhesion(): bool
{
return in_array($this->type, [
return \in_array($this->type, [
TypeEnum::INVITATION,
TypeEnum::PREREGISTRATION,
], true);
}

public function isReported(): bool
{
return StatusEnum::REPORTED === $this->status;
}

public function report(): void
{
$this->status = StatusEnum::REPORTED;
}
}
Loading

0 comments on commit 9ea77e2

Please sign in to comment.