diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java index 290f811..c395606 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java @@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.domain.service; import fr.titionfire.ffsaf.data.model.*; import fr.titionfire.ffsaf.data.repository.*; +import fr.titionfire.ffsaf.rest.client.SirenService; import fr.titionfire.ffsaf.rest.client.StateIdService; import fr.titionfire.ffsaf.rest.data.SimpleAffiliation; import fr.titionfire.ffsaf.rest.data.SimpleReqAffiliation; @@ -22,6 +23,7 @@ import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; import org.hibernate.reactive.mutiny.Mutiny; import org.jboss.logging.Logger; @@ -62,9 +64,12 @@ public class AffiliationService { @Inject LoggerService ls; - @Inject + @RestClient StateIdService stateIdService; + @RestClient + SirenService sirenService; + @ConfigProperty(name = "upload_dir") String media; @@ -87,13 +92,15 @@ public class AffiliationService { throw new DBadRequestException("Saison non valid"); } })) - .chain(() -> stateIdService.get_status(affModel.getState_id()).onItem().transform(o -> { - if (o.getId_rna() != null && !o.getId_rna().isBlank()) - out.add(o.getId_rna()); - if (o.getId_siren() != null && !o.getId_siren().isBlank()) - out.add(o.getId_siren()); - if (o.getIdentite().getId_siret_siege() != null && !o.getIdentite().getId_siret_siege().isBlank()) - out.add(o.getIdentite().getId_siret_siege()); + .chain(() -> ((affModel.getState_id().charAt(0) == 'W') ? stateIdService.get_rna( + affModel.getState_id()) : sirenService.get_unite(affModel.getState_id()) + .chain(stateIdService::getAssoDataFromUnit)).onItem().transform(o -> { + if (o.getRna() != null && !o.getRna().isBlank()) + out.add(o.getRna()); + if (o.getSiren() != null && !o.getSiren().isBlank()) + out.add(o.getSiren()); + if (o.getIdentite().getSiret_siege() != null && !o.getIdentite().getSiret_siege().isBlank()) + out.add(o.getIdentite().getSiret_siege()); return out; }).onFailure().recoverWithItem(out) .chain(a -> repositoryRequest.count("state_id IN ?1 and saison = ?2", @@ -379,9 +386,10 @@ public class AffiliationService { club.setAddress(form.getAddress()); club.setContact_intern(form.getContact()); return Panache.withTransaction(() -> clubRepository.persist(club) - .chain(() -> repository.persist(new AffiliationModel(null, club, model.getSaison()))) - .chain(() -> repositoryRequest.delete(model))) - .call(() -> nameChange.get() ? keycloakService.updateGroupFromClub(club) // update group in keycloak + .chain(() -> repository.persist(new AffiliationModel(null, club, model.getSaison()))) + .chain(() -> repositoryRequest.delete(model))) + .call(() -> nameChange.get() ? keycloakService.updateGroupFromClub( + club) // update group in keycloak : Uni.createFrom().nullItem()); }) .map(__ -> club); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/AssoEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/AssoEndpoints.java index 118124b..42b8956 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/AssoEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/AssoEndpoints.java @@ -1,26 +1,31 @@ package fr.titionfire.ffsaf.rest; +import fr.titionfire.ffsaf.rest.client.SirenService; import fr.titionfire.ffsaf.rest.client.StateIdService; import fr.titionfire.ffsaf.rest.data.AssoData; import fr.titionfire.ffsaf.rest.exception.DNotFoundException; import io.smallrye.mutiny.Uni; -import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("api/asso") public class AssoEndpoints { - @Inject + @RestClient StateIdService stateIdService; + @RestClient + SirenService sirenService; + @GET @Path("state_id/{stateId}") @Produces(MediaType.APPLICATION_JSON) @Operation(hidden = true) public Uni getAssoInfo(@PathParam("stateId") String stateId) { - return stateIdService.get_status(stateId).onFailure().transform(throwable -> { + return ((stateId.charAt(0) == 'W') ? stateIdService.get_rna(stateId) : sirenService.get_unite( + stateId).chain(stateIdService::getAssoDataFromUnit)).onFailure().transform(throwable -> { if (throwable instanceof WebApplicationException exception) { if (exception.getResponse().getStatus() == 404) return new DNotFoundException("Service momentanément indisponible"); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/client/SirenService.java b/src/main/java/fr/titionfire/ffsaf/rest/client/SirenService.java new file mode 100644 index 0000000..d52bc6a --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/rest/client/SirenService.java @@ -0,0 +1,21 @@ +package fr.titionfire.ffsaf.rest.client; + +import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot; +import io.quarkus.cache.CacheResult; +import io.smallrye.mutiny.Uni; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@Path("/") +@RegisterRestClient +@ClientHeaderParam(name = "X-Client-Secret", value = "${siren-api.key}") +public interface SirenService { + + @GET + @Path("/v3/unites_legales/{SIREN}") + @CacheResult(cacheName = "AssoData_siren") + Uni get_unite(@PathParam("SIREN") String siren); +} \ No newline at end of file diff --git a/src/main/java/fr/titionfire/ffsaf/rest/client/StateIdService.java b/src/main/java/fr/titionfire/ffsaf/rest/client/StateIdService.java index 69985bf..44a74e3 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/client/StateIdService.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/client/StateIdService.java @@ -1,21 +1,48 @@ package fr.titionfire.ffsaf.rest.client; import fr.titionfire.ffsaf.rest.data.AssoData; +import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot; +import io.quarkus.cache.CacheResult; import io.smallrye.mutiny.Uni; -import jakarta.enterprise.context.ApplicationScoped; -import org.apache.commons.lang3.NotImplementedException; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; -// @Path("/") -// @RegisterRestClient -@ApplicationScoped -public class StateIdService { +@Path("/") +@RegisterRestClient +public interface StateIdService { - /*@GET - @Path("/structure/{id}") - @CacheResult(cacheName = "AssoData_status") - Uni get_status(@PathParam("id") String id);*/ + @GET + @Path("/associations/{rna}") + @CacheResult(cacheName = "AssoData_rna") + Uni get_rna(@PathParam("rna") String rna); - public Uni get_status(String id){ - return Uni.createFrom().failure(new NotImplementedException()); + default Uni getAssoDataFromUnit(UniteLegaleRoot u) { + AssoData assoData = new AssoData(); + assoData.setSiren(u.getUnite_legale().getSiren()); + assoData.setRna(u.getUnite_legale().getIdentifiant_association()); + + AssoData.Identite identite = new AssoData.Identite(); + identite.setNom(u.getUnite_legale().getDenomination()); + identite.setSiret_siege(u.getUnite_legale().getEtablissement_siege().getSiret()); + assoData.setIdentite(identite); + + AssoData.Address address = new AssoData.Address(); + StringBuilder voie = new StringBuilder(); + if (u.getUnite_legale().getEtablissement_siege().getNumero_voie() != null) + voie.append(u.getUnite_legale().getEtablissement_siege().getNumero_voie()).append(' '); + if (u.getUnite_legale().getEtablissement_siege().getType_voie() != null) + voie.append(u.getUnite_legale().getEtablissement_siege().getType_voie()).append(' '); + if (u.getUnite_legale().getEtablissement_siege().getLibelle_voie() != null) + voie.append(u.getUnite_legale().getEtablissement_siege().getLibelle_voie()).append(' '); + address.setVoie(voie.toString().trim()); + address.setComplement(u.getUnite_legale().getEtablissement_siege().getComplement_adresse()); + address.setCode_postal(u.getUnite_legale().getEtablissement_siege().getCode_postal()); + address.setCommune( + new AssoData.Commune(u.getUnite_legale().getEtablissement_siege().getLibelle_commune())); + assoData.setCoordonnees(new AssoData.Coordonnee(address)); + + return Uni.createFrom().item(assoData); } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/data/AssoData.java b/src/main/java/fr/titionfire/ffsaf/rest/data/AssoData.java index 4bb71fb..d9c0844 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/data/AssoData.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/data/AssoData.java @@ -1,13 +1,15 @@ package fr.titionfire.ffsaf.rest.data; import io.quarkus.runtime.annotations.RegisterForReflection; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; @Data @RegisterForReflection public class AssoData { - String id_siren; - String id_rna; + String siren; + String rna; Identite identite; Coordonnee coordonnees; @@ -15,25 +17,32 @@ public class AssoData { @RegisterForReflection public static class Identite { String nom; - String id_siret_siege; + String siret_siege; } @Data @RegisterForReflection + @NoArgsConstructor + @AllArgsConstructor public static class Coordonnee { - Address adresse_siege; + Address adresse_gestion; } @Data @RegisterForReflection public static class Address { - String cplt_1; - String cplt_2; - String cplt_3; - String num_voie; - String type_voie; String voie; - String cp; - String commune; + String complement; + String code_postal; + String pays; + Commune commune; + } + + @Data + @RegisterForReflection + @NoArgsConstructor + @AllArgsConstructor + public static class Commune { + String nom; } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/data/UniteLegaleRoot.java b/src/main/java/fr/titionfire/ffsaf/rest/data/UniteLegaleRoot.java new file mode 100644 index 0000000..ab72ad4 --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/rest/data/UniteLegaleRoot.java @@ -0,0 +1,107 @@ +package fr.titionfire.ffsaf.rest.data; + +import io.quarkus.runtime.annotations.RegisterForReflection; +import lombok.Data; + +import java.util.ArrayList; +import java.util.Date; + +@Data +@RegisterForReflection +public class UniteLegaleRoot { + public UniteLegale unite_legale; + + @Data + @RegisterForReflection + public static class UniteLegale { + public String activite_principale; + public Object annee_categorie_entreprise; + public Object annee_effectifs; + public Object caractere_employeur; + public Object categorie_entreprise; + public String categorie_juridique; + public String date_creation; + public String date_debut; + public Date date_dernier_traitement; + public String denomination; + public Object denomination_usuelle_1; + public Object denomination_usuelle_2; + public Object denomination_usuelle_3; + public String economie_sociale_solidaire; + public Etablissement etablissement_siege; + public ArrayList etablissements; + public String etat_administratif; + public String identifiant_association; + public String nic_siege; + public String nom; + public String nom_usage; + public int nombre_periodes; + public String nomenclature_activite_principale; + public Object prenom_1; + public Object prenom_2; + public Object prenom_3; + public Object prenom_4; + public Object prenom_usuel; + public Object pseudonyme; + public Object sexe; + public Object sigle; + public String siren; + public String societe_mission; + public String statut_diffusion; + public Object tranche_effectifs; + public Object unite_purgee; + } + + @Data + @RegisterForReflection + public static class Etablissement { + private String activite_principale; + private Object activite_principale_registre_metiers; + private Object annee_effectifs; + private String caractere_employeur; + private Object code_cedex; + private Object code_cedex_2; + private String code_commune; + private Object code_commune_2; + private Object code_pays_etranger; + private Object code_pays_etranger_2; + private String code_postal; + private Object code_postal_2; + private String complement_adresse; + private Object complement_adresse2; + private String date_creation; + private String date_debut; + private Date date_dernier_traitement; + private Object denomination_usuelle; + private Object distribution_speciale; + private Object distribution_speciale_2; + private Object enseigne_1; + private Object enseigne_2; + private Object enseigne_3; + private boolean etablissement_siege; + private String etat_administratif; + private Object indice_repetition; + private Object indice_repetition_2; + private Object libelle_cedex; + private Object libelle_cedex_2; + private String libelle_commune; + private Object libelle_commune_2; + private Object libelle_commune_etranger; + private Object libelle_commune_etranger_2; + private Object libelle_pays_etranger; + private Object libelle_pays_etranger_2; + private String libelle_voie; + private Object libelle_voie_2; + private String nic; + private int nombre_periodes; + private String nomenclature_activite_principale; + private String numero_voie; + private Object numero_voie_2; + private String siren; + private String siret; + private String statut_diffusion; + private Object tranche_effectifs; + private String type_voie; + private Object type_voie_2; + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 387faeb..984ee85 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -41,7 +41,9 @@ database.pass= notif.affRequest.mail= -quarkus.rest-client."fr.titionfire.ffsaf.rest.client.StateIdService".url=https://siva-int.menjes.ate.info/apim/api-asso/api/ +siren-api.key=siren-ap +quarkus.rest-client."fr.titionfire.ffsaf.rest.client.SirenService".url=https://data.siren-api.fr/ +quarkus.rest-client."fr.titionfire.ffsaf.rest.client.StateIdService".url=https://www.data-asso.fr/api/ #Login quarkus.oidc.token-state-manager.split-tokens=true diff --git a/src/main/webapp/src/pages/DemandeAff.jsx b/src/main/webapp/src/pages/DemandeAff.jsx index 90f08f4..bdd2b0a 100644 --- a/src/main/webapp/src/pages/DemandeAff.jsx +++ b/src/main/webapp/src/pages/DemandeAff.jsx @@ -3,7 +3,7 @@ import {apiAxios, errFormater, getSaison} from "../utils/Tools.js"; import {toast} from "react-toastify"; import {useLocation, useNavigate} from "react-router-dom"; -const notUpperCase = ["de", "la", "le", "les", "des", "du", "d'", "l'", "sur"]; +const notUpperCase = ["de", "la", "le", "les", "des", "du", "d'", "l'", "sur", 'lieu', 'dit']; function formatAdresse(data) { const words = data.split(" "); @@ -19,23 +19,14 @@ function formatAdresse(data) { function reconstruireAdresse2(infos) { let adresseReconstruite = ""; - if (infos?.cplt_1) { - adresseReconstruite += formatAdresse(infos.cplt_1) + ', '; - } - if (infos?.cplt_2) { - adresseReconstruite += formatAdresse(infos.cplt_2) + ', '; - } - if (infos?.cplt_3) { - adresseReconstruite += formatAdresse(infos.cplt_3) + ', '; - } + if (infos?.complement) + adresseReconstruite += formatAdresse(infos.complement) + ', '; - if (infos?.num_voie) { - adresseReconstruite += infos.num_voie + ' '; - } - - adresseReconstruite += formatAdresse(infos.type_voie) + ' '; adresseReconstruite += formatAdresse(infos.voie) + ', '; - adresseReconstruite += infos.cp + ' ' + infos.commune + ', '; + adresseReconstruite += infos.code_postal + ' ' + infos.commune.nom + ', '; + + if (infos?.pays) + adresseReconstruite += formatAdresse(infos.pays) + ', '; if (adresseReconstruite.endsWith(', ')) { adresseReconstruite = adresseReconstruite.slice(0, -2); @@ -221,14 +212,18 @@ function AssoInfo({initData, needFile}) { const [contact, setContact] = useState(initData.contact ? initData.contact : "") const fetchStateId = () => { - const regex = /^(?:\d{14}|W?\d{9})$/; + const regex = /^(?:\d{14}|W\d{9})$/; + let sid = stateId; if (!regex.test(stateId)) { toast.error("Le format du SIRET/RNA est invalide"); return; + }else{ + if (stateId[0] !== 'W') + sid = stateId.substring(0, 9); // Pour les SIRET, on ne garde que les 9 premiers chiffres (SIREN) } toast.promise( - apiAxios.get(`asso/state_id/${stateId}`), + apiAxios.get(`asso/state_id/${sid}`), { pending: "Recherche de l'association en cours", success: "Association trouvée avec succès 🎉", @@ -242,7 +237,7 @@ function AssoInfo({initData, needFile}) { const data2 = data.data setDenomination(data2.identite.nom) if (!initData.saison || adresse === "") - setAdresse(reconstruireAdresse2(data2.coordonnees.adresse_siege)) + setAdresse(reconstruireAdresse2(data2.coordonnees.adresse_gestion)) }) } return <> @@ -260,11 +255,11 @@ function AssoInfo({initData, needFile}) { setStateId(e.target.value)}/> -