Skip to content

Commit

Permalink
fix: validate with envaction when its from bff, validate without when…
Browse files Browse the repository at this point in the history
… its from api/public
  • Loading branch information
maximeperrault committed Feb 11, 2025
1 parent 7b71561 commit de6d839
Show file tree
Hide file tree
Showing 9 changed files with 650 additions and 553 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class CreateOrUpdateEnvActions(

@Throws(IllegalArgumentException::class)
fun execute(
// @UseCaseValidation<MissionEntity>(validator = MissionValidator::class)
mission: MissionEntity,
envActions: List<EnvActionEntity>?,
): MissionEntity {
Expand Down Expand Up @@ -55,6 +54,7 @@ class CreateOrUpdateEnvActions(
},
)
}

ActionTypeEnum.SURVEILLANCE -> {
val surveillance = it as EnvActionSurveillanceEntity
val normalizedGeometry =
Expand All @@ -76,6 +76,7 @@ class CreateOrUpdateEnvActions(
},
)
}

ActionTypeEnum.NOTE -> {
(it as EnvActionNoteEntity).copy()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package fr.gouv.cacem.monitorenv.domain.use_cases.missions

// import fr.gouv.cacem.monitorenv.domain.validators.mission.MissionValidator
import fr.gouv.cacem.monitorenv.config.UseCase
import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity
import fr.gouv.cacem.monitorenv.domain.repositories.IFacadeAreasRepository
import fr.gouv.cacem.monitorenv.domain.repositories.IMissionRepository
import fr.gouv.cacem.monitorenv.domain.repositories.IPostgisFunctionRepository
import fr.gouv.cacem.monitorenv.domain.use_cases.missions.events.UpdateMissionEvent
import fr.gouv.cacem.monitorenv.domain.validators.UseCaseValidation
import fr.gouv.cacem.monitorenv.domain.validators.mission.MissionValidator
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationEventPublisher

Expand All @@ -21,7 +22,7 @@ class CreateOrUpdateMission(

@Throws(IllegalArgumentException::class)
fun execute(
// @UseCaseValidation<MissionEntity>(validator = MissionValidator::class)
@UseCaseValidation<MissionEntity>(validator = MissionValidator::class)
mission: MissionEntity,
): MissionEntity {
logger.info("Attempt to CREATE or UPDATE mission ${mission.id}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

package fr.gouv.cacem.monitorenv.domain.use_cases.missions

// import fr.gouv.cacem.monitorenv.domain.validators.mission.MissionValidator
import fr.gouv.cacem.monitorenv.config.UseCase
import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity
import fr.gouv.cacem.monitorenv.domain.exceptions.ReportingAlreadyAttachedException
import fr.gouv.cacem.monitorenv.domain.repositories.IReportingRepository
import fr.gouv.cacem.monitorenv.domain.use_cases.missions.dtos.EnvActionAttachedToReportingIds
import fr.gouv.cacem.monitorenv.domain.use_cases.missions.dtos.MissionDetailsDTO
import fr.gouv.cacem.monitorenv.domain.validators.UseCaseValidation
import fr.gouv.cacem.monitorenv.domain.validators.mission.MissionWithEnvActionsValidator
import org.slf4j.LoggerFactory
import java.util.UUID

Expand All @@ -27,7 +28,7 @@ class CreateOrUpdateMissionWithActionsAndAttachedReporting(

@Throws(IllegalArgumentException::class)
fun execute(
// @UseCaseValidation<MissionEntity>(validator = MissionValidator::class)
@UseCaseValidation<MissionEntity>(validator = MissionWithEnvActionsValidator::class)
mission: MissionEntity,
attachedReportingIds: List<Int>,
envActionsAttachedToReportingIds: List<EnvActionAttachedToReportingIds>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,24 @@ import org.aspectj.lang.JoinPoint
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
import org.aspectj.lang.reflect.MethodSignature
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Component

@Component
@Aspect
class UseCaseValidationAspect {
class UseCaseValidationAspect(private val applicationContext: ApplicationContext) {
@Before("execution(* fr.gouv.cacem.monitorenv.domain.use_cases..*.execute(..))")
fun before(joinPoint: JoinPoint) {
val method = (joinPoint.signature as MethodSignature).method

// Parcourir les paramètres de la méthode
method.parameters.forEachIndexed { index, parameter ->
val annotation = parameter.getAnnotation(UseCaseValidation::class.java)
if (annotation != null) {
// Récupérer l'argument associé à ce paramètre
val arg = joinPoint.args[index]

// Instancier et exécuter le validateur spécifié dans l'annotation
val validator =
annotation.validator.objectInstance
?: annotation.validator.java.getDeclaredConstructor().newInstance()
(validator as Validator<Any>).validate(arg) // Valide l'objet
// Récupérer le validateur depuis le contexte Spring
val validator = applicationContext.getBean(annotation.validator.java) as Validator<Any>
validator.validate(arg)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
package fr.gouv.cacem.monitorenv.domain.validators.mission

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.ActionTargetTypeEnum
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.EnvActionControlEntity
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.infraction.AdministrativeResponseEnum
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.infraction.FormalNoticeEnum
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.infraction.InfractionTypeEnum
import fr.gouv.cacem.monitorenv.domain.entities.mission.envAction.envActionControl.infraction.SeizureTypeEnum
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.slf4j.LoggerFactory
import org.springframework.stereotype.Component
import java.time.ZonedDateTime

private const val NB_CHAR_MAX = 3

Expand Down Expand Up @@ -62,203 +52,5 @@ class MissionValidator : Validator<MissionEntity> {
data = "Le trigramme \"ouvert par\" doit avoir 3 lettres",
)
}
validateEnvActions(mission)
}

private fun validateEnvActions(mission: MissionEntity) {
val isMissionEnded =
mission.endDateTimeUtc != null &&
ZonedDateTime.now().isAfter(mission.endDateTimeUtc)

mission.envActions?.forEach { envAction ->
if (envAction is EnvActionControlEntity) {
validateControl(envAction, mission, isMissionEnded)
}

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

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

if (isMissionEnded) {
if (control.geom === null) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "La géométrie du contrôle est obligatoire",
)
}
if (control.vehicleType === null &&
control.actionTargetType === ActionTargetTypeEnum.VEHICLE
) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le type de véhicule est obligatoire",
)
}
validateControlPlan(control)
}

validateInfractions(control, isMissionEnded)
}

private fun validateInfractions(
control: EnvActionControlEntity,
isMissionEnded: Boolean,
) {
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",
)
}
if (isMissionEnded) {
if (infraction.infractionType === InfractionTypeEnum.WAITING) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le type d'infraction ne peut pas être \"en attente\"",
)
}
if (infraction.seizure === SeizureTypeEnum.PENDING) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "L'appréhension/saisie ne peut pas être \"en attente\"",
)
}
if (infraction.administrativeResponse === AdministrativeResponseEnum.PENDING) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "La réponse administrative ne peut pas être \"en attente\"",
)
}
if (infraction.formalNotice === FormalNoticeEnum.PENDING) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "La mise en demeure ne peut pas être \"en attente\"",
)
}
}
}
}

private fun validateSurveillance(
surveillance: EnvActionSurveillanceEntity,
mission: MissionEntity,
isMissionEnded: Boolean,
) {
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}")
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data =
"La date de fin de la surveillance doit être antérieure à celle de fin de mission",
)
}
if (surveillance.actionEndDateTimeUtc?.isBefore(mission.startDateTimeUtc) == true) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data =
"La date de fin de la surveillance doit être postérieure à celle du début de mission",
)
}
if (isMissionEnded) {
validateControlPlan(surveillance)
}
}

private fun validateEnvAction(
envAction: EnvActionEntity,
mission: MissionEntity,
) {
val actionType =
if (envAction.actionType === ActionTypeEnum.CONTROL) {
"du contrôle"
} else {
"de la surveillance"
}
if (envAction.actionStartDateTimeUtc?.isBefore(mission.startDateTimeUtc) == true) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data =
"La date de début $actionType doit être postérieure à celle du début de mission",
)
}
if (envAction.actionStartDateTimeUtc?.isAfter(mission.endDateTimeUtc) == true) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data =
"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",
)
}
}

private fun validateControlPlan(envAction: EnvActionEntity) {
if (envAction.controlPlans?.isEmpty() == true) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le plan de contrôle est obligatoire",
)
} else {
envAction.controlPlans?.forEach { controlPlan ->
if (controlPlan.subThemeIds?.isEmpty() == true) {
throw BackendUsageException(
code = BackendUsageErrorCode.UNVALID_PROPERTY,
data = "Le sous-thème du plan de contrôle est obligatoire",
)
}
}
}
}
}
Loading

0 comments on commit de6d839

Please sign in to comment.