diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php index 1e15490dc..0bb804689 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdApiController.php @@ -6,10 +6,12 @@ use Chill\MainBundle\CRUD\Controller\ApiController; use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Serializer\Model\Collection; use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Entity\Household\Household; use Chill\PersonBundle\Repository\Household\HouseholdRepository; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; +use Symfony\Component\Routing\Annotation\Route; class HouseholdApiController extends ApiController { @@ -50,4 +52,45 @@ class HouseholdApiController extends ApiController return $this->json($collection, Response::HTTP_OK, [], [ "groups" => ["read"]]); } + + /** + * @Route("/api/1.0/person/address/suggest/by-household/{household_id}.{_format}", + * name="chill_person_address_suggest_by_household", + * requirements={ + * "_format"="json" + * } + * ) + * @ParamConverter("household", options={"id" = "household_id"}) + */ + public function suggestAddressByHousehold(Household $household, string $_format) + { + // TODO add acl + + $addresses = []; + // collect addresses from location in courses + foreach ($household->getCurrentPersons() as $person) { + foreach ($person->getAccompanyingPeriodParticipations() as $participation) { + if (null !== $participation->getAccompanyingPeriod()->getAddressLocation()) { + $a = $participation->getAccompanyingPeriod()->getAddressLocation(); + $addresses[$a->getId()] = $a; + } + if (null !== $personLocation = $participation + ->getAccompanyingPeriod()->getPersonLocation()) { + $a = $personLocation->getCurrentHouseholdAddress(); + if (null !== $a) { + $addresses[$a->getId()] = $a; + } + } + } + } + + // remove the actual address + $actual = $household->getCurrentAddress(); + if (null !== $actual) { + $addresses = \array_filter($addresses, fn($a) => $a !== $actual); + } + + return $this->json(\array_values($addresses), Response::HTTP_OK, [], + [ 'groups' => [ 'read' ] ]); + } } diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php b/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php index 62b61a942..b3f4087eb 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonApiController.php @@ -77,13 +77,15 @@ class PersonApiController extends ApiController $a = $participation->getAccompanyingPeriod()->getAddressLocation(); $addresses[$a->getId()] = $a; } - if (null !== $participation->getAccompanyingPeriod()->getPersonLocation()) { - $a = $participation->getAccompanyingPeriod()->getAddressLocation(); - $addresses[$a->getId()] = $a; + if (null !== $personLocation = $participation + ->getAccompanyingPeriod()->getPersonLocation()) { + $a = $personLocation->getCurrentHouseholdAddress(); + if (null !== $a) { + $addresses[$a->getId()] = $a; + } } } - \array_unique($addresses); // remove the actual address $actual = $person->getCurrentHouseholdAddress(); if (null !== $actual) { diff --git a/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php b/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php index f6adc5d01..273824782 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php @@ -4,6 +4,7 @@ namespace Chill\PersonBundle\Tests\Controller; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\MainBundle\Test\PrepareClientTrait; +use Chill\PersonBundle\Entity\Household\Household; use Symfony\Component\HttpFoundation\Request; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; @@ -29,6 +30,21 @@ class HouseholdApiControllerTest extends WebTestCase $this->assertResponseIsSuccessful(); } + /** + * @dataProvider generateHouseholdId + */ + public function testSuggestAddressByHousehold(int $householdId) + { + $client = $this->getClientAuthenticated(); + + $client->request( + Request::METHOD_GET, + "/api/1.0/person/address/suggest/by-household/{$householdId}.json" + ); + + $this->assertResponseIsSuccessful(); + } + public function generatePersonId() { self::bootKernel(); @@ -51,5 +67,33 @@ class HouseholdApiControllerTest extends WebTestCase ->first()->getPerson(); yield [ $person->getId() ]; - } + } + + public function generateHouseholdId() + { + self::bootKernel(); + + $qb = self::$container->get(EntityManagerInterface::class) + ->createQueryBuilder(); + + $householdIds = $qb + ->select('DISTINCT household.id') + ->from(Household::class, 'household') + ->join('household.members', 'members') + ->join('members.person', 'person') + ->join('person.center', 'center') + ->where($qb->expr()->eq('center.name', ':center_name')) + ->andWhere($qb->expr()->gt('SIZE(person.accompanyingPeriodParticipations)', 0)) + ->setParameter('center_name', 'Center A') + ->setMaxResults(100) + ->getQuery() + ->getResult() + ; + + \shuffle($householdIds); + + yield [ \array_pop($householdIds)['id'] ]; + yield [ \array_pop($householdIds)['id'] ]; + yield [ \array_pop($householdIds)['id'] ]; + } } diff --git a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml index e89088c86..0684a352c 100644 --- a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml @@ -384,6 +384,34 @@ paths: 200: description: "OK" + /1.0/person/address/suggest/by-household/{id}.json: + get: + tags: + - address + summary: get a list of suggested address for a household + description: > + The address are computed from various source. Currently: + + - the address of course to which the members is participating + + The current household address is always ignored. + parameters: + - name: id + in: path + required: true + description: The household id + schema: + type: integer + format: integer + minimum: 1 + responses: + 401: + description: "Unauthorized" + 404: + description: "Not found" + 200: + description: "OK" + /1.0/person/accompanying-course/{id}.json: get: tags: