feat: implement server-side pagination, eager query loading, and dynamic column filtering via HTMX for Payment History
This commit is contained in:
+106
-4
@@ -1,23 +1,125 @@
|
||||
package com.astalange.web.controller;
|
||||
|
||||
import com.astalange.core.entity.Paiement;
|
||||
import com.astalange.core.repository.CategorieRepository;
|
||||
import com.astalange.core.repository.ModePaiementRepository;
|
||||
import com.astalange.core.repository.PaiementRepository;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
public class PaiementsController {
|
||||
|
||||
private final PaiementRepository paiementRepository;
|
||||
private final CategorieRepository categorieRepository;
|
||||
private final ModePaiementRepository modePaiementRepository;
|
||||
|
||||
public PaiementsController(PaiementRepository paiementRepository) {
|
||||
public PaiementsController(PaiementRepository paiementRepository,
|
||||
CategorieRepository categorieRepository,
|
||||
ModePaiementRepository modePaiementRepository) {
|
||||
this.paiementRepository = paiementRepository;
|
||||
this.categorieRepository = categorieRepository;
|
||||
this.modePaiementRepository = modePaiementRepository;
|
||||
}
|
||||
|
||||
@GetMapping("/paiements")
|
||||
public String listPaiements(Model model) {
|
||||
model.addAttribute("paiements", paiementRepository.findAll(Sort.by(Sort.Direction.DESC, "datePaiement", "id")));
|
||||
public String listPaiements(
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) String adherent,
|
||||
@RequestParam(required = false) String categorie,
|
||||
@RequestParam(required = false) String saison,
|
||||
@RequestParam(required = false) String modePaiement,
|
||||
@RequestParam(required = false) String montant,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "20") int size,
|
||||
Model model) {
|
||||
|
||||
List<Paiement> allPaiements = paiementRepository.findAllWithAssociations();
|
||||
|
||||
List<Paiement> filtered = allPaiements.stream()
|
||||
.filter(p -> {
|
||||
// Global query
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
String q = query.toLowerCase().trim();
|
||||
String fullName = (p.getLicence().getAdherent().getPrenom() + " " + p.getLicence().getAdherent().getNom()).toLowerCase();
|
||||
String catName = p.getLicence().getCategorie().getNom().toLowerCase();
|
||||
String modeName = p.getModePaiement().getNom().toLowerCase();
|
||||
String seasonName = p.getLicence().getSaison().getNom().toLowerCase();
|
||||
if (!fullName.contains(q) && !catName.contains(q) && !modeName.contains(q) && !seasonName.contains(q)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Column filters
|
||||
if (adherent != null && !adherent.trim().isEmpty()) {
|
||||
String af = adherent.toLowerCase().trim();
|
||||
String fullName = (p.getLicence().getAdherent().getPrenom() + " " + p.getLicence().getAdherent().getNom()).toLowerCase();
|
||||
if (!fullName.contains(af)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (categorie != null && !categorie.trim().isEmpty()) {
|
||||
if (!p.getLicence().getCategorie().getNom().equalsIgnoreCase(categorie.trim())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (saison != null && !saison.trim().isEmpty()) {
|
||||
String sf = saison.toLowerCase().trim();
|
||||
if (!p.getLicence().getSaison().getNom().toLowerCase().contains(sf)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (modePaiement != null && !modePaiement.trim().isEmpty()) {
|
||||
if (!p.getModePaiement().getNom().equalsIgnoreCase(modePaiement.trim())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (montant != null && !montant.trim().isEmpty()) {
|
||||
String mf = montant.trim();
|
||||
if (!p.getMontant().toString().contains(mf)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
int totalElements = filtered.size();
|
||||
int totalPages = (int) Math.ceil((double) totalElements / size);
|
||||
int fromIndex = page * size;
|
||||
int toIndex = Math.min(fromIndex + size, totalElements);
|
||||
|
||||
List<Paiement> paginated = List.of();
|
||||
if (fromIndex < totalElements) {
|
||||
paginated = filtered.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
model.addAttribute("paiements", paginated);
|
||||
model.addAttribute("categories", categorieRepository.findAll());
|
||||
model.addAttribute("modesPaiement", modePaiementRepository.findAll());
|
||||
model.addAttribute("currentPage", page);
|
||||
model.addAttribute("pageSize", size);
|
||||
model.addAttribute("totalPages", totalPages);
|
||||
model.addAttribute("totalElements", totalElements);
|
||||
|
||||
// Keep filter values in model to restore inputs after swap
|
||||
model.addAttribute("searchQuery", query);
|
||||
model.addAttribute("adherentFilter", adherent);
|
||||
model.addAttribute("categorieFilter", categorie);
|
||||
model.addAttribute("saisonFilter", saison);
|
||||
model.addAttribute("modePaiementFilter", modePaiement);
|
||||
model.addAttribute("montantFilter", montant);
|
||||
|
||||
return "paiements/list";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user