From 45828174d1156c45a86cd16fcdb4f2d5639cce16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 23 Apr 2024 23:39:01 +0200 Subject: [PATCH] Add addressee history to ticket serialization This update extends the tickets serialization and normalisation process to include addressee history. With the changes, AddresseeHistory class now also keeps track of who removed an addressee. Additional types, tests and interfaces have been introduced to support this change. --- .../ChillMainBundle/Resources/public/types.ts | 2 ++ .../src/Entity/AddresseeHistory.php | 24 +++++++++++++ .../src/Resources/public/types.ts | 35 +++++++++++++++---- .../Normalizer/TicketNormalizer.php | 19 ++++++++++ .../Normalizer/TicketNormalizerTest.php | 18 ++++++++-- 5 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Resources/public/types.ts b/src/Bundle/ChillMainBundle/Resources/public/types.ts index 840a0e939..ada3089a0 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/types.ts +++ b/src/Bundle/ChillMainBundle/Resources/public/types.ts @@ -51,6 +51,8 @@ export interface UserGroup { excludeKey: string, } +export type UserGroupOrUser = User | UserGroup; + export interface UserAssociatedInterface { type: "user"; id: number; diff --git a/src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php b/src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php index b3718a9ca..2717df2a5 100644 --- a/src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php +++ b/src/Bundle/ChillTicketBundle/src/Entity/AddresseeHistory.php @@ -18,9 +18,11 @@ use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\UserGroup; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; #[ORM\Entity()] #[ORM\Table(name: 'addressee_history', schema: 'chill_ticket')] +#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['ticket_addressee_history' => AddresseeHistory::class])] class AddresseeHistory implements TrackUpdateInterface, TrackCreationInterface { use TrackCreationTrait; @@ -29,6 +31,7 @@ class AddresseeHistory implements TrackUpdateInterface, TrackCreationInterface #[ORM\Id] #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: false)] #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Serializer\Groups(['read'])] private ?int $id = null; #[ORM\ManyToOne(targetEntity: User::class)] @@ -39,11 +42,19 @@ class AddresseeHistory implements TrackUpdateInterface, TrackCreationInterface #[ORM\JoinColumn(nullable: true)] private ?UserGroup $addresseeGroup = null; + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => 'null'])] + #[Serializer\Groups(['read'])] private ?\DateTimeImmutable $endDate = null; + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: true)] + #[Serializer\Groups(['read'])] + private ?User $removedBy = null; + public function __construct( User|UserGroup $addressee, #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: false)] + #[Serializer\Groups(['read'])] private \DateTimeImmutable $startDate, #[ORM\ManyToOne(targetEntity: Ticket::class)] #[ORM\JoinColumn(nullable: false)] @@ -58,6 +69,7 @@ class AddresseeHistory implements TrackUpdateInterface, TrackCreationInterface $this->ticket->addAddresseeHistory($this); } + #[Serializer\Groups(['read'])] public function getAddressee(): UserGroup|User { if (null !== $this->addresseeGroup) { @@ -97,6 +109,18 @@ class AddresseeHistory implements TrackUpdateInterface, TrackCreationInterface return $this->ticket; } + public function getRemovedBy(): ?User + { + return $this->removedBy; + } + + public function setRemovedBy(?User $removedBy): self + { + $this->removedBy = $removedBy; + + return $this; + } + public function setEndDate(?\DateTimeImmutable $endDate): self { $this->endDate = $endDate; diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts b/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts index 2df53da99..0bcd1ecbb 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts @@ -1,4 +1,10 @@ -import {DateTime, TranslatableString, User} from "../../../../ChillMainBundle/Resources/public/types"; +import { + DateTime, + TranslatableString, + User, + UserGroup, + UserGroupOrUser +} from "../../../../ChillMainBundle/Resources/public/types"; import {Person} from "../../../../ChillPersonBundle/Resources/public/types"; export interface Motive { @@ -46,18 +52,33 @@ interface Comment { updatedAt: DateTime|null, } +interface AddresseeHistory { + type: "ticket_addressee_history", + id: number, + startDate: DateTime|null, + addressee: UserGroupOrUser, + endDate: DateTime|null, + removedBy: User|null, + createdBy: User|null, + createdAt: DateTime|null, + updatedBy: User|null, + updatedAt: DateTime|null, +} + interface AddPersonEvent extends TicketHistory<"add_person", PersonHistory> {}; interface AddCommentEvent extends TicketHistory<"add_comment", Comment> {}; interface SetMotiveEvent extends TicketHistory<"set_motive", MotiveHistory> {}; +interface AddAddressee extends TicketHistory<"add_addressee", AddresseeHistory> {}; -type TicketHistoryLine = AddPersonEvent | AddCommentEvent | SetMotiveEvent; +type TicketHistoryLine = AddPersonEvent | AddCommentEvent | SetMotiveEvent | AddAddressee; export interface Ticket { - type: "ticket_ticket" - id: number - externalRef: string - currentPersons: Person[] - currentMotive: null|Motive + type: "ticket_ticket", + id: number, + externalRef: string, + currentAddressees: UserGroupOrUser[], + currentPersons: Person[], + currentMotive: null|Motive, history: TicketHistoryLine[], } diff --git a/src/Bundle/ChillTicketBundle/src/Serializer/Normalizer/TicketNormalizer.php b/src/Bundle/ChillTicketBundle/src/Serializer/Normalizer/TicketNormalizer.php index c68ab34ef..f7aff602b 100644 --- a/src/Bundle/ChillTicketBundle/src/Serializer/Normalizer/TicketNormalizer.php +++ b/src/Bundle/ChillTicketBundle/src/Serializer/Normalizer/TicketNormalizer.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\TicketBundle\Serializer\Normalizer; +use Chill\TicketBundle\Entity\AddresseeHistory; use Chill\TicketBundle\Entity\Comment; use Chill\TicketBundle\Entity\MotiveHistory; use Chill\TicketBundle\Entity\PersonHistory; @@ -79,6 +80,24 @@ final class TicketNormalizer implements NormalizerInterface, NormalizerAwareInte ], $ticket->getComments()->toArray(), ), + ...array_map( + fn (AddresseeHistory $history) => [ + 'event_type' => 'add_addressee', + 'at' => $history->getStartDate(), + 'by' => $history->getCreatedBy(), + 'data' => $history, + ], + $ticket->getAddresseeHistories()->toArray(), + ), + ...array_map( + fn (AddresseeHistory $history) => [ + 'event_type' => 'remove_addressee', + 'at' => $history->getStartDate(), + 'by' => $history->getRemovedBy(), + 'data' => $history, + ], + $ticket->getAddresseeHistories()->filter(fn (AddresseeHistory $history) => null !== $history->getEndDate())->toArray() + ), ]; usort( diff --git a/src/Bundle/ChillTicketBundle/tests/Serializer/Normalizer/TicketNormalizerTest.php b/src/Bundle/ChillTicketBundle/tests/Serializer/Normalizer/TicketNormalizerTest.php index 447bebfbf..415fc15fb 100644 --- a/src/Bundle/ChillTicketBundle/tests/Serializer/Normalizer/TicketNormalizerTest.php +++ b/src/Bundle/ChillTicketBundle/tests/Serializer/Normalizer/TicketNormalizerTest.php @@ -12,7 +12,9 @@ declare(strict_types=1); namespace Chill\TicketBundle\Tests\Serializer\Normalizer; use Chill\MainBundle\Entity\User; +use Chill\MainBundle\Entity\UserGroup; use Chill\PersonBundle\Entity\Person; +use Chill\TicketBundle\Entity\AddresseeHistory; use Chill\TicketBundle\Entity\Comment; use Chill\TicketBundle\Entity\Motive; use Chill\TicketBundle\Entity\MotiveHistory; @@ -108,6 +110,8 @@ class TicketNormalizerTest extends KernelTestCase ->willReturn(['motiveHistory']); $normalizer->normalize(Argument::type(Comment::class), 'json', Argument::type('array')) ->willReturn(['comment']); + $normalizer->normalize(Argument::type(AddresseeHistory::class), 'json', Argument::type('array')) + ->willReturn(['addresseeHistory']); // null values $normalizer->normalize(null, 'json', Argument::type('array'))->willReturn(null); @@ -142,6 +146,9 @@ class TicketNormalizerTest extends KernelTestCase $comment = new Comment('blabla test', $ticket); $comment->setCreatedAt(new \DateTimeImmutable('2024-04-01T12:04:00')); $comment->setCreatedBy(new User()); + $addresseeHistory = new AddresseeHistory(new User(), new \DateTimeImmutable('2024-04-01T12:05:00'), $ticket); + $addresseeHistory->setEndDate(new \DateTimeImmutable('2024-04-01T12:06:00')); + new AddresseeHistory(new UserGroup(), new \DateTimeImmutable('2024-04-01T12:07:00'), $ticket); yield [ $ticket, @@ -150,10 +157,17 @@ class TicketNormalizerTest extends KernelTestCase 'id' => null, 'externalRef' => '2134', 'currentPersons' => ['embedded'], - 'currentAddressees' => [], + 'currentAddressees' => ['embedded'], 'currentInputs' => [], 'currentMotive' => ['type' => 'motive', 'id' => 0], - 'history' => [['event_type' => 'add_person'], ['event_type' => 'set_motive'], ['event_type' => 'add_comment']], + 'history' => [ + ['event_type' => 'add_person'], + ['event_type' => 'set_motive'], + ['event_type' => 'add_comment'], + ['event_type' => 'add_addressee'], + ['event_type' => 'remove_addressee'], + ['event_type' => 'add_addressee'], + ], ], ]; }