diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index afbb91963..611f1763e 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -26,6 +26,7 @@ use DateTimeImmutable; use DateTimeInterface; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\ReadableCollection; use Doctrine\ORM\Mapping as ORM; use LogicException; use Symfony\Component\Serializer\Annotation as Serializer; @@ -154,14 +155,11 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues private PrivateCommentEmbeddable $privateComment; /** - * @var Collection - * @ORM\ManyToMany(targetEntity=User::class) + * @var Collection + * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork") * @ORM\JoinTable(name="chill_person_accompanying_period_work_referrer") - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"accompanying_period_work:create"}) */ - private Collection $referrers; + private Collection $referrersHistory; /** * @var Collection @@ -220,7 +218,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues $this->thirdParties = new ArrayCollection(); $this->persons = new ArrayCollection(); $this->accompanyingPeriodWorkEvaluations = new ArrayCollection(); - $this->referrers = new ArrayCollection(); + $this->referrersHistory = new ArrayCollection(); } public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self @@ -254,8 +252,9 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues public function addReferrer(User $referrer): self { - if (!$this->referrers->contains($referrer)) { - $this->referrers[] = $referrer; + if (!$this->getReferrers()->contains($referrer)) { + $this->referrersHistory[] = + new AccompanyingPeriodWorkReferrerHistory($this, $referrer, new DateTimeImmutable('today')); } return $this; @@ -351,15 +350,18 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues } /** - * @return Collection|User[] + * @return ReadableCollection + * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + * @Serializer\Groups({"accompanying_period_work:create"}) */ - public function getReferrers(): Collection + public function getReferrers(): ReadableCollection { - return $this->referrers; + return $this->referrersHistory->map(fn (AccompanyingPeriodWorkReferrerHistory $h) => $h->getUser()); } /** - * @return Collection|Result[] + * @return Collection */ public function getResults(): Collection { @@ -434,7 +436,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues public function removeReferrer(User $referrer): self { - $this->referrers->removeElement($referrer); + foreach ($this->referrersHistory as $history) { + if ($history->isOpen() && $referrer === $history->getUser()) { + $history->setEndDate(new DateTimeImmutable('today')); + + if ($history->isDateRangeEmpty()) { + $history->removeAccompanyingPeriodWork(); + } + } + } return $this; } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php new file mode 100644 index 000000000..48b75d3e4 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php @@ -0,0 +1,125 @@ +accompanyingPeriodWork = $accompanyingPeriodWork; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function setEndDate(?\DateTimeImmutable $endDate): AccompanyingPeriodWorkReferrerHistory + { + $this->endDate = $endDate; + return $this; + } + + public function getAccompanyingPeriodWork(): AccompanyingPeriodWork + { + return $this->accompanyingPeriodWork; + } + + public function getUser(): User + { + return $this->user; + } + + public function getStartDate(): \DateTimeImmutable + { + return $this->startDate; + } + + /** + * to be used when the history is removed (when startDate = endDate) + * + * @return self + */ + public function removeAccompanyingPeriodWork(): self + { + $this->accompanyingPeriodWork = null; + + return $this; + } + + /** + * @return bool true if the endDate is null + */ + public function isOpen(): bool + { + return null === $this->getEndDate(); + } + + /** + * return true if the date range is empty (start date and end date are equal). + * + * @return bool true if the start date and end date are equal. + */ + public function isDateRangeEmpty(): bool + { + return $this->getStartDate()->format('Y-m-d') === $this->getEndDate()?->format('Y-m-d'); + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20231004142738.php b/src/Bundle/ChillPersonBundle/migrations/Version20231004142738.php new file mode 100644 index 000000000..0c9840fff --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20231004142738.php @@ -0,0 +1,85 @@ +addSql('CREATE SEQUENCE chill_person_accompanying_period_work_referrer_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT fk_3619f5ebb99f6060'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT FK_3619F5EBA76ED395'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT chill_person_accompanying_period_work_referrer_pkey'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD id INT NOT NULL DEFAULT nextval(\'chill_person_accompanying_period_work_referrer_id_seq\')'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD endDate DATE DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD startDate DATE DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER accompanyingperiodwork_id DROP NOT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER user_id DROP NOT NULL'); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.endDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.startDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EBC55C1209 FOREIGN KEY (accompanyingPeriodWork_id) REFERENCES chill_person_accompanying_period_work (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EBA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD PRIMARY KEY (id)'); + $this->addSql('ALTER INDEX idx_3619f5ebb99f6060 RENAME TO IDX_3619F5EBC55C1209'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD createdBy_id INT DEFAULT NULL;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD updatedBy_id INT DEFAULT NULL;'); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.endDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.startDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.updatedAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EB3174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EB65FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE;'); + $this->addSql('CREATE INDEX IDX_3619F5EB3174800F ON chill_person_accompanying_period_work_referrer (createdBy_id);'); + $this->addSql('CREATE INDEX IDX_3619F5EB65FF1AEC ON chill_person_accompanying_period_work_referrer (updatedBy_id);'); + + // set a default date on startDate + $this->addSql('UPDATE chill_person_accompanying_period_work_referrer r SET startdate=w.startdate FROM chill_person_accompanying_period_work w WHERE w.id = r.accompanyingperiodwork_id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER startDate SET NOT NULL'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT cpapwr_start_date_before_end CHECK (startdate <= enddate OR enddate IS NULL)'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer + ADD CONSTRAINT acc_period_work_ref_history_not_overlaps + EXCLUDE USING GIST (accompanyingperiodwork_id with =, user_id with =, tsrange(startdate, enddate) with &&) + DEFERRABLE INITIALLY DEFERRED'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_person_accompanying_period_work_referrer_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT FK_3619F5EBC55C1209'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT fk_3619f5eba76ed395'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT cpapwr_start_date_before_end'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT acc_period_work_ref_history_not_overlaps'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT chill_person_accompanying_period_work_referrer_pkey'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP endDate'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP startDate'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER user_id SET NOT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER accompanyingPeriodWork_id SET NOT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT fk_3619f5ebb99f6060 FOREIGN KEY (accompanyingperiodwork_id) REFERENCES chill_person_accompanying_period_work (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT fk_3619f5eba76ed395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD PRIMARY KEY (accompanyingperiodwork_id, user_id)'); + $this->addSql('ALTER INDEX idx_3619f5ebc55c1209 RENAME TO idx_3619f5ebb99f6060'); + } +}