diff --git a/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php b/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php index 2bb1fec47..e178dbd9f 100644 --- a/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php +++ b/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php @@ -24,6 +24,9 @@ final class LocationFixture extends Fixture implements DependentFixtureInterface public const UUID_TYPICAL = '51449b82-5032-43c8-a427-46b9ddb44762'; public const UUID_PUBLISHED = '2d79e1ff-c991-4767-b8c0-36b644038d0f'; + public const UUID_PUBLISHED2 = '064ca782-771c-783f-8000-e67473eabea6'; + public const UUID_PUBLISHED3 = '0655b3f6-124a-7f8d-8000-7c747883d40d'; + public const UUID_PUBLISHED4 = '065f9436-0ff3-74e3-8000-d9ac9b5a16ad'; public const UUID_COMPLEX_VEHICLES = self::UUID_PUBLISHED; public const UUID_PERMANENT_ONLY_ONE = 'f15ed802-fa9b-4d75-ab04-d62ea46597e9'; @@ -151,7 +154,7 @@ public function load(ObjectManager $manager): void ); $publishedLocation2 = new Location( - '064ca782-771c-783f-8000-e67473eabea6', + self::UUID_PUBLISHED2, $this->getReference('publishedMeasure', Measure::class), roadType: RoadTypeEnum::LANE->value, geometry: '{"type":"LineString","coordinates":[[1.352105256,44.016810494],[1.35213207,44.01678578],[1.35216909,44.01675663],[1.35221741,44.01672495],[1.35226814,44.01669601],[1.35232384,44.01666804],[1.35272189,44.0164913],[1.35280254,44.01646281],[1.35301215,44.016390795]]}', @@ -169,7 +172,7 @@ public function load(ObjectManager $manager): void ); $publishedLocation3 = new Location( - '0655b3f6-124a-7f8d-8000-7c747883d40d', + self::UUID_PUBLISHED3, $this->getReference('publishedMeasure', Measure::class), roadType: RoadTypeEnum::LANE->value, geometry: '{"type":"MultiLineString","coordinates":[[[1.34352783,44.01741201],[1.34351021,44.01728842],[1.34344305,44.01672388]],[[1.34361127,44.01827476],[1.34363309,44.01855416],[1.34367982,44.01909228],[1.34373623,44.01964046],[1.34376444,44.02004327]],[[1.34355908,44.01762403],[1.34352783,44.01741201]],[[1.34361127,44.01827476],[1.34359579,44.01799187],[1.34355908,44.01762403]]]}', @@ -187,7 +190,7 @@ public function load(ObjectManager $manager): void ); $publishedLocation4DepartmentalRoad = new Location( - '065f9436-0ff3-74e3-8000-d9ac9b5a16ad', + self::UUID_PUBLISHED4, $this->getReference('publishedMeasure', Measure::class), roadType: RoadTypeEnum::DEPARTMENTAL_ROAD->value, geometry: '{"type":"MultiLineString","coordinates":[[[4.663492283,49.820771105],[4.663561067,49.820708163],[4.663623202,49.820654298],[4.663725129,49.820585513],[4.66385317,49.820508284],[4.663996569,49.820433542],[4.664156393,49.820351386],[4.664302802,49.820283791],[4.664436862,49.820220858],[4.664595794,49.82015399],[4.664760103,49.820081657],[4.664970675,49.819979937],[4.66510358,49.819924207],[4.66516665,49.819899084],[4.665248891,49.819865612],[4.665391601,49.819812444],[4.665544028,49.819759143],[4.665691049,49.819710408],[4.665836593,49.819658998],[4.66598766,49.819606614],[4.666138405,49.819544349],[4.66630138,49.819473829]]]}', diff --git a/src/Infrastructure/Persistence/Doctrine/Fixtures/PeriodFixture.php b/src/Infrastructure/Persistence/Doctrine/Fixtures/PeriodFixture.php index 1ef4884f1..566c773a5 100644 --- a/src/Infrastructure/Persistence/Doctrine/Fixtures/PeriodFixture.php +++ b/src/Infrastructure/Persistence/Doctrine/Fixtures/PeriodFixture.php @@ -34,6 +34,14 @@ public function load(ObjectManager $manager): void endDateTime: new \DateTimeImmutable('2023-03-20 23:59:00', $tz), recurrenceType: 'everyDay', ); + $publishedPeriod2 = new Period( + uuid: '212d8eda-58ce-4dce-80ee-92504690e16c', + measure: $this->getReference('publishedMeasure', Measure::class), + // Single day with hours + startDateTime: new \DateTimeImmutable('2023-03-28 08:00:00', $tz), + endDateTime: new \DateTimeImmutable('2023-03-28 22:00:00', $tz), + recurrenceType: 'everyDay', + ); $permanentPeriod = new Period( uuid: '06717be6-ddb3-7635-8000-431d53fcd535', measure: $this->getReference('permanentMeasure', Measure::class), @@ -142,6 +150,7 @@ public function load(ObjectManager $manager): void $manager->persist($typicalPeriod); $manager->persist($publishedPeriod); + $manager->persist($publishedPeriod2); $manager->persist($permanentPeriod); $manager->persist($fullCityPeriod); $manager->persist($cifsPeriod1); diff --git a/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/LocationRepository.php b/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/LocationRepository.php index 5d2bf24ac..0f91961ce 100644 --- a/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/LocationRepository.php +++ b/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/LocationRepository.php @@ -35,9 +35,13 @@ public function delete(Location $location): void public function findOneByUuid(string $uuid): ?Location { return $this->createQueryBuilder('l') - ->addSelect('m') - ->where('l.uuid = :uuid') + ->addSelect('m', 'v', 'p', 'd', 't') ->innerJoin('l.measure', 'm') + ->innerjoin('m.periods', 'p') + ->leftJoin('m.vehicleSet', 'v') + ->leftJoin('p.dailyRange', 'd') + ->leftJoin('p.timeSlots', 't') + ->where('l.uuid = :uuid') ->setParameter('uuid', $uuid) ->getQuery() ->getOneOrNullResult() @@ -79,16 +83,21 @@ public function findAllForMapAsGeoJSON( // Renvoie un résultat vide pour éviter une erreur dans le cas où la date de fin est avant la date de début $measureDatesCondition = 'AND FALSE'; } else { - // Principe : on garde une localisation si l'intervalle défini par les dates des périodes + // Principe : on garde une localisation si l'intervalle défini par ses périodes // intersecte au moins partiellement l'intervalle défini par les filtres. - // En PostgreSQL, daterange permet de représenter un intervalle de date. + // En PostgreSQL, tsrange permet de représenter un intervalle de date et heure. // https://www.postgresql.org/docs/13/rangetypes.html // NB : si l'arrêté n'a pas encore de période, EXISTS renverra FALSE, donc on ne retiendra pas ses localisations, comme attendu. $measureDatesCondition = 'AND EXISTS ( SELECT 1 FROM period AS p - WHERE p.measure_uuid = m.uuid - AND daterange((:startDate)::date, (:endDate)::date, \'[]\') && daterange(p.start_datetime::date, p.end_datetime::date) + WHERE p.measure_uuid = m.uuid + -- ATTENTION : startDate et endDate sont données comme "inclus" toutes les deux, + -- et elles ont une heure qui vaut 00h00. + -- Donc dans le cas où startDate et endDate désignent toutes les deux le 12/01/2025 par exemple, + -- cela correspondrait à un intervalle de temps vide, et on ne sélectionnerait rien. + -- Pour inclure le 12/01/2025 en entier, il faut prendre (startDate inclus, endDate + 1 jour exclus) + AND tsrange((:startDate)::timestamp, ((:endDate)::timestamp + make_interval(days => 1))::timestamp, \'[)\') && tsrange(p.start_datetime::timestamp, p.end_datetime::timestamp) )'; $parameters['startDate'] = $startDate?->format(\DateTimeInterface::ATOM); diff --git a/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml b/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml index 71402813b..84875a94d 100644 --- a/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml +++ b/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml @@ -647,7 +647,7 @@ definedByValidityTimeSpec 2023-03-09T23:00:00+00:00 - 2023-03-20T22:59:00+00:00 + 2023-03-28T21:00:00+00:00 @@ -671,6 +671,15 @@ + + + definedByValidityTimeSpec + + 2023-03-28T07:00:00+00:00 + 2023-03-28T21:00:00+00:00 + + + diff --git a/tests/Integration/Infrastructure/Controller/Map/Fragment/GetLocationControllerTest.php b/tests/Integration/Infrastructure/Controller/Map/Fragment/GetLocationControllerTest.php index 548fae810..6549cd0b8 100644 --- a/tests/Integration/Infrastructure/Controller/Map/Fragment/GetLocationControllerTest.php +++ b/tests/Integration/Infrastructure/Controller/Map/Fragment/GetLocationControllerTest.php @@ -24,7 +24,7 @@ public function testGet(): void $this->assertSame('Circulation interdite', $li->eq(0)->text()); $this->assertSame('Avenue de Fonneuve du n° 695 au n° 253 à Montauban (82000)', $li->eq(1)->text()); $this->assertSame('Pour les véhicules de plus de 3,5 tonnes, 12 mètres de long ou 2,4 mètres de haut, matières dangereuses, Crit\'Air 4 et Crit\'Air 5, sauf piétons, véhicules d\'urgence et convois exceptionnels', $li->eq(2)->text()); - $this->assertSame('Du 10/03/2023 à 00h00 au 20/03/2023 à 23h59', $li->eq(3)->text()); + $this->assertSame('Du 10/03/2023 à 00h00 au 20/03/2023 à 23h59du 28/03/2023 à 08h00 au 28/03/2023 à 22h00', $li->eq(3)->text()); $detailsLink = $crawler->selectLink('Voir les détails'); $this->assertSame('_blank', $detailsLink->attr('target')); diff --git a/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php b/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php index 0a71d9fb8..f05f36826 100644 --- a/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php +++ b/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php @@ -85,6 +85,15 @@ private function provideTestMeasureDatesFilter(): array 'queryString' => '&map_filter_form[startDate]=2018-12-10&map_filter_form[endDate]=2018-12-10', 'locationUuids' => [], ], + 'interval-both-exact' => [ + 'queryString' => '&map_filter_form[startDate]=2023-03-28&map_filter_form[endDate]=2023-03-28', + 'locationUuids' => [ + LocationFixture::UUID_PUBLISHED, + LocationFixture::UUID_PUBLISHED2, + LocationFixture::UUID_PUBLISHED3, + LocationFixture::UUID_PUBLISHED4, + ], + ], // Test on cifsPeriod2 (2023-06-02 -> 2023-06-06) 'interval-start-exact' => [ 'queryString' => '&map_filter_form[startDate]=2023-06-01&map_filter_form[endDate]=2023-06-02', diff --git a/tests/Integration/Infrastructure/Controller/Regulation/Fragments/GetMeasureControllerTest.php b/tests/Integration/Infrastructure/Controller/Regulation/Fragments/GetMeasureControllerTest.php index 625e58c93..2b2e8af76 100644 --- a/tests/Integration/Infrastructure/Controller/Regulation/Fragments/GetMeasureControllerTest.php +++ b/tests/Integration/Infrastructure/Controller/Regulation/Fragments/GetMeasureControllerTest.php @@ -48,7 +48,7 @@ public function testGetWithComplexVehicles(): void $this->assertSame('Circulation interdite', $measure1Header->filter('h3')->text()); $this->assertSame('pour les véhicules de plus de 3,5 tonnes, 12 mètres de long ou 2,4 mètres de haut, matières dangereuses, Crit\'Air 4 et Crit\'Air 5, sauf piétons, véhicules d\'urgence et convois exceptionnels', $measure1Content->filter('li')->eq(0)->text()); - $this->assertSame('du 10/03/2023 à 00h00 au 20/03/2023 à 23h59', $measure1Content->filter('li')->eq(1)->text()); + $this->assertSame('du 10/03/2023 à 00h00 au 20/03/2023 à 23h59du 28/03/2023 à 08h00 au 28/03/2023 à 22h00', $measure1Content->filter('li')->eq(1)->text()); $this->assertSame('Rue de l\'Hôtel de Ville du n° 30 au n° 12 à Montauban (82000)', $measure1Content->filter('li')->eq(3)->text()); $this->assertSame('Rue Gamot à Montauban (82000)', $measure1Content->filter('li')->eq(4)->text()); $this->assertSame('D322 (Ardennes) du PR 1+0 (côté U) au PR 4+0 (côté U)', $measure1Content->filter('li')->eq(5)->text()); diff --git a/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php b/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php index 96d08b490..0178f87ff 100644 --- a/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php +++ b/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php @@ -107,7 +107,7 @@ public function testPublishedRegulationRendering(): void $this->assertSame('FO2/2023', $row0->eq(0)->text()); $this->assertSame('Main Org', $row0->eq(1)->text()); $this->assertSame('Montauban (82000) Avenue de Fonneuve + 3 localisations', $row0->eq(2)->text()); - $this->assertSame('du 10/03/2023 au 20/03/2023 passé', $row0->eq(3)->text()); + $this->assertSame('du 10/03/2023 au 28/03/2023 passé', $row0->eq(3)->text()); $this->assertSame('Publié', $row0->eq(4)->text()); $links = $row0->eq(5)->filter('a');