# 🚀 Exemple d'ImplĂ©mentation : Lazy Loading pour Factures ## 📋 Objectif Transformer la liste des factures pour utiliser le lazy loading avec pagination cĂŽtĂ© serveur. --- ## 📁 Fichiers Ă  CrĂ©er/Modifier ### 1. CrĂ©er FactureLazyDataModel.java **Chemin** : `src/main/java/dev/lions/btpxpress/view/model/FactureLazyDataModel.java` ```java package dev.lions.btpxpress.view.model; import dev.lions.btpxpress.service.FactureService; import dev.lions.btpxpress.view.FactureView.Facture; import org.primefaces.model.FilterMeta; import org.primefaces.model.LazyDataModel; import org.primefaces.model.SortMeta; import org.primefaces.model.SortOrder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; import java.util.*; public class FactureLazyDataModel extends LazyDataModel implements Serializable { private static final Logger LOG = LoggerFactory.getLogger(FactureLazyDataModel.class); private final FactureService factureService; public FactureLazyDataModel(FactureService factureService) { this.factureService = factureService; } @Override public int count(Map filterBy) { try { Map filterParams = buildFilterParams(filterBy); int count = factureService.countFactures(filterParams); LOG.debug("Count factures with filters: {}", count); return count; } catch (Exception e) { LOG.error("Erreur lors du comptage des factures", e); return 0; } } @Override public List load(int first, int pageSize, Map sortBy, Map filterBy) { try { Map params = new HashMap<>(); params.put("offset", first); params.put("limit", pageSize); // Ajouter les paramĂštres de tri if (sortBy != null && !sortBy.isEmpty()) { SortMeta sortMeta = sortBy.values().iterator().next(); params.put("sortField", sortMeta.getField()); params.put("sortOrder", sortMeta.getOrder() == SortOrder.ASCENDING ? "ASC" : "DESC"); } // Ajouter les paramĂštres de filtrage params.putAll(buildFilterParams(filterBy)); LOG.debug("Loading factures with params: {}", params); List factures = factureService.getFacturesLazy(params); LOG.debug("Loaded {} factures", factures.size()); return factures; } catch (Exception e) { LOG.error("Erreur lors du chargement des factures", e); return Collections.emptyList(); } } @Override public String getRowKey(Facture facture) { return facture.getId() != null ? facture.getId().toString() : null; } @Override public Facture getRowData(String rowKey) { // Cette mĂ©thode est appelĂ©e pour rĂ©cupĂ©rer une facture par son ID // Pour l'instant, on retourne null car on ne garde pas de cache local return null; } private Map buildFilterParams(Map filterBy) { Map params = new HashMap<>(); if (filterBy != null) { filterBy.forEach((field, filterMeta) -> { Object filterValue = filterMeta.getFilterValue(); if (filterValue != null && !filterValue.toString().trim().isEmpty()) { params.put("filter_" + field, filterValue); } }); } return params; } } ``` --- ### 2. Modifier FactureService.java **Ajouter les mĂ©thodes pour le lazy loading** : ```java package dev.lions.btpxpress.service; import dev.lions.btpxpress.view.FactureView.Facture; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @ApplicationScoped public class FactureService { private static final Logger LOG = LoggerFactory.getLogger(FactureService.class); @Inject @RestClient BtpXpressApiClient apiClient; /** * RĂ©cupĂšre les factures avec pagination et filtres */ public List getFacturesLazy(Map params) { try { int offset = (int) params.getOrDefault("offset", 0); int limit = (int) params.getOrDefault("limit", 10); String sortField = (String) params.get("sortField"); String sortOrder = (String) params.get("sortOrder"); // Extraire les filtres String filtreNumero = (String) params.get("filter_numero"); String filtreClient = (String) params.get("filter_client"); String filtreStatut = (String) params.get("filter_statut"); // Appel API (Ă  adapter selon votre backend) List> facturesData = apiClient.getFacturesLazy( offset, limit, sortField, sortOrder, filtreNumero, filtreClient, filtreStatut ); // Mapper vers les objets Facture return facturesData.stream() .map(this::mapToFacture) .collect(Collectors.toList()); } catch (Exception e) { LOG.error("Erreur lors de la rĂ©cupĂ©ration lazy des factures", e); return Collections.emptyList(); } } /** * Compte le nombre total de factures avec filtres */ public int countFactures(Map params) { try { String filtreNumero = (String) params.get("filter_numero"); String filtreClient = (String) params.get("filter_client"); String filtreStatut = (String) params.get("filter_statut"); return apiClient.countFactures(filtreNumero, filtreClient, filtreStatut); } catch (Exception e) { LOG.error("Erreur lors du comptage des factures", e); return 0; } } private Facture mapToFacture(Map data) { Facture f = new Facture(); f.setId(data.get("id") != null ? Long.valueOf(data.get("id").toString()) : null); f.setNumero((String) data.get("numero")); f.setObjet((String) data.get("objet")); // Mapping du client Object clientObj = data.get("client"); if (clientObj instanceof Map) { Map clientData = (Map) clientObj; String entreprise = (String) clientData.get("entreprise"); String nom = (String) clientData.get("nom"); String prenom = (String) clientData.get("prenom"); f.setClient(entreprise != null && !entreprise.trim().isEmpty() ? entreprise : (prenom != null ? prenom + " " : "") + (nom != null ? nom : "")); } else if (clientObj instanceof String) { f.setClient((String) clientObj); } // Mapping des dates if (data.get("dateEmission") != null) { f.setDateEmission(LocalDate.parse(data.get("dateEmission").toString())); } if (data.get("dateEcheance") != null) { f.setDateEcheance(LocalDate.parse(data.get("dateEcheance").toString())); } // Mapping des montants f.setStatut((String) data.get("statut")); f.setMontantHT(data.get("montantHT") != null ? Double.valueOf(data.get("montantHT").toString()) : 0.0); f.setMontantTTC(data.get("montantTTC") != null ? Double.valueOf(data.get("montantTTC").toString()) : 0.0); f.setMontantPaye(data.get("montantPaye") != null ? Double.valueOf(data.get("montantPaye").toString()) : 0.0); return f; } } ``` --- ### 3. Modifier BtpXpressApiClient.java **Ajouter les endpoints pour le lazy loading** : ```java package dev.lions.btpxpress.service; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; import java.util.List; import java.util.Map; @Path("/api") @RegisterRestClient(configKey = "btpxpress-api") public interface BtpXpressApiClient { // ... mĂ©thodes existantes ... @GET @Path("/factures/lazy") @Produces(MediaType.APPLICATION_JSON) List> getFacturesLazy( @QueryParam("offset") int offset, @QueryParam("limit") int limit, @QueryParam("sortField") String sortField, @QueryParam("sortOrder") String sortOrder, @QueryParam("filter_numero") String filtreNumero, @QueryParam("filter_client") String filtreClient, @QueryParam("filter_statut") String filtreStatut ); @GET @Path("/factures/count") @Produces(MediaType.APPLICATION_JSON) int countFactures( @QueryParam("filter_numero") String filtreNumero, @QueryParam("filter_client") String filtreClient, @QueryParam("filter_statut") String filtreStatut ); } ``` --- ## ✅ Prochaines Étapes 1. CrĂ©er les fichiers ci-dessus 2. Tester avec des donnĂ©es de test 3. VĂ©rifier les logs pour le debugging 4. Adapter le backend si nĂ©cessaire 5. RĂ©pliquer pour les autres modules (Devis, Clients, etc.)