diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index c491ee94d..f97f8a243 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -164,8 +164,12 @@ use Symfony\Component\Validator\Constraints as Assert; * @var Collection * @ORM\OneToMany( * targetEntity=AccompanyingPeriodWorkEvaluation::class, - * mappedBy="accompanyingPeriodWork" + * mappedBy="accompanyingPeriodWork", + * cascade={"persist"}, + * orphanRemoval=true * ) + * @Serializer\Groups({"read"}) + * @internal /!\ the serialization for read / write evaluations is handled in `AccompanyingPeriodWorkDenormalizer` */ private Collection $accompanyingPeriodWorkEvaluations; @@ -398,6 +402,11 @@ use Symfony\Component\Validator\Constraints as Assert; return $this->thirdParties; } + public function getThirdPartys(): Collection + { + return $this->getThirdParties(); + } + public function addThirdParty(ThirdParty $thirdParty): self { if (!$this->thirdParties->contains($thirdParty)) { @@ -434,4 +443,31 @@ use Symfony\Component\Validator\Constraints as Assert; return $this; } + + /** + * @return Collection + */ + public function getAccompanyingPeriodWorkEvaluations() + { + return $this->accompanyingPeriodWorkEvaluations; + } + + public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self + { + if (!$this->accompanyingPeriodWorkEvaluations->contains($evaluation)) { + $this->accompanyingPeriodWorkEvaluations[] = $evaluation; + $evaluation->setAccompanyingPeriodWork($this); + } + + return $this; + } + + public function removeAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self + { + $this->accompanyingPeriodWorkEvaluations + ->removeElement($evaluation); + $evaluation->setAccompanyingPeriodWork(null); + + return $this; + } } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php index ea7fa57b1..cce032621 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php @@ -12,10 +12,14 @@ use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; /** * @ORM\Entity * @ORM\Table("chill_person_accompanying_period_work_evaluation") + * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ + * "accompanying_period_work_evaluation"=AccompanyingPeriodWorkEvaluation::class, + * }) */ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCreationInterface { @@ -23,8 +27,9 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") + * @Serializer\Groups({"read"}) */ - private ?int $id; + private ?int $id = null; /** * @ORM\ManyToOne( @@ -32,60 +37,82 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre * inversedBy="accompanyingPeriodWorkEvaluations" * ) */ - private ?AccompanyingPeriodWork $accompanyingPeriodWork; + private ?AccompanyingPeriodWork $accompanyingPeriodWork = null; /** * @ORM\ManyToOne( * targetEntity=Evaluation::class * ) + * @Serializer\Groups({"read"}) + * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ - private ?Evaluation $evaluation; + private ?Evaluation $evaluation = null; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) + * @Serializer\Groups({"write"}) + * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ - private ?DateTimeImmutable $startDate; + private ?DateTimeImmutable $startDate = null; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) + * @Serializer\Groups({"write"}) + * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ - private ?DateTimeImmutable $endDate; + private ?DateTimeImmutable $endDate = null; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) + * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ - private ?DateTimeImmutable $maxDate; + private ?DateTimeImmutable $maxDate = null; /** * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) + * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ - private ?DateInterval $warningInterval; + private ?DateInterval $warningInterval = null; + /** + * @var string + * @Serializer\Groups({"read"}) + * @Serializer\Groups({"write"}) + * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) + */ private string $comment = ''; /** * @ORM\ManyToOne( * targetEntity=User::class * ) - */ - private ?User $createdBy; + * @Serializer\Groups({"read"}) + */ + private ?User $createdBy = null; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) */ - private ?DateTimeImmutable $createdAt; + private ?DateTimeImmutable $createdAt = null; /** * @ORM\ManyToOne( * targetEntity=User::class * ) + * @Serializer\Groups({"read"}) */ - private ?User $updatedBy; + private ?User $updatedBy = null; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) */ - private ?DateTimeImmutable $updatedAt; + private ?DateTimeImmutable $updatedAt = null; /** * @var Collection @@ -93,6 +120,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre * targetEntity=AccompanyingPeriodWorkEvaluationDocument::class, * mappedBy="accompanyingPeriodWorkEvaluation" * ) + * @Serializer\Groups({"read"}) */ private Collection $documents; @@ -123,6 +151,14 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre */ public function setAccompanyingPeriodWork(?AccompanyingPeriodWork $accompanyingPeriodWork): AccompanyingPeriodWorkEvaluation { + if ( + $accompanyingPeriodWork instanceof AccompanyingPeriodWork + && $this->accompanyingPeriodWork instanceof AccompanyingPeriodWork + && $this->accompanyingPeriodWork->getId() !== $accompanyingPeriodWork->getId()) { + throw new \RuntimeException("Changing the ". + "accompanyingPeriodWork is not allowed"); + } + $this->accompanyingPeriodWork = $accompanyingPeriodWork; return $this; } @@ -141,7 +177,20 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre */ public function setEvaluation(?Evaluation $evaluation): AccompanyingPeriodWorkEvaluation { + if ( + ($evaluation instanceof Evaluation + && $this->evaluation instanceof Evaluation + && $evaluation->getId() !== $this->evaluation->getId()) + || + ($this->evaluation instanceof Evaluation + && null === $evaluation) + ) { + throw new \LogicException("once set, an ${self::class} cannot + change or remove the linked Evaluation::class"); + } + $this->evaluation = $evaluation; + return $this; } @@ -306,4 +355,14 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre $this->updatedAt = $updatedAt; return $this; } + + /** + * @return Collection + */ + public function getDocuments() + { + return $this->documents; + } + + } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php index b0ddd7bab..4d652f338 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocument.php @@ -7,10 +7,14 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Entity\User; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; /** * @ORM\Entity * @ORM\Table("chill_person_accompanying_period_work_evaluation_document") + * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ + * "accompanying_period_work_evaluation_document"=AccompanyingPeriodWorkEvaluationDocument::class + * }) */ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doctrine\Model\TrackCreationInterface, \Chill\MainBundle\Doctrine\Model\TrackUpdateInterface { @@ -22,8 +26,10 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct * * @internal the default name exceeds 64 characters, we must set manually: * @ORM\SequenceGenerator(sequenceName="chill_person_social_work_eval_doc_id_seq", allocationSize=1, initialValue=1000) + * @Serializer\Groups({"read"}) */ private ?int $id; + /** * @var AccompanyingPeriodWorkEvaluation|null * @ORM\ManyToOne( @@ -37,11 +43,13 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct * @ORM\ManyToOne( * targetEntity=User::class * ) + * @Serializer\Groups({"read"}) */ private ?User $createdBy; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) */ private ?\DateTimeImmutable $createdAt; @@ -49,11 +57,13 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct * @ORM\ManyToOne( * targetEntity=User::class * ) + * @Serializer\Groups({"read"}) */ private ?User $updatedBy; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) */ private ?DateTimeImmutable $updatedAt; @@ -121,5 +131,44 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct return $this; } + /** + * @return int|null + */ + public function getId(): ?int + { + return $this->id; + } + + /** + * @return User|null + */ + public function getCreatedBy(): ?User + { + return $this->createdBy; + } + + /** + * @return \DateTimeImmutable|null + */ + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->createdAt; + } + + /** + * @return User|null + */ + public function getUpdatedBy(): ?User + { + return $this->updatedBy; + } + + /** + * @return DateTimeImmutable|null + */ + public function getUpdatedAt(): ?DateTimeInterface + { + return $this->updatedAt; + } } diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php index adc7f54fb..f01b2a4c1 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php @@ -3,10 +3,14 @@ namespace Chill\PersonBundle\Entity\SocialWork; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; /** * @ORM\Entity * @ORM\Table(name="chill_person_social_work_evaluation") + * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ + * "social_work_evaluation"=Evaluation::class + * }) */ class Evaluation { @@ -14,21 +18,25 @@ class Evaluation * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") + * @Serializer\Groups({"read"}) */ private $id; /** * @ORM\Column(type="json") + * @Serializer\Groups({"read"}) */ private $title = []; /** * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) */ private $delay; /** * @ORM\Column(type="dateinterval", nullable=true, options={"default": null}) + * @Serializer\Groups({"read"}) */ private $notificationDelay; diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkDenormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkDenormalizer.php new file mode 100644 index 000000000..4a8d51aa1 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkDenormalizer.php @@ -0,0 +1,132 @@ +workRepository = $workRepository; + $this->em = $em; + } + + /** + * @inheritDoc + */ + public function denormalize($data, string $type, string $format = null, array $context = []) + { + $work = $this->denormalizer->denormalize($data, $type, $format, \array_merge($context, + ['skip' => self::class])); + + if (\in_array('accompanying_period_work:edit', $context['groups'] ?? [])) { + $this->handleEvaluationCollection($data, $work, $format, $context); + } + + return $work; + } + + private function handleEvaluationCollection(array $data, AccompanyingPeriodWork $work, string $format, array $context) + { + $dataById = []; + $dataWithoutId = []; + foreach ($data['accompanyingPeriodWorkEvaluations'] as $e) { + if (\array_key_exists('id', $e)) { + $dataById[$e['id']] = $e; + } else { + $dataWithoutId[] = $e; + } + } + + // partition the separate kept evaluations and removed one + list($kept, $removed) = $work->getAccompanyingPeriodWorkEvaluations() + ->partition( + fn(int $key, AccompanyingPeriodWorkEvaluation $a) => \array_key_exists($a->getId(), $dataById) + ); + + // remove the evaluations from work + foreach ($removed as $r) { + $work->removeAccompanyingPeriodWorkEvaluation($r); + } + // handle the evaluation kept + foreach ($kept as $k) { + $this->denormalizer->denormalize( + $dataById[$k->getId()], + AccompanyingPeriodWorkEvaluation::class, + $format, + \array_merge( + $context, + [ + 'groups' => [ 'write' ], + AbstractNormalizer::OBJECT_TO_POPULATE => $k + ] + ) + ); + } + // create new evaluation + foreach ($dataWithoutId as $newData) { + $evaluation = $this->denormalizer->denormalize( + $newData, + AccompanyingPeriodWorkEvaluation::class, + $format, + \array_merge($context, ['groups' => [ 'accompanying_period_work_evaluation:create']] + ) + ); + $work->addAccompanyingPeriodWorkEvaluation($evaluation); + } + } + + /** + * @inheritDoc + */ + public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool + { + return $type === AccompanyingPeriodWork::class + && ($context['skip'] ?? null) !== self::class + && \is_array($data) + && \array_key_exists("type", $data) + && $data["type"] === 'accompanying_period_work'; + } + + +}