Integrate audit functionality into AccompanyingCourseWork actions

- Added `TriggerAuditInterface` to controllers and implemented audit triggers for create, update, delete, view, and list actions.
- Replaced `EventDispatcherInterface` with `triggerAudit` calls in relevant points.
- Enhanced French translations (`messages.fr.yml`) with audit-related labels for accompanying course work actions.
This commit is contained in:
2026-02-27 17:37:41 +01:00
parent e28dc355e8
commit 7714828637
3 changed files with 50 additions and 16 deletions

View File

@@ -11,24 +11,46 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\Audit\TriggerAuditInterface;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\Entity\AuditTrail;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Serializer\Model\Collection;
use Chill\MainBundle\Serializer\Model\Counter;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\ConstraintViolationListInterface;
class AccompanyingCourseWorkApiController extends ApiController
{
public function __construct(
private readonly AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository,
private readonly Security $security,
private readonly TriggerAuditInterface $triggerAudit,
) {}
protected function onAfterFlush(string $action, Request $request, string $_format, $entity, ConstraintViolationListInterface $errors, array $more = []): ?Response
{
if (Request::METHOD_GET === $request->getMethod()) {
$this->triggerAudit->triggerAudit(AuditTrail::AUDIT_VIEW, $entity);
} elseif (Request::METHOD_PUT === $request->getMethod() || Request::METHOD_PATCH === $request->getMethod()) {
$this->triggerAudit->triggerAudit(AuditTrail::AUDIT_UPDATE, $entity);
} elseif (Request::METHOD_POST === $request->getMethod()) {
$this->triggerAudit->triggerAudit(AuditTrail::AUDIT_CREATE, $entity);
} elseif (Request::METHOD_DELETE === $request->getMethod()) {
$this->triggerAudit->triggerAudit(AuditTrail::AUDIT_DELETE, $entity);
} else {
throw new \RuntimeException(sprintf('Unsupported HTTP method "%s" for audit trail.', $action));
}
return parent::onAfterFlush($action, $request, $_format, $entity, $errors, $more);
}
#[Route(path: '/api/1.0/person/accompanying-period/work/my-near-end')]
public function myWorksNearEndDate(Request $request): JsonResponse
{

View File

@@ -11,7 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\Audit\AuditEvent;
use Chill\MainBundle\Audit\TriggerAuditInterface;
use Chill\MainBundle\Entity\AuditTrail;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Pagination\PaginatorFactory;
@@ -23,7 +23,6 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
@@ -46,7 +45,7 @@ final class AccompanyingCourseWorkController extends AbstractController
private readonly TranslatableStringHelperInterface $translatableStringHelper,
private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory,
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
private readonly EventDispatcherInterface $eventDispatcher,
private readonly TriggerAuditInterface $triggerAudit,
) {}
#[Route(path: '{_locale}/person/accompanying-period/{id}/work/new', name: 'chill_person_accompanying_period_work_new', methods: ['GET'])]
@@ -70,6 +69,12 @@ final class AccompanyingCourseWorkController extends AbstractController
$json = $this->serializer->normalize($period, 'json', ['groups' => ['read']]);
$this->triggerAudit->triggerAudit(
AuditTrail::AUDIT_CREATE,
$period,
metadata: ['action' => 'create_form']
);
return $this->render('@ChillPerson/AccompanyingCourseWork/create.html.twig', [
'accompanyingCourse' => $period,
'json' => $json,
@@ -95,6 +100,11 @@ final class AccompanyingCourseWorkController extends AbstractController
'accompanying_period_id' => $work->getAccompanyingPeriod()->getId(),
]);
$this->triggerAudit->triggerAudit(
AuditTrail::AUDIT_DELETE,
$work,
);
$em->remove($work);
$em->flush();
@@ -117,12 +127,18 @@ final class AccompanyingCourseWorkController extends AbstractController
}
#[Route(path: '{_locale}/person/accompanying-period/work/{id}/edit', name: 'chill_person_accompanying_period_work_edit', methods: ['GET'])]
public function editWork(AccompanyingPeriodWork $work): Response
public function editWork(AccompanyingPeriodWork $work, Request $request): Response
{
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work);
$previousVersion = $work->getVersion();
$json = $this->serializer->normalize($work, 'json', ['groups' => ['read']]);
$this->triggerAudit->triggerAudit(
AuditTrail::AUDIT_VIEW,
$work,
);
return $this->render('@ChillPerson/AccompanyingCourseWork/edit.html.twig', [
'accompanyingCourse' => $work->getAccompanyingPeriod(),
'work' => $work,
@@ -159,13 +175,10 @@ final class AccompanyingCourseWorkController extends AbstractController
$paginator->getCurrentPageFirstItemNumber()
);
$this->eventDispatcher->dispatch(
new AuditEvent(
AuditTrail::AUDIT_VIEW,
$period,
description: new TranslatableMessage('accompanying_period.audit.show_list_work'),
metadata: ['action' => 'show_list_work']
)
$this->triggerAudit->triggerAudit(
AuditTrail::AUDIT_LIST,
$period,
description: new TranslatableMessage('audit.accompanying_period_work.list'),
);
return $this->render('@ChillPerson/AccompanyingCourseWork/index.html.twig', [
@@ -185,11 +198,9 @@ final class AccompanyingCourseWorkController extends AbstractController
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::SEE, $work);
$this->eventDispatcher->dispatch(
new AuditEvent(
AuditTrail::AUDIT_VIEW,
$work,
)
$this->triggerAudit->triggerAudit(
AuditTrail::AUDIT_VIEW,
$work,
);
return $this->render('@ChillPerson/AccompanyingCourseWork/show.html.twig', [

View File

@@ -1588,6 +1588,7 @@ audit:
remove_confidential: 'Indique parcours comme non-confidentiel'
accompanying_period_work:
accompanying_period_work_number: "Action d'accompagnement n°{id}"
list: Liste des actions d'accompagnement d'un parcours
person_resource:
list: Liste des personnes ressources
person_resource_number: "Personne ressource n°{id}: {name}"