Configure Maven repository for unionflow-server-api dependency
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AdhesionDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service REST client pour la gestion des adhésions
|
||||
* Interface correspondant exactement au backend AdhesionResource
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/adhesions")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface AdhesionService {
|
||||
|
||||
/**
|
||||
* Récupère toutes les adhésions avec pagination
|
||||
*/
|
||||
@GET
|
||||
List<AdhesionDTO> listerToutes(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère une adhésion par son ID
|
||||
*/
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
AdhesionDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
/**
|
||||
* Récupère une adhésion par son numéro de référence
|
||||
*/
|
||||
@GET
|
||||
@Path("/reference/{numeroReference}")
|
||||
AdhesionDTO obtenirParReference(@PathParam("numeroReference") String numeroReference);
|
||||
|
||||
/**
|
||||
* Crée une nouvelle adhésion
|
||||
*/
|
||||
@POST
|
||||
AdhesionDTO creer(AdhesionDTO adhesion);
|
||||
|
||||
/**
|
||||
* Met à jour une adhésion existante
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
AdhesionDTO modifier(@PathParam("id") UUID id, AdhesionDTO adhesion);
|
||||
|
||||
/**
|
||||
* Supprime une adhésion
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
/**
|
||||
* Approuve une adhésion
|
||||
*/
|
||||
@POST
|
||||
@Path("/{id}/approuver")
|
||||
AdhesionDTO approuver(
|
||||
@PathParam("id") UUID id,
|
||||
@QueryParam("approuvePar") String approuvePar
|
||||
);
|
||||
|
||||
/**
|
||||
* Rejette une adhésion
|
||||
*/
|
||||
@POST
|
||||
@Path("/{id}/rejeter")
|
||||
AdhesionDTO rejeter(
|
||||
@PathParam("id") UUID id,
|
||||
@QueryParam("motifRejet") String motifRejet
|
||||
);
|
||||
|
||||
/**
|
||||
* Enregistre un paiement pour une adhésion
|
||||
*/
|
||||
@POST
|
||||
@Path("/{id}/paiement")
|
||||
AdhesionDTO enregistrerPaiement(
|
||||
@PathParam("id") UUID id,
|
||||
@QueryParam("montantPaye") BigDecimal montantPaye,
|
||||
@QueryParam("methodePaiement") String methodePaiement,
|
||||
@QueryParam("referencePaiement") String referencePaiement
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les adhésions d'un membre
|
||||
*/
|
||||
@GET
|
||||
@Path("/membre/{membreId}")
|
||||
List<AdhesionDTO> obtenirParMembre(
|
||||
@PathParam("membreId") UUID membreId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les adhésions d'une organisation
|
||||
*/
|
||||
@GET
|
||||
@Path("/organisation/{organisationId}")
|
||||
List<AdhesionDTO> obtenirParOrganisation(
|
||||
@PathParam("organisationId") UUID organisationId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les adhésions par statut
|
||||
*/
|
||||
@GET
|
||||
@Path("/statut/{statut}")
|
||||
List<AdhesionDTO> obtenirParStatut(
|
||||
@PathParam("statut") String statut,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les adhésions en attente
|
||||
*/
|
||||
@GET
|
||||
@Path("/en-attente")
|
||||
List<AdhesionDTO> obtenirEnAttente(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les statistiques des adhésions
|
||||
*/
|
||||
@GET
|
||||
@Path("/stats")
|
||||
Map<String, Object> obtenirStatistiques();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AnalyticsDataDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/v1/analytics")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface AnalyticsService {
|
||||
|
||||
@GET
|
||||
@Path("/metriques/{typeMetrique}")
|
||||
AnalyticsDataDTO calculerMetrique(
|
||||
@PathParam("typeMetrique") String typeMetrique,
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/tendances/{typeMetrique}")
|
||||
Map<String, Object> calculerTendanceKPI(
|
||||
@PathParam("typeMetrique") String typeMetrique,
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/kpis")
|
||||
Map<String, Object> obtenirTousLesKPI(
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/evolutions")
|
||||
Map<String, Object> obtenirEvolutionsKPI(
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/performance-globale")
|
||||
Map<String, Object> calculerPerformanceGlobale(
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/dashboard/widgets")
|
||||
List<Map<String, Object>> obtenirWidgetsTableauBord(
|
||||
@QueryParam("organisationId") String organisationId,
|
||||
@QueryParam("utilisateurId") String utilisateurId
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/organisations")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface AssociationService {
|
||||
|
||||
@GET
|
||||
List<AssociationDTO> listerToutes(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("1000") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
AssociationDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/recherche")
|
||||
List<AssociationDTO> rechercher(
|
||||
@QueryParam("nom") String nom,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("region") String region,
|
||||
@QueryParam("ville") String ville,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/type/{type}")
|
||||
List<AssociationDTO> listerParType(@PathParam("type") String type);
|
||||
|
||||
@GET
|
||||
@Path("/region/{region}")
|
||||
List<AssociationDTO> listerParRegion(@PathParam("region") String region);
|
||||
|
||||
@POST
|
||||
AssociationDTO creer(AssociationDTO association);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
AssociationDTO modifier(@PathParam("id") UUID id, AssociationDTO association);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
// Côté serveur: POST /{id}/activer
|
||||
@POST
|
||||
@Path("/{id}/activer")
|
||||
AssociationDTO activer(@PathParam("id") UUID id);
|
||||
|
||||
// Suspension: POST /{id}/suspendre (alias historique "désactiver")
|
||||
@POST
|
||||
@Path("/{id}/suspendre")
|
||||
AssociationDTO suspendre(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/dissoudre")
|
||||
AssociationDTO dissoudre(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/statistiques")
|
||||
StatistiquesAssociationDTO obtenirStatistiques();
|
||||
|
||||
@GET
|
||||
@Path("/{id}/membres/count")
|
||||
Long compterMembres(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/{id}/performance")
|
||||
PerformanceAssociationDTO obtenirPerformance(@PathParam("id") UUID id);
|
||||
|
||||
// Classes DTO internes
|
||||
class StatistiquesAssociationDTO {
|
||||
public Long totalAssociations;
|
||||
public Long associationsActives;
|
||||
public Long associationsInactives;
|
||||
public Long associationsSuspendues;
|
||||
public Long associationsDissoutes;
|
||||
public Long nouvellesAssociations30Jours;
|
||||
public Double tauxActivite;
|
||||
public java.util.Map<String, Long> repartitionParType;
|
||||
public java.util.Map<String, Long> repartitionParRegion;
|
||||
|
||||
// Constructeurs
|
||||
public StatistiquesAssociationDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public Long getTotalAssociations() { return totalAssociations; }
|
||||
public void setTotalAssociations(Long totalAssociations) { this.totalAssociations = totalAssociations; }
|
||||
|
||||
public Long getAssociationsActives() { return associationsActives; }
|
||||
public void setAssociationsActives(Long associationsActives) { this.associationsActives = associationsActives; }
|
||||
|
||||
public Long getAssociationsInactives() { return associationsInactives; }
|
||||
public void setAssociationsInactives(Long associationsInactives) { this.associationsInactives = associationsInactives; }
|
||||
|
||||
public Long getAssociationsSuspendues() { return associationsSuspendues; }
|
||||
public void setAssociationsSuspendues(Long associationsSuspendues) { this.associationsSuspendues = associationsSuspendues; }
|
||||
|
||||
public Long getAssociationsDissoutes() { return associationsDissoutes; }
|
||||
public void setAssociationsDissoutes(Long associationsDissoutes) { this.associationsDissoutes = associationsDissoutes; }
|
||||
|
||||
public Long getNouvellesAssociations30Jours() { return nouvellesAssociations30Jours; }
|
||||
public void setNouvellesAssociations30Jours(Long nouvellesAssociations30Jours) { this.nouvellesAssociations30Jours = nouvellesAssociations30Jours; }
|
||||
|
||||
public Double getTauxActivite() { return tauxActivite; }
|
||||
public void setTauxActivite(Double tauxActivite) { this.tauxActivite = tauxActivite; }
|
||||
|
||||
public java.util.Map<String, Long> getRepartitionParType() { return repartitionParType; }
|
||||
public void setRepartitionParType(java.util.Map<String, Long> repartitionParType) { this.repartitionParType = repartitionParType; }
|
||||
|
||||
public java.util.Map<String, Long> getRepartitionParRegion() { return repartitionParRegion; }
|
||||
public void setRepartitionParRegion(java.util.Map<String, Long> repartitionParRegion) { this.repartitionParRegion = repartitionParRegion; }
|
||||
}
|
||||
|
||||
class PerformanceAssociationDTO {
|
||||
public UUID associationId;
|
||||
public String nom;
|
||||
public Integer scoreGlobal;
|
||||
public Integer scoreMembres;
|
||||
public Integer scoreActivites;
|
||||
public Integer scoreFinances;
|
||||
public String tendance;
|
||||
public java.time.LocalDateTime derniereMiseAJour;
|
||||
|
||||
// Constructeurs
|
||||
public PerformanceAssociationDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public UUID getAssociationId() { return associationId; }
|
||||
public void setAssociationId(UUID associationId) { this.associationId = associationId; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public Integer getScoreGlobal() { return scoreGlobal; }
|
||||
public void setScoreGlobal(Integer scoreGlobal) { this.scoreGlobal = scoreGlobal; }
|
||||
|
||||
public Integer getScoreMembres() { return scoreMembres; }
|
||||
public void setScoreMembres(Integer scoreMembres) { this.scoreMembres = scoreMembres; }
|
||||
|
||||
public Integer getScoreActivites() { return scoreActivites; }
|
||||
public void setScoreActivites(Integer scoreActivites) { this.scoreActivites = scoreActivites; }
|
||||
|
||||
public Integer getScoreFinances() { return scoreFinances; }
|
||||
public void setScoreFinances(Integer scoreFinances) { this.scoreFinances = scoreFinances; }
|
||||
|
||||
public String getTendance() { return tendance; }
|
||||
public void setTendance(String tendance) { this.tendance = tendance; }
|
||||
|
||||
public java.time.LocalDateTime getDerniereMiseAJour() { return derniereMiseAJour; }
|
||||
public void setDerniereMiseAJour(java.time.LocalDateTime derniereMiseAJour) { this.derniereMiseAJour = derniereMiseAJour; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AuditLogDTO;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.Map;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
/**
|
||||
* Service REST client pour la gestion des logs d'audit
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
*/
|
||||
@RegisterRestClient(baseUri = "http://localhost:8085")
|
||||
@RegisterClientHeaders
|
||||
@Path("/api/audit")
|
||||
public interface AuditService {
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Map<String, Object> listerTous(
|
||||
@QueryParam("page") int page,
|
||||
@QueryParam("size") int size,
|
||||
@QueryParam("sortBy") String sortBy,
|
||||
@QueryParam("sortOrder") String sortOrder);
|
||||
|
||||
@POST
|
||||
@Path("/rechercher")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Map<String, Object> rechercher(
|
||||
@QueryParam("dateDebut") String dateDebut,
|
||||
@QueryParam("dateFin") String dateFin,
|
||||
@QueryParam("typeAction") String typeAction,
|
||||
@QueryParam("severite") String severite,
|
||||
@QueryParam("utilisateur") String utilisateur,
|
||||
@QueryParam("module") String module,
|
||||
@QueryParam("ipAddress") String ipAddress,
|
||||
@QueryParam("page") int page,
|
||||
@QueryParam("size") int size);
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
AuditLogDTO enregistrerLog(AuditLogDTO dto);
|
||||
|
||||
@GET
|
||||
@Path("/statistiques")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Map<String, Object> getStatistiques();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.auth.LoginRequest;
|
||||
import dev.lions.unionflow.client.dto.auth.LoginResponse;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ApplicationScoped
|
||||
public class AuthenticationService {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(AuthenticationService.class.getName());
|
||||
|
||||
@ConfigProperty(name = "unionflow.backend.url", defaultValue = "http://localhost:8080")
|
||||
String backendUrl;
|
||||
|
||||
private final Client client;
|
||||
|
||||
public AuthenticationService() {
|
||||
this.client = ClientBuilder.newClient();
|
||||
}
|
||||
|
||||
public LoginResponse authenticate(LoginRequest loginRequest) {
|
||||
try {
|
||||
String endpoint = backendUrl + "/api/auth/login";
|
||||
|
||||
LOGGER.info("Tentative d'authentification vers: " + endpoint);
|
||||
|
||||
Response response = client.target(endpoint)
|
||||
.request(MediaType.APPLICATION_JSON)
|
||||
.post(Entity.entity(loginRequest, MediaType.APPLICATION_JSON));
|
||||
|
||||
if (response.getStatus() == 200) {
|
||||
LoginResponse loginResponse = response.readEntity(LoginResponse.class);
|
||||
LOGGER.info("Authentification réussie pour l'utilisateur: " + loginRequest.getUsername());
|
||||
return loginResponse;
|
||||
} else {
|
||||
LOGGER.warning("Échec de l'authentification. Code de statut: " + response.getStatus());
|
||||
throw new AuthenticationException("Nom d'utilisateur ou mot de passe incorrect");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'authentification: " + e.getMessage());
|
||||
|
||||
// Mode simulation pour le développement
|
||||
if ("demo".equals(loginRequest.getUsername()) || isValidDemoCredentials(loginRequest)) {
|
||||
return createDemoLoginResponse(loginRequest);
|
||||
}
|
||||
|
||||
throw new AuthenticationException("Erreur de connexion au serveur d'authentification");
|
||||
}
|
||||
}
|
||||
|
||||
public LoginResponse refreshToken(String refreshToken) {
|
||||
try {
|
||||
String endpoint = backendUrl + "/api/auth/refresh";
|
||||
|
||||
Response response = client.target(endpoint)
|
||||
.request(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "Bearer " + refreshToken)
|
||||
.post(Entity.text(""));
|
||||
|
||||
if (response.getStatus() == 200) {
|
||||
return response.readEntity(LoginResponse.class);
|
||||
} else {
|
||||
throw new AuthenticationException("Token de rafraîchissement invalide");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du rafraîchissement du token: " + e.getMessage());
|
||||
throw new AuthenticationException("Erreur lors du rafraîchissement du token");
|
||||
}
|
||||
}
|
||||
|
||||
public void logout(String accessToken) {
|
||||
try {
|
||||
String endpoint = backendUrl + "/api/auth/logout";
|
||||
|
||||
client.target(endpoint)
|
||||
.request()
|
||||
.header("Authorization", "Bearer " + accessToken)
|
||||
.post(Entity.text(""));
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors de la déconnexion: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidDemoCredentials(LoginRequest request) {
|
||||
return ("admin".equals(request.getUsername()) && "admin".equals(request.getPassword())) ||
|
||||
("superadmin".equals(request.getUsername()) && "admin".equals(request.getPassword())) ||
|
||||
("membre".equals(request.getUsername()) && "membre".equals(request.getPassword()));
|
||||
}
|
||||
|
||||
private LoginResponse createDemoLoginResponse(LoginRequest request) {
|
||||
LoginResponse.UserInfo userInfo = new LoginResponse.UserInfo();
|
||||
|
||||
// UUIDs fixes pour la démonstration (pour cohérence entre les sessions)
|
||||
UUID superAdminId = UUID.fromString("00000000-0000-0000-0000-000000000001");
|
||||
UUID adminId = UUID.fromString("00000000-0000-0000-0000-000000000002");
|
||||
UUID membreId = UUID.fromString("00000000-0000-0000-0000-000000000003");
|
||||
UUID entiteId = UUID.fromString("00000000-0000-0000-0000-000000000010");
|
||||
|
||||
switch (request.getUsername()) {
|
||||
case "superadmin":
|
||||
userInfo.setId(superAdminId);
|
||||
userInfo.setNom("Diallo");
|
||||
userInfo.setPrenom("Amadou");
|
||||
userInfo.setEmail("amadou.diallo@unionflow.sn");
|
||||
userInfo.setUsername("superadmin");
|
||||
userInfo.setTypeCompte("SUPER_ADMIN");
|
||||
userInfo.setRoles(java.util.Arrays.asList("SUPER_ADMIN", "ADMIN"));
|
||||
break;
|
||||
|
||||
case "admin":
|
||||
userInfo.setId(adminId);
|
||||
userInfo.setNom("Traoré");
|
||||
userInfo.setPrenom("Fatou");
|
||||
userInfo.setEmail("fatou.traore@association-example.sn");
|
||||
userInfo.setUsername("admin");
|
||||
userInfo.setTypeCompte("ADMIN_ENTITE");
|
||||
userInfo.setRoles(java.util.Arrays.asList("ADMIN_ENTITE"));
|
||||
|
||||
// Entité de démonstration
|
||||
LoginResponse.EntiteInfo entite = new LoginResponse.EntiteInfo();
|
||||
entite.setId(entiteId);
|
||||
entite.setNom("Association des Jeunes Entrepreneurs");
|
||||
entite.setType("Association");
|
||||
entite.setPays("Sénégal");
|
||||
entite.setVille("Dakar");
|
||||
userInfo.setEntite(entite);
|
||||
break;
|
||||
|
||||
default:
|
||||
userInfo.setId(membreId);
|
||||
userInfo.setNom("Ndiaye");
|
||||
userInfo.setPrenom("Moussa");
|
||||
userInfo.setEmail("moussa.ndiaye@exemple.sn");
|
||||
userInfo.setUsername("membre");
|
||||
userInfo.setTypeCompte("MEMBRE");
|
||||
userInfo.setRoles(java.util.Arrays.asList("MEMBRE"));
|
||||
|
||||
// Entité de démonstration
|
||||
LoginResponse.EntiteInfo entiteMembre = new LoginResponse.EntiteInfo();
|
||||
entiteMembre.setId(entiteId);
|
||||
entiteMembre.setNom("Association des Jeunes Entrepreneurs");
|
||||
entiteMembre.setType("Association");
|
||||
entiteMembre.setPays("Sénégal");
|
||||
entiteMembre.setVille("Dakar");
|
||||
userInfo.setEntite(entiteMembre);
|
||||
break;
|
||||
}
|
||||
|
||||
return new LoginResponse(
|
||||
"demo_access_token_" + System.currentTimeMillis(),
|
||||
"demo_refresh_token_" + System.currentTimeMillis(),
|
||||
3600L, // 1 heure
|
||||
userInfo
|
||||
);
|
||||
}
|
||||
|
||||
public static class AuthenticationException extends RuntimeException {
|
||||
public AuthenticationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AuthenticationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.CotisationDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service REST client pour la gestion des cotisations
|
||||
* Interface correspondant exactement au backend CotisationResource
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/cotisations")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface CotisationService {
|
||||
|
||||
/**
|
||||
* Récupère toutes les cotisations avec pagination
|
||||
*/
|
||||
@GET
|
||||
List<CotisationDTO> listerToutes(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère une cotisation par son ID
|
||||
*/
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
CotisationDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
/**
|
||||
* Récupère une cotisation par son numéro de référence
|
||||
*/
|
||||
@GET
|
||||
@Path("/reference/{numeroReference}")
|
||||
CotisationDTO obtenirParReference(@PathParam("numeroReference") String numeroReference);
|
||||
|
||||
/**
|
||||
* Récupère les cotisations d'un membre
|
||||
*/
|
||||
@GET
|
||||
@Path("/membre/{membreId}")
|
||||
List<CotisationDTO> obtenirParMembre(
|
||||
@PathParam("membreId") UUID membreId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les cotisations par statut
|
||||
*/
|
||||
@GET
|
||||
@Path("/statut/{statut}")
|
||||
List<CotisationDTO> obtenirParStatut(
|
||||
@PathParam("statut") String statut,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les cotisations en retard
|
||||
*/
|
||||
@GET
|
||||
@Path("/en-retard")
|
||||
List<CotisationDTO> obtenirEnRetard(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Recherche avancée de cotisations
|
||||
*/
|
||||
@GET
|
||||
@Path("/recherche")
|
||||
List<CotisationDTO> rechercher(
|
||||
@QueryParam("membreId") UUID membreId,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("typeCotisation") String typeCotisation,
|
||||
@QueryParam("annee") Integer annee,
|
||||
@QueryParam("mois") Integer mois,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère les statistiques des cotisations
|
||||
*/
|
||||
@GET
|
||||
@Path("/stats")
|
||||
Map<String, Object> obtenirStatistiques();
|
||||
|
||||
/**
|
||||
* Crée une nouvelle cotisation
|
||||
*/
|
||||
@POST
|
||||
CotisationDTO creer(CotisationDTO cotisation);
|
||||
|
||||
/**
|
||||
* Met à jour une cotisation existante
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
CotisationDTO modifier(@PathParam("id") UUID id, CotisationDTO cotisation);
|
||||
|
||||
/**
|
||||
* Supprime une cotisation
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
/**
|
||||
* Envoie des rappels de cotisations groupés à plusieurs membres (WOU/DRY)
|
||||
*
|
||||
* @param membreIds Liste des IDs des membres destinataires
|
||||
* @return Nombre de rappels envoyés
|
||||
*/
|
||||
@POST
|
||||
@Path("/rappels/groupes")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Map<String, Integer> envoyerRappelsGroupes(List<UUID> membreIds);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.DemandeAideDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/demandes-aide")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface DemandeAideService {
|
||||
|
||||
@GET
|
||||
List<DemandeAideDTO> listerToutes(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
DemandeAideDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/search")
|
||||
List<DemandeAideDTO> rechercher(
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("urgence") String urgence,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@POST
|
||||
DemandeAideDTO creer(DemandeAideDTO demande);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
DemandeAideDTO modifier(@PathParam("id") UUID id, DemandeAideDTO demande);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/approuver")
|
||||
DemandeAideDTO approuver(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/rejeter")
|
||||
DemandeAideDTO rejeter(@PathParam("id") UUID id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.EvenementDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service REST client pour la gestion des événements
|
||||
* Correspond exactement aux endpoints du backend EvenementResource
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/evenements")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface EvenementService {
|
||||
|
||||
/**
|
||||
* Liste tous les événements actifs avec pagination
|
||||
*/
|
||||
@GET
|
||||
Map<String, Object> listerTous(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size,
|
||||
@QueryParam("sort") @DefaultValue("dateDebut") String sortField,
|
||||
@QueryParam("direction") @DefaultValue("asc") String sortDirection
|
||||
);
|
||||
|
||||
/**
|
||||
* Récupère un événement par son ID
|
||||
*/
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
EvenementDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
/**
|
||||
* Crée un nouvel événement
|
||||
*/
|
||||
@POST
|
||||
EvenementDTO creer(EvenementDTO evenement);
|
||||
|
||||
/**
|
||||
* Met à jour un événement existant
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
EvenementDTO modifier(@PathParam("id") UUID id, EvenementDTO evenement);
|
||||
|
||||
/**
|
||||
* Supprime un événement
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
/**
|
||||
* Liste les événements à venir
|
||||
*/
|
||||
@GET
|
||||
@Path("/a-venir")
|
||||
Map<String, Object> listerAVenir(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("10") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Recherche d'événements avec filtres
|
||||
*/
|
||||
@GET
|
||||
@Path("/search")
|
||||
Map<String, Object> rechercher(
|
||||
@QueryParam("titre") String titre,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("dateDebut") String dateDebut,
|
||||
@QueryParam("dateFin") String dateFin,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Liste les événements par statut
|
||||
*/
|
||||
@GET
|
||||
@Path("/statut/{statut}")
|
||||
Map<String, Object> listerParStatut(
|
||||
@PathParam("statut") String statut,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Liste les événements par association
|
||||
*/
|
||||
@GET
|
||||
@Path("/association/{associationId}")
|
||||
Map<String, Object> listerParAssociation(
|
||||
@PathParam("associationId") UUID associationId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
/**
|
||||
* Compte le nombre d'événements
|
||||
*/
|
||||
@GET
|
||||
@Path("/count")
|
||||
Map<String, Object> compter();
|
||||
|
||||
/**
|
||||
* Inscrit un participant à un événement
|
||||
*/
|
||||
@POST
|
||||
@Path("/{evenementId}/participants/{membreId}")
|
||||
void inscrireParticipant(@PathParam("evenementId") UUID evenementId, @PathParam("membreId") UUID membreId);
|
||||
|
||||
/**
|
||||
* Désinscrit un participant d'un événement
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{evenementId}/participants/{membreId}")
|
||||
void desinscrireParticipant(@PathParam("evenementId") UUID evenementId, @PathParam("membreId") UUID membreId);
|
||||
|
||||
/**
|
||||
* Liste les participants d'un événement
|
||||
*/
|
||||
@GET
|
||||
@Path("/{evenementId}/participants")
|
||||
List<Map<String, Object>> listerParticipants(@PathParam("evenementId") UUID evenementId);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service REST client pour l'export des données
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/export")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface ExportClientService {
|
||||
|
||||
@GET
|
||||
@Path("/cotisations/csv")
|
||||
@Produces("text/csv")
|
||||
byte[] exporterCotisationsCSV(
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("associationId") UUID associationId
|
||||
);
|
||||
|
||||
@POST
|
||||
@Path("/cotisations/csv")
|
||||
@Produces("text/csv")
|
||||
byte[] exporterCotisationsSelectionneesCSV(List<UUID> cotisationIds);
|
||||
|
||||
@GET
|
||||
@Path("/cotisations/{cotisationId}/recu")
|
||||
@Produces("text/plain")
|
||||
byte[] genererRecu(@PathParam("cotisationId") UUID cotisationId);
|
||||
|
||||
@POST
|
||||
@Path("/cotisations/recus")
|
||||
@Produces("text/plain")
|
||||
byte[] genererRecusGroupes(List<UUID> cotisationIds);
|
||||
|
||||
@GET
|
||||
@Path("/rapport/mensuel")
|
||||
@Produces("text/plain")
|
||||
byte[] genererRapportMensuel(
|
||||
@QueryParam("annee") int annee,
|
||||
@QueryParam("mois") int mois,
|
||||
@QueryParam("associationId") UUID associationId
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.FormulaireDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/formulaires")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface FormulaireService {
|
||||
|
||||
@GET
|
||||
List<FormulaireDTO> listerTous();
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
FormulaireDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/actifs")
|
||||
List<FormulaireDTO> listerActifs();
|
||||
|
||||
@GET
|
||||
@Path("/populaires")
|
||||
List<FormulaireDTO> listerPopulaires();
|
||||
|
||||
@POST
|
||||
FormulaireDTO creer(FormulaireDTO formulaire);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
FormulaireDTO modifier(@PathParam("id") UUID id, FormulaireDTO formulaire);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/activer")
|
||||
FormulaireDTO activer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/desactiver")
|
||||
FormulaireDTO desactiver(@PathParam("id") UUID id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.jboss.resteasy.reactive.PartType;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MembreImportMultipartForm {
|
||||
@FormParam("file")
|
||||
@PartType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
public byte[] file;
|
||||
|
||||
@FormParam("fileName")
|
||||
public String fileName;
|
||||
|
||||
@FormParam("organisationId")
|
||||
public UUID organisationId;
|
||||
|
||||
@FormParam("typeMembreDefaut")
|
||||
public String typeMembreDefaut;
|
||||
|
||||
@FormParam("mettreAJourExistants")
|
||||
public boolean mettreAJourExistants;
|
||||
|
||||
@FormParam("ignorerErreurs")
|
||||
public boolean ignorerErreurs;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.MembreDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/membres")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface MembreService {
|
||||
|
||||
@GET
|
||||
List<MembreDTO> listerTous();
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
MembreDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/numero/{numeroMembre}")
|
||||
MembreDTO obtenirParNumero(@PathParam("numeroMembre") String numeroMembre);
|
||||
|
||||
@GET
|
||||
@Path("/search")
|
||||
List<MembreDTO> rechercher(
|
||||
@QueryParam("nom") String nom,
|
||||
@QueryParam("prenom") String prenom,
|
||||
@QueryParam("email") String email,
|
||||
@QueryParam("telephone") String telephone,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("associationId") UUID associationId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/association/{associationId}")
|
||||
List<MembreDTO> listerParAssociation(@PathParam("associationId") UUID associationId);
|
||||
|
||||
@GET
|
||||
@Path("/actifs")
|
||||
List<MembreDTO> listerActifs();
|
||||
|
||||
@GET
|
||||
@Path("/inactifs")
|
||||
List<MembreDTO> listerInactifs();
|
||||
|
||||
@POST
|
||||
MembreDTO creer(MembreDTO membre);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
MembreDTO modifier(@PathParam("id") UUID id, MembreDTO membre);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/activer")
|
||||
MembreDTO activer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/desactiver")
|
||||
MembreDTO desactiver(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/suspendre")
|
||||
MembreDTO suspendre(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/radier")
|
||||
MembreDTO radier(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/statistiques")
|
||||
StatistiquesMembreDTO obtenirStatistiques();
|
||||
|
||||
@GET
|
||||
@Path("/export")
|
||||
@Produces({"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "text/csv", "application/pdf", "application/json"})
|
||||
byte[] exporterExcel(
|
||||
@QueryParam("format") @DefaultValue("EXCEL") String format,
|
||||
@QueryParam("associationId") UUID associationId,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("dateAdhesionDebut") String dateAdhesionDebut,
|
||||
@QueryParam("dateAdhesionFin") String dateAdhesionFin,
|
||||
@QueryParam("colonnes") List<String> colonnesExport,
|
||||
@QueryParam("inclureHeaders") @DefaultValue("true") boolean inclureHeaders,
|
||||
@QueryParam("formaterDates") @DefaultValue("true") boolean formaterDates,
|
||||
@QueryParam("inclureStatistiques") @DefaultValue("false") boolean inclureStatistiques,
|
||||
@QueryParam("motDePasse") String motDePasse
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/export/count")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Long compterMembresPourExport(
|
||||
@QueryParam("associationId") UUID associationId,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("dateAdhesionDebut") String dateAdhesionDebut,
|
||||
@QueryParam("dateAdhesionFin") String dateAdhesionFin
|
||||
);
|
||||
|
||||
@POST
|
||||
@Path("/import")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
ResultatImportDTO importerDonnees(MembreImportMultipartForm form);
|
||||
|
||||
@GET
|
||||
@Path("/import/modele")
|
||||
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
byte[] telechargerModeleImport();
|
||||
|
||||
@GET
|
||||
@Path("/autocomplete/villes")
|
||||
List<String> obtenirVilles(@QueryParam("query") String query);
|
||||
|
||||
@GET
|
||||
@Path("/autocomplete/professions")
|
||||
List<String> obtenirProfessions(@QueryParam("query") String query);
|
||||
|
||||
@POST
|
||||
@Path("/export/selection")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
byte[] exporterSelection(
|
||||
List<UUID> membreIds,
|
||||
@QueryParam("format") @DefaultValue("EXCEL") String format);
|
||||
|
||||
// Classes DTO internes pour les réponses spécialisées
|
||||
class StatistiquesMembreDTO {
|
||||
public Long totalMembres;
|
||||
public Long membresActifs;
|
||||
public Long membresInactifs;
|
||||
public Long membresSuspendus;
|
||||
public Long membresRadies;
|
||||
public Long nouveauxMembres30Jours;
|
||||
public Double tauxActivite;
|
||||
public Double tauxCroissance;
|
||||
|
||||
// Constructeurs
|
||||
public StatistiquesMembreDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public Long getTotalMembres() { return totalMembres; }
|
||||
public void setTotalMembres(Long totalMembres) { this.totalMembres = totalMembres; }
|
||||
|
||||
public Long getMembresActifs() { return membresActifs; }
|
||||
public void setMembresActifs(Long membresActifs) { this.membresActifs = membresActifs; }
|
||||
|
||||
public Long getMembresInactifs() { return membresInactifs; }
|
||||
public void setMembresInactifs(Long membresInactifs) { this.membresInactifs = membresInactifs; }
|
||||
|
||||
public Long getMembresSuspendus() { return membresSuspendus; }
|
||||
public void setMembresSuspendus(Long membresSuspendus) { this.membresSuspendus = membresSuspendus; }
|
||||
|
||||
public Long getMembresRadies() { return membresRadies; }
|
||||
public void setMembresRadies(Long membresRadies) { this.membresRadies = membresRadies; }
|
||||
|
||||
public Long getNouveauxMembres30Jours() { return nouveauxMembres30Jours; }
|
||||
public void setNouveauxMembres30Jours(Long nouveauxMembres30Jours) { this.nouveauxMembres30Jours = nouveauxMembres30Jours; }
|
||||
|
||||
public Double getTauxActivite() { return tauxActivite; }
|
||||
public void setTauxActivite(Double tauxActivite) { this.tauxActivite = tauxActivite; }
|
||||
|
||||
public Double getTauxCroissance() { return tauxCroissance; }
|
||||
public void setTauxCroissance(Double tauxCroissance) { this.tauxCroissance = tauxCroissance; }
|
||||
}
|
||||
|
||||
class ResultatImportDTO {
|
||||
public Integer totalLignes;
|
||||
public Integer lignesTraitees;
|
||||
public Integer lignesErreur;
|
||||
public List<String> erreurs;
|
||||
public List<MembreDTO> membresImportes;
|
||||
|
||||
// Constructeurs
|
||||
public ResultatImportDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public Integer getTotalLignes() { return totalLignes; }
|
||||
public void setTotalLignes(Integer totalLignes) { this.totalLignes = totalLignes; }
|
||||
|
||||
public Integer getLignesTraitees() { return lignesTraitees; }
|
||||
public void setLignesTraitees(Integer lignesTraitees) { this.lignesTraitees = lignesTraitees; }
|
||||
|
||||
public Integer getLignesErreur() { return lignesErreur; }
|
||||
public void setLignesErreur(Integer lignesErreur) { this.lignesErreur = lignesErreur; }
|
||||
|
||||
public List<String> getErreurs() { return erreurs; }
|
||||
public void setErreurs(List<String> erreurs) { this.erreurs = erreurs; }
|
||||
|
||||
public List<MembreDTO> getMembresImportes() { return membresImportes; }
|
||||
public void setMembresImportes(List<MembreDTO> membresImportes) { this.membresImportes = membresImportes; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Service REST client pour les notifications
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/notifications")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface NotificationClientService {
|
||||
|
||||
@POST
|
||||
@Path("/groupe")
|
||||
List<Map<String, Object>> envoyerNotificationGroupe(
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("titre") String titre,
|
||||
@QueryParam("message") String message,
|
||||
List<String> destinatairesIds
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/utilisateur/{utilisateurId}")
|
||||
List<Map<String, Object>> obtenirNotifications(
|
||||
@PathParam("utilisateurId") String utilisateurId,
|
||||
@QueryParam("includeArchivees") @DefaultValue("false") boolean includeArchivees,
|
||||
@QueryParam("limite") @DefaultValue("50") int limite
|
||||
);
|
||||
|
||||
@PUT
|
||||
@Path("/{notificationId}/lue")
|
||||
Map<String, Object> marquerCommeLue(
|
||||
@PathParam("notificationId") String notificationId,
|
||||
@QueryParam("utilisateurId") String utilisateurId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/stats")
|
||||
Map<String, Long> obtenirStatistiques();
|
||||
|
||||
@POST
|
||||
@Path("/test/{utilisateurId}")
|
||||
Map<String, Object> envoyerNotificationTest(
|
||||
@PathParam("utilisateurId") String utilisateurId,
|
||||
@QueryParam("type") @DefaultValue("SYSTEME") String type
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service REST Client pour la gestion des notifications (WOU/DRY)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/notifications")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface NotificationService {
|
||||
|
||||
/**
|
||||
* Envoie des notifications groupées à plusieurs membres (WOU/DRY)
|
||||
*
|
||||
* @param request DTO contenant les IDs des membres, sujet, corps et canaux
|
||||
* @return Nombre de notifications créées
|
||||
*/
|
||||
@POST
|
||||
@Path("/groupees")
|
||||
Map<String, Integer> envoyerNotificationsGroupees(NotificationGroupeeRequest request);
|
||||
|
||||
/**
|
||||
* Classe interne pour les requêtes de notifications groupées (WOU/DRY)
|
||||
*/
|
||||
class NotificationGroupeeRequest {
|
||||
public List<UUID> membreIds;
|
||||
public String sujet;
|
||||
public String corps;
|
||||
public List<String> canaux;
|
||||
|
||||
public NotificationGroupeeRequest() {}
|
||||
|
||||
public NotificationGroupeeRequest(List<UUID> membreIds, String sujet, String corps, List<String> canaux) {
|
||||
this.membreIds = membreIds;
|
||||
this.sujet = sujet;
|
||||
this.corps = corps;
|
||||
this.canaux = canaux;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/preferences")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface PreferencesService {
|
||||
|
||||
@GET
|
||||
@Path("/{utilisateurId}")
|
||||
Map<String, Boolean> obtenirPreferences(@PathParam("utilisateurId") UUID utilisateurId);
|
||||
|
||||
@PUT
|
||||
@Path("/{utilisateurId}")
|
||||
void mettreAJourPreferences(
|
||||
@PathParam("utilisateurId") UUID utilisateurId,
|
||||
Map<String, Boolean> preferences
|
||||
);
|
||||
|
||||
@POST
|
||||
@Path("/{utilisateurId}/reinitialiser")
|
||||
void reinitialiserPreferences(@PathParam("utilisateurId") UUID utilisateurId);
|
||||
|
||||
@GET
|
||||
@Path("/{utilisateurId}/export")
|
||||
Map<String, Object> exporterPreferences(@PathParam("utilisateurId") UUID utilisateurId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class RestClientExceptionMapper implements ResponseExceptionMapper<RuntimeException> {
|
||||
|
||||
@Override
|
||||
public RuntimeException toThrowable(Response response) {
|
||||
int status = response.getStatus();
|
||||
String reasonPhrase = response.getStatusInfo().getReasonPhrase();
|
||||
|
||||
// Lire le corps de la réponse pour plus de détails
|
||||
String body = "";
|
||||
try {
|
||||
if (response.hasEntity()) {
|
||||
body = response.readEntity(String.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
body = "Impossible de lire le détail de l'erreur";
|
||||
}
|
||||
|
||||
return switch (status) {
|
||||
case 400 -> new BadRequestException("Requête invalide: " + body);
|
||||
case 401 -> new UnauthorizedException("Non autorisé: " + reasonPhrase);
|
||||
case 403 -> new ForbiddenException("Accès interdit: " + reasonPhrase);
|
||||
case 404 -> new NotFoundException("Ressource non trouvée: " + reasonPhrase);
|
||||
case 409 -> new ConflictException("Conflit: " + body);
|
||||
case 422 -> new UnprocessableEntityException("Données non valides: " + body);
|
||||
case 500 -> new InternalServerErrorException("Erreur serveur interne: " + body);
|
||||
case 502 -> new BadGatewayException("Erreur de passerelle: " + reasonPhrase);
|
||||
case 503 -> new ServiceUnavailableException("Service indisponible: " + reasonPhrase);
|
||||
case 504 -> new GatewayTimeoutException("Timeout de passerelle: " + reasonPhrase);
|
||||
default -> new UnknownHttpStatusException("Erreur HTTP " + status + ": " + reasonPhrase + (body.isEmpty() ? "" : " - " + body));
|
||||
};
|
||||
}
|
||||
|
||||
// Classes d'exception personnalisées
|
||||
public static class BadRequestException extends RuntimeException {
|
||||
public BadRequestException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class UnauthorizedException extends RuntimeException {
|
||||
public UnauthorizedException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class ForbiddenException extends RuntimeException {
|
||||
public ForbiddenException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class NotFoundException extends RuntimeException {
|
||||
public NotFoundException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class ConflictException extends RuntimeException {
|
||||
public ConflictException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class UnprocessableEntityException extends RuntimeException {
|
||||
public UnprocessableEntityException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class InternalServerErrorException extends RuntimeException {
|
||||
public InternalServerErrorException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class BadGatewayException extends RuntimeException {
|
||||
public BadGatewayException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class ServiceUnavailableException extends RuntimeException {
|
||||
public ServiceUnavailableException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class GatewayTimeoutException extends RuntimeException {
|
||||
public GatewayTimeoutException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class UnknownHttpStatusException extends RuntimeException {
|
||||
public UnknownHttpStatusException(String message) { super(message); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.SouscriptionDTO;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/souscriptions")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface SouscriptionService {
|
||||
|
||||
@GET
|
||||
List<SouscriptionDTO> listerToutes(
|
||||
@QueryParam("organisationId") UUID organisationId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
SouscriptionDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/organisation/{organisationId}/active")
|
||||
SouscriptionDTO obtenirActive(@PathParam("organisationId") UUID organisationId);
|
||||
|
||||
@POST
|
||||
SouscriptionDTO creer(SouscriptionDTO souscription);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
SouscriptionDTO modifier(@PathParam("id") UUID id, SouscriptionDTO souscription);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/renouveler")
|
||||
SouscriptionDTO renouveler(@PathParam("id") UUID id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.TypeOrganisationClientDTO;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
/**
|
||||
* REST client pour le catalogue des types d'organisation.
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/types-organisations")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface TypeOrganisationClientService {
|
||||
|
||||
@GET
|
||||
List<TypeOrganisationClientDTO> list(@QueryParam("onlyActifs") @DefaultValue("true") boolean onlyActifs);
|
||||
|
||||
@POST
|
||||
TypeOrganisationClientDTO create(TypeOrganisationClientDTO dto);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
TypeOrganisationClientDTO update(@PathParam("id") UUID id, TypeOrganisationClientDTO dto);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void disable(@PathParam("id") UUID id);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ApplicationScoped
|
||||
public class ValidationService {
|
||||
|
||||
@Inject
|
||||
Validator validator;
|
||||
|
||||
/**
|
||||
* Valide un objet et retourne la liste des erreurs
|
||||
*/
|
||||
public <T> ValidationResult validate(T object) {
|
||||
Set<ConstraintViolation<T>> violations = validator.validate(object);
|
||||
|
||||
ValidationResult result = new ValidationResult();
|
||||
result.setValid(violations.isEmpty());
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (ConstraintViolation<T> violation : violations) {
|
||||
messages.add(violation.getPropertyPath() + ": " + violation.getMessage());
|
||||
}
|
||||
result.setErrorMessages(messages);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide une propriété spécifique d'un objet
|
||||
*/
|
||||
public <T> ValidationResult validateProperty(T object, String propertyName) {
|
||||
Set<ConstraintViolation<T>> violations = validator.validateProperty(object, propertyName);
|
||||
|
||||
ValidationResult result = new ValidationResult();
|
||||
result.setValid(violations.isEmpty());
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (ConstraintViolation<T> violation : violations) {
|
||||
messages.add(violation.getMessage());
|
||||
}
|
||||
result.setErrorMessages(messages);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide une valeur contre les contraintes d'une propriété
|
||||
*/
|
||||
public <T> ValidationResult validateValue(Class<T> beanType, String propertyName, Object value) {
|
||||
Set<ConstraintViolation<T>> violations = validator.validateValue(beanType, propertyName, value);
|
||||
|
||||
ValidationResult result = new ValidationResult();
|
||||
result.setValid(violations.isEmpty());
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (ConstraintViolation<T> violation : violations) {
|
||||
messages.add(violation.getMessage());
|
||||
}
|
||||
result.setErrorMessages(messages);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Classe pour encapsuler le résultat de validation
|
||||
*/
|
||||
public static class ValidationResult {
|
||||
private boolean valid;
|
||||
private List<String> errorMessages = new ArrayList<>();
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
public void setValid(boolean valid) {
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
public List<String> getErrorMessages() {
|
||||
return errorMessages;
|
||||
}
|
||||
|
||||
public void setErrorMessages(List<String> errorMessages) {
|
||||
this.errorMessages = errorMessages;
|
||||
}
|
||||
|
||||
public String getFirstErrorMessage() {
|
||||
return errorMessages.isEmpty() ? null : errorMessages.get(0);
|
||||
}
|
||||
|
||||
public String getAllErrorMessages() {
|
||||
return String.join(", ", errorMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.WaveCheckoutSessionDTO;
|
||||
import dev.lions.unionflow.client.dto.WaveBalanceDTO;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
/**
|
||||
* Service REST client pour l'intégration Wave Money
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-17
|
||||
*/
|
||||
@RegisterRestClient(baseUri = "http://localhost:8085")
|
||||
@Path("/api/wave")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface WaveService {
|
||||
|
||||
@POST
|
||||
@Path("/checkout/sessions")
|
||||
WaveCheckoutSessionDTO creerSessionPaiement(
|
||||
@QueryParam("montant") BigDecimal montant,
|
||||
@QueryParam("devise") String devise,
|
||||
@QueryParam("successUrl") String successUrl,
|
||||
@QueryParam("errorUrl") String errorUrl,
|
||||
@QueryParam("reference") String referenceUnionFlow,
|
||||
@QueryParam("description") String description,
|
||||
@QueryParam("organisationId") UUID organisationId,
|
||||
@QueryParam("membreId") UUID membreId);
|
||||
|
||||
@GET
|
||||
@Path("/checkout/sessions/{sessionId}")
|
||||
WaveCheckoutSessionDTO verifierStatutSession(@PathParam("sessionId") String sessionId);
|
||||
|
||||
@GET
|
||||
@Path("/balance")
|
||||
WaveBalanceDTO consulterSolde();
|
||||
|
||||
@GET
|
||||
@Path("/test")
|
||||
Map<String, Object> testerConnexion();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user