diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt index 9356e1377c..15edce2518 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt @@ -17,6 +17,8 @@ interface IReportingRepository { fun attachReportingsToMission(reportingIds: List, missionId: Int) + fun detachDanglingEnvActions(missionId: Int, envActionIds: List) + fun count(): Long fun delete(reportingId: Int) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt index bc22e3137c..36176c8eaa 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt @@ -20,9 +20,8 @@ class CreateOrUpdateMission( ) { @Throws(IllegalArgumentException::class) fun execute( - mission: MissionEntity?, + mission: MissionEntity, ): MissionEntity { - require(mission != null) { "No mission to create or update" } val envActions = mission.envActions?.map { when (it.actionType) { diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMissionWithAttachedReporting.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMissionWithAttachedReporting.kt index 18081a1a61..e4070bdb6f 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMissionWithAttachedReporting.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMissionWithAttachedReporting.kt @@ -8,6 +8,7 @@ import fr.gouv.cacem.monitorenv.domain.repositories.IMissionRepository import fr.gouv.cacem.monitorenv.domain.repositories.IReportingRepository import fr.gouv.cacem.monitorenv.domain.use_cases.missions.dtos.MissionDTO import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.bff.inputs.missions.EnvActionAttachedToReportingIds +import java.util.UUID @UseCase class CreateOrUpdateMissionWithAttachedReporting( @@ -17,10 +18,15 @@ class CreateOrUpdateMissionWithAttachedReporting( ) { @Throws(IllegalArgumentException::class) fun execute( - mission: MissionEntity?, + mission: MissionEntity, attachedReportingIds: List, envActionsAttachedToReportingIds: List, ): MissionDTO { + + if (mission.id != null) { + reportingRepository.detachDanglingEnvActions(mission.id, getListOfEnvActionIds(mission)) + } + val savedMission = createOrUpdateMission.execute(mission) require(savedMission.id != null) { "The mission id is null" } @@ -32,4 +38,8 @@ class CreateOrUpdateMissionWithAttachedReporting( return missionRepository.findFullMissionById(savedMission.id) } + + private fun getListOfEnvActionIds(mission: MissionEntity?) : List{ + return mission?.envActions?.map { it.id } ?: emptyList() + } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/EnvActionModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/EnvActionModel.kt index fa94a264a8..7713184a88 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/EnvActionModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/EnvActionModel.kt @@ -43,29 +43,47 @@ data class EnvActionModel( @JdbcType(UUIDJdbcType::class) @Column(name = "id", nullable = false, updatable = false, columnDefinition = "uuid") val id: UUID, + @Column(name = "action_start_datetime_utc") val actionStartDateTime: Instant? = null, + @Column(name = "action_end_datetime_utc") val actionEndDateTime: Instant? = null, + @JsonSerialize(using = GeometrySerializer::class) @JsonDeserialize(contentUsing = GeometryDeserializer::class) @Column(name = "geom") val geom: Geometry? = null, + @Column(name = "action_type") @Enumerated(EnumType.STRING) val actionType: ActionTypeEnum, + @Type(JsonBinaryType::class) @Column(name = "value", columnDefinition = "jsonb") val value: String, + @Column(name = "facade") val facade: String? = null, + @Column(name = "department") val department: String? = null, + @ManyToOne(fetch = FetchType.EAGER, optional = false) @JoinColumn(name = "mission_id") @JsonBackReference val mission: MissionModel, - @Column(name = "is_administrative_control") val isAdministrativeControl: Boolean? = null, + + @Column(name = "is_administrative_control") + val isAdministrativeControl: Boolean? = null, + @Column(name = "is_compliance_with_water_regulations_control") val isComplianceWithWaterRegulationsControl: Boolean? = null, + @Column(name = "is_safety_equipment_and_standards_compliance_control") val isSafetyEquipmentAndStandardsComplianceControl: Boolean? = null, - @Column(name = "is_seafarers_control") val isSeafarersControl: Boolean? = null, - @OneToMany(fetch = FetchType.EAGER, mappedBy = "attachedEnvAction") + + @Column(name = "is_seafarers_control") + val isSeafarersControl: Boolean? = null, + + @OneToMany( + fetch = FetchType.EAGER, + mappedBy = "attachedEnvAction", + ) @JsonManagedReference val attachedReporting: List? = listOf(), ) { diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt index af4ae22afb..8deb206d0e 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt @@ -66,6 +66,7 @@ data class MissionModel( @Column(name = "is_geometry_computed_from_controls", nullable = false) val isGeometryComputedFromControls: Boolean, @Column(name = "is_under_jdp", nullable = false) val isUnderJdp: Boolean, + @OneToMany( mappedBy = "mission", cascade = [CascadeType.ALL], @@ -75,6 +76,7 @@ data class MissionModel( @JsonManagedReference @Fetch(value = FetchMode.SUBSELECT) val envActions: MutableList? = ArrayList(), + @OneToMany( mappedBy = "mission", cascade = [CascadeType.ALL], @@ -84,6 +86,7 @@ data class MissionModel( @JsonManagedReference @Fetch(value = FetchMode.SUBSELECT) val controlResources: MutableList? = ArrayList(), + @OneToMany( mappedBy = "mission", cascade = [CascadeType.ALL], @@ -93,6 +96,7 @@ data class MissionModel( @JsonManagedReference @Fetch(value = FetchMode.SUBSELECT) val controlUnits: MutableList? = ArrayList(), + @OneToMany(mappedBy = "mission") @JsonManagedReference @Fetch(value = FetchMode.SUBSELECT) 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 d98af63d7f..8eb0d387d8 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 @@ -112,7 +112,7 @@ class JpaMissionRepository( val missionModel = MissionModel.fromMissionEntity(mission, mapper, controlUnitResourceModelMap) - return dbMissionRepository.save(missionModel).toMissionDTO(mapper) + return dbMissionRepository.saveAndFlush(missionModel).toMissionDTO(mapper) } private fun convertToPGArray(array: List?): String { diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt index c9f95d34c2..fa0f22cfa7 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt @@ -33,17 +33,20 @@ class JpaReportingRepository( ) : IReportingRepository { @Transactional - @Modifying(clearAutomatically = true, flushAutomatically = true) override fun attachEnvActionsToReportings(envActionId: UUID, reportingIds: List) { dbReportingRepository.attachEnvActionsToReportings(envActionId, reportingIds) } @Transactional - @Modifying(clearAutomatically = true, flushAutomatically = true) override fun attachReportingsToMission(reportingIds: List, missionId: Int) { dbReportingRepository.attachReportingsToMission(reportingIds, missionId) } + @Transactional + override fun detachDanglingEnvActions(missionId: Int, envActionIds: List) { + dbReportingRepository.detachDanglingEnvActions(missionId, envActionIds) + } + override fun findById(reportingId: Int): ReportingDTO { return dbReportingRepository.findById(reportingId).get().toReportingDTO(mapper) } @@ -136,7 +139,6 @@ class JpaReportingRepository( } @Transactional - @Modifying(clearAutomatically = true, flushAutomatically = true) override fun delete(reportingId: Int) { dbReportingRepository.delete(reportingId) } @@ -146,19 +148,16 @@ class JpaReportingRepository( } @Transactional - @Modifying(clearAutomatically = true, flushAutomatically = true) override fun archiveOutdatedReportings(): Int { return dbReportingRepository.archiveOutdatedReportings() } @Transactional - @Modifying(clearAutomatically = true, flushAutomatically = true) override fun archiveReportings(ids: List) { dbReportingRepository.archiveReportings(ids) } @Transactional - @Modifying(clearAutomatically = true, flushAutomatically = true) override fun deleteReportings(ids: List) { dbReportingRepository.deleteReportings(ids) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt index 32a5f69207..6ace59bfc2 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt @@ -9,7 +9,7 @@ import java.time.Instant import java.util.UUID interface IDBReportingRepository : JpaRepository { - @Modifying(clearAutomatically = true) + @Modifying(clearAutomatically = true, flushAutomatically = true) @Query( value = """ @@ -21,7 +21,7 @@ interface IDBReportingRepository : JpaRepository { ) fun archiveOutdatedReportings(): Int - @Modifying(clearAutomatically = true) + @Modifying(clearAutomatically = true, flushAutomatically = true) @Query( value = """ @@ -33,7 +33,7 @@ interface IDBReportingRepository : JpaRepository { ) fun archiveReportings(ids: List) - @Modifying(clearAutomatically = true) + @Modifying(clearAutomatically = true, flushAutomatically = true) @Query( value = """ @@ -60,7 +60,7 @@ interface IDBReportingRepository : JpaRepository { ) fun attachEnvActionsToReportings(envActionId: UUID, reportingIds: List) - @Modifying(clearAutomatically = true) + @Modifying(clearAutomatically = true, flushAutomatically = true) @Query( value = """ @@ -72,7 +72,7 @@ interface IDBReportingRepository : JpaRepository { ) fun delete(id: Int) - @Modifying(clearAutomatically = true) + @Modifying(clearAutomatically = true, flushAutomatically = true) @Query( value = """ @@ -84,6 +84,18 @@ interface IDBReportingRepository : JpaRepository { ) fun deleteReportings(ids: List) + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query( + value = + """ + UPDATE reportings + SET attached_env_action_id = NULL + WHERE mission_id = :missionId AND (:envActionIds IS NULL OR attached_env_action_id NOT IN (:envActionIds)) + """, + nativeQuery = true, + ) + fun detachDanglingEnvActions(missionId: Int, envActionIds: List) + @Query( value = """ diff --git a/backend/src/main/resources/db/testdata/V666.6__insert_dummy_env_actions.sql b/backend/src/main/resources/db/testdata/V666.6__insert_dummy_env_actions.sql index e598a2cbec..367bbeda94 100644 --- a/backend/src/main/resources/db/testdata/V666.6__insert_dummy_env_actions.sql +++ b/backend/src/main/resources/db/testdata/V666.6__insert_dummy_env_actions.sql @@ -10,8 +10,8 @@ INSERT INTO public.env_actions VALUES ('475d2887-5344-46cd-903b-8cb5e42f9a9c', 4 INSERT INTO public.env_actions VALUES ('16eeb9e8-f30c-430e-b36b-32b4673f81ce', 49, 'NOTE', '{"observations": "Note libre"}', NULL, NULL); INSERT INTO public.env_actions VALUES ('6d4b7d0a-79ce-47cf-ac26-2024d2b27f28', 49, 'CONTROL', '{"themes": [{"theme": "AMP sans réglementation particulière", "subThemes": ["Contrôle dans une AMP sans réglementation particulière"], "protectedSpecies": []}], "infractions": [{"id": "e56648c1-6ca3-4d5e-a5d2-114aa7c17126", "natinf": ["10231", "10228"], "toProcess": true, "vesselSize": null, "vesselType": null, "companyName": null, "formalNotice": "PENDING", "observations": "RAS", "relevantCourt": "PRE", "infractionType": "WAITING", "registrationNumber": null, "controlledPersonIdentity": "M DURAND"}], "vehicleType": null, "actionTargetType": "INDIVIDUAL", "actionNumberOfControls": 1}', NULL, '0104000020E61000000100000001010000003B0DADC6D4BB01C0A8387A2964714740'); -INSERT INTO public.env_actions VALUES ('b8007c8a-5135-4bc3-816f-c69c7b75d807', 34, 'SURVEILLANCE', '{"themes": [{"theme": "Police des espèces protégées et de leurs habitats (faune et flore)", "subThemes": ["Destruction, capture, arrachage", "Atteinte aux habitats d''espèces protégées"], "protectedSpecies": ["FLORA", "BIRDS"]}, {"theme": "Police des mouillages", "subThemes": ["Mouillage individuel", "ZMEL"], "protectedSpecies": []}], "duration": 0.0, "observations": "RAS", "coverMissionZone": true, "protectedSpecies": []}', '2022-07-16 10:03:12.588693', NULL, NULL, NULL, '2022-07-16 12:03:12.588693'); -INSERT INTO public.env_actions VALUES ('c52c6f20-e495-4b29-b3df-d7edfb67fdd7', 34, 'CONTROL', '{"themes": [{"theme": "Police des mouillages", "subThemes": ["Mouillage individuel", "ZMEL"], "protectedSpecies": []}], "observations": "RAS", "infractions": [{"id": "5d5b7829-68cd-4436-8c0b-1cc8db7788a0", "natinf": ["10038","10231"], "toProcess": false, "vesselSize": "FROM_24_TO_46m", "vesselType": "COMMERCIAL", "companyName": null, "formalNotice": "PENDING", "observations": "Pas d''observations", "relevantCourt": "LOCAL_COURT", "infractionType": "WITH_REPORT", "registrationNumber": "BALTIK", "controlledPersonIdentity": "John Doe"}], "vehicleType": "VESSEL", "actionTargetType": "VEHICLE", "actionNumberOfControls": 1}', '2022-07-16 09:03:12.588693', '0104000020E610000001000000010100000047A07E6651E3DEBF044620AB65C54840', NULL, NULL, '2022-07-16 12:03:12.588693'); +INSERT INTO public.env_actions VALUES ('c52c6f20-e495-4b29-b3df-d7edfb67fdd7', 34, 'SURVEILLANCE', '{"themes": [{"theme": "Police des espèces protégées et de leurs habitats (faune et flore)", "subThemes": ["Destruction, capture, arrachage", "Atteinte aux habitats d''espèces protégées"], "protectedSpecies": ["FLORA", "BIRDS"]}, {"theme": "Police des mouillages", "subThemes": ["Mouillage individuel", "ZMEL"], "protectedSpecies": []}], "duration": 0.0, "observations": "RAS", "coverMissionZone": true, "protectedSpecies": []}', '2022-07-16 10:03:12.588693', NULL, NULL, NULL, '2022-07-16 12:03:12.588693'); +INSERT INTO public.env_actions VALUES ('b8007c8a-5135-4bc3-816f-c69c7b75d807', 34, 'CONTROL', '{"themes": [{"theme": "Police des mouillages", "subThemes": ["Mouillage individuel", "ZMEL"], "protectedSpecies": []}], "observations": "RAS", "infractions": [{"id": "5d5b7829-68cd-4436-8c0b-1cc8db7788a0", "natinf": ["10038","10231"], "toProcess": false, "vesselSize": "FROM_24_TO_46m", "vesselType": "COMMERCIAL", "companyName": null, "formalNotice": "PENDING", "observations": "Pas d''observations", "relevantCourt": "LOCAL_COURT", "infractionType": "WITH_REPORT", "registrationNumber": "BALTIK", "controlledPersonIdentity": "John Doe"}], "vehicleType": "VESSEL", "actionTargetType": "VEHICLE", "actionNumberOfControls": 1}', '2022-07-16 09:03:12.588693', '0104000020E610000001000000010100000047A07E6651E3DEBF044620AB65C54840', NULL, NULL, '2022-07-16 12:03:12.588693'); INSERT INTO public.env_actions VALUES ('4d9a3139-6c60-49a5-b443-0e6238a6a120', 41, 'CONTROL', '{"themes": [{"theme": "Police des mouillages", "subThemes": ["Contrôle administratif"], "protectedSpecies": []}], "infractions": [], "vehicleType": null, "observations": "", "actionTargetType": null, "actionNumberOfControls": null}','2022-07-01 02:44:16.588693', NULL, NULL, NULL, NULL, TRUE, TRUE, TRUE, TRUE); diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt index faa1aac9c0..1e77d26ed6 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt @@ -34,24 +34,6 @@ class CreateOrUpdateMissionUTests { @MockBean private lateinit var facadeAreasRepository: IFacadeAreasRepository - @Test - fun `execute Should throw an exception when input mission is null`() { - // When - val throwable = - Assertions.catchThrowable { - CreateOrUpdateMission( - departmentRepository = departmentRepository, - missionRepository = missionRepository, - facadeRepository = facadeAreasRepository, - ) - .execute(null) - } - - // Then - assertThat(throwable).isInstanceOf(IllegalArgumentException::class.java) - assertThat(throwable.message).contains("No mission to create or update") - } - @Test fun `should return the mission to create or update with computed facade and department info`() { // Given diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionWithAttachedReportingUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionWithAttachedReportingUTests.kt index ff78143351..c1bac10f5d 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionWithAttachedReportingUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionWithAttachedReportingUTests.kt @@ -119,6 +119,7 @@ class CreateOrUpdateMissionWithAttachedReportingUTests { val missionToCreate = MissionEntity( + id = 100, missionTypes = listOf(MissionTypeEnum.LAND), facade = "Outre-Mer", geom = polygon, @@ -156,7 +157,7 @@ class CreateOrUpdateMissionWithAttachedReportingUTests { ) val envActionAttachedToReportingIds = Pair(envActionControl.id, listOf(1)) - given(createOrUpdateMission.execute(anyOrNull())).willReturn(missionToCreate.copy(id = 100)) + given(createOrUpdateMission.execute(anyOrNull())).willReturn(missionToCreate) given(missionRepository.save(anyOrNull())) .willReturn(MissionDTO(mission = missionToCreate.copy(id = 100))) given(missionRepository.findFullMissionById(100)).willReturn(expectedCreatedMission) @@ -178,7 +179,7 @@ class CreateOrUpdateMissionWithAttachedReportingUTests { ) // Then - + verify(reportingRepository,times(1)).detachDanglingEnvActions(missionId = 100, envActionIds = listOf(envActionControl.id)) verify(reportingRepository, times(1)).attachReportingsToMission(attachedReportingIds, 100) verify( reportingRepository, 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 e13f4b297d..0cd5c21f67 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 @@ -29,7 +29,11 @@ import java.time.ZonedDateTime import java.util.* class JpaMissionRepositoryITests : AbstractDBTests() { - @Autowired private lateinit var jpaMissionRepository: JpaMissionRepository + @Autowired + private lateinit var jpaMissionRepository: JpaMissionRepository + + @Autowired + private lateinit var jpaReportingRepository: JpaReportingRepository @Test @Transactional @@ -791,6 +795,101 @@ class JpaMissionRepositoryITests : AbstractDBTests() { assertThat(updatedMission).isEqualTo(expectedUpdatedMission) } + @Test + @Transactional + fun `save Should be able to delete envActions associated with a reporting`() { + // Given + val wktReader = WKTReader() + val multipolygonString = + "MULTIPOLYGON (((-4.54877816747593 48.305559876971, -4.54997332394943 48.3059760121399, -4.54998501370013 48.3071882334181, -4.54879290083417 48.3067746138142, -4.54877816747593 48.305559876971)))" + val polygon = wktReader.read(multipolygonString) as MultiPolygon + + + val missionToUpdate = + MissionEntity( + id = 34, + missionTypes = listOf(MissionTypeEnum.LAND), + facade = "NAMO", + geom = polygon, + observationsCacem = null, + observationsCnsp = null, + startDateTimeUtc = ZonedDateTime.parse("2022-01-15T04:50:09Z"), + endDateTimeUtc = ZonedDateTime.parse("2022-01-23T20:29:03Z"), + isClosed = false, + isDeleted = false, + envActions = listOf( + EnvActionControlEntity( + id = + UUID.fromString( + "33310163-4e22-4d3d-b585-dac4431eb4b5", + ), + facade = "Facade 1", + department = "Department 1", + geom = polygon, + vehicleType = VehicleTypeEnum.VEHICLE_LAND, + isAdministrativeControl = true, + isComplianceWithWaterRegulationsControl = true, + isSafetyEquipmentAndStandardsComplianceControl = + true, + isSeafarersControl = true, + ), + ), + missionSource = MissionSourceEnum.MONITORENV, + hasMissionOrder = false, + isUnderJdp = false, + isGeometryComputedFromControls = false, + ) + val expectedUpdatedMission = + MissionEntity( + id = 34, + missionTypes = listOf(MissionTypeEnum.LAND), + facade = "NAMO", + geom = polygon, + observationsCacem = null, + observationsCnsp = null, + startDateTimeUtc = + ZonedDateTime.parse("2022-01-15T04:50:09Z"), + endDateTimeUtc = + ZonedDateTime.parse("2022-01-23T20:29:03Z"), + isClosed = false, + isDeleted = false, + envActions = listOf( + EnvActionControlEntity( + id = + UUID.fromString( + "33310163-4e22-4d3d-b585-dac4431eb4b5", + ), + facade = "Facade 1", + department = "Department 1", + geom = polygon, + vehicleType = VehicleTypeEnum.VEHICLE_LAND, + isAdministrativeControl = true, + isComplianceWithWaterRegulationsControl = true, + isSafetyEquipmentAndStandardsComplianceControl = + true, + isSeafarersControl = true, + ), + ), + missionSource = MissionSourceEnum.MONITORENV, + hasMissionOrder = false, + isUnderJdp = false, + isGeometryComputedFromControls = false, + ) + + val attachedReporting = jpaReportingRepository.findById(6) + assertThat(attachedReporting.reporting.attachedEnvActionId).isEqualTo(UUID.fromString("b8007c8a-5135-4bc3-816f-c69c7b75d807")) + + // When + jpaMissionRepository.save(missionToUpdate) + + // Then + val updatedMission = jpaMissionRepository.findFullMissionById(34) + val updatedReporting = jpaReportingRepository.findById(6) + assertThat(updatedMission.mission).isEqualTo(expectedUpdatedMission) + assertThat(updatedMission.attachedReportingIds).isEqualTo(listOf(6,7)) + assertThat(updatedReporting.reporting.attachedEnvActionId).isNull() + } + @Test @Transactional fun `delete Should set the deleted flag as true`() { diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepositoryITests.kt.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepositoryITests.kt.kt index ba5ec485bd..e156d8fcb1 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepositoryITests.kt.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepositoryITests.kt.kt @@ -22,136 +22,6 @@ import java.util.* class JpaReportingRepositoryITests : AbstractDBTests() { @Autowired private lateinit var jpaReportingRepository: JpaReportingRepository - @Test - @Transactional - fun `findByControlUnitId() should find the matching reportings`() { - val foundReportings = jpaReportingRepository.findByControlUnitId(10000) - - assertThat(foundReportings).hasSize(1) - } - - @Test - @Transactional - fun `save should create a new Reporting`() { - // Given - val numberOfExistingReportings = jpaReportingRepository.count() - assertThat(numberOfExistingReportings).isEqualTo(8) - - // When - val wktReader = WKTReader() - val multipolygonString = - "MULTIPOLYGON (((-4.54877816747593 48.305559876971, -4.54997332394943 48.3059760121399, -4.54998501370013 48.3071882334181, -4.54879290083417 48.3067746138142, -4.54877816747593 48.305559876971)))" - val polygon = wktReader.read(multipolygonString) as MultiPolygon - - val newReporting = - ReportingEntity( - sourceType = SourceTypeEnum.SEMAPHORE, - semaphoreId = 21, - targetType = TargetTypeEnum.VEHICLE, - vehicleType = VehicleTypeEnum.VESSEL, - geom = polygon, - seaFront = "NAMO", - description = "Test reporting", - reportType = ReportingTypeEnum.INFRACTION_SUSPICION, - theme = "Police des mouillages", - subThemes = listOf("ZMEL"), - actionTaken = "Aucune", - isControlRequired = false, - hasNoUnitAvailable = false, - createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), - validityTime = 24, - isArchived = false, - isDeleted = false, - openBy = "CDA", - ) - - jpaReportingRepository.save(newReporting) - - val reportingDTO = jpaReportingRepository.findById(9) - - // Then - assertThat(reportingDTO.reporting.id).isEqualTo(9) - assertThat(reportingDTO.reporting.reportingId).isEqualTo(2300009) - assertThat(reportingDTO.reporting.sourceType).isEqualTo(SourceTypeEnum.SEMAPHORE) - assertThat(reportingDTO.reporting.semaphoreId).isEqualTo(21) - assertThat(reportingDTO.reporting.targetType).isEqualTo(TargetTypeEnum.VEHICLE) - assertThat(reportingDTO.reporting.vehicleType).isEqualTo(VehicleTypeEnum.VESSEL) - assertThat(reportingDTO.reporting.geom).isEqualTo(polygon) - assertThat(reportingDTO.reporting.seaFront).isEqualTo("NAMO") - assertThat(reportingDTO.reporting.description).isEqualTo("Test reporting") - assertThat(reportingDTO.reporting.reportType) - .isEqualTo(ReportingTypeEnum.INFRACTION_SUSPICION) - assertThat(reportingDTO.reporting.theme).isEqualTo("Police des mouillages") - assertThat(reportingDTO.reporting.subThemes).isEqualTo(listOf("ZMEL")) - assertThat(reportingDTO.reporting.actionTaken).isEqualTo("Aucune") - assertThat(reportingDTO.reporting.isControlRequired).isEqualTo(false) - assertThat(reportingDTO.reporting.hasNoUnitAvailable).isEqualTo(false) - assertThat(reportingDTO.reporting.createdAt) - .isEqualTo(ZonedDateTime.parse("2023-04-01T00:00:00Z")) - assertThat(reportingDTO.reporting.validityTime).isEqualTo(24) - assertThat(reportingDTO.reporting.isArchived).isEqualTo(false) - assertThat(reportingDTO.reporting.openBy).isEqualTo("CDA") - - val numberOfExistingReportingsAfterSave = jpaReportingRepository.count() - assertThat(numberOfExistingReportingsAfterSave).isEqualTo(9) - } - - @Test - fun `findById should return specified reporting`() { - val reportingDTO = jpaReportingRepository.findById(1) - assertThat(reportingDTO.reporting.id).isEqualTo(1) - assertThat(reportingDTO.reporting.reportingId).isEqualTo(2300001) - assertThat(reportingDTO.reporting.sourceType).isEqualTo(SourceTypeEnum.SEMAPHORE) - assertThat(reportingDTO.reporting.semaphoreId).isEqualTo(21) - assertThat(reportingDTO.reporting.controlUnitId).isNull() - assertThat(reportingDTO.reporting.sourceName).isNull() - assertThat(reportingDTO.reporting.targetType).isEqualTo(TargetTypeEnum.VEHICLE) - assertThat(reportingDTO.reporting.vehicleType).isEqualTo(VehicleTypeEnum.VESSEL) - assertThat(reportingDTO.reporting.validityTime).isEqualTo(24) - } - - @Test - fun `findAll should return all reportings`() { - val reportings = - jpaReportingRepository.findAll( - Pageable.unpaged(), - startedAfter = ZonedDateTime.parse("2022-01-01T00:01:00Z").toInstant(), - startedBefore = null, - reportingType = null, - seaFronts = null, - sourcesType = null, - status = null, - ) - assertThat(reportings.size).isEqualTo(8) - } - - @Test - @Transactional - fun `save should update an existing Reporting`() { - // Given - val numberOfExistingReportings = jpaReportingRepository.count() - assertThat(numberOfExistingReportings).isEqualTo(8) - - // When - val existingReportingDTO = jpaReportingRepository.findById(1) - val updatedReporting = - existingReportingDTO.reporting.copy( - sourceType = SourceTypeEnum.SEMAPHORE, - semaphoreId = 23, - createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), - isArchived = false, - openBy = "CDA", - ) - val savedReportingDTO = jpaReportingRepository.save(updatedReporting) - // Then - assertThat(savedReportingDTO.reporting.id).isEqualTo(1) - assertThat(savedReportingDTO.reporting.sourceType).isEqualTo(SourceTypeEnum.SEMAPHORE) - assertThat(savedReportingDTO.reporting.semaphoreId).isEqualTo(23) - - val numberOfExistingReportingsAfterSave = jpaReportingRepository.count() - assertThat(numberOfExistingReportingsAfterSave).isEqualTo(8) - } - @Test @Transactional fun `archiveReportings should archive multiples reportings`() { @@ -169,24 +39,6 @@ class JpaReportingRepositoryITests : AbstractDBTests() { assertThat(secondArchivedReportingDTO.reporting.isArchived).isEqualTo(true) } - @Test - @Transactional - fun `delete should soft delete reporting`() { - // Given - val numberOfExistingReportings = jpaReportingRepository.count() - assertThat(numberOfExistingReportings).isEqualTo(8) - - // When - jpaReportingRepository.delete(1) - - // Then - val numberOfExistingReportingsAfterSave = jpaReportingRepository.count() - assertThat(numberOfExistingReportingsAfterSave).isEqualTo(8) - - val deletedReportingDTO = jpaReportingRepository.findById(1) - assertThat(deletedReportingDTO.reporting.isDeleted).isEqualTo(true) - } - @Test @Transactional fun `archive should archive outdated reporting`() { @@ -292,6 +144,191 @@ class JpaReportingRepositoryITests : AbstractDBTests() { ) } + @Test + @Transactional + fun `delete should soft delete reporting`() { + // Given + val numberOfExistingReportings = jpaReportingRepository.count() + assertThat(numberOfExistingReportings).isEqualTo(8) + + // When + jpaReportingRepository.delete(1) + + // Then + val numberOfExistingReportingsAfterSave = jpaReportingRepository.count() + assertThat(numberOfExistingReportingsAfterSave).isEqualTo(8) + + val deletedReportingDTO = jpaReportingRepository.findById(1) + assertThat(deletedReportingDTO.reporting.isDeleted).isEqualTo(true) + } + + @Test + @Transactional + fun `detachDanglingEnvActions should set attached_envaction_id to null if envActionIds is not provided`() { + // Given + val envActionId = UUID.fromString("b8007c8a-5135-4bc3-816f-c69c7b75d807") + val existingReportingDTO = jpaReportingRepository.findById(6) + assertThat(existingReportingDTO.reporting.attachedEnvActionId).isEqualTo(envActionId) + // When + jpaReportingRepository.detachDanglingEnvActions(missionId = 34, envActionIds = emptyList()) + // Then + val detachedReportingDTO = jpaReportingRepository.findById(6) + val otherReportingDTO = jpaReportingRepository.findById(7) + assertThat(detachedReportingDTO.reporting.missionId).isEqualTo(34) + assertThat(detachedReportingDTO.reporting.attachedEnvActionId).isNull() + assertThat(otherReportingDTO.reporting.missionId).isEqualTo(34) + assertThat(otherReportingDTO.reporting.attachedEnvActionId).isNull() + } + + @Test + @Transactional + fun `detachDanglingEnvActions should set attached_envaction_id to null if envActionId is not in provided list`() { + // Given + val envActionId = UUID.fromString("b8007c8a-5135-4bc3-816f-c69c7b75d807") + val otherEnvActionId = UUID.fromString("475d2887-5344-46cd-903b-8cb5e42f9a9c") + val existingReportingDTO = jpaReportingRepository.findById(6) + assertThat(existingReportingDTO.reporting.attachedEnvActionId).isEqualTo(envActionId) + // When + jpaReportingRepository.detachDanglingEnvActions(missionId = 34, envActionIds = listOf(otherEnvActionId)) + // Then + val detachedReportingDTO = jpaReportingRepository.findById(6) + val otherReportingDTO = jpaReportingRepository.findById(7) + assertThat(detachedReportingDTO.reporting.missionId).isEqualTo(34) + assertThat(detachedReportingDTO.reporting.attachedEnvActionId).isNull() + assertThat(otherReportingDTO.reporting.missionId).isEqualTo(34) + assertThat(otherReportingDTO.reporting.attachedEnvActionId).isNull() + } + + + @Test + fun `findAll should return all reportings`() { + val reportings = + jpaReportingRepository.findAll( + Pageable.unpaged(), + startedAfter = ZonedDateTime.parse("2022-01-01T00:01:00Z").toInstant(), + startedBefore = null, + reportingType = null, + seaFronts = null, + sourcesType = null, + status = null, + ) + assertThat(reportings.size).isEqualTo(8) + } + + @Test + fun `findByControlUnitId() should find the matching reportings`() { + val foundReportings = jpaReportingRepository.findByControlUnitId(10000) + + assertThat(foundReportings).hasSize(1) + } + + @Test + fun `findById should return specified reporting`() { + val reportingDTO = jpaReportingRepository.findById(1) + assertThat(reportingDTO.reporting.id).isEqualTo(1) + assertThat(reportingDTO.reporting.reportingId).isEqualTo(2300001) + assertThat(reportingDTO.reporting.sourceType).isEqualTo(SourceTypeEnum.SEMAPHORE) + assertThat(reportingDTO.reporting.semaphoreId).isEqualTo(21) + assertThat(reportingDTO.reporting.controlUnitId).isNull() + assertThat(reportingDTO.reporting.sourceName).isNull() + assertThat(reportingDTO.reporting.targetType).isEqualTo(TargetTypeEnum.VEHICLE) + assertThat(reportingDTO.reporting.vehicleType).isEqualTo(VehicleTypeEnum.VESSEL) + assertThat(reportingDTO.reporting.validityTime).isEqualTo(24) + } + + @Test + @Transactional + fun `save should create a new Reporting`() { + // Given + val numberOfExistingReportings = jpaReportingRepository.count() + assertThat(numberOfExistingReportings).isEqualTo(8) + + // When + val wktReader = WKTReader() + val multipolygonString = + "MULTIPOLYGON (((-4.54877816747593 48.305559876971, -4.54997332394943 48.3059760121399, -4.54998501370013 48.3071882334181, -4.54879290083417 48.3067746138142, -4.54877816747593 48.305559876971)))" + val polygon = wktReader.read(multipolygonString) as MultiPolygon + + val newReporting = + ReportingEntity( + sourceType = SourceTypeEnum.SEMAPHORE, + semaphoreId = 21, + targetType = TargetTypeEnum.VEHICLE, + vehicleType = VehicleTypeEnum.VESSEL, + geom = polygon, + seaFront = "NAMO", + description = "Test reporting", + reportType = ReportingTypeEnum.INFRACTION_SUSPICION, + theme = "Police des mouillages", + subThemes = listOf("ZMEL"), + actionTaken = "Aucune", + isControlRequired = false, + hasNoUnitAvailable = false, + createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), + validityTime = 24, + isArchived = false, + isDeleted = false, + openBy = "CDA", + ) + + jpaReportingRepository.save(newReporting) + + val reportingDTO = jpaReportingRepository.findById(9) + + // Then + assertThat(reportingDTO.reporting.id).isEqualTo(9) + assertThat(reportingDTO.reporting.reportingId).isEqualTo(2300009) + assertThat(reportingDTO.reporting.sourceType).isEqualTo(SourceTypeEnum.SEMAPHORE) + assertThat(reportingDTO.reporting.semaphoreId).isEqualTo(21) + assertThat(reportingDTO.reporting.targetType).isEqualTo(TargetTypeEnum.VEHICLE) + assertThat(reportingDTO.reporting.vehicleType).isEqualTo(VehicleTypeEnum.VESSEL) + assertThat(reportingDTO.reporting.geom).isEqualTo(polygon) + assertThat(reportingDTO.reporting.seaFront).isEqualTo("NAMO") + assertThat(reportingDTO.reporting.description).isEqualTo("Test reporting") + assertThat(reportingDTO.reporting.reportType) + .isEqualTo(ReportingTypeEnum.INFRACTION_SUSPICION) + assertThat(reportingDTO.reporting.theme).isEqualTo("Police des mouillages") + assertThat(reportingDTO.reporting.subThemes).isEqualTo(listOf("ZMEL")) + assertThat(reportingDTO.reporting.actionTaken).isEqualTo("Aucune") + assertThat(reportingDTO.reporting.isControlRequired).isEqualTo(false) + assertThat(reportingDTO.reporting.hasNoUnitAvailable).isEqualTo(false) + assertThat(reportingDTO.reporting.createdAt) + .isEqualTo(ZonedDateTime.parse("2023-04-01T00:00:00Z")) + assertThat(reportingDTO.reporting.validityTime).isEqualTo(24) + assertThat(reportingDTO.reporting.isArchived).isEqualTo(false) + assertThat(reportingDTO.reporting.openBy).isEqualTo("CDA") + + val numberOfExistingReportingsAfterSave = jpaReportingRepository.count() + assertThat(numberOfExistingReportingsAfterSave).isEqualTo(9) + } + + @Test + @Transactional + fun `save should update an existing Reporting`() { + // Given + val numberOfExistingReportings = jpaReportingRepository.count() + assertThat(numberOfExistingReportings).isEqualTo(8) + + // When + val existingReportingDTO = jpaReportingRepository.findById(1) + val updatedReporting = + existingReportingDTO.reporting.copy( + sourceType = SourceTypeEnum.SEMAPHORE, + semaphoreId = 23, + createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), + isArchived = false, + openBy = "CDA", + ) + val savedReportingDTO = jpaReportingRepository.save(updatedReporting) + // Then + assertThat(savedReportingDTO.reporting.id).isEqualTo(1) + assertThat(savedReportingDTO.reporting.sourceType).isEqualTo(SourceTypeEnum.SEMAPHORE) + assertThat(savedReportingDTO.reporting.semaphoreId).isEqualTo(23) + + val numberOfExistingReportingsAfterSave = jpaReportingRepository.count() + assertThat(numberOfExistingReportingsAfterSave).isEqualTo(8) + } + // Test of db constraints, not specific to repository implementations @Test @Transactional diff --git a/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts b/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts index 82071478d6..e8cceb9549 100644 --- a/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts +++ b/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts @@ -25,7 +25,7 @@ context('Mission actions', () => { // Then cy.wait('@updateMission').then(({ request, response }) => { expect(response && response.statusCode).equal(200) - const { infractions } = request.body.envActions.find(a => a.id === 'c52c6f20-e495-4b29-b3df-d7edfb67fdd7') + const { infractions } = request.body.envActions.find(a => a.id === 'b8007c8a-5135-4bc3-816f-c69c7b75d807') expect(infractions.length).equal(2) const duplicatedInfraction = infractions[1] @@ -39,7 +39,7 @@ context('Mission actions', () => { expect(duplicatedInfraction.toProcess).equal(false) expect(duplicatedInfraction.vesselSize).equal('FROM_24_TO_46m') expect(duplicatedInfraction.vesselType).equal('COMMERCIAL') - expect(duplicatedInfraction.id).not.equal('c52c6f20-e495-4b29-b3df-d7edfb67fdd7') + expect(duplicatedInfraction.id).not.equal('b8007c8a-5135-4bc3-816f-c69c7b75d807') }) }) @@ -76,7 +76,7 @@ context('Mission actions', () => { cy.wait('@updateMission').then(({ request, response }) => { expect(response && response.statusCode).equal(200) - const { themes } = request.body.envActions.find(a => a.id === 'c52c6f20-e495-4b29-b3df-d7edfb67fdd7') + const { themes } = request.body.envActions.find(a => a.id === 'b8007c8a-5135-4bc3-816f-c69c7b75d807') expect(themes.length).equal(1) expect(themes[0].theme).equal('Police des espèces protégées et de leurs habitats (faune et flore)') expect(themes[0].subThemes.length).equal(2) @@ -104,10 +104,13 @@ context('Mission actions', () => { // Then cy.wait('@updateMission').then(({ request, response }) => { - expect(response && response.statusCode).equal(200) - - const { observations } = request.body.envActions.find(a => a.id === 'c52c6f20-e495-4b29-b3df-d7edfb67fdd7') + const { observations } = request.body.envActions.find(a => a.id === 'b8007c8a-5135-4bc3-816f-c69c7b75d807') expect(observations).equal('RUne observation importante') + + expect(response && response.statusCode).equal(200) + expect( + response && response.body.envActions.find(a => a.id === 'b8007c8a-5135-4bc3-816f-c69c7b75d807')?.observations + ).equal('RUne observation importante') }) }) @@ -144,7 +147,7 @@ context('Mission actions', () => { cy.wait('@updateMission').then(({ response }) => { expect(response && response.statusCode).equal(200) - const { themes } = response && response.body.envActions.find(a => a.id === 'b8007c8a-5135-4bc3-816f-c69c7b75d807') + const { themes } = response && response.body.envActions.find(a => a.id === 'c52c6f20-e495-4b29-b3df-d7edfb67fdd7') expect(themes.length).equal(3) expect(themes[0].theme).equal('Police des réserves naturelles') expect(themes[0].subThemes.length).equal(0) @@ -160,4 +163,22 @@ context('Mission actions', () => { expect(themes[2].protectedSpecies.length).equal(0) }) }) + + it(`Should be able to delete action with linked reporting`, () => { + // Given + cy.get('*[data-cy="edit-mission-34"]').click({ force: true }) + cy.get('*[data-cy="action-card"]').eq(0).click() + // TODO + cy.get('*[data-cy="actioncard-delete-button-b8007c8a-5135-4bc3-816f-c69c7b75d807"]').click() + + cy.intercept('PUT', `/bff/v1/missions/34`).as('updateMission') + cy.clickButton('Enregistrer et quitter') + // Then + cy.wait('@updateMission').then(({ response }) => { + expect(response && response.statusCode).equal(200) + + const { envActions } = response && response.body + expect(envActions.length).equal(1) + }) + }) }) diff --git a/frontend/cypress/e2e/side_window/reporting/reportings.spec.ts b/frontend/cypress/e2e/side_window/reporting/reportings.spec.ts index ca2d1bd415..5f1cab44a8 100644 --- a/frontend/cypress/e2e/side_window/reporting/reportings.spec.ts +++ b/frontend/cypress/e2e/side_window/reporting/reportings.spec.ts @@ -64,10 +64,10 @@ context('Missions', () => { }) it('Reporting should be delete in Reportings Table', () => { - cy.intercept('DELETE', '/bff/v1/reportings/6').as('deleteReporting') + cy.intercept('DELETE', '/bff/v1/reportings/4').as('deleteReporting') cy.get('*[data-cy="status-filter-Archivés"]').click() - cy.get('*[data-cy="more-actions-reporting-6"]').scrollIntoView().click({ force: true }) - cy.get('*[data-cy="delete-reporting-6"]').scrollIntoView().click({ force: true }) + cy.get('*[data-cy="more-actions-reporting-4"]').scrollIntoView().click({ force: true }) + cy.get('*[data-cy="delete-reporting-4"]').scrollIntoView().click({ force: true }) cy.clickButton('Confirmer la suppression') @@ -101,4 +101,18 @@ context('Missions', () => { cy.get('*[data-cy="add-semaphore-source"]').contains('Sémaphore de Dieppe') cy.get('*[data-cy="reporting-target-type"]').contains('Personne morale') }) + + it('Mission with attached env_action can be detached', () => { + cy.intercept('PUT', '/bff/v1/reportings/6').as('updateReporting') + cy.get('*[data-cy="status-filter-Archivés"]').click() + + cy.get('*[data-cy="edit-reporting-6"]').click({ force: true }) + cy.clickButton('Délier la mission') + cy.clickButton('Enregistrer et quitter') + + cy.wait('@updateReporting').then(({ response }) => { + expect(response && response.statusCode).equal(200) + expect(response && response.body?.attachedEnvActionId).equal(null) + }) + }) }) diff --git a/frontend/src/features/Reportings/ReportingForm/AttachMission/index.tsx b/frontend/src/features/Reportings/ReportingForm/AttachMission/index.tsx index 81f01008e2..df75c8b01f 100644 --- a/frontend/src/features/Reportings/ReportingForm/AttachMission/index.tsx +++ b/frontend/src/features/Reportings/ReportingForm/AttachMission/index.tsx @@ -27,6 +27,7 @@ export function AttachMission({ setIsAttachNewMission }) { const unattachMission = () => { setFieldValue('detachedFromMissionAtUtc', new Date().toISOString()) + setFieldValue('attachedEnvActionId', null) } const createMission = async () => { diff --git a/frontend/src/features/missions/MissionForm/ActionCards/index.tsx b/frontend/src/features/missions/MissionForm/ActionCards/index.tsx index fd3435e9a9..48a7038d09 100644 --- a/frontend/src/features/missions/MissionForm/ActionCards/index.tsx +++ b/frontend/src/features/missions/MissionForm/ActionCards/index.tsx @@ -59,6 +59,7 @@ export function ActionCards({ - + ) diff --git a/frontend/src/features/missions/MissionForm/ActionForm/ControlForm/OtherControlTypesForm.tsx b/frontend/src/features/missions/MissionForm/ActionForm/ControlForm/OtherControlTypesForm.tsx index 57d0725055..3829de99d0 100644 --- a/frontend/src/features/missions/MissionForm/ActionForm/ControlForm/OtherControlTypesForm.tsx +++ b/frontend/src/features/missions/MissionForm/ActionForm/ControlForm/OtherControlTypesForm.tsx @@ -6,7 +6,7 @@ import { ControlUnit } from '../../../../../domain/entities/controlUnit' import type { Mission } from '../../../../../domain/entities/missions' -export function OtherControlTypesForm({ currentActionIndex }: { currentActionIndex: string }) { +export function OtherControlTypesForm({ currentActionIndex }: { currentActionIndex: number }) { const { values: { controlUnits } } = useFormikContext()