Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageErrorCode
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
import fr.gouv.cacem.monitorenv.domain.mappers.PatchEntity
import fr.gouv.cacem.monitorenv.domain.repositories.IEnvActionRepository
import fr.gouv.cacem.monitorenv.domain.validators.mission.EnvActionValidator
import org.slf4j.LoggerFactory
import java.util.*
import java.util.UUID

@UseCase
class PatchEnvAction(
private val envActionRepository: IEnvActionRepository,
private val patchEnvAction: PatchEntity<EnvActionEntity, PatchableEnvActionEntity>,
private val envActionValidator: EnvActionValidator,
) {
private val logger = LoggerFactory.getLogger(PatchEnvAction::class.java)

Expand All @@ -24,6 +26,7 @@ class PatchEnvAction(
logger.info("Attempt to PATCH envaction $id")
envActionRepository.findById(id)?.let {
patchEnvAction.execute(it, patchableEnvActionEntity)
envActionValidator.validate(it)
val patchedEnvAction = envActionRepository.save(it)
logger.info("envaction $id patched")
return patchedEnvAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
import fr.gouv.cacem.monitorenv.domain.mappers.PatchEntity
import fr.gouv.cacem.monitorenv.domain.repositories.IMissionRepository
import fr.gouv.cacem.monitorenv.domain.use_cases.missions.dtos.MissionDetailsDTO
import fr.gouv.cacem.monitorenv.domain.validators.mission.MissionWithEnvActionsValidator
import org.slf4j.LoggerFactory

@UseCase
class PatchMission(
private val missionRepository: IMissionRepository,
private val patchEntity: PatchEntity<MissionEntity, PatchableMissionEntity>,
private val missionWithEnvActionsValidator: MissionWithEnvActionsValidator,
) {
private val logger = LoggerFactory.getLogger(GetFullMissionWithFishAndRapportNavActions::class.java)

Expand All @@ -24,6 +26,7 @@ class PatchMission(
logger.info("Attempt to PATCH mission $id")
missionRepository.findById(id)?.let {
patchEntity.execute(it, patchableMissionEntity)
missionWithEnvActionsValidator.validate(it)
val patchedMission = missionRepository.save(it)
logger.info("Mission $id patched")
return patchedMission
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package fr.gouv.cacem.monitorenv.domain.validators.mission

import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.EnvActionEntity
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.EnvActionControlEntity
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.infraction.InfractionTypeEnum
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionSurveillance.EnvActionSurveillanceEntity
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageErrorCode
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
import fr.gouv.cacem.monitorenv.domain.validators.Validator
import org.springframework.stereotype.Component

private const val NB_CHAR_MAX = 3

@Component
class EnvActionValidator : Validator<EnvActionEntity> {
override fun validate(envAction: EnvActionEntity) {
validateEnvAction(envAction)
}

private fun validateEnvAction(envAction: EnvActionEntity) {
if (envAction is EnvActionControlEntity) {
validateCommonProperties(envAction)
validateInfractions(envAction)
}
if (envAction is EnvActionSurveillanceEntity) {
validateCommonProperties(envAction)
validateSurveillance(envAction)
}
}
}

private fun validateInfractions(control: EnvActionControlEntity) {
val sumOfNbTarget = control.infractions?.sumOf { infraction -> infraction.nbTarget }
if (sumOfNbTarget != 0 &&
sumOfNbTarget != null &&
(
control.actionNumberOfControls != null &&
sumOfNbTarget > control.actionNumberOfControls
)
) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le nombre de cibles excède le nombre total de contrôles",
)
}

control.infractions?.forEach { infraction ->
if (infraction.infractionType !== InfractionTypeEnum.WAITING &&
infraction.natinf?.isEmpty() == true
) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data =
"Une infraction doit avoir une natinf si le type d'infraction n'est pas \"En attente\"",
)
}
if (infraction.nbTarget < 1) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "le nombre minimum de cible est 1",
)
}
}
}

private fun validateSurveillance(surveillance: EnvActionSurveillanceEntity) {
if (surveillance.geom === null) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "La géométrie de la surveillance est obligatoire",
)
}
if (surveillance.completedBy !== null && surveillance.completedBy.length != NB_CHAR_MAX) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le trigramme \"complété par\" doit avoir 3 lettres",
)
}
}

private fun validateCommonProperties(envAction: EnvActionEntity) {
if (envAction.openBy?.length != NB_CHAR_MAX) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le trigramme \"ouvert par\" doit avoir 3 lettres",
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.ActionTypeEnum
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.EnvActionEntity
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.EnvActionControlEntity
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.infraction.InfractionTypeEnum
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionSurveillance.EnvActionSurveillanceEntity
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageErrorCode
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
Expand All @@ -17,6 +16,7 @@ private const val NB_CHAR_MAX = 3
@Component
class MissionWithEnvActionsValidator(
private val missionValidator: MissionValidator,
private val envActionValidator: EnvActionValidator,
) : Validator<MissionEntity> {
private val logger = LoggerFactory.getLogger(MissionWithEnvActionsValidator::class.java)

Expand All @@ -28,77 +28,21 @@ class MissionWithEnvActionsValidator(

private fun validateEnvActions(mission: MissionEntity) {
mission.envActions?.forEach { envAction ->
envActionValidator.validate(envAction)
if (envAction is EnvActionControlEntity) {
validateControl(envAction, mission)
validateCommonDates(envAction, mission)
}

if (envAction is EnvActionSurveillanceEntity) {
validateSurveillance(envAction, mission)
}
}
}

private fun validateControl(
control: EnvActionControlEntity,
mission: MissionEntity,
) {
validateEnvAction(control, mission)

validateInfractions(control)
}

private fun validateInfractions(control: EnvActionControlEntity) {
val sumOfNbTarget = control.infractions?.sumOf { infraction -> infraction.nbTarget }
if (sumOfNbTarget != 0 &&
sumOfNbTarget != null &&
(
control.actionNumberOfControls != null &&
sumOfNbTarget > control.actionNumberOfControls
)
) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le nombre de cibles excède le nombre total de contrôles",
)
}

control.infractions?.forEach { infraction ->
if (infraction.infractionType !== InfractionTypeEnum.WAITING &&
infraction.natinf?.isEmpty() == true
) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data =
"Une infraction doit avoir une natinf si le type d'infraction n'est pas \"En attente\"",
)
}
if (infraction.nbTarget < 1) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "le nombre minimum de cible est 1",
)
validateCommonDates(envAction, mission)
validateSurveillanceDates(envAction, mission)
}
}
}

private fun validateSurveillance(
private fun validateSurveillanceDates(
surveillance: EnvActionSurveillanceEntity,
mission: MissionEntity,
) {
validateEnvAction(surveillance, mission)

if (surveillance.geom === null) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "La géométrie de la surveillance est obligatoire",
)
}
if (surveillance.completedBy !== null && surveillance.completedBy.length != NB_CHAR_MAX) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le trigramme \"complété par\" doit avoir 3 lettres",
)
}
if (surveillance.actionEndDateTimeUtc?.isAfter(mission.endDateTimeUtc) == true) {
logger.info("Validating mission surveillance: ${surveillance.actionEndDateTimeUtc}")
logger.info("Validating mission: ${mission.endDateTimeUtc}")
Expand All @@ -117,7 +61,7 @@ class MissionWithEnvActionsValidator(
}
}

private fun validateEnvAction(
private fun validateCommonDates(
envAction: EnvActionEntity,
mission: MissionEntity,
) {
Expand All @@ -141,11 +85,5 @@ class MissionWithEnvActionsValidator(
"La date de début $actionType doit être antérieure à celle de fin de mission",
)
}
if (envAction.openBy?.length != NB_CHAR_MAX) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le trigramme \"ouvert par\" doit avoir 3 lettres",
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package fr.gouv.cacem.monitorenv.domain.use_cases.actions

import com.nhaarman.mockitokotlin2.given
import com.nhaarman.mockitokotlin2.verify
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.EnvActionEntity
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.PatchableEnvActionEntity
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
import fr.gouv.cacem.monitorenv.domain.mappers.PatchEntity
import fr.gouv.cacem.monitorenv.domain.repositories.IEnvActionRepository
import fr.gouv.cacem.monitorenv.domain.use_cases.actions.fixtures.EnvActionFixture.Companion.anEnvAction
import fr.gouv.cacem.monitorenv.domain.validators.mission.EnvActionValidator
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.springframework.boot.test.system.CapturedOutput
import org.springframework.boot.test.system.OutputCaptureExtension
Expand All @@ -23,13 +24,16 @@ import java.util.UUID
@ExtendWith(OutputCaptureExtension::class)
class PatchEnvActionUTest {
private val envActionRepository: IEnvActionRepository = mock()
private val envActionValidator: EnvActionValidator = mock()
private val patchEntity: PatchEntity<EnvActionEntity, PatchableEnvActionEntity> = PatchEntity()
private val patchEnvAction: PatchEnvAction = PatchEnvAction(envActionRepository, patchEntity)
private val patchEnvAction: PatchEnvAction = PatchEnvAction(envActionRepository, patchEntity, envActionValidator)
private val jsonMapper: JsonMapper = JsonMapper()

@Test
fun `execute() should return the patched entity`(log: CapturedOutput) {
// Given
val inOrder = Mockito.inOrder(envActionValidator, envActionRepository)

val id = UUID.randomUUID()
val today = ZonedDateTime.now()
val tomorrow = ZonedDateTime.now().plusDays(1)
Expand Down Expand Up @@ -86,7 +90,8 @@ class PatchEnvActionUTest {
assertThat(savedEnvAction.observationsByUnit).isEqualTo(envActionPatched.observationsByUnit)
assertThat(savedEnvAction.hasDivingDuringOperation).isEqualTo(envActionPatched.hasDivingDuringOperation)
assertThat(savedEnvAction.incidentDuringOperation).isEqualTo(envActionPatched.incidentDuringOperation)
verify(envActionRepository).save(envActionPatched)
inOrder.verify(envActionValidator).validate(envActionPatched)
inOrder.verify(envActionRepository).save(envActionPatched)
assertThat(log.out).contains("Attempt to PATCH envaction $id")
assertThat(log.out).contains("envaction $id patched")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package fr.gouv.cacem.monitorenv.domain.use_cases.missions

import com.nhaarman.mockitokotlin2.given
import com.nhaarman.mockitokotlin2.verify
import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitResourceType
import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.LegacyControlUnitEntity
import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.LegacyControlUnitResourceEntity
Expand All @@ -13,10 +12,12 @@ import fr.gouv.cacem.monitorenv.domain.mappers.PatchEntity
import fr.gouv.cacem.monitorenv.domain.repositories.IMissionRepository
import fr.gouv.cacem.monitorenv.domain.use_cases.missions.dtos.MissionDetailsDTO
import fr.gouv.cacem.monitorenv.domain.use_cases.missions.fixtures.MissionFixture.Companion.aMissionEntity
import fr.gouv.cacem.monitorenv.domain.validators.mission.MissionWithEnvActionsValidator
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.springframework.boot.test.system.CapturedOutput
import org.springframework.boot.test.system.OutputCaptureExtension
Expand All @@ -27,12 +28,15 @@ import kotlin.random.Random
@ExtendWith(OutputCaptureExtension::class)
class PatchMissionUTest {
private val missionRepository: IMissionRepository = mock()
private val missionWithEnvActionsValidator: MissionWithEnvActionsValidator = mock()
private val patchEntity: PatchEntity<MissionEntity, PatchableMissionEntity> = PatchEntity()
private val patchMission: PatchMission = PatchMission(missionRepository, patchEntity)
private val patchMission: PatchMission =
PatchMission(missionRepository, patchEntity, missionWithEnvActionsValidator)

@Test
fun `execute() should return the patched entity`(log: CapturedOutput) {
fun `execute() should validate then return the patched entity`(log: CapturedOutput) {
// Given
val inOrder = Mockito.inOrder(missionWithEnvActionsValidator, missionRepository)
val id = Random.nextInt()
val today = ZonedDateTime.now()
val tomorrow = ZonedDateTime.now().plusDays(1)
Expand Down Expand Up @@ -91,7 +95,8 @@ class PatchMissionUTest {
assertThat(savedMission.mission.isUnderJdp).isEqualTo(missionPatched.isUnderJdp)
assertThat(savedMission.mission.controlUnits).isEqualTo(missionPatched.controlUnits)
assertThat(savedMission.mission.missionTypes).isEqualTo(missionPatched.missionTypes)
verify(missionRepository).save(missionPatched)
inOrder.verify(missionWithEnvActionsValidator).validate(missionPatched)
inOrder.verify(missionRepository).save(missionPatched)
assertThat(log.out).contains("Attempt to PATCH mission $id")
assertThat(log.out).contains("Mission $id patched")
}
Expand Down
Loading
Loading