Skip to content

Commit

Permalink
Merge pull request #68 from MTES-MCT/fixes
Browse files Browse the repository at this point in the history
Allow editing target for Env infractions on targets reported by the u…
  • Loading branch information
lwih authored Dec 29, 2023
2 parents 60a8f76 + 0a7196f commit d0c1212
Show file tree
Hide file tree
Showing 44 changed files with 2,337 additions and 2,178 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/trivy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name: trivy

on:
push:
branches: ["CHANGEME"]
branches: [ "main" ]
# pull_request:
# # The branches below must be a subset of the branches above
# branches: [ "main" ]
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:
with:
context: .
builder: ${{ steps.buildx.outputs.name }}
file: infra/docker/app/Dockerfile
file: infra/docker/app/DockerfileCI
push: true
tags: |
ghcr.io/mtes-mct/rapportnav2/rapportnav-app:${{ github.sha }}
Expand Down
3 changes: 3 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ variables:
PROJECT_NAME:
value: rapportnav-v2
description: "Nom du projet à déployer"
BDD_IAMGE:
value: postgres:15-bookworm
description: "Image de la base de données"
PROJECT_VERSION:
value: "0.0.1-alpha.10"
description: "Version du projet à déployer"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction

import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity
import fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infraction.InfractionEnvTargetModel

interface IInfractionEnvTargetRepository {
fun save(infractionTarget: InfractionEnvTargetEntity, infraction: InfractionEntity): InfractionEnvTargetModel

fun findByActionIdAndVesselIdentifier(actionId: String, vesselIdentifier: String): List<InfractionEnvTargetModel>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction

import fr.gouv.dgampa.rapportnav.config.UseCase
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity
import fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction.IInfractionEnvTargetRepository

@UseCase
class AddOrUpdateInfractionEnvTarget(
private val repo: IInfractionEnvTargetRepository,
) {
fun execute(infractionTarget: InfractionEnvTargetEntity, infraction: InfractionEntity): InfractionEnvTargetEntity {
val savedData = repo.save(infractionTarget, infraction).toInfractionEnvTargetEntity()
return savedData
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import java.util.*
@UseCase
class GetInfractionById(private val repo: IInfractionRepository) {
fun execute(id: UUID): InfractionEntity? {
val optionalInfractionModel = repo.findById(id)
return optionalInfractionModel.map { it.toInfractionEntity() }.orElse(null)
val infractionModel = repo.findById(id)
if (infractionModel.isPresent) {
return infractionModel.get().toInfractionEntity()
} else {
return null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction

import fr.gouv.dgampa.rapportnav.config.UseCase
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.control.ControlType
import fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction.IInfractionEnvTargetRepository

@UseCase
class IsControlledAllowedForTarget(
private val repo: IInfractionEnvTargetRepository,
private val getInfractionById: GetInfractionById,
) {
fun execute(actionId: String, vesselIdentifier: String, controlType: ControlType): Boolean {
val targets = repo.findByActionIdAndVesselIdentifier(actionId = actionId, vesselIdentifier = vesselIdentifier)
val controlledAllowed = targets.map {
val infraction = it.infraction?.toInfractionEntity()
return controlType != infraction?.controlType
}
return controlledAllowed.all { true }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ class ActionEnvController(
infractionsByVessel = infractionsByVessel.map { byVessel ->
// a target reported by monitorEnv will have an infraction with controlType null
// the next field is to help the frontend hide/show information according to whom has reported the target
val targetAddedInRapportNav = !byVessel.infractions.any { it.controlType == null }
val targetAddedByUnit = !byVessel.infractions.any { it.controlType == null }

// the next field is to help the frontend show different options for which control type to report an infraction
val reportedControlTypes = byVessel.infractions.mapNotNull { it.controlType }

val updatedByVessel = byVessel.copy(
controlTypesWithInfraction = reportedControlTypes,
targetAddedInRapportNav = targetAddedInRapportNav
targetAddedByUnit = targetAddedByUnit
)
updatedByVessel
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package fr.gouv.dgampa.rapportnav.infrastructure.bff

import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselSizeEnum
import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselTypeEnum
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.control.ControlType
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.AddOrUpdateInfraction
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.DeleteInfraction
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.GetInfractionById
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.GetNatinfs
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.*
import fr.gouv.dgampa.rapportnav.infrastructure.bff.adapters.infraction.InfractionInput
import fr.gouv.dgampa.rapportnav.infrastructure.bff.adapters.infraction.InfractionWithNewTargetInput
import fr.gouv.dgampa.rapportnav.infrastructure.bff.model.infraction.Infraction
import fr.gouv.dgampa.rapportnav.infrastructure.bff.model.infraction.Natinf
import org.slf4j.LoggerFactory
import org.springframework.graphql.data.method.annotation.Argument
import org.springframework.graphql.data.method.annotation.MutationMapping
import org.springframework.graphql.data.method.annotation.QueryMapping
Expand All @@ -22,8 +23,13 @@ class InfractionController(
private val deleteInfraction: DeleteInfraction,
private val getInfractionById: GetInfractionById,
private val getNatinfs: GetNatinfs,
private val addOrUpdateInfractionEnvTarget: AddOrUpdateInfractionEnvTarget,
private val isControlledAllowedForTarget: IsControlledAllowedForTarget,
) {

private val logger = LoggerFactory.getLogger(InfractionController::class.java)


@QueryMapping
fun natinfs(): List<Natinf> {
return getNatinfs.execute().map { Natinf.fromNatinfEntity(it) }
Expand All @@ -49,22 +55,57 @@ class InfractionController(

@MutationMapping
fun addOrUpdateInfractionForEnvTarget(@Argument infraction: InfractionWithNewTargetInput): Infraction? {
val target: InfractionEnvTargetEntity?
var target: InfractionEnvTargetEntity?


if (infraction.id == null) {
// check if there is not already an infraction with the same controlType for this target
val isAllowed = isControlledAllowedForTarget.execute(
actionId = infraction.actionId,
vesselIdentifier = infraction.vesselIdentifier,
controlType = ControlType.valueOf(infraction.controlType)
)
if (!isAllowed) {
logger.error("addOrUpdateInfractionForEnvTarget - controlType=${infraction.controlType} already exists for target name=${infraction.vesselIdentifier}")
throw Exception("Ce type de contrôle a déjà été reporté pour cette cible. Veuillez annuler et modifier le contrôle déjà existant.")
} else {
target = null
}
} else {

// get the infraction if it already exists and set its target
if (infraction.id != null) {
// get the infraction if it already exists and set its target
val repoInfraction = getInfractionById.execute(id = UUID.fromString(infraction.id))
target = repoInfraction?.target
} else {
target = null
}

// TODO must also verify that there is not already an infraction for this target and this controlType
// Check if target has changed or not by crossing fields between InfractionWithNewTargetInput and InfractionEnvTargetEntity
if (target != null && hasTargetChanged(infraction, target)) {
// Update the target
val newTarget = InfractionEnvTargetEntity(
id = target.id,
missionId = target.missionId,
actionId = target.actionId,
infractionId = target.infractionId,
vesselIdentifier = infraction.vesselIdentifier,
vesselSize = VesselSizeEnum.valueOf(infraction.vesselSize),
vesselType = VesselTypeEnum.valueOf(infraction.vesselType),
identityControlledPerson = infraction.identityControlledPerson
)
target = addOrUpdateInfractionEnvTarget.execute(newTarget, infraction.toInfractionEntity(newTarget))
}
}

val input = infraction.toInfractionEntity(target)
val infractionEntity = addOrUpdateInfraction.execute(input)
return Infraction.fromInfractionEntity(infractionEntity)
}

// Function to check if the target has changed
private fun hasTargetChanged(input: InfractionWithNewTargetInput, target: InfractionEnvTargetEntity): Boolean {
return input.vesselType != target.vesselType.name ||
input.vesselSize != target.vesselSize.name ||
input.vesselIdentifier != target.vesselIdentifier ||
input.identityControlledPerson != target.identityControlledPerson
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ data class InfractionsByVessel(
val vesselIdentifier: String? = null,
val vesselType: VesselTypeEnum? = null,
val controlTypesWithInfraction: List<ControlType>? = null,
val targetAddedInRapportNav: Boolean? = null,
val targetAddedByUnit: Boolean? = null,
val infractions: List<Infraction>
) {
fun groupInfractionsByVesselIdentifier(infractions: List<Infraction>): List<InfractionsByVessel> {
Expand All @@ -20,7 +20,7 @@ data class InfractionsByVessel(
vesselType = infractions.firstOrNull()?.target?.vesselType,
infractions = infractions,
controlTypesWithInfraction = controlTypesWithInfraction,
targetAddedInRapportNav = targetAddedInRapportNav,
targetAddedByUnit = targetAddedByUnit,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infracti
import com.fasterxml.jackson.annotation.JsonIgnore
import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselSizeEnum
import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselTypeEnum
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity
import jakarta.persistence.*
import java.util.*
Expand Down Expand Up @@ -53,14 +54,19 @@ data class InfractionEnvTargetModel(
}

companion object {
fun fromInfractionEnvTargetEntity(infraction: InfractionEnvTargetEntity) = InfractionEnvTargetModel(
id = infraction.id,
missionId = infraction.missionId,
actionId = infraction.actionId,
vesselIdentifier = infraction.vesselIdentifier,
identityControlledPerson = infraction.identityControlledPerson,
vesselType = infraction.vesselType.toString(),
vesselSize = infraction.vesselSize.toString(),
)
fun fromInfractionEnvTargetEntity(
infractionTarget: InfractionEnvTargetEntity,
infraction: InfractionEntity? = null
) =
InfractionEnvTargetModel(
id = infractionTarget.id,
missionId = infractionTarget.missionId,
actionId = infractionTarget.actionId,
infraction = infraction?.let { it -> InfractionModel.fromInfractionEntity(it) },
vesselIdentifier = infractionTarget.vesselIdentifier,
identityControlledPerson = infractionTarget.identityControlledPerson,
vesselType = infractionTarget.vesselType.toString(),
vesselSize = infractionTarget.vesselSize.toString(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,20 @@ class InfractionModel(
}

companion object {
fun fromInfractionEntity(infraction: InfractionEntity) = InfractionModel(
id = infraction.id,
missionId = infraction.missionId,
actionId = infraction.actionId,
controlType = infraction.controlType.toString(),
infractionType = infraction.infractionType?.toString(),
natinfs = infraction.natinfs,
observations = infraction.observations,
target = infraction.target?.let {
listOf(
InfractionEnvTargetModel.fromInfractionEnvTargetEntity(
infraction.target!!
)
)
}
)
fun fromInfractionEntity(infraction: InfractionEntity): InfractionModel {
return InfractionModel(
id = infraction.id,
missionId = infraction.missionId,
actionId = infraction.actionId,
controlType = infraction.controlType.toString(),
infractionType = infraction.infractionType?.toString(),
natinfs = infraction.natinfs,
observations = infraction.observations,
target = infraction.target?.let {
listOf(InfractionEnvTargetModel.fromInfractionEnvTargetEntity(it))
} ?: emptyList() // Provide an empty list if target is null
)
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package fr.gouv.dgampa.rapportnav.infrastructure.database.repositories.interfaces.mission.infraction

import fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infraction.InfractionEnvTargetModel
import org.springframework.data.jpa.repository.JpaRepository
import java.util.*

interface IDBInfractionEnvTargetRepository : JpaRepository<InfractionEnvTargetModel, UUID> {
fun findByActionIdAndVesselIdentifier(actionId: String, vesselIdentifier: String): List<InfractionEnvTargetModel>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package fr.gouv.dgampa.rapportnav.infrastructure.database.repositories.mission.infraction

import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity
import fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction.IInfractionEnvTargetRepository
import fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infraction.InfractionEnvTargetModel
import fr.gouv.dgampa.rapportnav.infrastructure.database.repositories.interfaces.mission.infraction.IDBInfractionEnvTargetRepository
import org.springframework.dao.InvalidDataAccessApiUsageException
import org.springframework.stereotype.Repository
import org.springframework.transaction.annotation.Transactional


@Repository
class JPAInfractionEnvTargetRepository(
private val dbRepo: IDBInfractionEnvTargetRepository,
) : IInfractionEnvTargetRepository {

@Transactional
override fun save(
infractionTarget: InfractionEnvTargetEntity,
infraction: InfractionEntity
): InfractionEnvTargetModel {
return try {
val model = InfractionEnvTargetModel.fromInfractionEnvTargetEntity(infractionTarget, infraction)
dbRepo.save(model)
} catch (e: InvalidDataAccessApiUsageException) {
throw Exception("Error saving or updating Infraction Env Target", e)
}
}

override fun findByActionIdAndVesselIdentifier(
actionId: String,
vesselIdentifier: String
): List<InfractionEnvTargetModel> {
return try {
val models = dbRepo.findByActionIdAndVesselIdentifier(actionId, vesselIdentifier)
models
} catch (e: InvalidDataAccessApiUsageException) {
throw Exception("Error findByActionIdAndVesselIdentifier Infraction Env Target", e)
}
}


}
2 changes: 1 addition & 1 deletion backend/src/main/resources/graphql/infraction.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type InfractionByTarget {
vesselIdentifier: String
vesselType: VesselType
controlTypesWithInfraction: [ControlType]
targetAddedInRapportNav: Boolean
targetAddedByUnit: Boolean
infractions: [Infraction]
}

Expand Down
Loading

0 comments on commit d0c1212

Please sign in to comment.