feat(types-org): validation LCB-FT FINANCIER_SOLIDAIRE + code auto-normalisation
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 2m55s
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 2m55s
TypeReferenceService : - validerLbcFtSiFinancierSolidaire() : LCB_FT obligatoire BCEAO appelé avant persist et update - genererCodeDepuisLibelle() / normaliserCode() : UPPER_SNAKE_CASE sans accents - assurerUniciteCode() : suffixe _2/_3 en cas de doublon TypeReferenceServiceTest : 6 tests validerLbcFtSiFinancierSolidaire (avec/sans LCB_FT, catégorie non-financière, modification suppressionLcbFt)
This commit is contained in:
@@ -11,6 +11,7 @@ import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.text.Normalizer;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -157,6 +158,9 @@ public class TypeReferenceService {
|
||||
.modulesRequis(request.modulesRequis())
|
||||
.build();
|
||||
|
||||
validerLbcFtSiFinancierSolidaire(
|
||||
entity.getCategorie(), entity.getModulesRequis());
|
||||
|
||||
if (request.organisationId() != null) {
|
||||
Organisation org = organisationRepository
|
||||
.findById(request.organisationId());
|
||||
@@ -211,6 +215,8 @@ public class TypeReferenceService {
|
||||
}
|
||||
|
||||
appliquerMiseAJour(entity, request);
|
||||
validerLbcFtSiFinancierSolidaire(
|
||||
entity.getCategorie(), entity.getModulesRequis());
|
||||
entity.setModifiePar(
|
||||
keycloakService.getCurrentUserEmail());
|
||||
repository.update(entity);
|
||||
@@ -353,6 +359,26 @@ public class TypeReferenceService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Réglementation BCEAO : LCB_FT obligatoire pour FINANCIER_SOLIDAIRE.
|
||||
* Appelé avant persist et avant update pour couvrir les deux flux.
|
||||
*/
|
||||
private void validerLbcFtSiFinancierSolidaire(
|
||||
String categorie, String modulesRequis) {
|
||||
if (!"FINANCIER_SOLIDAIRE".equals(categorie)) {
|
||||
return;
|
||||
}
|
||||
boolean contientLbcFt = modulesRequis != null
|
||||
&& Arrays.asList(modulesRequis.split(","))
|
||||
.contains("LCB_FT");
|
||||
if (!contientLbcFt) {
|
||||
throw new IllegalArgumentException(
|
||||
"Le module LCB_FT (anti-blanchiment) est obligatoire "
|
||||
+ "pour les types d'organisation de catégorie "
|
||||
+ "FINANCIER_SOLIDAIRE (réglementation BCEAO)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide l'unicité du code dans un domaine.
|
||||
*
|
||||
|
||||
@@ -506,4 +506,128 @@ class TypeReferenceServiceTest {
|
||||
assertThat(updated.getOrdreAffichage()).isEqualTo(10);
|
||||
assertThat(updated.getEstDefaut()).isTrue();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// validerLbcFtSiFinancierSolidaire — règle BCEAO
|
||||
// ================================================================
|
||||
|
||||
@Test
|
||||
@TestTransaction
|
||||
@DisplayName("creer FINANCIER_SOLIDAIRE sans LCB_FT lance IllegalArgumentException")
|
||||
void creer_financierSolidaire_sansLbcFt_throws() {
|
||||
String domaine = "TYPE_ORGANISATION";
|
||||
CreateTypeReferenceRequest request = CreateTypeReferenceRequest.builder()
|
||||
.domaine(domaine)
|
||||
.code("FS_" + UUID.randomUUID().toString().substring(0, 8))
|
||||
.libelle("Mutuelle test")
|
||||
.categorie("FINANCIER_SOLIDAIRE")
|
||||
.modulesRequis("COTISATIONS,EPARGNE,CREDIT")
|
||||
.organisationId(null)
|
||||
.build();
|
||||
|
||||
assertThatThrownBy(() -> typeReferenceService.creer(request))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("LCB_FT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestTransaction
|
||||
@DisplayName("creer FINANCIER_SOLIDAIRE avec modulesRequis null lance IllegalArgumentException")
|
||||
void creer_financierSolidaire_modulesNull_throws() {
|
||||
CreateTypeReferenceRequest request = CreateTypeReferenceRequest.builder()
|
||||
.domaine("TYPE_ORGANISATION")
|
||||
.code("FS_NULL_" + UUID.randomUUID().toString().substring(0, 6))
|
||||
.libelle("Mutuelle sans modules")
|
||||
.categorie("FINANCIER_SOLIDAIRE")
|
||||
.modulesRequis(null)
|
||||
.organisationId(null)
|
||||
.build();
|
||||
|
||||
assertThatThrownBy(() -> typeReferenceService.creer(request))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("LCB_FT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestTransaction
|
||||
@DisplayName("creer FINANCIER_SOLIDAIRE avec LCB_FT réussit")
|
||||
void creer_financierSolidaire_avecLbcFt_succes() {
|
||||
CreateTypeReferenceRequest request = CreateTypeReferenceRequest.builder()
|
||||
.domaine("TYPE_ORGANISATION")
|
||||
.code("FS_OK_" + UUID.randomUUID().toString().substring(0, 6))
|
||||
.libelle("Mutuelle conforme")
|
||||
.categorie("FINANCIER_SOLIDAIRE")
|
||||
.modulesRequis("COTISATIONS,EPARGNE,CREDIT,LCB_FT")
|
||||
.organisationId(null)
|
||||
.build();
|
||||
|
||||
TypeReferenceResponse created = typeReferenceService.creer(request);
|
||||
assertThat(created).isNotNull();
|
||||
assertThat(created.getModulesRequis()).contains("LCB_FT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestTransaction
|
||||
@DisplayName("creer catégorie ASSOCIATIF sans LCB_FT réussit (pas de contrainte)")
|
||||
void creer_autreCategorie_sansLbcFt_succes() {
|
||||
CreateTypeReferenceRequest request = CreateTypeReferenceRequest.builder()
|
||||
.domaine("TYPE_ORGANISATION")
|
||||
.code("ASSOC_" + UUID.randomUUID().toString().substring(0, 6))
|
||||
.libelle("Association simple")
|
||||
.categorie("ASSOCIATIF")
|
||||
.modulesRequis("COTISATIONS,EVENEMENTS")
|
||||
.organisationId(null)
|
||||
.build();
|
||||
|
||||
TypeReferenceResponse created = typeReferenceService.creer(request);
|
||||
assertThat(created).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestTransaction
|
||||
@DisplayName("modifier FINANCIER_SOLIDAIRE en retirant LCB_FT lance IllegalArgumentException")
|
||||
void modifier_financierSolidaire_suppressionLbcFt_throws() {
|
||||
TypeReferenceResponse created = typeReferenceService.creer(
|
||||
CreateTypeReferenceRequest.builder()
|
||||
.domaine("TYPE_ORGANISATION")
|
||||
.code("FS_MOD_" + UUID.randomUUID().toString().substring(0, 6))
|
||||
.libelle("Mutuelle à modifier")
|
||||
.categorie("FINANCIER_SOLIDAIRE")
|
||||
.modulesRequis("COTISATIONS,LCB_FT")
|
||||
.organisationId(null)
|
||||
.build());
|
||||
|
||||
UpdateTypeReferenceRequest update = new UpdateTypeReferenceRequest(
|
||||
null, null, null, null, null, null, null, null, null,
|
||||
null, // categorie inchangée → reste FINANCIER_SOLIDAIRE
|
||||
"COTISATIONS,EPARGNE"); // LCB_FT retiré
|
||||
|
||||
assertThatThrownBy(() -> typeReferenceService.modifier(created.getId(), update))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("LCB_FT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestTransaction
|
||||
@DisplayName("modifier FINANCIER_SOLIDAIRE sans changer modulesRequis réussit")
|
||||
void modifier_financierSolidaire_sansChangerModules_succes() {
|
||||
TypeReferenceResponse created = typeReferenceService.creer(
|
||||
CreateTypeReferenceRequest.builder()
|
||||
.domaine("TYPE_ORGANISATION")
|
||||
.code("FS_NOCHG_" + UUID.randomUUID().toString().substring(0, 5))
|
||||
.libelle("Mutuelle initiale")
|
||||
.categorie("FINANCIER_SOLIDAIRE")
|
||||
.modulesRequis("COTISATIONS,LCB_FT")
|
||||
.organisationId(null)
|
||||
.build());
|
||||
|
||||
UpdateTypeReferenceRequest update = new UpdateTypeReferenceRequest(
|
||||
null, "Mutuelle renommée", null, null, null, null, null, null, null,
|
||||
null, // categorie inchangée
|
||||
null); // modulesRequis inchangé → LCB_FT conservé en entité
|
||||
|
||||
TypeReferenceResponse updated = typeReferenceService.modifier(created.getId(), update);
|
||||
assertThat(updated.getLibelle()).isEqualTo("Mutuelle renommée");
|
||||
assertThat(updated.getModulesRequis()).contains("LCB_FT");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user