Migration du frontend React/Next.js vers Quarkus + PrimeFaces Freya 5.0.0 Dashboard: - Extension de BtpXpressApiClient avec tous les endpoints dashboard - Création de DashboardService pour récupérer les données API - Refactorisation DashboardView : uniquement données réelles de l'API - Restructuration dashboard.xhtml avec tous les aspects métiers BTP - Suppression complète de toutes les données fictives Topbar: - Amélioration du menu profil utilisateur avec header professionnel - Ajout UserSessionBean pour gérer les informations utilisateur - Styles CSS personnalisés pour une disposition raffinée - Badges de notifications conditionnels Configuration: - Intégration du thème Freya 5.0.0-jakarta - Configuration OIDC pour Keycloak (security.lions.dev) - Gestion des erreurs HTTP 431 (headers size) - Support du format Fcfa avec séparateurs d'espaces Converters: - Création de FcfaConverter pour formater les montants en Fcfa avec espaces (x xxx xxx format) Code Quality: - Code entièrement documenté en français avec Javadoc exemplaire - Respect du principe Java 'Write once, use many times' - Logging complet pour le débogage - Gestion d'erreurs robuste
312 lines
12 KiB
Java
312 lines
12 KiB
Java
package dev.lions.btpxpress.service;
|
|
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import jakarta.enterprise.context.ApplicationScoped;
|
|
import jakarta.inject.Inject;
|
|
import jakarta.ws.rs.core.Response;
|
|
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Service pour récupérer et transformer les données du dashboard depuis l'API backend.
|
|
*
|
|
* <p>Ce service encapsule tous les appels à l'API dashboard et transforme
|
|
* les réponses JSON en objets Java utilisables par les vues JSF.</p>
|
|
*
|
|
* @author BTP Xpress Team
|
|
* @version 1.0
|
|
*/
|
|
@ApplicationScoped
|
|
public class DashboardService {
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(DashboardService.class);
|
|
|
|
@Inject
|
|
@RestClient
|
|
BtpXpressApiClient apiClient;
|
|
|
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
|
/**
|
|
* Récupère les métriques du dashboard principal.
|
|
*
|
|
* @return JsonNode contenant les métriques ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getDashboardPrincipal() {
|
|
try {
|
|
Response response = apiClient.getDashboardPrincipal();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
if (entity == null) {
|
|
logger.warn("Réponse vide du dashboard principal");
|
|
return null;
|
|
}
|
|
// REST Client avec Jackson désérialise déjà en Map/Object
|
|
return convertToJsonNode(entity);
|
|
} else {
|
|
logger.error("Erreur API dashboard principal: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du dashboard principal", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convertit un objet en JsonNode, quel que soit son type (String, Map, Object, etc.).
|
|
*/
|
|
private JsonNode convertToJsonNode(Object entity) {
|
|
try {
|
|
if (entity instanceof String) {
|
|
return objectMapper.readTree((String) entity);
|
|
} else if (entity instanceof Map || entity instanceof List) {
|
|
// Map ou List sont déjà désérialisés par REST Client
|
|
return objectMapper.valueToTree(entity);
|
|
} else {
|
|
// Pour les autres objets, conversion via ObjectMapper
|
|
return objectMapper.valueToTree(entity);
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la conversion en JsonNode", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les métriques des chantiers.
|
|
*
|
|
* @return JsonNode contenant les métriques des chantiers ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getDashboardChantiers() {
|
|
try {
|
|
Response response = apiClient.getDashboardChantiers();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return convertToJsonNode(entity);
|
|
} else {
|
|
logger.error("Erreur API dashboard chantiers: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du dashboard chantiers", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les métriques financières.
|
|
*
|
|
* @param periode Période en jours (défaut: 30)
|
|
* @return JsonNode contenant les métriques financières ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getDashboardFinances(int periode) {
|
|
try {
|
|
Response response = apiClient.getDashboardFinances(periode);
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return entity instanceof String ? objectMapper.readTree((String) entity) : objectMapper.valueToTree(entity);
|
|
} else {
|
|
logger.error("Erreur API dashboard finances: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du dashboard finances", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les métriques de maintenance.
|
|
*
|
|
* @return JsonNode contenant les métriques de maintenance ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getDashboardMaintenance() {
|
|
try {
|
|
Response response = apiClient.getDashboardMaintenance();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return entity instanceof String ? objectMapper.readTree((String) entity) : objectMapper.valueToTree(entity);
|
|
} else {
|
|
logger.error("Erreur API dashboard maintenance: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du dashboard maintenance", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les métriques des ressources.
|
|
*
|
|
* @return JsonNode contenant les métriques des ressources ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getDashboardRessources() {
|
|
try {
|
|
Response response = apiClient.getDashboardRessources();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return entity instanceof String ? objectMapper.readTree((String) entity) : objectMapper.valueToTree(entity);
|
|
} else {
|
|
logger.error("Erreur API dashboard ressources: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du dashboard ressources", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les alertes.
|
|
*
|
|
* @return JsonNode contenant les alertes ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getAlertes() {
|
|
try {
|
|
Response response = apiClient.getAlertes();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return entity instanceof String ? objectMapper.readTree((String) entity) : objectMapper.valueToTree(entity);
|
|
} else {
|
|
logger.error("Erreur API alertes: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération des alertes", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les KPIs.
|
|
*
|
|
* @param periode Période en jours (défaut: 30)
|
|
* @return JsonNode contenant les KPIs ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getKPI(int periode) {
|
|
try {
|
|
Response response = apiClient.getKPI(periode);
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return entity instanceof String ? objectMapper.readTree((String) entity) : objectMapper.valueToTree(entity);
|
|
} else {
|
|
logger.error("Erreur API KPI: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération des KPIs", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les activités récentes.
|
|
*
|
|
* @param limit Nombre d'activités à récupérer
|
|
* @return JsonNode contenant les activités récentes ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getActivitesRecentes(int limit) {
|
|
try {
|
|
Response response = apiClient.getActivitesRecentes(limit);
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return entity instanceof String ? objectMapper.readTree((String) entity) : objectMapper.valueToTree(entity);
|
|
} else {
|
|
logger.error("Erreur API activités récentes: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération des activités récentes", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère le résumé quotidien.
|
|
*
|
|
* @return JsonNode contenant le résumé quotidien ou null en cas d'erreur
|
|
*/
|
|
public JsonNode getResumeQuotidien() {
|
|
try {
|
|
Response response = apiClient.getResumeQuotidien();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
Object entity = response.getEntity();
|
|
return entity instanceof String ? objectMapper.readTree((String) entity) : objectMapper.valueToTree(entity);
|
|
} else {
|
|
logger.error("Erreur API résumé quotidien: status {}", response.getStatus());
|
|
return null;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du résumé quotidien", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère le nombre de clients.
|
|
*
|
|
* @return Nombre de clients ou 0 en cas d'erreur
|
|
*/
|
|
public int getNombreClients() {
|
|
try {
|
|
Response response = apiClient.getClients();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
List<?> clients = (List<?>) response.getEntity();
|
|
return clients != null ? clients.size() : 0;
|
|
}
|
|
return 0;
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du nombre de clients", e);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère le nombre de devis en attente.
|
|
*
|
|
* @return Nombre de devis en attente ou 0 en cas d'erreur
|
|
*/
|
|
public int getNombreDevisEnAttente() {
|
|
try {
|
|
Response response = apiClient.getDevis();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
List<?> devis = (List<?>) response.getEntity();
|
|
// TODO: Filtrer par statut EN_ATTENTE si l'API le permet
|
|
return devis != null ? devis.size() : 0;
|
|
}
|
|
return 0;
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du nombre de devis", e);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère le nombre de factures impayées.
|
|
*
|
|
* @return Nombre de factures impayées ou 0 en cas d'erreur
|
|
*/
|
|
public int getNombreFacturesImpayees() {
|
|
try {
|
|
Response response = apiClient.getFactures();
|
|
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
|
|
List<?> factures = (List<?>) response.getEntity();
|
|
// TODO: Filtrer par statut IMPAYEE si l'API le permet
|
|
return factures != null ? factures.size() : 0;
|
|
}
|
|
return 0;
|
|
} catch (Exception e) {
|
|
logger.error("Erreur lors de la récupération du nombre de factures", e);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|