2023-09-14 15:47:17 +02:00

276 lines
10 KiB
PHP

<?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 Action\Remove;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
use Chill\PersonBundle\Actions\Remove\PersonMove;
use Chill\PersonBundle\Actions\Remove\PersonMoveManager;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Relationships\Relation;
use Chill\PersonBundle\Entity\Relationships\Relationship;
use Chill\PersonBundle\Repository\PersonRepository;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* @internal
* @coversNothing
*/
class PersonMoveTest extends KernelTestCase
{
private EntityManagerInterface $em;
private PersonMoveManager $personMoveManager;
private EventDispatcherInterface $eventDispatcher;
private CenterRepositoryInterface $centerRepository;
/**
* @var list<array{0: class-string, 1: int}>
*/
private static $entitiesToDelete = [];
public function setUp(): void
{
self::bootKernel();
$this->em = self::$container->get(EntityManagerInterface::class);
$this->personMoveManager = self::$container->get(PersonMoveManager::class);
$this->eventDispatcher = self::$container->get(EventDispatcherInterface::class);
$this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
}
public static function tearDownAfterClass(): void
{
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class);
foreach (self::$entitiesToDelete as [$class, $id]) {
$entity = $em->find($class, $id);
if (null !== $entity) {
$em->remove($entity);
}
}
$em->flush();
}
/**
* @dataProvider dataProviderMovePerson
*/
public function testMovePersonSimple(Person $personA, Person $personB, string $message): void
{
$move = new PersonMove($this->em, $this->personMoveManager, $this->eventDispatcher);
$sqls = $move->getSQL($personA, $personB);
$this->em->getConnection()->transactional(function (Connection $conn) use ($personA, $personB, $sqls) {
foreach ($sqls as $sql) {
$conn->executeStatement($sql);
}
});
$personsByIdOfA = $this->em->createQuery("SELECT p FROM " . Person::class . " p WHERE p.id = :id")
->setParameter('id', $personA->getId())
->getResult();
$personB = $this->em->find(Person::class, $personB->getId());
self::assertCount(0, $personsByIdOfA);
self::assertNotNull($personB?->getId(), $message);
}
public function testMovePersonCenterHistory(): void
{
$personA = new Person();
$personB = new Person();
[$centerA, $centerB] = $this->centerRepository->findAll();
$this->em->persist($personA);
$this->em->persist($personB);
$personCenterHistoryAFirst = (new Person\PersonCenterHistory())->setCenter($centerA)
->setStartDate(new \DateTimeImmutable('2023-01-01'))
->setEndDate(new \DateTimeImmutable('2023-06-30'));
$personCenterHistoryASecond = (new Person\PersonCenterHistory())->setCenter($centerB)
->setStartDate(new \DateTimeImmutable('2023-06-30'))
->setEndDate(new \DateTimeImmutable('2023-09-30'));
$personCenterHistoryBFirst = (new Person\PersonCenterHistory())->setCenter($centerA)
->setStartDate(new \DateTimeImmutable('2023-03-01'))
->setEndDate(new \DateTimeImmutable('2023-07-15'));
$personCenterHistoryBSecond = (new Person\PersonCenterHistory())->setCenter($centerB)
->setStartDate(new \DateTimeImmutable('2023-07-15'))
->setEndDate(new \DateTimeImmutable('2023-09-30'));
$this->em->persist($personCenterHistoryAFirst);
$this->em->persist($personCenterHistoryASecond);
$this->em->persist($personCenterHistoryBFirst);
$this->em->persist($personCenterHistoryBSecond);
$personA->addCenterHistory($personCenterHistoryAFirst);
$personA->addCenterHistory($personCenterHistoryASecond);
$personB->addCenterHistory($personCenterHistoryBFirst);
$personB->addCenterHistory($personCenterHistoryBSecond);
$this->em->flush();
$this->em->clear();
$move = new PersonMove($this->em, $this->personMoveManager, $this->eventDispatcher);
$sqls = $move->getSQL($personA, $personB);
$this->em->getConnection()->transactional(function (Connection $conn) use ($personA, $personB, $sqls) {
foreach ($sqls as $sql) {
$conn->executeStatement($sql);
}
});
$personsByIdOfA = $this->em->createQuery("SELECT p FROM " . Person::class . " p WHERE p.id = :id")
->setParameter('id', $personA->getId())
->getResult();
/** @var Person $personB */
$personB = $this->em->find(Person::class, $personB->getId());
$message = 'Move persons with overlapping center histories';
$this->em->refresh($personB);
self::assertCount(0, $personsByIdOfA);
self::assertNotNull($personB?->getId(), $message);
$centerHistoriesB = $personB->getCenterHistory();
$oldestDate = new \DateTimeImmutable('2023-01-01');
$this->em->refresh($centerHistoriesB->first());
self::assertCount(2, $centerHistoriesB);
self::assertEquals($oldestDate, $centerHistoriesB->first()->getStartDate());
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryAFirst];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryASecond];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryBFirst];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryBSecond];
}
public function dataProviderMovePerson(): iterable
{
$this->setUp();
$personA = new Person();
$personB = new Person();
$this->em->persist($personA);
$this->em->persist($personB);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
yield [$personA, $personB, "move 2 people without any associated data"];
$personA = new Person();
$personB = new Person();
$activity = new Activity();
$activity->setDate(new \DateTime('today'));
$activity->addPerson($personA);
$activity->addPerson($personB);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($activity);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [Activity::class, $activity];
yield [$personA, $personB, "move 2 people having an activity"];
$personA = new Person();
$personB = new Person();
$household = new Household();
$household->addMember(
$memberA = (new HouseholdMember())->setPerson($personA)->setShareHousehold(true)
->setStartDate(new \DateTimeImmutable('2023-01-01'))
);
$household->addMember(
$memberB = (new HouseholdMember())->setPerson($personB)->setShareHousehold(true)
->setStartDate(new \DateTimeImmutable('2023-01-01'))
);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($household);
$this->em->persist($memberA);
$this->em->persist($memberB);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [HouseholdMember::class, $memberA];
self::$entitiesToDelete[] = [HouseholdMember::class, $memberB];
self::$entitiesToDelete[] = [Household::class, $household];
yield [$personA, $personB, "move 2 people having the same household at the same time"];
$personA = new Person();
$personB = new Person();
$parcours = new AccompanyingPeriod();
$parcours->addPerson($personA);
$parcours->addPerson($personB);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($parcours);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [AccompanyingPeriod::class, $parcours];
yield [$personA, $personB, "move 2 people participating to the same parcours"];
$personA = new Person();
$personB = new Person();
$relationship = new Relationship();
$relation = new Relation();
$user = (new User())->setUsername(uniqid())->setEmail(uniqid() . '@foo.com');
$relationship->setRelation($relation);
$relationship->setToPerson($personA);
$relationship->setFromPerson($personB);
$relationship->setReverse(false);
$relationship->setCreatedBy($user);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($relation);
$this->em->persist($user);
$this->em->persist($relationship);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [Relation::class, $relation];
self::$entitiesToDelete[] = [User::class, $user];
self::$entitiesToDelete[] = [Relationship::class, $relationship];
yield [$personA, $personB, "move 2 people with a relationship"];
$this->em->flush();
$this->em->clear();
}
}