Fix: force the consistency of location in accompanying period

- internally, the entity remove the addressLocation when the
  personLocation is set, and vice-versa;
- this commit add a migration which may solve the case when both case
  happens (priority to personLocation + keep the history)
- add a constraint on the database to avoid such situation
This commit is contained in:
Julien Fastré 2023-06-29 12:44:28 +02:00
parent 90e8687799
commit 347eda05df
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
5 changed files with 85 additions and 8 deletions

View File

@ -0,0 +1,6 @@
kind: Fixed
body: Force the db to have either a person_location or a address_location, and avoid
to have both also internally in the entity
time: 2023-06-29T12:44:12.019663991+02:00
custom:
Issue: ""

View File

@ -786,7 +786,7 @@ class AccompanyingPeriod implements
} }
/** /**
* @return Collection|AccompanyingPeriodLocationHistory[] * @return Collection<AccompanyingPeriodLocationHistory>
*/ */
public function getLocationHistories(): Collection public function getLocationHistories(): Collection
{ {
@ -797,6 +797,7 @@ class AccompanyingPeriod implements
* Get where the location is. * Get where the location is.
* *
* @Groups({"read"}) * @Groups({"read"})
* @return 'person'|'address'|'none'
*/ */
public function getLocationStatus(): string public function getLocationStatus(): string
{ {
@ -1209,6 +1210,7 @@ class AccompanyingPeriod implements
$this->addressLocation = $addressLocation; $this->addressLocation = $addressLocation;
if (null !== $addressLocation) { if (null !== $addressLocation) {
$this->setPersonLocation(null);
$locationHistory = new AccompanyingPeriodLocationHistory(); $locationHistory = new AccompanyingPeriodLocationHistory();
$locationHistory $locationHistory
->setStartDate(new DateTimeImmutable('now')) ->setStartDate(new DateTimeImmutable('now'))
@ -1327,6 +1329,7 @@ class AccompanyingPeriod implements
$this->personLocation = $person; $this->personLocation = $person;
if (null !== $person) { if (null !== $person) {
$this->setAddressLocation(null);
$locationHistory = new AccompanyingPeriodLocationHistory(); $locationHistory = new AccompanyingPeriodLocationHistory();
$locationHistory $locationHistory
->setStartDate(new DateTimeImmutable('now')) ->setStartDate(new DateTimeImmutable('now'))

View File

@ -138,12 +138,14 @@ final class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase
$this->assertCount(1, $period->getLocationHistories()); $this->assertCount(1, $period->getLocationHistories());
$this->assertSame($address, $period->getLocationHistories()->first()->getAddressLocation()); $this->assertSame($address, $period->getLocationHistories()->first()->getAddressLocation());
$this->assertNull($period->getLocationHistories()->first()->getPersonLocation());
$period->setPersonLocation($person); $period->setPersonLocation($person);
$period->setAddressLocation(null); $period->setAddressLocation(null);
$this->assertCount(2, $period->getLocationHistories()); $this->assertCount(2, $period->getLocationHistories());
$this->assertSame($person, $period->getLocationHistories()->last()->getPersonLocation()); $this->assertSame($person, $period->getLocationHistories()->last()->getPersonLocation());
$this->assertNull($period->getLocationHistories()->last()->getAddressLocation());
$period->setAddressLocation($address); $period->setAddressLocation($address);
$period->setPersonLocation(null); $period->setPersonLocation(null);
@ -172,14 +174,35 @@ final class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase
} while ($iterator->valid()); } while ($iterator->valid());
} }
public function testIsClosed()
{
$period = new AccompanyingPeriod(new DateTime());
$period->setClosingDate(new DateTime('tomorrow'));
$this->assertFalse($period->isOpen()); public function testHistoryLocationNotHavingBothAtStart()
{
$period = new AccompanyingPeriod();
$person = new Person();
$address = new Address();
$period->setAddressLocation($address);
$period->setPersonLocation($person);
$period->setStep(AccompanyingPeriod::STEP_CONFIRMED);
$this->assertCount(1, $period->getLocationHistories());
self::assertNull($period->getAddressLocation());
self::assertNull($period->getLocationHistories()->first()->getAddressLocation());
self::assertSame($person, $period->getLocationHistories()->first()->getPersonLocation());
self::assertSame($person, $period->getPersonLocation());
self::assertEquals('person', $period->getLocationStatus());
} }
public function testIsClosed()
{
$period = new AccompanyingPeriod(new DateTime());
$period->setClosingDate(new DateTime('tomorrow'));
$this->assertFalse($period->isOpen());
}
public function testIsOpen() public function testIsOpen()
{ {
$period = new AccompanyingPeriod(new DateTime()); $period = new AccompanyingPeriod(new DateTime());

View File

@ -0,0 +1,45 @@
<?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\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20230628152138 extends AbstractMigration
{
public function getDescription(): string
{
return 'An accompanying period cannot have both a locaiton on a period and on an address';
}
public function up(Schema $schema): void
{
$this->addSql('UPDATE chill_person_accompanying_period SET addresslocation_id = NULL
where personlocation_id IS NOT NULL AND addresslocation_id IS NOT NULL');
$this->addSql('INSERT INTO chill_person_accompanying_period_location_history
(id, period_id, startdate, enddate, createdat, personlocation_id, addresslocation_id, createdby_id)
SELECT nextval(\'chill_person_accompanying_period_location_history_id_seq\'), period_id, startdate, startdate, now(), null, addresslocation_id, null
FROM chill_person_accompanying_period_location_history
WHERE personlocation_id IS NOT NULL AND addresslocation_id IS NOT NULL
');
$this->addSql('UPDATE chill_person_accompanying_period_location_history SET addresslocation_id = NULL WHERE addresslocation_id IS NOT NULL AND personlocation_id IS NOT NULL');
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT location_check CHECK (personlocation_id IS NULL OR addresslocation_id IS NULL)');
$this->addSql('ALTER TABLE chill_person_accompanying_period_location_history ADD CONSTRAINT location_check CHECK (personlocation_id IS NULL OR addresslocation_id IS NULL)');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT location_check');
$this->addSql('ALTER TABLE chill_person_accompanying_period_location_history DROP CONSTRAINT location_check');
}
}

View File

@ -585,8 +585,8 @@ Filter by creator job: Filtrer les parcours par métier du créateur
'Filtered by creator job: only %jobs%': 'Filtré par métier du créateur: uniquement %jobs%' 'Filtered by creator job: only %jobs%': 'Filtré par métier du créateur: uniquement %jobs%'
Group by creator job: Grouper les parcours par métier du créateur Group by creator job: Grouper les parcours par métier du créateur
Filter by current actions: Filtrer les actions en cours Filter actions without end date: Filtre les actions sans date de fin (ouvertes)
Filtered by current action: 'Filtré: uniquement les actions en cours (sans date de fin)' Filtered actions without end date: 'Filtré: uniquement les actions sans date de fin (ouvertes)'
Filter by start date evaluations: Filtrer les évaluations par date de début Filter by start date evaluations: Filtrer les évaluations par date de début
Filter by end date evaluations: Filtrer les évaluations par date de fin Filter by end date evaluations: Filtrer les évaluations par date de fin
start period date: Date de début de la période start period date: Date de début de la période