diff --git a/backend/lib/build.gradle.kts b/backend/lib/build.gradle.kts deleted file mode 100644 index 4473ecfd60..0000000000 --- a/backend/lib/build.gradle.kts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * This generated file contains a sample Kotlin library project to get you started. - * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.4/userguide/building_java_projects.html in the Gradle documentation. - */ - -plugins { - // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. - id("org.jetbrains.kotlin.jvm") version "1.9.10" - - // Apply the java-library plugin for API and implementation separation. - `java-library` -} - -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() -} - -dependencies { - // Use the Kotlin JUnit 5 integration. - testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") - - // Use the JUnit 5 integration. - testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3") - - testRuntimeOnly("org.junit.platform:junit-platform-launcher") - - // This dependency is exported to consumers, that is to say found on their compile classpath. - api("org.apache.commons:commons-math3:3.6.1") - - // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation("com.google.guava:guava:32.1.1-jre") -} - -// Apply a specific Java toolchain to ease working on different environments. -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) - } -} - -tasks.named("test") { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} diff --git a/backend/lib/src/main/kotlin/monitorenv/Library.kt b/backend/lib/src/main/kotlin/monitorenv/Library.kt deleted file mode 100644 index 26f99fd0d5..0000000000 --- a/backend/lib/src/main/kotlin/monitorenv/Library.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package monitorenv - -class Library { - fun someLibraryMethod(): Boolean { - return true - } -} diff --git a/backend/lib/src/test/kotlin/monitorenv/LibraryTest.kt b/backend/lib/src/test/kotlin/monitorenv/LibraryTest.kt deleted file mode 100644 index 668c160b3b..0000000000 --- a/backend/lib/src/test/kotlin/monitorenv/LibraryTest.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package monitorenv - -import kotlin.test.Test -import kotlin.test.assertTrue - -class LibraryTest { - @Test fun someLibraryMethodReturnsTrue() { - val classUnderTest = Library() - assertTrue(classUnderTest.someLibraryMethod(), "someLibraryMethod should return 'true'") - } -} diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IMissionRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IMissionRepository.kt index bda4ecede2..96caafb001 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IMissionRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IMissionRepository.kt @@ -21,6 +21,8 @@ interface IMissionRepository { pageable: Pageable, ): List + fun findAllIncludedIn(ids: List): List + fun findByControlUnitId(controlUnitId: Int): List fun findById(missionId: Int): MissionDTO diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissionsIncludedIn.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissionsIncludedIn.kt new file mode 100644 index 0000000000..a5897082b0 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissionsIncludedIn.kt @@ -0,0 +1,14 @@ +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.missions + +import fr.gouv.cacem.monitorenv.config.UseCase +import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity +import fr.gouv.cacem.monitorenv.domain.repositories.IMissionRepository + +@UseCase +class GetMissionsIncludedIn(private val missionRepository: IMissionRepository) { + fun execute(ids: List): List { + return missionRepository.findAllIncludedIn(ids) + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/MissionDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/MissionDataOutput.kt index 2bd68dc0f5..6022e7e1b6 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/MissionDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/MissionDataOutput.kt @@ -2,6 +2,7 @@ package fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.outputs import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.LegacyControlUnitEntity import fr.gouv.cacem.monitorenv.domain.entities.mission.EnvActionEntity +import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionSourceEnum import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionTypeEnum import fr.gouv.cacem.monitorenv.domain.use_cases.missions.dtos.MissionDTO @@ -53,5 +54,31 @@ data class MissionDataOutput( isGeometryComputedFromControls = dto.mission.isGeometryComputedFromControls, ) } + + fun fromMissionEntity(mission: MissionEntity): MissionDataOutput { + requireNotNull(mission.id) { + "a mission must have an id" + } + + return MissionDataOutput( + id = mission.id, + missionTypes = mission.missionTypes, + controlUnits = mission.controlUnits, + openBy = mission.openBy, + closedBy = mission.closedBy, + observationsCacem = mission.observationsCacem, + observationsCnsp = mission.observationsCnsp, + facade = mission.facade, + geom = mission.geom, + startDateTimeUtc = mission.startDateTimeUtc, + endDateTimeUtc = mission.endDateTimeUtc, + envActions = mission.envActions, + missionSource = mission.missionSource, + isClosed = mission.isClosed, + hasMissionOrder = mission.hasMissionOrder, + isUnderJdp = mission.isUnderJdp, + isGeometryComputedFromControls = mission.isGeometryComputedFromControls, + ) + } } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsController.kt index 5e5628e7a3..c350880455 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsController.kt @@ -22,6 +22,7 @@ class ApiMissionsController( private val getMissionById: GetMissionById, private val deleteMission: DeleteMission, private val getEngagedControlUnits: GetEngagedControlUnits, + private val getMissionsIncludedIn: GetMissionsIncludedIn ) { @GetMapping("") @@ -67,6 +68,17 @@ class ApiMissionsController( return missions.map { MissionDataOutput.fromMissionDTO(it) } } + @GetMapping("/find") + @Operation(summary = "Get missions of specified identifiers") + fun getMissionsOfIdsController( + @Parameter(description = "Requested identifiers") + @RequestParam(name = "ids") + ids: List, + ): List { + val missions = getMissionsIncludedIn.execute(ids) + return missions.map { MissionDataOutput.fromMissionEntity(it) } + } + @PostMapping("", consumes = ["application/json"]) @Operation(summary = "Create a new mission") fun createMissionController( diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt index d5b18dbddb..2ae877b16f 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt @@ -52,6 +52,10 @@ class JpaMissionRepository( ).map { it.toMissionDTO(mapper) } } + override fun findAllIncludedIn(ids: List): List { + return dbMissionRepository.findAllIncludedIn(ids).map { it.toMissionEntity(mapper) } + } + override fun findByControlUnitId(controlUnitId: Int): List { return dbMissionRepository.findByControlUnitId(controlUnitId).map { it.toMissionEntity(mapper) } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBMissionRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBMissionRepository.kt index ac2ff0553a..d93dee905d 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBMissionRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBMissionRepository.kt @@ -80,6 +80,19 @@ interface IDBMissionRepository : JpaRepository { pageable: Pageable, ): List + @Query( + value = """ + SELECT * + FROM missions + WHERE + deleted IS FALSE AND + id IN :ids + ORDER BY start_datetime_utc DESC + """, + nativeQuery = true, + ) + fun findAllIncludedIn(ids: List): List + @Query("SELECT mm FROM MissionModel mm JOIN mm.controlUnits mmcu WHERE mmcu.unit.id = :controlUnitId") fun findByControlUnitId(controlUnitId: Int): List } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsControllerITests.kt index 9556293a8f..403ae6b16c 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiMissionsControllerITests.kt @@ -11,11 +11,7 @@ import fr.gouv.cacem.monitorenv.domain.entities.mission.EnvActionControlEntity import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionSourceEnum import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionTypeEnum -import fr.gouv.cacem.monitorenv.domain.use_cases.missions.CreateOrUpdateMission -import fr.gouv.cacem.monitorenv.domain.use_cases.missions.DeleteMission -import fr.gouv.cacem.monitorenv.domain.use_cases.missions.GetEngagedControlUnits -import fr.gouv.cacem.monitorenv.domain.use_cases.missions.GetMissionById -import fr.gouv.cacem.monitorenv.domain.use_cases.missions.GetMissions +import fr.gouv.cacem.monitorenv.domain.use_cases.missions.* import fr.gouv.cacem.monitorenv.domain.use_cases.missions.dtos.MissionDTO import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.inputs.CreateOrUpdateMissionDataInput import org.hamcrest.Matchers.equalTo @@ -56,6 +52,9 @@ class ApiMissionsControllerITests { @MockBean private lateinit var deleteMission: DeleteMission + @MockBean + private lateinit var getMissionsIncludedIn: GetMissionsIncludedIn + @MockBean private lateinit var getEngagedControlUnits: GetEngagedControlUnits @@ -163,6 +162,40 @@ class ApiMissionsControllerITests { .andExpect(status().isOk) } + @Test + fun `Should get all missions included in ids`() { + // Given + val wktReader = WKTReader() + val multipolygonString = + "MULTIPOLYGON (((-4.54877817 48.30555988, -4.54997332 48.30597601, -4.54998501 48.30718823, -4.5487929 48.30677461, -4.54877817 48.30555988)))" + val polygon = wktReader.read(multipolygonString) as MultiPolygon + + val expectedFirstMission = MissionEntity( + id = 10, + missionTypes = listOf(MissionTypeEnum.SEA), + facade = "Outre-Mer", + geom = polygon, + observationsCnsp = null, + startDateTimeUtc = ZonedDateTime.parse("2022-01-15T04:50:09Z"), + endDateTimeUtc = ZonedDateTime.parse("2022-01-23T20:29:03Z"), + isDeleted = false, + missionSource = MissionSourceEnum.MONITORFISH, + isClosed = false, + hasMissionOrder = false, + isUnderJdp = false, + isGeometryComputedFromControls = false, + ) + given( + getMissionsIncludedIn.execute(any()), + ).willReturn(listOf(expectedFirstMission)) + + // When + mockMvc.perform(get("/api/v1/missions/find?ids=55,52")) + // Then + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk) + } + @Test fun `Should get specific mission when requested by Id`() { // Given diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt index db15805e5b..74c64793b8 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt @@ -739,4 +739,12 @@ class JpaMissionRepositoryITests : AbstractDBTests() { ) assertThat(nextMissionList).hasSize(20) } + + @Test + @Transactional + fun `findAllIncludedIn() should find the matching missions`() { + val foundMissions = jpaMissionRepository.findAllIncludedIn(listOf(50, 51, 52)) + + assertThat(foundMissions).hasSize(3) + } }