diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/administration/AdministrationEntity.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/administration/AdministrationEntity.kt index 3685dff119..b893826f60 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/administration/AdministrationEntity.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/administration/AdministrationEntity.kt @@ -2,5 +2,6 @@ package fr.gouv.cacem.monitorenv.domain.entities.administration data class AdministrationEntity( val id: Int? = null, + val isArchived: Boolean, val name: String, ) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IAdministrationRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IAdministrationRepository.kt index 0dd4493b8e..ed1678ba1c 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IAdministrationRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IAdministrationRepository.kt @@ -4,6 +4,8 @@ import fr.gouv.cacem.monitorenv.domain.entities.administration.AdministrationEnt import fr.gouv.cacem.monitorenv.domain.use_cases.administration.dtos.FullAdministrationDTO interface IAdministrationRepository { + fun archiveById(administrationId: Int) + fun deleteById(administrationId: Int) fun findById(administrationId: Int): FullAdministrationDTO diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/ArchiveAdministration.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/ArchiveAdministration.kt new file mode 100644 index 0000000000..a1f3550a77 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/ArchiveAdministration.kt @@ -0,0 +1,11 @@ +package fr.gouv.cacem.monitorenv.domain.use_cases.administration + +import fr.gouv.cacem.monitorenv.config.UseCase +import fr.gouv.cacem.monitorenv.domain.repositories.IAdministrationRepository + +@UseCase +class ArchiveAdministration(private val administrationRepository: IAdministrationRepository) { + fun execute(administrationId: Int) { + administrationRepository.archiveById(administrationId) + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/DeleteAdministration.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/DeleteAdministration.kt new file mode 100644 index 0000000000..eae99e795b --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/DeleteAdministration.kt @@ -0,0 +1,11 @@ +package fr.gouv.cacem.monitorenv.domain.use_cases.administration + +import fr.gouv.cacem.monitorenv.config.UseCase +import fr.gouv.cacem.monitorenv.domain.repositories.IAdministrationRepository + +@UseCase +class DeleteAdministration(private val administrationRepository: IAdministrationRepository) { + fun execute(administrationId: Int) { + administrationRepository.deleteById(administrationId) + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/dtos/FullAdministrationDTO.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/dtos/FullAdministrationDTO.kt index e0034ee5c3..f57dcd5b27 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/dtos/FullAdministrationDTO.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/administration/dtos/FullAdministrationDTO.kt @@ -6,5 +6,6 @@ data class FullAdministrationDTO( val id: Int? = null, val controlUnitIds: List, val controlUnits: List, + val isArchived: Boolean, val name: String, ) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateAdministrationDataInput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateAdministrationDataInput.kt index 9a3b7b77c3..a3ad378aea 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateAdministrationDataInput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateAdministrationDataInput.kt @@ -4,11 +4,13 @@ import fr.gouv.cacem.monitorenv.domain.entities.administration.AdministrationEnt data class CreateOrUpdateAdministrationDataInput( val id: Int? = null, + val isArchived: Boolean, val name: String, ) { fun toAdministration(): AdministrationEntity { return AdministrationEntity( id = this.id, + isArchived = this.isArchived, name = this.name, ) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/AdministrationDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/AdministrationDataOutput.kt index 1fcfcd27e6..f65bdf2cc5 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/AdministrationDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/AdministrationDataOutput.kt @@ -4,12 +4,14 @@ import fr.gouv.cacem.monitorenv.domain.entities.administration.AdministrationEnt data class AdministrationDataOutput( val id: Int, + val isArchived: Boolean, val name: String, ) { companion object { fun fromAdministration(administration: AdministrationEntity): AdministrationDataOutput { return AdministrationDataOutput( id = requireNotNull(administration.id), + isArchived = administration.isArchived, name = administration.name, ) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullAdministrationDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullAdministrationDataOutput.kt index 88c2a4075f..7ba9bcfbc9 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullAdministrationDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullAdministrationDataOutput.kt @@ -7,6 +7,7 @@ data class FullAdministrationDataOutput( val id: Int, val controlUnitIds: List, val controlUnits: List, + val isArchived: Boolean, val name: String, ) { companion object { @@ -15,6 +16,7 @@ data class FullAdministrationDataOutput( id = requireNotNull(fullAdministration.id), controlUnits = fullAdministration.controlUnits, controlUnitIds = fullAdministration.controlUnitIds, + isArchived = fullAdministration.isArchived, name = fullAdministration.name, ) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt index bc03a4139c..d29024463b 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt @@ -1,8 +1,6 @@ package fr.gouv.cacem.monitorenv.infrastructure.api.endpoints.publicapi -import fr.gouv.cacem.monitorenv.domain.use_cases.administration.CreateOrUpdateAdministration -import fr.gouv.cacem.monitorenv.domain.use_cases.administration.GetAdministrationById -import fr.gouv.cacem.monitorenv.domain.use_cases.administration.GetAdministrations +import fr.gouv.cacem.monitorenv.domain.use_cases.administration.* import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.inputs.CreateOrUpdateAdministrationDataInput import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.outputs.AdministrationDataOutput import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.outputs.FullAdministrationDataOutput @@ -16,10 +14,22 @@ import org.springframework.web.bind.annotation.* @RequestMapping("/api/v1/administrations") @Tag(name = "Administrations") class ApiAdministrationsController( + private val archiveAdministration: ArchiveAdministration, private val createOrUpdateAdministration: CreateOrUpdateAdministration, + private val deleteAdministration: DeleteAdministration, private val getAdministrations: GetAdministrations, private val getAdministrationById: GetAdministrationById, ) { + @PostMapping("/{administrationId}/archive") + @Operation(summary = "Archive an administration") + fun archive( + @PathParam("Administration ID") + @PathVariable(name = "administrationId") + administrationId: Int, + ) { + archiveAdministration.execute(administrationId) + } + @PostMapping("", consumes = ["application/json"]) @Operation(summary = "Create an administration") @ResponseStatus(HttpStatus.CREATED) @@ -33,8 +43,18 @@ class ApiAdministrationsController( return AdministrationDataOutput.fromAdministration(createdAdministration) } + @DeleteMapping("/{administrationId}") + @Operation(summary = "Delete an administration") + fun delete( + @PathParam("Administration ID") + @PathVariable(name = "administrationId") + controlUnitId: Int, + ) { + deleteAdministration.execute(controlUnitId) + } + @GetMapping("/{administrationId}") - @Operation(summary = "Get a administration by its ID") + @Operation(summary = "Get an administration by its ID") fun get( @PathParam("Administration ID") @PathVariable(name = "administrationId") @@ -56,7 +76,7 @@ class ApiAdministrationsController( @PutMapping(value = ["/{administrationId}"], consumes = ["application/json"]) @Operation(summary = "Update an administration") fun update( - @PathParam("Control unit administration ID") + @PathParam("Administration ID") @PathVariable(name = "administrationId") administrationId: Int, @RequestBody diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt index 69d2b65201..6228ceed77 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt @@ -22,6 +22,9 @@ data class AdministrationModel( @JsonManagedReference var controlUnits: List? = mutableListOf(), + @Column(name = "is_archived") + var isArchived: Boolean, + @Column(name = "name", nullable = false, unique = true) var name: String, @@ -44,6 +47,7 @@ data class AdministrationModel( return AdministrationModel( id = administration.id, controlUnits = controlUnitModels, + isArchived = administration.isArchived, name = administration.name, ) } @@ -52,6 +56,7 @@ data class AdministrationModel( fun toAdministration(): AdministrationEntity { return AdministrationEntity( id, + isArchived, name, ) } @@ -62,6 +67,7 @@ data class AdministrationModel( controlUnitIds = requireIds(controlUnits) { it.id }, // TODO Remove `requireNotNullList()` once `controlUnits` is non-nullable. controlUnits = requireNotNullList(controlUnits).map { it.toControlUnit() }, + isArchived, name, ) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlUnitModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlUnitModel.kt index b5dd4bdbcc..00f946122e 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlUnitModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlUnitModel.kt @@ -1,15 +1,7 @@ package fr.gouv.cacem.monitorenv.infrastructure.database.model import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.LegacyControlUnitEntity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.FetchType -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id -import jakarta.persistence.JoinColumn -import jakarta.persistence.ManyToOne -import jakarta.persistence.Table +import jakarta.persistence.* @Entity @Table(name = "missions_control_units") @@ -35,7 +27,7 @@ data class MissionControlUnitModel( MissionControlUnitModel( unit = ControlUnitModel( id = legacyControlUnit.id, - administration = AdministrationModel(name = legacyControlUnit.administration), + administration = AdministrationModel(isArchived = false, name = legacyControlUnit.administration), areaNote = null, controlUnitContacts = listOf(), controlUnitResources = listOf(), diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt index 0aa6952897..191fc5fd32 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt @@ -14,6 +14,11 @@ import org.springframework.transaction.annotation.Transactional class JpaAdministrationRepository( private val dbAdministrationRepository: IDBAdministrationRepository, ) : IAdministrationRepository { + @Transactional + override fun archiveById(administrationId: Int) { + dbAdministrationRepository.archiveById(administrationId) + } + override fun deleteById(administrationId: Int) { dbAdministrationRepository.deleteById(administrationId) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBAdministrationRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBAdministrationRepository.kt index 916407888c..81c279aac6 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBAdministrationRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBAdministrationRepository.kt @@ -2,11 +2,23 @@ package fr.gouv.cacem.monitorenv.infrastructure.database.repositories.interfaces import fr.gouv.cacem.monitorenv.infrastructure.database.model.AdministrationModel import org.hibernate.annotations.DynamicUpdate +import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Query import org.springframework.data.repository.CrudRepository @DynamicUpdate interface IDBAdministrationRepository : CrudRepository { + @Modifying(clearAutomatically = true) + @Query( + value = """ + UPDATE administrations + SET is_archived = TRUE + WHERE id = :administrationId + """, + nativeQuery = true, + ) + fun archiveById(administrationId: Int) + @Query( value = """ SELECT * diff --git a/backend/src/main/resources/db/migration/internal/V0.097__alter_control_unit_resources_tables.sql b/backend/src/main/resources/db/migration/internal/V0.097__alter_control_unit_resources_table.sql similarity index 100% rename from backend/src/main/resources/db/migration/internal/V0.097__alter_control_unit_resources_tables.sql rename to backend/src/main/resources/db/migration/internal/V0.097__alter_control_unit_resources_table.sql diff --git a/backend/src/main/resources/db/migration/internal/V0.098__alter_administrations_table copy.sql b/backend/src/main/resources/db/migration/internal/V0.098__alter_administrations_table copy.sql new file mode 100644 index 0000000000..ae7348da4d --- /dev/null +++ b/backend/src/main/resources/db/migration/internal/V0.098__alter_administrations_table copy.sql @@ -0,0 +1,2 @@ +ALTER TABLE public.administrations + ADD COLUMN is_archived BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt index ddb5fdca5f..893f2133f0 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt @@ -20,6 +20,7 @@ class CreateOrUpdateAdministrationUTests { @Test fun `execute() should return save() result`() { val newAdministration = AdministrationEntity( + isArchived = false, name = "Administration Name" ) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateReportingUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateReportingUTests.kt index ecf9d0d196..ea2122e2f4 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateReportingUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateReportingUTests.kt @@ -124,6 +124,7 @@ class CreateOrUpdateReportingUTests { id = 1, administration = AdministrationEntity( id = 1, + isArchived = false, name = "administration 1", ), administrationId = 2, diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt index 7c27af8e16..e7a7238441 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt @@ -5,9 +5,7 @@ import com.nhaarman.mockitokotlin2.any import fr.gouv.cacem.monitorenv.config.MapperConfiguration import fr.gouv.cacem.monitorenv.config.WebSecurityConfig import fr.gouv.cacem.monitorenv.domain.entities.administration.AdministrationEntity -import fr.gouv.cacem.monitorenv.domain.use_cases.administration.CreateOrUpdateAdministration -import fr.gouv.cacem.monitorenv.domain.use_cases.administration.GetAdministrationById -import fr.gouv.cacem.monitorenv.domain.use_cases.administration.GetAdministrations +import fr.gouv.cacem.monitorenv.domain.use_cases.administration.* import fr.gouv.cacem.monitorenv.domain.use_cases.administration.dtos.FullAdministrationDTO import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.inputs.CreateOrUpdateAdministrationDataInput import org.hamcrest.Matchers @@ -31,9 +29,15 @@ class ApiAdministrationsControllerITests { @Autowired private lateinit var mockMvc: MockMvc + @MockBean + private lateinit var archiveAdministration: ArchiveAdministration + @MockBean private lateinit var createOrUpdateAdministration: CreateOrUpdateAdministration + @MockBean + private lateinit var deleteAdministration: DeleteAdministration + @MockBean private lateinit var getAdministrationById: GetAdministrationById @@ -47,10 +51,12 @@ class ApiAdministrationsControllerITests { fun `Should create an administration`() { val expectedCreatedAdministration = AdministrationEntity( id = 1, + isArchived = false, name = "Administration Name", ) val newAdministrationData = CreateOrUpdateAdministrationDataInput( + isArchived = false, name = "Administration Name", ) val requestBody = objectMapper.writeValueAsString(newAdministrationData) @@ -72,6 +78,7 @@ class ApiAdministrationsControllerITests { id = 1, controlUnitIds = listOf(), controlUnits = listOf(), + isArchived = false, name = "Administration Name", ) @@ -92,6 +99,7 @@ class ApiAdministrationsControllerITests { id = 1, controlUnitIds = listOf(), controlUnits = listOf(), + isArchived = false, name = "Administration Name", ), @@ -99,6 +107,7 @@ class ApiAdministrationsControllerITests { id = 2, controlUnitIds = listOf(), controlUnits = listOf(), + isArchived = false, name = "Administration Name 2", ) ) @@ -116,11 +125,13 @@ class ApiAdministrationsControllerITests { fun `Should update an administration`() { val expectedUpdatedAdministration = AdministrationEntity( id = 1, + isArchived = false, name = "Updated Administration Name", ) val nextAdministrationData = CreateOrUpdateAdministrationDataInput( id = 1, + isArchived = false, name = "Updated Administration Name", ) val requestBody = objectMapper.writeValueAsString(nextAdministrationData) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt index c294be264a..20516254a8 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt @@ -87,6 +87,7 @@ class ApiControlUnitsControllerITests { id = 1, administration = AdministrationEntity( id = 0, + isArchived = false, name = "Administration Name", ), administrationId = 0, @@ -117,6 +118,7 @@ class ApiControlUnitsControllerITests { id = 1, administration = AdministrationEntity( id = 0, + isArchived = false, name = "Administration Name", ), administrationId = 0, @@ -134,6 +136,7 @@ class ApiControlUnitsControllerITests { id = 2, administration = AdministrationEntity( id = 0, + isArchived = false, name = "Administration Name", ), administrationId = 0, diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt index c1288109e5..fd179ae358 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt @@ -11,21 +11,19 @@ import org.springframework.transaction.annotation.Transactional class JpaAdministrationRepositoryITests : AbstractDBTests() { @Autowired private lateinit var jpaAdministrationRepository: JpaAdministrationRepository - + @Test @Transactional - fun `deleteById() should delete an administration by its ID`() { - val beforeAdministrationIds = jpaAdministrationRepository.findAll().map { it.id } + fun `archiveById() should archive an administration by its ID`() { + val beforeFullAdministration = jpaAdministrationRepository.findById(2006) - assertThat(beforeAdministrationIds).hasSize(33) - assertThat(beforeAdministrationIds).contains(1) + assertThat(beforeFullAdministration.isArchived).isFalse() - jpaAdministrationRepository.deleteById(1) + jpaAdministrationRepository.archiveById(2006) - val afterAdministrationIds = jpaAdministrationRepository.findAll().map { it.id } + val afterFullAdministration = jpaAdministrationRepository.findById(2006) - assertThat(afterAdministrationIds).hasSize(32) - assertThat(afterAdministrationIds).doesNotContain(1) + assertThat(afterFullAdministration.isArchived).isTrue() } @Test @@ -41,6 +39,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { id = 1007, controlUnitIds = listOf(), controlUnits = listOf(), + isArchived = false, name = "AECP" ) ) @@ -50,6 +49,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { id = 2004, controlUnitIds = listOf(), controlUnits = listOf(), + isArchived = false, name = "Sécurité Civile" ) ) @@ -82,6 +82,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { termsNote = null, ), ), + isArchived = false, name = "Gendarmerie Nationale" ) ) @@ -89,11 +90,12 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { @Test @Transactional - fun `save() should create and update an administration`() { + fun `save() should create and update an administration, deleteById() should delete an administration`() { // --------------------------------------------------------------------- // Create val newAdministration = AdministrationEntity( + isArchived = false, name = "Administration Name" ) @@ -106,6 +108,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { val nextAdministration = AdministrationEntity( id = 2007, + isArchived = false, name = "Updated Administration Name" ) @@ -114,8 +117,12 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { assertThat(updatedAdministration).isEqualTo(nextAdministration) // --------------------------------------------------------------------- - // Reset + // Delete jpaAdministrationRepository.deleteById(2007) + + val administrationIds = jpaAdministrationRepository.findAll().map { requireNotNull(it.id) }.sorted() + + assertThat(administrationIds).doesNotContain(2007) } } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt index f1e991f1ff..7840c1d583 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt @@ -44,6 +44,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { id = 24, administration = AdministrationEntity( id = 3, + isArchived = false, name = "Marine Nationale" ), administrationId = 3, @@ -63,6 +64,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { id = 8, administration = AdministrationEntity( id = 1005, + isArchived = false, name = "DDTM" ), administrationId = 1005, @@ -88,6 +90,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { id = 1, administration = AdministrationEntity( id = 1005, + isArchived = false, name = "DDTM" ), administrationId = 1005, diff --git a/frontend/cypress/e2e/back_office/administration_form.spec.ts b/frontend/cypress/e2e/back_office/administration_form.spec.ts index e3f037afb7..8f8bed997f 100644 --- a/frontend/cypress/e2e/back_office/administration_form.spec.ts +++ b/frontend/cypress/e2e/back_office/administration_form.spec.ts @@ -1,5 +1,3 @@ -import { FAKE_API_POST_RESPONSE, FAKE_API_PUT_RESPONSE } from '../constants' - context('Back Office > Administration Form', () => { beforeEach(() => { cy.intercept('GET', `/api/v1/administrations`).as('getAdministrations') @@ -9,8 +7,11 @@ context('Back Office > Administration Form', () => { cy.wait('@getAdministrations') }) - it('Should create an administration', () => { - cy.intercept('POST', `/api/v1/administrations`, FAKE_API_POST_RESPONSE).as('createAdministration') + it('Should create, edit, archive and delete an administration', () => { + // ------------------------------------------------------------------------- + // Create + + cy.intercept('POST', `/api/v1/administrations`).as('createAdministration') cy.clickButton('Nouvelle administration') @@ -24,17 +25,17 @@ context('Back Office > Administration Form', () => { } assert.deepEqual(interception.request.body, { + isArchived: false, name: 'Administration 1' }) }) - }) - it('Should edit an administration', () => { - cy.intercept('PUT', `/api/v1/administrations/1005`, FAKE_API_PUT_RESPONSE).as('updateAdministration') + // ------------------------------------------------------------------------- + // Edit - cy.clickButton('Éditer cette administration', { - withinSelector: 'tbody > tr:nth-child(10)' - }) + cy.intercept('PUT', `/api/v1/administrations/2007`).as('updateAdministration') + + cy.getTableRowById(2007).clickButton('Éditer cette administration') cy.fill('Nom', 'Administration 2') @@ -46,9 +47,38 @@ context('Back Office > Administration Form', () => { } assert.deepInclude(interception.request.body, { - id: 1005, + id: 2007, + isArchived: false, name: 'Administration 2' }) }) + + // ------------------------------------------------------------------------- + // Archive + + cy.intercept('POST', `/api/v1/administrations/2007/archive`).as('archiveAdministration') + + cy.getTableRowById(2007).clickButton('Archiver cette administration') + cy.clickButton('Confirmer') + + cy.wait('@archiveAdministration') + + cy.getTableRowById(2007).should('not.exist') + cy.clickButton('Administrations archivées') + cy.getTableRowById(2007).should('exist') + + // ------------------------------------------------------------------------- + // Delete + + cy.intercept('DELETE', `/api/v1/administrations/2007`).as('deleteAdministration') + + cy.getTableRowById(2007).clickButton('Supprimer cette administration') + cy.clickButton('Confirmer') + + cy.wait('@deleteAdministration') + + cy.getTableRowById(2007).should('not.exist') + cy.clickButton('Administrations actives') + cy.getTableRowById(2007).should('not.exist') }) }) diff --git a/frontend/cypress/e2e/back_office/control_unit_list/filter_bar.spec.ts b/frontend/cypress/e2e/back_office/control_unit_list/filter_bar.spec.ts index b60446e53e..9e662b59d5 100644 --- a/frontend/cypress/e2e/back_office/control_unit_list/filter_bar.spec.ts +++ b/frontend/cypress/e2e/back_office/control_unit_list/filter_bar.spec.ts @@ -8,16 +8,17 @@ context('Back Office > Control Unit List > Filter Bar', () => { }) it('Should show all control units by default', () => { - cy.get('tbody > tr').should('have.length', 33) - cy.get('tbody > tr:first-child > td:nth-child(3)').should('have.text', 'A636 Maïto') - cy.get('tbody > tr:last-child > td:nth-child(3)').should('have.text', 'SML 50') + cy.get('tbody > tr').should('have.length', 31) + cy.getTableRowByText('A636 Maïto').should('exist', 'A636 Maïto') + cy.getTableRowByText('A636 Maïto').should('exist', 'SML 50') + cy.getTableRowByText('BGC Ajaccio').should('not.exist') }) it('Should find control units matching the search query', () => { cy.fill('Rechercher...', 'marine') cy.get('tbody > tr').should('have.length', 4) - cy.get('tbody > tr:first-child > td:nth-child(3)').should('have.text', 'A636 Maïto') - cy.get('tbody > tr:last-child > td:nth-child(3)').should('have.text', 'Natura 2000 Côte Bleue Marine') + cy.getTableRowByText('A636 Maïto').should('exist', 'A636 Maïto') + cy.getTableRowByText('SML 50').should('not.exist') }) }) diff --git a/frontend/src/api/administrationsAPI.ts b/frontend/src/api/administrationsAPI.ts index 4b2b3e2eb2..3cdcc4e6b5 100644 --- a/frontend/src/api/administrationsAPI.ts +++ b/frontend/src/api/administrationsAPI.ts @@ -8,6 +8,14 @@ const GET_ADMINISTRATIONS_ERROR_MESSAGE = "Nous n'avons pas pu récupérer la li export const administrationsAPI = monitorenvPublicApi.injectEndpoints({ endpoints: builder => ({ + archiveAdministration: builder.mutation({ + invalidatesTags: () => [{ type: 'Administrations' }], + query: administrationId => ({ + method: 'POST', + url: `/v1/administrations/${administrationId}/archive` + }) + }), + createAdministration: builder.mutation({ invalidatesTags: () => [{ type: 'Administrations' }], query: newAdministrationData => ({ @@ -17,6 +25,14 @@ export const administrationsAPI = monitorenvPublicApi.injectEndpoints({ }) }), + deleteAdministration: builder.mutation({ + invalidatesTags: () => [{ type: 'Administrations' }], + query: administrationId => ({ + method: 'DELETE', + url: `/v1/administrations/${administrationId}` + }) + }), + getAdministration: builder.query({ providesTags: () => [{ type: 'Administrations' }], query: administrationId => `/v1/administrations/${administrationId}`, @@ -41,7 +57,9 @@ export const administrationsAPI = monitorenvPublicApi.injectEndpoints({ }) export const { + useArchiveAdministrationMutation, useCreateAdministrationMutation, + useDeleteAdministrationMutation, useGetAdministrationQuery, useGetAdministrationsQuery, useUpdateAdministrationMutation diff --git a/frontend/src/api/controlUnitsAPI.ts b/frontend/src/api/controlUnitsAPI.ts index c95d02ffef..efc1960cc3 100644 --- a/frontend/src/api/controlUnitsAPI.ts +++ b/frontend/src/api/controlUnitsAPI.ts @@ -26,7 +26,7 @@ export const controlUnitsAPI = monitorenvPublicApi.injectEndpoints({ }), deleteControlUnit: builder.mutation({ - invalidatesTags: () => [{ type: 'ControlUnits' }], + invalidatesTags: () => [{ type: 'Administrations' }, { type: 'ControlUnits' }], query: controlUnitId => ({ method: 'DELETE', url: `/v2/control_units/${controlUnitId}` diff --git a/frontend/src/domain/entities/administration.ts b/frontend/src/domain/entities/administration.ts index 9426e42829..2369b181fe 100644 --- a/frontend/src/domain/entities/administration.ts +++ b/frontend/src/domain/entities/administration.ts @@ -5,6 +5,7 @@ export namespace Administration { controlUnitIds: number[] controlUnits: ControlUnit.ControlUnitData[] id: number + isArchived: boolean name: string } diff --git a/frontend/src/domain/use_cases/administration/archiveAdministration.ts b/frontend/src/domain/use_cases/administration/archiveAdministration.ts new file mode 100644 index 0000000000..301055fd8f --- /dev/null +++ b/frontend/src/domain/use_cases/administration/archiveAdministration.ts @@ -0,0 +1,24 @@ +import { logSoftError } from '@mtes-mct/monitor-ui' + +import { administrationsAPI } from '../../../api/administrationsAPI' + +import type { AppThunk } from '../../../store' + +export const archiveAdministration = (): AppThunk> => async (dispatch, getState) => { + const administrationId = getState().backOffice.confirmationModalActionId + + try { + const { error } = await dispatch( + administrationsAPI.endpoints.archiveAdministration.initiate(administrationId) as any + ) + if (error) { + throw error + } + } catch (err) { + logSoftError({ + message: `An error happened while archiving an administration (ID=${administrationId}").`, + originalError: err, + userMessage: "Une erreur est survenue pendant l'archivage de l'administration." + }) + } +} diff --git a/frontend/src/domain/use_cases/administration/deleteAdministration.ts b/frontend/src/domain/use_cases/administration/deleteAdministration.ts new file mode 100644 index 0000000000..d520efe020 --- /dev/null +++ b/frontend/src/domain/use_cases/administration/deleteAdministration.ts @@ -0,0 +1,24 @@ +import { logSoftError } from '@mtes-mct/monitor-ui' + +import { administrationsAPI } from '../../../api/administrationsAPI' + +import type { AppThunk } from '../../../store' + +export const deleteAdministration = (): AppThunk> => async (dispatch, getState) => { + const administrationId = getState().backOffice.confirmationModalActionId + + try { + const { error } = await dispatch( + administrationsAPI.endpoints.deleteAdministration.initiate(administrationId) as any + ) + if (error) { + throw error + } + } catch (err) { + logSoftError({ + message: `An error happened while deleting an administration (ID=${administrationId}").`, + originalError: err, + userMessage: "Une erreur est survenue pendant la suppression de l'administration." + }) + } +} diff --git a/frontend/src/domain/use_cases/backOffice/handleModalConfirmation.ts b/frontend/src/domain/use_cases/backOffice/handleModalConfirmation.ts index 342e5c100c..7736badf6e 100644 --- a/frontend/src/domain/use_cases/backOffice/handleModalConfirmation.ts +++ b/frontend/src/domain/use_cases/backOffice/handleModalConfirmation.ts @@ -1,5 +1,7 @@ import { BackOfficeConfirmationModalActionType } from './types' import { closeConfirmationModal } from '../../shared_slices/BackOffice' +import { archiveAdministration } from '../administration/archiveAdministration' +import { deleteAdministration } from '../administration/deleteAdministration' import { archiveControlUnit } from '../controlUnit/archiveControlUnit' import { deleteControlUnit } from '../controlUnit/deleteControlUnit' @@ -9,10 +11,18 @@ export const handleModalConfirmation = (): AppThunk => async (dispatch, ge const { confirmationModalActionType } = getState().backOffice switch (confirmationModalActionType) { + case BackOfficeConfirmationModalActionType.ARCHIVE_ADMINISTRATION: + await dispatch(archiveAdministration()) + break + case BackOfficeConfirmationModalActionType.ARCHIVE_CONTROL_UNIT: await dispatch(archiveControlUnit()) break + case BackOfficeConfirmationModalActionType.DELETE_ADMINISTRATION: + await dispatch(deleteAdministration()) + break + case BackOfficeConfirmationModalActionType.DELETE_CONTROL_UNIT: await dispatch(deleteControlUnit()) break diff --git a/frontend/src/domain/use_cases/backOffice/types.ts b/frontend/src/domain/use_cases/backOffice/types.ts index e006b96c85..13a2e6eedd 100644 --- a/frontend/src/domain/use_cases/backOffice/types.ts +++ b/frontend/src/domain/use_cases/backOffice/types.ts @@ -1,4 +1,6 @@ export enum BackOfficeConfirmationModalActionType { + 'ARCHIVE_ADMINISTRATION' = 'ARCHIVE_ADMINISTRATION', 'ARCHIVE_CONTROL_UNIT' = 'ARCHIVE_CONTROL_UNIT', + 'DELETE_ADMINISTRATION' = 'DELETE_ADMINISTRATION', 'DELETE_CONTROL_UNIT' = 'DELETE_CONTROL_UNIT' } diff --git a/frontend/src/domain/use_cases/controlUnit/deleteControlUnit.ts b/frontend/src/domain/use_cases/controlUnit/deleteControlUnit.ts index fef4933470..596da0f354 100644 --- a/frontend/src/domain/use_cases/controlUnit/deleteControlUnit.ts +++ b/frontend/src/domain/use_cases/controlUnit/deleteControlUnit.ts @@ -14,7 +14,7 @@ export const deleteControlUnit = (): AppThunk> => async (dispatch, } } catch (err) { logSoftError({ - message: `An error happened while archiving a control unit (ID=${controlUnitId}").`, + message: `An error happened while deleting a control unit (ID=${controlUnitId}").`, originalError: err, userMessage: "Une erreur est survenue pendant la suppression de l'unité de contrôle." }) diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationForm/constants.tsx b/frontend/src/features/Administrations/BackOfficeAdministrationForm/constants.tsx index 820cec69f5..19c846da02 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationForm/constants.tsx +++ b/frontend/src/features/Administrations/BackOfficeAdministrationForm/constants.tsx @@ -43,5 +43,6 @@ export const CONTROL_UNIT_TABLE_COLUMNS: Array {({ handleSubmit }) => ( -
+ + {/* This is a quick way to implement "unarchiving" for users in case of human error. */} + {initialValues.isArchived && } - + )} )} @@ -108,6 +110,12 @@ const Title = styled.h1` margin: 0 0 24px; ` +const Form = styled.form` + > div:not(:first-child, :last-child) { + margin-top: 16px; + } +` + const ActionGroup = styled.div` margin-top: 24px; diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/TabMenu.tsx b/frontend/src/features/Administrations/BackOfficeAdministrationList/TabMenu.tsx new file mode 100644 index 0000000000..9a8d146e9f --- /dev/null +++ b/frontend/src/features/Administrations/BackOfficeAdministrationList/TabMenu.tsx @@ -0,0 +1,30 @@ +import { backOfficeAdministrationListActions } from './slice' +import { useAppDispatch } from '../../../hooks/useAppDispatch' +import { useAppSelector } from '../../../hooks/useAppSelector' +import { TabBar } from '../../BackOffice/components/TabBar' + +export function TabMenu() { + const dispatch = useAppDispatch() + const backOfficeAdministrationList = useAppSelector(store => store.backOfficeAdministrationList) + + const filterArchivedAdministrations = (isArchived: boolean) => { + dispatch(backOfficeAdministrationListActions.setFilter({ key: 'isArchived', value: isArchived })) + } + + return ( + + filterArchivedAdministrations(false)} + > + Administrations actives + + filterArchivedAdministrations(true)} + > + Administrations archivées + + + ) +} diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/index.tsx b/frontend/src/features/Administrations/BackOfficeAdministrationList/index.tsx index 0cb3b4cd4c..11dd147418 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/index.tsx +++ b/frontend/src/features/Administrations/BackOfficeAdministrationList/index.tsx @@ -2,18 +2,25 @@ import { DataTable } from '@mtes-mct/monitor-ui' import { useMemo } from 'react' import styled from 'styled-components' -import { ADMINISTRATION_TABLE_COLUMNS } from './constants' import { FilterBar } from './FilterBar' -import { getFilters } from './utils' +import { TabMenu } from './TabMenu' +import { getAdministrationTableColumns, getFilters } from './utils' import { useGetAdministrationsQuery } from '../../../api/administrationsAPI' +import { useAppDispatch } from '../../../hooks/useAppDispatch' import { useAppSelector } from '../../../hooks/useAppSelector' import { NavButton } from '../../../ui/NavButton' import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' export function BackOfficeAdministrationList() { const backOfficeAdministrationList = useAppSelector(store => store.backOfficeAdministrationList) + const dispatch = useAppDispatch() const { data: administrations } = useGetAdministrationsQuery() + const administrationTableColumns = useMemo( + () => getAdministrationTableColumns(dispatch, backOfficeAdministrationList.filtersState.isArchived), + [backOfficeAdministrationList.filtersState.isArchived, dispatch] + ) + const filteredAdministrations = useMemo(() => { if (!administrations) { return undefined @@ -28,6 +35,8 @@ export function BackOfficeAdministrationList() { <> Administration des administrations + + @@ -37,7 +46,7 @@ export function BackOfficeAdministrationList() { diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/slice.ts b/frontend/src/features/Administrations/BackOfficeAdministrationList/slice.ts index ef5de5e06e..734045163d 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/slice.ts +++ b/frontend/src/features/Administrations/BackOfficeAdministrationList/slice.ts @@ -10,7 +10,10 @@ export type BackOfficeAdministrationListState = { } const INITIAL_STATE: BackOfficeAdministrationListState = { - filtersState: {} + filtersState: { + isArchived: false, + query: undefined + } } const persistConfig = { diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/types.ts b/frontend/src/features/Administrations/BackOfficeAdministrationList/types.ts index 20db8ea6ed..067a4b8422 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/types.ts +++ b/frontend/src/features/Administrations/BackOfficeAdministrationList/types.ts @@ -1,3 +1,4 @@ export type FiltersState = { - query?: string + isArchived: boolean + query: string | undefined } diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.ts b/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.ts deleted file mode 100644 index efe55a142c..0000000000 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { CustomSearch, type Filter } from '@mtes-mct/monitor-ui' - -import type { FiltersState } from './types' -import type { Administration } from '../../../domain/entities/administration' - -export function getFilters( - data: Administration.Administration[], - filtersState: FiltersState -): Filter[] { - const customSearch = new CustomSearch(data, ['name'], { - cacheKey: 'BACK_OFFICE_ADMINISTRATION_LIST', - isStrict: true - }) - const filters: Array> = [] - - if (filtersState.query && filtersState.query.trim().length > 0) { - const filter: Filter = () => customSearch.find(filtersState.query as string) - - filters.push(filter) - } - - return filters -} diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.tsx b/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.tsx new file mode 100644 index 0000000000..15fd7e38e9 --- /dev/null +++ b/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.tsx @@ -0,0 +1,98 @@ +import { CustomSearch, IconButton, type Filter, Icon, Size } from '@mtes-mct/monitor-ui' + +import { ADMINISTRATION_TABLE_COLUMNS } from './constants' +import { openConfirmationModal } from '../../../domain/shared_slices/BackOffice' +import { BackOfficeConfirmationModalActionType } from '../../../domain/use_cases/backOffice/types' + +import type { FiltersState } from './types' +import type { Administration } from '../../../domain/entities/administration' +import type { AppDispatch } from '../../../store' +import type { ColumnDef } from '@tanstack/react-table' + +export function getAdministrationTableColumns( + dispatch: AppDispatch, + isArchived: boolean = false +): Array> { + const archiveColumn: ColumnDef = { + accessorFn: row => row, + cell: info => ( + + dispatch( + openConfirmationModal({ + actionId: info.getValue().id, + actionType: BackOfficeConfirmationModalActionType.ARCHIVE_ADMINISTRATION, + message: `Êtes-vous sûr de vouloir archiver l'administration "${ + info.getValue().name + }" ?` + }) + ) + } + size={Size.SMALL} + title="Archiver cette administration" + /> + ), + enableSorting: false, + header: () => '', + id: 'archive', + size: 44 + } + + const deleteColumn: ColumnDef = { + accessorFn: row => row, + cell: info => ( + + dispatch( + openConfirmationModal({ + actionId: info.getValue().id, + actionType: BackOfficeConfirmationModalActionType.DELETE_ADMINISTRATION, + message: `Êtes-vous sûr de vouloir supprimer l'administration "${ + info.getValue().name + }" ?` + }) + ) + } + size={Size.SMALL} + title="Supprimer cette administration" + /> + ), + enableSorting: false, + header: () => '', + id: 'delete', + size: 44 + } + + return !isArchived + ? [...ADMINISTRATION_TABLE_COLUMNS, archiveColumn, deleteColumn] + : [...ADMINISTRATION_TABLE_COLUMNS, deleteColumn] +} + +export function getFilters( + data: Administration.Administration[], + filtersState: FiltersState +): Filter[] { + const customSearch = new CustomSearch(data, ['name'], { + cacheKey: 'BACK_OFFICE_ADMINISTRATION_LIST', + isStrict: true + }) + const filters: Array> = [] + + // Search query + // ⚠️ Order matters! Search query should be before other filters. + if (filtersState.query && filtersState.query.trim().length > 0) { + const queryFilter: Filter = () => customSearch.find(filtersState.query as string) + + filters.push(queryFilter) + } + + // Archived or not archived? + const isArchivedFilter: Filter = administrations => + administrations.filter(administration => administration.isArchived === filtersState.isArchived) + + filters.push(isArchivedFilter) + + return filters +} diff --git a/frontend/src/features/ControlUnits/BackOfficeControlUnitList/index.tsx b/frontend/src/features/ControlUnits/BackOfficeControlUnitList/index.tsx index e313951b3f..6250ec19f6 100644 --- a/frontend/src/features/ControlUnits/BackOfficeControlUnitList/index.tsx +++ b/frontend/src/features/ControlUnits/BackOfficeControlUnitList/index.tsx @@ -36,6 +36,7 @@ export function BackOfficeControlUnitList() { Administration des unités de contrôle +