Skip to content

Commit

Permalink
[Mission] Traitement des retours sur le nouveau statut des missions (#…
Browse files Browse the repository at this point in the history
…1331)

## Related Pull Requests & Issues

- Resolve #1248
- Resolve #1283
- Resolve #1285

----

- [ ] Tests E2E (Cypress)
  • Loading branch information
claire2212 committed Apr 23, 2024
2 parents 5a5298b + 2b60815 commit e160d0a
Show file tree
Hide file tree
Showing 42 changed files with 415 additions and 209 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,6 @@ class GetFullMissions(

logger.info("Found ${missions.size} mission(s)")

return missions.map { missionAndFishActions ->
val mission = missionAndFishActions.mission

try {
val fishActions =
monitorFishMissionActionsRepository.findFishMissionActionsById(mission.id!!)
MissionDTO(mission = mission, fishActions = fishActions)
} catch (e: Exception) {
MissionDTO(mission = mission, fishActions = listOf())
}
}
return missions
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.LegacyControlUnitEnt
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
import fr.gouv.cacem.monitorenv.infrastructure.monitorfish.adapters.MonitorFishMissionActionDataOutput
import org.locationtech.jts.geom.MultiPolygon
import java.time.ZonedDateTime

Expand All @@ -21,7 +20,6 @@ data class MissionsDataOutput(
val startDateTimeUtc: ZonedDateTime,
val endDateTimeUtc: ZonedDateTime? = null,
val envActions: List<MissionEnvActionDataOutput>? = null,
val fishActions: List<MonitorFishMissionActionDataOutput>? = listOf(),
val missionSource: MissionSourceEnum,
val hasMissionOrder: Boolean,
val isUnderJdp: Boolean,
Expand Down Expand Up @@ -52,12 +50,6 @@ data class MissionsDataOutput(
dto.envActionsAttachedToReportingIds,
)
},
fishActions =
dto.fishActions?.map {
MonitorFishMissionActionDataOutput.fromMonitorFishMissionActionEntity(
it,
)
},
missionSource = dto.mission.missionSource,
hasMissionOrder = dto.mission.hasMissionOrder,
isUnderJdp = dto.mission.isUnderJdp,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ data class CreateOrUpdateMissionDataInput(
val missionTypes: List<MissionTypeEnum>,
val controlUnits: List<LegacyControlUnitEntity> = listOf(),
val openBy: String? = null,
val closedBy: String? = null,
val closedBy: String? = null, // TODO delete when Fish and RapportNav are removed
val completedBy: String? = null,
val observationsCacem: String? = null,
val observationsCnsp: String? = null,
val facade: String? = null,
Expand All @@ -31,7 +32,8 @@ data class CreateOrUpdateMissionDataInput(
missionTypes = this.missionTypes,
controlUnits = this.controlUnits,
openBy = this.openBy,
completedBy = this.closedBy,
// TODO delete condition and closedBy when Fish and RapportNav are removed
completedBy = this.completedBy ?: this.closedBy,
observationsCacem = this.observationsCacem,
observationsCnsp = this.observationsCnsp,
facade = this.facade,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ data class MissionDataOutput(
val missionTypes: List<MissionTypeEnum>,
val controlUnits: List<LegacyControlUnitEntity>? = listOf(),
val openBy: String? = null,
val closedBy: String? = null,
val closedBy: String? = null, // TODO delete when Fish and RapportNav are removed
val completedBy: String? = null,
val observationsCacem: String? = null,
val observationsCnsp: String? = null,
val facade: String? = null,
Expand All @@ -37,7 +38,9 @@ data class MissionDataOutput(
missionTypes = mission.missionTypes,
controlUnits = mission.controlUnits,
openBy = mission.openBy,
closedBy = mission.completedBy,
closedBy =
mission.completedBy, // TODO delete when Fish and RapportNav are removed
completedBy = mission.completedBy,
observationsCacem = mission.observationsCacem,
observationsCnsp = mission.observationsCnsp,
facade = mission.facade,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ INSERT INTO public.env_actions (id, mission_id, action_type, value, action_start
('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": 11, "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', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'ABC', null),
('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", "protectedSpecies": []}', '2022-07-16 10:03:12.588693', '0106000020E61000000100000001030000000100000009000000AD0812BCE168E4BFCCDEEA3227BD4840BE63AEABD812E4BF1C5E8873F8AC484044BD156CA117DABF84C0E2AF49AC48408E16A14DE463CCBFBC9F7168A2A5484008BF4C12D0F97B3F9494F5EA3CAB4840399BF9438A28B43FDC4BF050D9BB48404BAA02B73C2CCCBF24A79C8362CD4840BC46F7A9D24DE1BFA0238D36B2D04840AD0812BCE168E4BFCCDEEA3227BD4840', 'MEMN', NULL, '2022-07-16 12:03:12.588693', NULL, NULL, NULL, NULL, 'ABC', 'DEF'),
('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": 45, "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:01:12.588693', '0104000020E610000001000000010100000047A07E6651E3DEBF044620AB65C54840', NULL, NULL, '2022-07-16 12:03:12.588693', NULL, NULL, NULL, NULL, 'ABC', NULL),
('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, 'ABC', 'DEF')
('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}',NULL, NULL, NULL, NULL, NULL, TRUE, TRUE, TRUE, TRUE, 'ABC', 'DEF'),
('5865b619-3280-4c67-94ca-9f15da7d5aa7', 27, 'CONTROL' , '{"infractions": [], "vehicleType": "VESSEL", "observations": "", "actionTargetType": "VEHICLE", "actionNumberOfControls": 1}','2022-07-01 02:44:16.588693', NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, 'ABC', 'EFG')
;


Expand All @@ -35,7 +36,8 @@ INSERT INTO public.env_actions_control_plan_themes (env_action_id, theme_id) VAL
('f3e90d3a-6ba4-4bb3-805e-d391508aa46d', 15),
('e2257638-ddef-4611-960c-7675a3254c38', 9),
('4d9a3139-6c60-49a5-b443-0e6238a6a120', 12),
('6d4b7d0a-79ce-47cf-ac26-2024d2b27f28', 1)
('6d4b7d0a-79ce-47cf-ac26-2024d2b27f28', 1),
('5865b619-3280-4c67-94ca-9f15da7d5aa7', 3)
;

INSERT INTO public.env_actions_control_plan_sub_themes(env_action_id, subtheme_id) VALUES
Expand All @@ -49,7 +51,8 @@ INSERT INTO public.env_actions_control_plan_sub_themes(env_action_id, subtheme_i
('c52c6f20-e495-4b29-b3df-d7edfb67fdd7', 117),
('c52c6f20-e495-4b29-b3df-d7edfb67fdd7', 118),
('b8007c8a-5135-4bc3-816f-c69c7b75d807', 102),
('4d9a3139-6c60-49a5-b443-0e6238a6a120', 42)
('4d9a3139-6c60-49a5-b443-0e6238a6a120', 42),
('5865b619-3280-4c67-94ca-9f15da7d5aa7', 5)
;

INSERT INTO public.env_actions_control_plan_tags(env_action_id, tag_id) VALUES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class ApiLegacyMissionsITests {

@MockBean private lateinit var deleteMission: DeleteMission

@MockBean private lateinit var bypassActionCheckAndDeleteMission: BypassActionCheckAndDeleteMission
@MockBean
private lateinit var bypassActionCheckAndDeleteMission: BypassActionCheckAndDeleteMission

@MockBean private lateinit var canDeleteMission: CanDeleteMission

Expand Down Expand Up @@ -282,15 +283,13 @@ class ApiLegacyMissionsITests {

@Test
fun `Should delete mission`() {
mockMvc.perform(delete("/api/v1/missions/20"))
.andExpect(status().isOk)
mockMvc.perform(delete("/api/v1/missions/20")).andExpect(status().isOk)
Mockito.verify(bypassActionCheckAndDeleteMission).execute(20)
}

@Test
fun `Should delete mission with api v2`() {
mockMvc.perform(delete("/api/v2/missions/20?source=MONITORFISH"))
.andExpect(status().isOk)
mockMvc.perform(delete("/api/v2/missions/20?source=MONITORFISH")).andExpect(status().isOk)
Mockito.verify(deleteMission).execute(20, MissionSourceEnum.MONITORFISH)
}

Expand All @@ -313,7 +312,12 @@ class ApiLegacyMissionsITests {
val source = MissionSourceEnum.MONITORFISH

given(canDeleteMission.execute(missionId = missionId, source = source))
.willReturn(CanDeleteMissionResponse(canDelete = false, sources = listOf(MissionSourceEnum.MONITORENV)))
.willReturn(
CanDeleteMissionResponse(
canDelete = false,
sources = listOf(MissionSourceEnum.MONITORENV),
),
)

mockMvc.perform(get("/api/v1/missions/$missionId/can_delete?source=$source"))
.andExpect(status().isOk)
Expand All @@ -323,20 +327,21 @@ class ApiLegacyMissionsITests {
@Test
fun `Should get all engaged control units`() {
// Given
given(getEngagedControlUnits.execute()).willReturn(
listOf(
Pair(
LegacyControlUnitEntity(
id = 123,
administration = "Admin",
resources = listOf(),
isArchived = false,
name = "Control Unit Name",
given(getEngagedControlUnits.execute())
.willReturn(
listOf(
Pair(
LegacyControlUnitEntity(
id = 123,
administration = "Admin",
resources = listOf(),
isArchived = false,
name = "Control Unit Name",
),
listOf(MissionSourceEnum.MONITORFISH),
),
listOf(MissionSourceEnum.MONITORFISH),
),
),
)
)

// When
mockMvc.perform(get("/api/v1/missions/engaged_control_units"))
Expand All @@ -353,22 +358,26 @@ class ApiLegacyMissionsITests {
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 updateMissionEvent = UpdateMissionEvent(
mission = MissionEntity(
id = 132,
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,
hasMissionOrder = false,
isUnderJdp = false,
isGeometryComputedFromControls = false,
),
)
val updateMissionEvent =
UpdateMissionEvent(
mission =
MissionEntity(
id = 132,
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,
hasMissionOrder = false,
isUnderJdp = false,
isGeometryComputedFromControls = false,
),
)

// When we send an event from another thread
object : Thread() {
Expand All @@ -380,22 +389,25 @@ class ApiLegacyMissionsITests {
println(ex)
}
}
}.start()
}
.start()

// Then
val missionUpdateEvent = mockMvc.perform(get("/api/v1/missions/sse"))
.andExpect(status().isOk)
.andExpect(request().asyncStarted())
.andExpect(request().asyncResult(nullValue()))
.andExpect(header().string("Content-Type", "text/event-stream"))
.andDo(MockMvcResultHandlers.log())
.andReturn()
.response
.contentAsString
val missionUpdateEvent =
mockMvc.perform(get("/api/v1/missions/sse"))
.andExpect(status().isOk)
.andExpect(request().asyncStarted())
.andExpect(request().asyncResult(nullValue()))
.andExpect(header().string("Content-Type", "text/event-stream"))
.andDo(MockMvcResultHandlers.log())
.andReturn()
.response
.contentAsString

assertThat(missionUpdateEvent).contains("event:MISSION_UPDATE")
assertThat(missionUpdateEvent).contains(
"data:{\"id\":132,\"missionTypes\":[\"SEA\"],\"controlUnits\":[],\"openBy\":null,\"closedBy\":null,\"observationsCacem\":null,\"observationsCnsp\":null,\"facade\":\"Outre-Mer\",\"geom\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-4.54877817,48.30555988],[-4.54997332,48.30597601],[-4.54998501,48.30718823],[-4.5487929,48.30677461],[-4.54877817,48.30555988]]]]},\"startDateTimeUtc\":\"2022-01-15T04:50:09Z\",\"endDateTimeUtc\":\"2022-01-23T20:29:03Z\",\"createdAtUtc\":null,\"updatedAtUtc\":null,\"envActions\":[],\"missionSource\":\"MONITORFISH\",\"isClosed\":false,\"hasMissionOrder\":false,\"isUnderJdp\":false,\"isGeometryComputedFromControls\":false}",
)
assertThat(missionUpdateEvent)
.contains(
"data:{\"id\":132,\"missionTypes\":[\"SEA\"],\"controlUnits\":[],\"openBy\":null,\"closedBy\":null,\"completedBy\":null,\"observationsCacem\":null,\"observationsCnsp\":null,\"facade\":\"Outre-Mer\",\"geom\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-4.54877817,48.30555988],[-4.54997332,48.30597601],[-4.54998501,48.30718823],[-4.5487929,48.30677461],[-4.54877817,48.30555988]]]]},\"startDateTimeUtc\":\"2022-01-15T04:50:09Z\",\"endDateTimeUtc\":\"2022-01-23T20:29:03Z\",\"createdAtUtc\":null,\"updatedAtUtc\":null,\"envActions\":[],\"missionSource\":\"MONITORFISH\",\"isClosed\":false,\"hasMissionOrder\":false,\"isUnderJdp\":false,\"isGeometryComputedFromControls\":false}",
)
}
}
32 changes: 27 additions & 5 deletions frontend/cypress/e2e/side_window/mission_form/main_form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ context('Side Window > Mission Form > Main Form', () => {
cy.getDataCy('mission-status-tag-pending').should('exist')
cy.getDataCy('completion-mission-status-tag-to-completed').should('exist')

cy.get('div').contains('Mission non enregistrée.')
cy.get('div').contains('Mission non créée.')
cy.get('.Element-Tag').contains('Enregistrement auto. actif')
// When
cy.fill('Date de début (UTC)', [2024, 5, 26, 12, 0])
Expand Down Expand Up @@ -71,6 +71,7 @@ context('Side Window > Mission Form > Main Form', () => {
.should('eq', 200)
cy.get('div').contains('Mission créée par le')
cy.get('div').contains('Dernière modification enregistrée')
cy.get('.Component-Banner').contains('La mission a bien été créée')
})

it('A mission should be created When auto-save is not enabled', () => {
Expand Down Expand Up @@ -313,11 +314,13 @@ context('Side Window > Mission Form > Main Form', () => {
attachedReportingIds: [],
attachedReportings: [],
// Changed field
completedBy: 'LTH',
// TODO : uncomment this field when Fish andRapportNav have deleted closedBy field
// completedBy: 'LTH',
controlUnits: [
{
administration: 'Gendarmerie Nationale',
contact: null,
// Changed field
contact: 'contact',
id: 10020,
isArchived: false,
name: 'BN Toulon',
Expand Down Expand Up @@ -346,15 +349,26 @@ context('Side Window > Mission Form > Main Form', () => {
)
})

cy.wait(1500)
cy.wait(500)
cy.get('[name="missionTypes1"]').click({ force: true })
cy.wait(250)

cy.waitForLastRequest(
'@updateMission',
{
body: {
completedBy: 'LTH',
controlUnits: [
{
administration: 'Gendarmerie Nationale',
contact: 'contact',
id: 10020,
isArchived: false,
name: 'BN Toulon',
resources: []
}
],
// TODO : uncomment this field when Fish andRapportNav have deleted closedBy field
// completedBy: 'LTH',
missionTypes: ['SEA', 'LAND'],
observationsCnsp: 'Encore une observation',
openBy: 'LTH'
Expand Down Expand Up @@ -471,4 +485,12 @@ context('Side Window > Mission Form > Main Form', () => {
cy.getDataCy('add-control-unit').find('.rs-picker-toggle-value').contains('Unité archivée')
cy.getDataCy('add-control-administration').find('.rs-picker-toggle-value').contains('Administration Archivée 2')
})

it('Should display missing fields banner if mission is ended and has missing fields', () => {
visitSideWindow()
cy.fill('Période', 'Un mois')
cy.wait(500)
cy.getDataCy('edit-mission-27').scrollIntoView().click({ force: true })
cy.get('.Component-Banner').contains('euillez compléter ou corriger les éléments en rouge')
})
})
Loading

0 comments on commit e160d0a

Please sign in to comment.