mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2026-02-13 11:55:30 +00:00
Add audit logging and subject conversion for accompanying periods
- Added `AccompanyingPeriodSubjectConverter` to handle subject conversion for accompanying periods. - Integrated `AuditEvent` dispatching into `AccompanyingCourseController` for key actions (e.g., create, view, update, delete, reopen). - Extended translations to include audit-related messages for accompanying periods. - Introduced tests for `AccompanyingPeriodSubjectConverter` to ensure proper functionality.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Audit\SubjectConverter;
|
||||
|
||||
use Chill\MainBundle\Audit\Subject;
|
||||
use Chill\MainBundle\Audit\SubjectConverterInterface;
|
||||
use Chill\MainBundle\Audit\SubjectConverterManagerAwareInterface;
|
||||
use Chill\MainBundle\Audit\SubjectConverterManagerAwareTrait;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
|
||||
/**
|
||||
* @implements SubjectConverterInterface<AccompanyingPeriod>
|
||||
*/
|
||||
class AccompanyingPeriodSubjectConverter implements SubjectConverterInterface, SubjectConverterManagerAwareInterface
|
||||
{
|
||||
use SubjectConverterManagerAwareTrait;
|
||||
|
||||
public function convert(mixed $subject): array
|
||||
{
|
||||
$data = [new Subject('accompanying_period', ['id' => $subject->getId()])];
|
||||
|
||||
foreach ($subject->getCurrentParticipations() as $participation) {
|
||||
$subjects = $this->subjectConverterManager->getSubjectsForEntity($participation->getPerson());
|
||||
if ($subjects instanceof Subject) {
|
||||
$data[] = $subjects;
|
||||
} else {
|
||||
foreach ($subjects as $s) {
|
||||
$data[] = $s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function supportsConvert(mixed $subject): bool
|
||||
{
|
||||
return $subject instanceof AccompanyingPeriod;
|
||||
}
|
||||
|
||||
public static function getDefaultPriority(): int
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\MainBundle\Audit\AuditEvent;
|
||||
use Chill\MainBundle\Entity\AuditTrail;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
@@ -20,6 +22,7 @@ use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepos
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -27,6 +30,7 @@ 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\Translation\TranslatableMessage;
|
||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
@@ -46,6 +50,7 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
private readonly Security $security,
|
||||
private readonly PersonRepository $personRepository,
|
||||
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
|
||||
private readonly EventDispatcherInterface $eventDispatcher,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -72,6 +77,15 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
|
||||
$em->flush();
|
||||
|
||||
$this->eventDispatcher->dispatch(
|
||||
new AuditEvent(
|
||||
AuditTrail::AUDIT_UPDATE,
|
||||
[$accompanyingCourse],
|
||||
new TranslatableMessage('accompanying_period.audit.close'),
|
||||
['action' => 'close']
|
||||
)
|
||||
);
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_course_index', [
|
||||
'accompanying_period_id' => $accompanyingCourse->getId(),
|
||||
]);
|
||||
@@ -119,6 +133,8 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
$em->remove($accompanyingCourse);
|
||||
$em->flush();
|
||||
|
||||
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_DELETE, [$accompanyingCourse]));
|
||||
|
||||
$this->addFlash('success', $this->translator
|
||||
->trans('The accompanying course has been successfully removed.'));
|
||||
|
||||
@@ -157,6 +173,13 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
{
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $accompanyingCourse);
|
||||
|
||||
$this->eventDispatcher->dispatch(new AuditEvent(
|
||||
AuditTrail::AUDIT_VIEW,
|
||||
[$accompanyingCourse],
|
||||
new TranslatableMessage('accompanying_period.audit.show_edit_page'),
|
||||
['action' => 'show_edit_page']
|
||||
));
|
||||
|
||||
return $this->render('@ChillPerson/AccompanyingCourse/edit.html.twig', [
|
||||
'accompanyingCourse' => $accompanyingCourse,
|
||||
]);
|
||||
@@ -189,6 +212,8 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
{
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse);
|
||||
|
||||
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_VIEW, [$accompanyingCourse]));
|
||||
|
||||
// compute some warnings
|
||||
// get persons without household
|
||||
$withoutHousehold = [];
|
||||
@@ -258,6 +283,8 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
$em->persist($period);
|
||||
$em->flush();
|
||||
|
||||
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_CREATE, [$period]));
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_course_edit', [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
]);
|
||||
@@ -295,6 +322,8 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
$em->persist($period);
|
||||
$em->flush();
|
||||
|
||||
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_CREATE, [$period]));
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_course_edit', [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
]);
|
||||
@@ -319,6 +348,8 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
|
||||
$accompanyingCourse->reOpen();
|
||||
$this->managerRegistry->getManager()->flush();
|
||||
|
||||
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_UPDATE, [$accompanyingCourse], new TranslatableMessage('accompanying_period.audit.reopen'), ['action' => 'reopen']));
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_course_index', [
|
||||
'accompanying_period_id' => $accompanyingCourse->getId(),
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Tests\Audit\SubjectConverter;
|
||||
|
||||
use Chill\MainBundle\Audit\Subject;
|
||||
use Chill\MainBundle\Audit\SubjectConverterManagerInterface;
|
||||
use Chill\PersonBundle\Audit\SubjectConverter\AccompanyingPeriodSubjectConverter;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class AccompanyingPeriodSubjectConverterTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private AccompanyingPeriodSubjectConverter $converter;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->converter = new AccompanyingPeriodSubjectConverter();
|
||||
}
|
||||
|
||||
public function testSupportsConvert(): void
|
||||
{
|
||||
$this->assertTrue($this->converter->supportsConvert($this->prophesize(AccompanyingPeriod::class)->reveal()));
|
||||
$this->assertFalse($this->converter->supportsConvert(new \stdClass()));
|
||||
}
|
||||
|
||||
public function testConvert(): void
|
||||
{
|
||||
$accompanyingPeriod = $this->prophesize(AccompanyingPeriod::class);
|
||||
$accompanyingPeriod->getId()->willReturn(123);
|
||||
|
||||
$person1 = $this->prophesize(Person::class);
|
||||
$participation1 = $this->prophesize(AccompanyingPeriodParticipation::class);
|
||||
$participation1->getPerson()->willReturn($person1->reveal());
|
||||
|
||||
$person2 = $this->prophesize(Person::class);
|
||||
$participation2 = $this->prophesize(AccompanyingPeriodParticipation::class);
|
||||
$participation2->getPerson()->willReturn($person2->reveal());
|
||||
|
||||
$accompanyingPeriod->getCurrentParticipations()->willReturn(new ArrayCollection([
|
||||
$participation1->reveal(),
|
||||
$participation2->reveal(),
|
||||
]));
|
||||
|
||||
$subjectConverterManager = $this->prophesize(SubjectConverterManagerInterface::class);
|
||||
|
||||
$personSubject1 = new Subject('person', ['id' => 1]);
|
||||
$personSubject2 = new Subject('person', ['id' => 2]);
|
||||
|
||||
$subjectConverterManager->getSubjectsForEntity($person1->reveal())->willReturn($personSubject1);
|
||||
$subjectConverterManager->getSubjectsForEntity($person2->reveal())->willReturn([$personSubject2]);
|
||||
|
||||
$this->converter->setSubjectConverterManager($subjectConverterManager->reveal());
|
||||
|
||||
$result = $this->converter->convert($accompanyingPeriod->reveal());
|
||||
|
||||
$this->assertCount(3, $result);
|
||||
$this->assertInstanceOf(Subject::class, $result[0]);
|
||||
$this->assertSame('accompanying_period', $result[0]->type);
|
||||
$this->assertSame(['id' => 123], $result[0]->identifiers);
|
||||
|
||||
$this->assertSame($personSubject1, $result[1]);
|
||||
$this->assertSame($personSubject2, $result[2]);
|
||||
}
|
||||
}
|
||||
@@ -861,6 +861,11 @@ accompanying_period:
|
||||
CONFIRMED_INACTIVE_SHORT: Hors file active
|
||||
CONFIRMED_INACTIVE_LONG: Pré-archivé
|
||||
emergency: Urgent
|
||||
audit:
|
||||
reopen: 'Ré-ouverture du parcours'
|
||||
close: 'Clôture du parcours'
|
||||
show_edit_page: 'Visualiser la page de modification du parcours'
|
||||
show_list_work: 'Liste des actions d''accompagnement'
|
||||
occasional: ponctuel
|
||||
regular: régulier
|
||||
Confidential: confidentiel
|
||||
|
||||
Reference in New Issue
Block a user