Configure Maven repository for unionflow-server-api dependency

This commit is contained in:
dahoud
2025-12-10 01:12:54 +00:00
commit 2910809949
1173 changed files with 435718 additions and 0 deletions

View File

@@ -0,0 +1,456 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{cotisationsBean}"/>
<ui:define name="title">Gestion des Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-money-bill text-green-500" />
<ui:param name="title" value="Gestion des Cotisations" />
<ui:param name="description" value="Suivi et gestion des cotisations des membres" />
<ui:define name="actions">
<h:form id="formActionsCotisations">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle cotisation" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouvelleCotisation').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{cotisationsBean.exporterCotisations}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.cotisationsEnRetard}" />
<ui:param name="label" value="En Retard" />
<ui:param name="icon" value="pi pi-exclamation-triangle" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.montantRetardFormatte}" />
<ui:param name="label" value="Montant Retard" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Liste des cotisations -->
<div class="card">
<h:form id="formCotisations">
<h5>Liste des Cotisations</h5>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="searchMembre" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchMembre"
placeholder="Rechercher par membre..."
value="#{cotisationsBean.filtres.nomMembre}"
styleClass="w-full">
<p:ajax event="keyup" update="dtCotisations" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreStatut" value="Statut" />
<p:selectOneMenu id="filtreStatut"
value="#{cotisationsBean.filtres.statut}"
styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Payée" itemValue="PAYEE" />
<f:selectItem itemLabel="Partiellement payée" itemValue="PARTIELLEMENT_PAYEE" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<f:selectItem itemLabel="Annulée" itemValue="ANNULEE" />
<p:ajax event="change" update="dtCotisations" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreType" value="Type" />
<p:selectOneMenu id="filtreType"
value="#{cotisationsBean.filtres.typeCotisation}"
styleClass="w-full">
<f:selectItem itemLabel="Tous les types" itemValue="" />
<f:selectItem itemLabel="Mensuelle" itemValue="MENSUELLE" />
<f:selectItem itemLabel="Trimestrielle" itemValue="TRIMESTRIELLE" />
<f:selectItem itemLabel="Semestrielle" itemValue="SEMESTRIELLE" />
<f:selectItem itemLabel="Annuelle" itemValue="ANNUELLE" />
<f:selectItem itemLabel="Adhésion" itemValue="ADHESION" />
<f:selectItem itemLabel="Exceptionnelle" itemValue="EXCEPTIONNELLE" />
<p:ajax event="change" update="dtCotisations" />
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Filtres avancés"
icon="pi pi-filter"
onclick="PF('dlgFiltresAvances').show();"
styleClass="ui-button-secondary w-full" />
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Réinitialiser</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
action="#{cotisationsBean.reinitialiserFiltres}"
update="dtCotisations searchMembre filtreStatut filtreType"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Tableau des cotisations -->
<p:dataTable id="dtCotisations"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
currentPageReportTemplate="{startRecord} - {endRecord} sur {totalRecords}"
emptyMessage="Aucune cotisation trouvée"
selection="#{cotisationsBean.cotisationsSelectionnees}"
selectionMode="multiple">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Cotisations (#{cotisationsBean.cotisationsFiltrees.size()})</span>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Rappels groupés" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappelsGroupes}" />
<ui:param name="update" value="@form" />
<ui:param name="disabled" value="#{empty cotisationsBean.cotisationsSelectionnees}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</f:facet>
<p:column selectionMode="multiple" style="width:50px" />
<p:column headerText="Référence" sortBy="#{cotisation.numeroReference}" style="width:150px">
<h:outputText value="#{cotisation.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div class="flex align-items-center gap-2">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}"
severity="info"
icon="#{cotisation.typeCotisation == 'ADHESION' ? 'pi-user-plus' : 'pi-calendar'}" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Montant Payé" sortBy="#{cotisation.montantPaye}" style="width:120px">
<h:outputText value="#{cotisation.montantPayeFormatte}" />
</p:column>
<p:column headerText="Statut" sortBy="#{cotisation.statut}" style="width:150px">
<p:tag value="#{cotisation.statutLibelle}"
severity="#{cotisation.statutSeverity}"
icon="#{cotisation.statutIcon}" />
</p:column>
<p:column headerText="Échéance" sortBy="#{cotisation.dateEcheance}" style="width:120px">
<h:outputText value="#{cotisation.dateEcheanceFormatee}" />
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-check"
title="Marquer comme payée"
styleClass="p-button-rounded p-button-text p-button-success"
disabled="#{cotisation.statut == 'PAYEE'}"
action="#{cotisationsBean.marquerCommePaye(cotisation)}"
update="@form" />
<p:commandButton icon="pi pi-send"
title="Envoyer un rappel"
styleClass="p-button-rounded p-button-text p-button-warning"
action="#{cotisationsBean.envoyerRappel(cotisation)}"
update="@form" />
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formDetailsCotisation"
oncomplete="PF('dlgDetailsCotisation').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Nouvelle Cotisation -->
<p:dialog header="Nouvelle Cotisation" widgetVar="dlgNouvelleCotisation" modal="true" width="600" resizable="false">
<h:form id="formNouvelleCotisation">
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="title">Informations de la cotisation</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="libelle" />
<ui:param name="label" value="Libellé" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.libelle}" />
<ui:param name="required" value="true" />
<ui:param name="placeholder" value="Ex: Cotisation mensuelle janvier 2024" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="typeCotisation" />
<ui:param name="label" value="Type de cotisation" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.typeCotisation}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Mensuelle" itemValue="MENSUELLE" />
<f:selectItem itemLabel="Trimestrielle" itemValue="TRIMESTRIELLE" />
<f:selectItem itemLabel="Semestrielle" itemValue="SEMESTRIELLE" />
<f:selectItem itemLabel="Annuelle" itemValue="ANNUELLE" />
<f:selectItem itemLabel="Adhésion" itemValue="ADHESION" />
<f:selectItem itemLabel="Exceptionnelle" itemValue="EXCEPTIONNELLE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateEcheance" />
<ui:param name="label" value="Date d'échéance" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.dateEcheance}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="montantDu" value="Montant dû (FCFA)" />
<p:inputNumber id="montantDu"
value="#{cotisationsBean.nouvelleCotisation.montantDu}"
symbol=""
minValue="0"
styleClass="w-full" />
</div>
</div>
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observations" />
<ui:param name="label" value="Observations" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.observations}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgNouvelleCotisation').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.enregistrerCotisation}" />
<ui:param name="update" value="@form :formCotisations" />
<ui:param name="oncomplete" value="PF('dlgNouvelleCotisation').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Filtres Avancés -->
<p:dialog header="Filtres Avancés" widgetVar="dlgFiltresAvances" modal="true" width="500" resizable="false">
<h:form id="formFiltresAvances">
<div class="ui-fluid">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="club" />
<ui:param name="label" value="Club/Association" />
<ui:param name="value" value="#{cotisationsBean.filtres.club}" />
<ui:param name="placeholder" value="Rechercher par club..." />
</ui:include>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiement" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{cotisationsBean.filtres.methodePaiement}" />
<ui:define name="items">
<f:selectItem itemLabel="Toutes" itemValue="" />
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
</ui:define>
</ui:include>
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date début" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateDebut}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date fin" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateFin}" />
</ui:include>
</div>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgFiltresAvances').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Appliquer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.rechercher}" />
<ui:param name="update" value=":formCotisations" />
<ui:param name="oncomplete" value="PF('dlgFiltresAvances').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Détails Cotisation -->
<p:dialog header="Détails de la Cotisation" widgetVar="dlgDetailsCotisation" modal="true" width="600" resizable="false">
<h:form id="formDetailsCotisation">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{cotisationsBean.cotisationSelectionnee.statutLibelle}"
severity="#{cotisationsBean.cotisationSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">#{cotisationsBean.cotisationSelectionnee.numeroMembre}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Type</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.typeCotisationLibelle}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Montant dû</label>
<p class="text-600 font-bold">#{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Montant payé</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.montantPayeFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date d'échéance</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.dateEcheanceFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de paiement</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.datePaiementFormatee}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,253 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{cotisationsBean}"/>
<ui:define name="title">Historique des Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-history text-blue-500" />
<ui:param name="title" value="Historique des Cotisations" />
<ui:param name="description" value="Consultation de l'historique complet des cotisations et paiements" />
<ui:define name="actions">
<h:form id="formActionsHistorique">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{cotisationsBean.exporterCotisations}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Filtres d'historique -->
<div class="card">
<h:form id="formFiltresHistorique">
<h5>Filtres de Recherche</h5>
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date début" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateDebut}" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date fin" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateFin}" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="statutHistorique" />
<ui:param name="label" value="Statut" />
<ui:param name="value" value="#{cotisationsBean.filtres.statut}" />
<ui:define name="items">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="Payée" itemValue="PAYEE" />
<f:selectItem itemLabel="Partiellement payée" itemValue="PARTIELLEMENT_PAYEE" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<f:selectItem itemLabel="Annulée" itemValue="ANNULEE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel />
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Rechercher" />
<ui:param name="icon" value="pi pi-search" />
<ui:param name="action" value="#{cotisationsBean.rechercher}" />
<ui:param name="update" value=":formHistorique" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{cotisationsBean.reinitialiserFiltres}" />
<ui:param name="update" value="@form :formHistorique" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</div>
</div>
</h:form>
</div>
<!-- Tableau d'historique -->
<div class="card">
<h:form id="formHistorique">
<h5>Historique des Cotisations</h5>
<p:dataTable id="dtHistorique"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
sortMode="multiple"
emptyMessage="Aucune cotisation trouvée">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Historique (#{cotisationsBean.cotisationsFiltrees.size()} cotisation(s))</span>
</div>
</f:facet>
<p:column headerText="Date" sortBy="#{cotisation.dateCreation}" style="width:120px">
<h:outputText value="#{cotisation.dateCreation}" rendered="#{cotisation.dateCreation != null}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</p:column>
<p:column headerText="Référence" sortBy="#{cotisation.numeroReference}" style="width:150px">
<h:outputText value="#{cotisation.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}" severity="info" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Montant Payé" sortBy="#{cotisation.montantPaye}" style="width:120px">
<h:outputText value="#{cotisation.montantPayeFormatte}" />
</p:column>
<p:column headerText="Statut" sortBy="#{cotisation.statut}" style="width:150px">
<p:tag value="#{cotisation.statutLibelle}"
severity="#{cotisation.statutSeverity}"
icon="#{cotisation.statutIcon}" />
</p:column>
<p:column headerText="Date Paiement" sortBy="#{cotisation.datePaiement}" style="width:150px">
<h:outputText value="#{cotisation.datePaiementFormatee}" />
</p:column>
<p:column headerText="Méthode" style="width:120px">
<h:outputText value="#{cotisation.methodePaiementLibelle}" rendered="#{cotisation.methodePaiement != null}" />
</p:column>
<p:column headerText="Actions" style="width:100px">
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formDetailsCotisation"
oncomplete="PF('dlgDetailsCotisation').show();" />
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Détails Cotisation -->
<p:dialog header="Détails de la Cotisation" widgetVar="dlgDetailsCotisation" modal="true" width="600" resizable="false">
<h:form id="formDetailsCotisation">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{cotisationsBean.cotisationSelectionnee.statutLibelle}"
severity="#{cotisationsBean.cotisationSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">N° #{cotisationsBean.cotisationSelectionnee.numeroMembre}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Type</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.typeCotisationLibelle}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date d'échéance</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.dateEcheanceFormatee}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant dû</label>
<p class="text-600 font-bold">#{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant payé</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.montantPayeFormatte}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant restant</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.montantRestantFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de paiement</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.datePaiementFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Méthode de paiement</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.methodePaiementLibelle}</p>
</div>
</div>
<div class="col-12" rendered="#{cotisationsBean.cotisationSelectionnee.observations != null}">
<div class="field">
<label class="font-medium">Observations</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.observations}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,307 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{cotisationsBean}"/>
<ui:define name="title">Paiement de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-credit-card text-green-500" />
<ui:param name="title" value="Paiement de Cotisations" />
<ui:param name="description" value="Enregistrement et suivi des paiements de cotisations" />
<ui:define name="actions">
<h:form id="formActionsPaiement">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques de paiement -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.moyenneMensuelleFormattee}" />
<ui:param name="label" value="Moyenne Mensuelle" />
<ui:param name="icon" value="pi pi-chart-line" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.objectifAnnuelFormatte}" />
<ui:param name="label" value="Objectif Annuel" />
<ui:param name="icon" value="pi pi-target" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Répartition par méthode de paiement -->
<div class="card">
<h5>
<i class="pi pi-chart-pie mr-2"></i>
Répartition par Méthode de Paiement
</h5>
<div class="grid">
<div class="col-12 md:col-6">
<div class="flex flex-column gap-3">
<ui:repeat value="#{cotisationsBean.repartitionMethodes}" var="methode">
<div class="flex align-items-center justify-content-between p-3 border-round surface-50">
<div class="flex align-items-center gap-2">
<div class="border-round text-white text-center"
style="width: 2.5rem; height: 2.5rem; line-height: 2.5rem; background: var(--#{methode.couleur});">
<i class="#{methode.icon}"></i>
</div>
<div>
<div class="font-medium">#{methode.methode}</div>
<div class="text-600 text-sm">#{methode.montantFormatte}</div>
</div>
</div>
<div class="text-right">
<div class="font-bold text-xl">#{methode.pourcentageInt}%</div>
</div>
</div>
</ui:repeat>
</div>
</div>
<div class="col-12 md:col-6">
<div class="flex flex-column gap-2">
<ui:repeat value="#{cotisationsBean.repartitionMethodes}" var="methode">
<div>
<div class="flex justify-content-between mb-1">
<span class="font-medium">#{methode.methode}</span>
<span class="text-600">#{methode.pourcentageInt}%</span>
</div>
<p:progressBar value="#{methode.pourcentageInt}"
showValue="false"
styleClass="progressbar-custom" />
</div>
</ui:repeat>
</div>
</div>
</div>
</div>
<!-- Cotisations en attente de paiement -->
<div class="card">
<h:form id="formPaiements">
<h5>Cotisations en Attente de Paiement</h5>
<p:dataTable id="dtPaiements"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
filteredValue="#{cotisationsBean.cotisationsFiltrees}"
paginator="true"
rows="20"
emptyMessage="Aucune cotisation en attente"
selection="#{cotisationsBean.cotisationSelectionnee}"
selectionMode="single">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Cotisations à payer</span>
<p:selectOneMenu value="#{cotisationsBean.filtres.statut}" styleClass="w-12rem">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Partiellement payée" itemValue="PARTIELLEMENT_PAYEE" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<p:ajax update="dtPaiements" />
</p:selectOneMenu>
</div>
</f:facet>
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}" severity="info" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Montant Payé" sortBy="#{cotisation.montantPaye}" style="width:120px">
<h:outputText value="#{cotisation.montantPayeFormatte}" />
</p:column>
<p:column headerText="Restant" style="width:120px">
<h:outputText value="#{cotisation.montantRestantFormatte}"
styleClass="#{cotisation.montantRestant.compareTo(java.math.BigDecimal.ZERO) > 0 ? 'text-orange-500 font-bold' : 'text-green-500'}" />
</p:column>
<p:column headerText="Échéance" sortBy="#{cotisation.dateEcheance}" style="width:120px">
<h:outputText value="#{cotisation.dateEcheanceFormatee}" />
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton value="Payer"
icon="pi pi-check"
styleClass="p-button-success p-button-sm"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formPaiement"
oncomplete="PF('dlgPaiement').show();" />
<p:commandButton value="Partiel"
icon="pi pi-minus"
styleClass="p-button-info p-button-sm"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formPaiementPartiel"
oncomplete="PF('dlgPaiementPartiel').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Paiement Complet -->
<p:dialog header="Enregistrer un Paiement" widgetVar="dlgPaiement" modal="true" width="500" resizable="false">
<h:form id="formPaiement">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Cotisation</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference} - #{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Montant dû: #{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
</div>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiement" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.methodePaiement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement bancaire" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
<f:selectItem itemLabel="Orange Money" itemValue="ORANGE_MONEY" />
<f:selectItem itemLabel="Free Money" itemValue="FREE_MONEY" />
<f:selectItem itemLabel="Carte bancaire" itemValue="CARTE_BANCAIRE" />
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="referencePaiement" />
<ui:param name="label" value="Référence de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.referencePaiement}" />
<ui:param name="placeholder" value="Ex: WAVE-123456789" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observationsPaiement" />
<ui:param name="label" value="Observations" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.observations}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgPaiement').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.marquerCommePaye}" />
<ui:param name="update" value="@form :formPaiements" />
<ui:param name="oncomplete" value="PF('dlgPaiement').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Paiement Partiel -->
<p:dialog header="Enregistrer un Paiement Partiel" widgetVar="dlgPaiementPartiel" modal="true" width="500" resizable="false">
<h:form id="formPaiementPartiel">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Cotisation</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference} - #{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Montant dû: #{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
<p class="text-500 text-sm">Montant restant: #{cotisationsBean.cotisationSelectionnee.montantRestantFormatte}</p>
</div>
<div class="field">
<p:outputLabel for="montantPaye" value="Montant à payer (FCFA)" />
<p:inputNumber id="montantPaye"
value="#{cotisationsBean.cotisationSelectionnee.montantPaye}"
symbol=""
minValue="0"
maxValue="#{cotisationsBean.cotisationSelectionnee.montantDu}"
styleClass="w-full" />
</div>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiementPartiel" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.methodePaiement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement bancaire" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="referencePaiementPartiel" />
<ui:param name="label" value="Référence de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.referencePaiement}" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgPaiementPartiel').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.enregistrerPaiementPartiel(cotisationsBean.cotisationSelectionnee.montantPaye, cotisationsBean.cotisationSelectionnee.methodePaiement, cotisationsBean.cotisationSelectionnee.referencePaiement)}" />
<ui:param name="update" value="@form :formPaiements" />
<ui:param name="oncomplete" value="PF('dlgPaiementPartiel').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,185 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Rapports Financiers - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-chart-bar text-purple-500" />
<ui:param name="title" value="Rapports Financiers" />
<ui:param name="description" value="Analyse et rapports détaillés sur les cotisations et paiements" />
<ui:define name="actions">
<h:form id="formActionsRapports">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Générer rapport" />
<ui:param name="icon" value="pi pi-file-pdf" />
<ui:param name="action" value="#{cotisationsBean.genererRapportFinancier}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Vue d'ensemble -->
<div class="grid">
<div class="col-12 md:col-8">
<div class="card">
<h5>
<i class="pi pi-chart-line mr-2"></i>
Évolution des Paiements (12 derniers mois)
</h5>
<div class="flex flex-column gap-2 mt-3">
<ui:repeat value="#{cotisationsBean.evolutionPaiements}" var="evolution">
<div class="flex align-items-center gap-3">
<div class="text-600" style="width: 60px;">#{evolution.mois}</div>
<div class="flex-1">
<div class="flex align-items-center gap-2">
<div class="bg-blue-500 border-round"
style="width: #{evolution.hauteur}px; height: 20px; min-width: 10px;"></div>
<span class="text-600 text-sm">#{evolution.montantFormatte}</span>
</div>
</div>
</div>
</ui:repeat>
</div>
</div>
</div>
<div class="col-12 md:col-4">
<div class="card">
<h5>
<i class="pi pi-chart-pie mr-2"></i>
Répartition par Méthode
</h5>
<div class="flex flex-column gap-3 mt-3">
<ui:repeat value="#{cotisationsBean.repartitionMethodes}" var="methode">
<div>
<div class="flex justify-content-between mb-1">
<span class="font-medium">#{methode.methode}</span>
<span class="text-600">#{methode.pourcentageInt}%</span>
</div>
<p:progressBar value="#{methode.pourcentageInt}"
showValue="false" />
</div>
</ui:repeat>
</div>
</div>
</div>
</div>
<!-- Statistiques détaillées -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.objectifAnnuelFormatte}" />
<ui:param name="label" value="Objectif Annuel" />
<ui:param name="icon" value="pi pi-target" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.moyenneMensuelleFormattee}" />
<ui:param name="label" value="Moyenne Mensuelle" />
<ui:param name="icon" value="pi pi-chart-line" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Résumé des cotisations -->
<div class="card">
<h5>
<i class="pi pi-list mr-2"></i>
Résumé des Cotisations
</h5>
<div class="grid mt-3">
<div class="col-12 md:col-6">
<h6 class="mb-3">Par Statut</h6>
<div class="flex flex-column gap-2">
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Payées</span>
<p:tag value="#{cotisationsBean.compterParStatut('PAYEE')}"
severity="success" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Partiellement payées</span>
<p:tag value="#{cotisationsBean.compterParStatut('PARTIELLEMENT_PAYEE')}"
severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">En attente</span>
<p:tag value="#{cotisationsBean.compterParStatut('EN_ATTENTE')}"
severity="warning" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">En retard</span>
<p:tag value="#{cotisationsBean.compterParStatut('EN_RETARD')}"
severity="danger" />
</div>
</div>
</div>
<div class="col-12 md:col-6">
<h6 class="mb-3">Par Type</h6>
<div class="flex flex-column gap-2">
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Mensuelle</span>
<p:tag value="#{cotisationsBean.compterParType('MENSUELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Trimestrielle</span>
<p:tag value="#{cotisationsBean.compterParType('TRIMESTRIELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Semestrielle</span>
<p:tag value="#{cotisationsBean.compterParType('SEMESTRIELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Annuelle</span>
<p:tag value="#{cotisationsBean.compterParType('ANNUELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Adhésion</span>
<p:tag value="#{cotisationsBean.compterParType('ADHESION')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Exceptionnelle</span>
<p:tag value="#{cotisationsBean.compterParType('EXCEPTIONNELLE')}" severity="info" />
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,229 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Relances de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-send text-orange-500" />
<ui:param name="title" value="Relances de Cotisations" />
<ui:param name="description" value="Gestion et envoi des relances pour les cotisations en retard" />
<ui:define name="actions">
<h:form id="formActionsRelances">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Relances groupées" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="onclick" value="PF('dlgRelancesGroupes').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques de relances -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.cotisationsEnRetard}" />
<ui:param name="label" value="Cotisations en Retard" />
<ui:param name="icon" value="pi pi-exclamation-triangle" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.montantRetardFormatte}" />
<ui:param name="label" value="Montant en Retard" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="red" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.rappelsEnAttente.size()}" />
<ui:param name="label" value="Rappels en Attente" />
<ui:param name="icon" value="pi pi-bell" />
<ui:param name="bgColor" value="purple" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="blue" />
</ui:include>
</div>
<!-- Liste des rappels en attente -->
<div class="card">
<h5>
<i class="pi pi-bell mr-2"></i>
Rappels en Attente
</h5>
<p:dataTable id="dtRappels"
value="#{cotisationsBean.rappelsEnAttente}"
var="rappel"
paginator="true"
rows="20"
emptyMessage="Aucun rappel en attente">
<p:column headerText="Membre" sortBy="#{rappel.nomMembre}">
<div>
<div class="font-medium">#{rappel.nomMembre}</div>
<div class="text-600 text-sm">#{rappel.club}</div>
</div>
</p:column>
<p:column headerText="Montant Dû" sortBy="#{rappel.montantDu}" style="width:120px">
<h:outputText value="#{rappel.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Jours de Retard" sortBy="#{rappel.joursRetard}" style="width:120px">
<h:outputText value="#{rappel.joursRetard} jour(s)" />
</p:column>
<p:column headerText="Priorité" sortBy="#{rappel.priorite}" style="width:120px">
<p:tag value="#{rappel.priorite}"
severity="#{rappel.prioriteSeverity}" />
</p:column>
<p:column headerText="Actions" style="width:150px">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Envoyer" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappel}" />
<ui:param name="update" value="@form" />
<ui:param name="styleClass" value="p-button-sm" />
</ui:include>
</p:column>
</p:dataTable>
</div>
<!-- Cotisations en retard -->
<div class="card">
<h:form id="formRelances">
<h5>Cotisations en Retard</h5>
<p:dataTable id="dtRetard"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
filteredValue="#{cotisationsBean.cotisationsFiltrees}"
paginator="true"
rows="20"
emptyMessage="Aucune cotisation en retard"
selection="#{cotisationsBean.cotisationsSelectionnees}"
selectionMode="multiple">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Cotisations nécessitant une relance</span>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Relancer sélectionnées" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappelsGroupes}" />
<ui:param name="update" value="@form" />
<ui:param name="disabled" value="#{empty cotisationsBean.cotisationsSelectionnees}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</f:facet>
<p:column selectionMode="multiple" style="width:50px" />
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}" severity="info" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Échéance" sortBy="#{cotisation.dateEcheance}" style="width:120px">
<h:outputText value="#{cotisation.dateEcheanceFormatee}" />
</p:column>
<p:column headerText="Jours Retard" style="width:120px">
<h:outputText value="#{cotisation.joursRetard} jour(s)"
styleClass="#{cotisation.joursRetard > 30 ? 'text-red-500 font-bold' : cotisation.joursRetard > 15 ? 'text-orange-500' : 'text-yellow-500'}" />
</p:column>
<p:column headerText="Actions" style="width:150px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-send"
title="Envoyer un rappel"
styleClass="p-button-rounded p-button-text p-button-warning"
action="#{cotisationsBean.envoyerRappel(cotisation)}"
update="@form" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Relances Groupées -->
<p:dialog header="Relances Groupées" widgetVar="dlgRelancesGroupes" modal="true" width="500" resizable="false">
<h:form id="formRelancesGroupes">
<div class="ui-fluid">
<div class="field">
<p:outputLabel for="messageRelance" value="Message de relance" />
<p:inputTextarea id="messageRelance"
rows="5"
styleClass="w-full"
placeholder="Message personnalisé pour les relances..." />
</div>
<div class="field">
<p:selectBooleanCheckbox id="relanceUrgente" />
<p:outputLabel for="relanceUrgente" value=" Marquer comme urgente" />
</div>
<div class="surface-50 p-3 border-round">
<div class="font-medium mb-2">Destinataires :</div>
<div class="text-600 text-sm">#{cotisationsBean.cotisationsSelectionnees.size()} cotisation(s) sélectionnée(s)</div>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgRelancesGroupes').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Envoyer les relances" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappelsGroupes}" />
<ui:param name="update" value="@form :formRelances" />
<ui:param name="oncomplete" value="PF('dlgRelancesGroupes').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,108 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Rappels de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formReminders">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-bell text-primary mr-2"></i>
Rappels de Cotisations
</h3>
<p class="text-600 m-0 mt-2">
Gérez et envoyez les rappels de cotisations aux membres
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<p:commandButton value="Envoyer rappels"
icon="pi pi-send"
styleClass="ui-button-success"
action="#{cotisationsGestionBean.envoyerRappelsGroupes}"/>
</div>
</div>
</div>
<!-- Statistiques -->
<div class="grid mb-3">
<div class="col-12 md:col-3">
<div class="card bg-orange-100 border-left-3 border-orange-500">
<div class="flex justify-content-between">
<div>
<div class="text-orange-900 font-bold text-2xl">#{cotisationsGestionBean.nombreMembresEnRetard}</div>
<div class="text-orange-700">En Retard</div>
</div>
<div class="bg-orange-500 text-white border-round text-center"
style="width: 3rem; height: 3rem; line-height: 3rem;">
<i class="pi pi-exclamation-triangle text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="card bg-blue-100 border-left-3 border-blue-500">
<div class="flex justify-content-between">
<div>
<div class="text-blue-900 font-bold text-2xl">#{cotisationsGestionBean.nombreRappelsEnvoyes}</div>
<div class="text-blue-700">Rappels Envoyés</div>
</div>
<div class="bg-blue-500 text-white border-round text-center"
style="width: 3rem; height: 3rem; line-height: 3rem;">
<i class="pi pi-send text-xl"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Liste des membres en retard -->
<div class="card">
<h5 class="mb-3">Membres avec Cotisations en Retard</h5>
<p:dataTable id="dtRetard"
var="membre"
value="#{cotisationsGestionBean.membresEnRetard}"
paginator="true"
rows="10"
selection="#{cotisationsGestionBean.membresSelectionnes}"
selectionMode="multiple"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25">
<p:column selectionMode="multiple" style="width:50px"/>
<p:column headerText="Membre" sortBy="#{membre.nomComplet}">
<div>
<div class="font-medium">#{membre.nomComplet}</div>
<small class="text-600">#{membre.numeroMembre}</small>
</div>
</p:column>
<p:column headerText="Montant dû" sortBy="#{membre.montantDu}">
<div class="font-bold text-red-500">#{membre.montantDu} FCFA</div>
</p:column>
<p:column headerText="Jours de retard" sortBy="#{membre.joursRetard}">
<p:tag value="#{membre.joursRetard} jours" severity="danger"/>
</p:column>
<p:column headerText="Actions" style="width:150px">
<p:commandButton icon="pi pi-send"
styleClass="ui-button-rounded ui-button-text ui-button-primary"
action="#{cotisationsGestionBean.envoyerRappel(membre)}"
title="Envoyer rappel"/>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Rapports de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formReport">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-file-pdf text-primary mr-2"></i>
Rapports de Cotisations
</h3>
<p class="text-600 m-0 mt-2">
Générez et consultez les rapports détaillés sur les cotisations
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<p:commandButton value="Générer rapport"
icon="pi pi-file-pdf"
styleClass="ui-button-success"
action="#{cotisationsGestionBean.genererRapport}"/>
</div>
</div>
</div>
<!-- Filtres pour le rapport -->
<div class="card mb-3">
<h5 class="mb-3">Paramètres du Rapport</h5>
<div class="grid">
<div class="col-12 md:col-4">
<p:outputLabel for="periodeRapport" value="Période"/>
<p:selectOneMenu id="periodeRapport" styleClass="w-full">
<f:selectItem itemLabel="Ce mois" itemValue="MOIS_COURANT"/>
<f:selectItem itemLabel="Ce trimestre" itemValue="TRIMESTRE_COURANT"/>
<f:selectItem itemLabel="Cette année" itemValue="ANNEE_COURANTE"/>
<f:selectItem itemLabel="Personnalisée" itemValue="PERSONNALISEE"/>
</p:selectOneMenu>
</div>
<div class="col-12 md:col-4">
<p:outputLabel for="typeRapport" value="Type de rapport"/>
<p:selectOneMenu id="typeRapport" styleClass="w-full">
<f:selectItem itemLabel="Rapport complet" itemValue="COMPLET"/>
<f:selectItem itemLabel="Rapport simplifié" itemValue="SIMPLIFIE"/>
<f:selectItem itemLabel="Rapport analytique" itemValue="ANALYTIQUE"/>
</p:selectOneMenu>
</div>
<div class="col-12 md:col-4">
<p:outputLabel for="formatRapport" value="Format"/>
<p:selectOneMenu id="formatRapport" styleClass="w-full">
<f:selectItem itemLabel="PDF" itemValue="PDF"/>
<f:selectItem itemLabel="Excel" itemValue="EXCEL"/>
<f:selectItem itemLabel="CSV" itemValue="CSV"/>
</p:selectOneMenu>
</div>
</div>
</div>
<!-- Rapports disponibles -->
<div class="card">
<h5 class="mb-3">Rapports Disponibles</h5>
<div class="grid">
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-4 cursor-pointer hover:surface-200 transition-duration-200">
<div class="flex align-items-center mb-3">
<i class="pi pi-file-pdf text-red-500 text-2xl mr-3"></i>
<div>
<h6 class="m-0">Rapport Mensuel</h6>
<small class="text-600">Rapport complet du mois</small>
</div>
</div>
<p:commandButton value="Générer"
styleClass="ui-button-outlined ui-button-primary w-full"
action="#{cotisationsGestionBean.genererRapportMensuel}"/>
</div>
</div>
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-4 cursor-pointer hover:surface-200 transition-duration-200">
<div class="flex align-items-center mb-3">
<i class="pi pi-file-excel text-green-500 text-2xl mr-3"></i>
<div>
<h6 class="m-0">Rapport Annuel</h6>
<small class="text-600">Synthèse de l'année</small>
</div>
</div>
<p:commandButton value="Générer"
styleClass="ui-button-outlined ui-button-success w-full"
action="#{cotisationsGestionBean.genererRapportAnnuel}"/>
</div>
</div>
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-4 cursor-pointer hover:surface-200 transition-duration-200">
<div class="flex align-items-center mb-3">
<i class="pi pi-chart-bar text-blue-500 text-2xl mr-3"></i>
<div>
<h6 class="m-0">Rapport Analytique</h6>
<small class="text-600">Analyses et statistiques</small>
</div>
</div>
<p:commandButton value="Générer"
styleClass="ui-button-outlined ui-button-info w-full"
action="#{cotisationsGestionBean.genererRapportAnalytique}"/>
</div>
</div>
</div>
</div>
</h:form>
</ui:define>
</ui:composition>