package dev.lions.unionflow.client.view; import dev.lions.unionflow.client.dto.AssociationDTO; import dev.lions.unionflow.client.dto.MembreDTO; import dev.lions.unionflow.client.service.MembreService; import dev.lions.unionflow.client.service.AssociationService; import dev.lions.unionflow.client.service.ValidationService; import jakarta.faces.view.ViewScoped; import jakarta.inject.Named; import jakarta.inject.Inject; import jakarta.annotation.PostConstruct; import jakarta.faces.application.FacesMessage; import jakarta.faces.context.FacesContext; import org.eclipse.microprofile.rest.client.inject.RestClient; import java.io.Serializable; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; @Named("membreInscriptionBean") @ViewScoped public class MembreInscriptionBean implements Serializable { private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(MembreInscriptionBean.class.getName()); // Constantes de navigation outcomes (WOU/DRY - réutilisables) private static final String OUTCOME_MEMBRE_LISTE = "membreListPage"; private static final String OUTCOME_DASHBOARD = "dashboardPage"; @Inject @RestClient MembreService membreService; @Inject @RestClient AssociationService associationService; @Inject ValidationService validationService; @Inject SouscriptionBean souscriptionBean; // Propriétés système private String numeroGenere; // Informations personnelles private String prenom; private String nom; private String email; private String telephone; private String telephoneMobile; private String adresse; private String ville; private String codePostal; private String pays = "Sénégal"; private LocalDate dateNaissance; private String lieuNaissance; private String nationalite = "Sénégalaise"; private String sexe; private String situationMatrimoniale; private String profession; private String employeur; // Informations d'urgence private String contactUrgenceNom; private String contactUrgenceTelephone; private String contactUrgenceLien; // Informations bancaires private String numeroBanque; private String nomBanque; private String ribIban; // Informations adhésion private String typeAdhesion; private String numeroParrain; private String nomParrain; private String motifAdhesion; private String organisationId; // ID de l'organisation choisie private String organisationNom; // Nom de l'organisation affichée private List organisationsDisponibles = new ArrayList<>(); // Liste des organisations private boolean accepteReglement = false; private boolean acceptePrelevement = false; private boolean autorisationMarketing = false; // Statut de validation private String statutValidation = "EN_ATTENTE"; // EN_ATTENTE, VALIDE, REFUSE // Informations complémentaires private String competencesSpeciales; private String centresInteret; private String commentaires; // Photo et documents private String photoPath; private List documentsJoints = new ArrayList<>(); private org.primefaces.model.file.UploadedFile uploadedPhoto; private String photoBase64; public MembreInscriptionBean() { // Initialisation par défaut } @PostConstruct public void init() { // Générer un numéro de membre automatiquement this.numeroGenere = "M" + System.currentTimeMillis(); // Charger les organisations actives try { organisationsDisponibles = associationService.listerToutes(0, 1000); LOGGER.info("Chargement de " + organisationsDisponibles.size() + " organisations"); } catch (Exception e) { LOGGER.warning("Erreur lors du chargement des organisations: " + e.getMessage()); organisationsDisponibles = new ArrayList<>(); } } // Actions public String inscrire() { try { // Vérifier d'abord si l'organisation peut accepter de nouveaux membres if (!peutAccepterNouveauMembre()) { FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Quota atteint", "Cette organisation a atteint son quota maximum de membres."); FacesContext.getCurrentInstance().addMessage(null, message); return null; } // Vérification des champs obligatoires if (organisationId == null || organisationId.trim().isEmpty()) { FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Organisation manquante", "Vous devez sélectionner une organisation."); FacesContext.getCurrentInstance().addMessage(null, message); return null; } // Créer le DTO membre MembreDTO nouveauMembre = new MembreDTO(); nouveauMembre.setNumeroMembre(numeroGenere); nouveauMembre.setNom(nom); nouveauMembre.setPrenom(prenom); nouveauMembre.setEmail(email); nouveauMembre.setTelephone(telephone); nouveauMembre.setDateNaissance(dateNaissance); nouveauMembre.setAdresse(adresse); nouveauMembre.setProfession(profession); nouveauMembre.setStatutMatrimonial(situationMatrimoniale); nouveauMembre.setNationalite(nationalite); nouveauMembre.setStatut("ACTIF"); // Statut actif par défaut pour nouveaux membres nouveauMembre.setDateInscription(LocalDateTime.now()); // Conversion de l'organisationId String vers UUID try { nouveauMembre.setAssociationId(java.util.UUID.fromString(organisationId)); } catch (IllegalArgumentException e) { FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Identifiant d'organisation invalide."); FacesContext.getCurrentInstance().addMessage(null, message); return null; } // Validation des données ValidationService.ValidationResult validationResult = validationService.validate(nouveauMembre); if (!validationResult.isValid()) { FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreurs de validation", validationResult.getFirstErrorMessage()); FacesContext.getCurrentInstance().addMessage(null, message); return null; } // Appel du service REST pour créer le membre MembreDTO membreCreee = membreService.creer(nouveauMembre); // Gestion de la photo si disponible if (photoBase64 != null && !photoBase64.trim().isEmpty()) { LOGGER.info("Photo cadrée reçue: " + photoBase64.length() + " caractères"); // Note: La sauvegarde de la photo sera implémentée ultérieurement via un service dédié. // Le service appellera l'API backend pour stocker la photo associée au membre. } LOGGER.info("Membre inscrit avec succès: " + membreCreee.getNomComplet()); // Message de succès dans le Flash Scope pour qu'il survive à la redirection FacesContext context = FacesContext.getCurrentInstance(); context.getExternalContext().getFlash().setKeepMessages(true); FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Inscription réussie", "Le membre " + membreCreee.getNomComplet() + " a été inscrit avec succès (N° " + membreCreee.getNumeroMembre() + ")"); context.addMessage(null, message); return OUTCOME_MEMBRE_LISTE + "?faces-redirect=true"; } catch (Exception e) { LOGGER.severe("Erreur lors de l'inscription: " + e.getMessage()); FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Erreur lors de l'inscription: " + e.getMessage()); FacesContext.getCurrentInstance().addMessage(null, message); return null; } } // Méthodes de validation en temps réel public void validateNom() { if (nom != null && !nom.trim().isEmpty()) { ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "nom", nom); if (!result.isValid()) { LOGGER.info("Erreur validation nom: " + result.getFirstErrorMessage()); } } } public void validatePrenom() { if (prenom != null && !prenom.trim().isEmpty()) { ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "prenom", prenom); if (!result.isValid()) { LOGGER.info("Erreur validation prénom: " + result.getFirstErrorMessage()); } } } public void validateEmail() { if (email != null && !email.trim().isEmpty()) { ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "email", email); if (!result.isValid()) { LOGGER.info("Erreur validation email: " + result.getFirstErrorMessage()); } } } public void validateTelephone() { if (telephone != null && !telephone.trim().isEmpty()) { ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "telephone", telephone); if (!result.isValid()) { LOGGER.info("Erreur validation téléphone: " + result.getFirstErrorMessage()); } } } public String annuler() { return OUTCOME_DASHBOARD + "?faces-redirect=true"; } public void handleFileUpload(org.primefaces.event.FileUploadEvent event) { // Logique d'upload de documents org.primefaces.model.file.UploadedFile file = event.getFile(); if (file != null) { documentsJoints.add(file.getFileName()); } } public void ajouterDocument() { // Logique d'ajout de document } public void supprimerDocument(String document) { documentsJoints.remove(document); } public void rechercherParrain() { // Logique de recherche de parrain if (numeroParrain != null && !numeroParrain.trim().isEmpty()) { // Simulation de recherche nomParrain = "Membre trouvé - " + numeroParrain; } } public String enregistrerBrouillon() { // Logique d'enregistrement en brouillon return null; // Rester sur la même page } // Méthodes pour la progression public boolean isEtapePersonnelleComplete() { return prenom != null && !prenom.trim().isEmpty() && nom != null && !nom.trim().isEmpty() && dateNaissance != null && sexe != null && !sexe.trim().isEmpty(); } public boolean isEtapeCoordonneeComplete() { return adresse != null && !adresse.trim().isEmpty() && ville != null && !ville.trim().isEmpty() && email != null && !email.trim().isEmpty() && telephoneMobile != null && !telephoneMobile.trim().isEmpty(); } public boolean isEtapeAdhesionComplete() { return typeAdhesion != null && !typeAdhesion.trim().isEmpty(); } public boolean isEtapeDocumentsComplete() { return !documentsJoints.isEmpty() || (photoBase64 != null && !photoBase64.trim().isEmpty()); } public int getProgressionPourcentage() { int etapesCompletes = 0; if (isEtapePersonnelleComplete()) etapesCompletes++; if (isEtapeCoordonneeComplete()) etapesCompletes++; if (isEtapeAdhesionComplete()) etapesCompletes++; if (isEtapeDocumentsComplete()) etapesCompletes++; return (etapesCompletes * 100) / 4; } public boolean isFormulaireValide() { // Validation minimale : nom, prénom, email et acceptation du règlement boolean champsObligatoiresRemplis = nom != null && !nom.trim().isEmpty() && prenom != null && !prenom.trim().isEmpty() && email != null && !email.trim().isEmpty(); return champsObligatoiresRemplis && accepteReglement; } // Vérification du quota organisation public boolean peutAccepterNouveauMembre() { // Si le bean de souscription n'est pas disponible, autoriser l'inscription par défaut if (souscriptionBean == null || souscriptionBean.getSouscriptionActive() == null) { LOGGER.info("SouscriptionBean non disponible - autorisation par défaut"); return true; } return souscriptionBean.peutAccepterNouveauMembre(); } public String getMessageQuotaOrganisation() { if (souscriptionBean != null) { return souscriptionBean.getMessageQuota(); } return "Informations de quota non disponibles"; } // Getters et Setters public String getNumeroGenere() { return numeroGenere; } public void setNumeroGenere(String numeroGenere) { this.numeroGenere = numeroGenere; } public String getPrenom() { return prenom; } public void setPrenom(String prenom) { this.prenom = prenom; } public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getTelephoneMobile() { return telephoneMobile; } public void setTelephoneMobile(String telephoneMobile) { this.telephoneMobile = telephoneMobile; } public String getAdresse() { return adresse; } public void setAdresse(String adresse) { this.adresse = adresse; } public String getVille() { return ville; } public void setVille(String ville) { this.ville = ville; } public String getCodePostal() { return codePostal; } public void setCodePostal(String codePostal) { this.codePostal = codePostal; } public String getPays() { return pays; } public void setPays(String pays) { this.pays = pays; } public LocalDate getDateNaissance() { return dateNaissance; } public void setDateNaissance(LocalDate dateNaissance) { this.dateNaissance = dateNaissance; } public String getLieuNaissance() { return lieuNaissance; } public void setLieuNaissance(String lieuNaissance) { this.lieuNaissance = lieuNaissance; } public String getNationalite() { return nationalite; } public void setNationalite(String nationalite) { this.nationalite = nationalite; } public String getSexe() { return sexe; } public void setSexe(String sexe) { this.sexe = sexe; } public String getSituationMatrimoniale() { return situationMatrimoniale; } public void setSituationMatrimoniale(String situationMatrimoniale) { this.situationMatrimoniale = situationMatrimoniale; } public String getProfession() { return profession; } public void setProfession(String profession) { this.profession = profession; } public String getEmployeur() { return employeur; } public void setEmployeur(String employeur) { this.employeur = employeur; } public String getContactUrgenceNom() { return contactUrgenceNom; } public void setContactUrgenceNom(String contactUrgenceNom) { this.contactUrgenceNom = contactUrgenceNom; } public String getContactUrgenceTelephone() { return contactUrgenceTelephone; } public void setContactUrgenceTelephone(String contactUrgenceTelephone) { this.contactUrgenceTelephone = contactUrgenceTelephone; } public String getContactUrgenceLien() { return contactUrgenceLien; } public void setContactUrgenceLien(String contactUrgenceLien) { this.contactUrgenceLien = contactUrgenceLien; } public String getNumeroBanque() { return numeroBanque; } public void setNumeroBanque(String numeroBanque) { this.numeroBanque = numeroBanque; } public String getNomBanque() { return nomBanque; } public void setNomBanque(String nomBanque) { this.nomBanque = nomBanque; } public String getRibIban() { return ribIban; } public void setRibIban(String ribIban) { this.ribIban = ribIban; } public String getTypeAdhesion() { return typeAdhesion; } public void setTypeAdhesion(String typeAdhesion) { this.typeAdhesion = typeAdhesion; } public String getNumeroParrain() { return numeroParrain; } public void setNumeroParrain(String numeroParrain) { this.numeroParrain = numeroParrain; } public String getNomParrain() { return nomParrain; } public void setNomParrain(String nomParrain) { this.nomParrain = nomParrain; } public String getMotifAdhesion() { return motifAdhesion; } public void setMotifAdhesion(String motifAdhesion) { this.motifAdhesion = motifAdhesion; } public boolean isAccepteReglement() { return accepteReglement; } public void setAccepteReglement(boolean accepteReglement) { this.accepteReglement = accepteReglement; } public boolean isAcceptePrelevement() { return acceptePrelevement; } public void setAcceptePrelevement(boolean acceptePrelevement) { this.acceptePrelevement = acceptePrelevement; } public boolean isAutorisationMarketing() { return autorisationMarketing; } public void setAutorisationMarketing(boolean autorisationMarketing) { this.autorisationMarketing = autorisationMarketing; } public String getCompetencesSpeciales() { return competencesSpeciales; } public void setCompetencesSpeciales(String competencesSpeciales) { this.competencesSpeciales = competencesSpeciales; } public String getCentresInteret() { return centresInteret; } public void setCentresInteret(String centresInteret) { this.centresInteret = centresInteret; } public String getCommentaires() { return commentaires; } public void setCommentaires(String commentaires) { this.commentaires = commentaires; } public String getPhotoPath() { return photoPath; } public void setPhotoPath(String photoPath) { this.photoPath = photoPath; } public List getDocumentsJoints() { return documentsJoints; } public void setDocumentsJoints(List documentsJoints) { this.documentsJoints = documentsJoints; } public org.primefaces.model.file.UploadedFile getUploadedPhoto() { return uploadedPhoto; } public void setUploadedPhoto(org.primefaces.model.file.UploadedFile uploadedPhoto) { this.uploadedPhoto = uploadedPhoto; } public String getPhotoBase64() { return photoBase64; } public void setPhotoBase64(String photoBase64) { this.photoBase64 = photoBase64; } public String getOrganisationId() { return organisationId; } public void setOrganisationId(String organisationId) { this.organisationId = organisationId; } public String getOrganisationNom() { return organisationNom; } public void setOrganisationNom(String organisationNom) { this.organisationNom = organisationNom; } public List getOrganisationsDisponibles() { return organisationsDisponibles; } public void setOrganisationsDisponibles(List organisationsDisponibles) { this.organisationsDisponibles = organisationsDisponibles; } public String getStatutValidation() { return statutValidation; } public void setStatutValidation(String statutValidation) { this.statutValidation = statutValidation; } // Listes pour les sélections public List getSexeOptions() { List options = new ArrayList<>(); options.add("Masculin"); options.add("Féminin"); return options; } public List getSituationMatrimonialeOptions() { List options = new ArrayList<>(); options.add("Célibataire"); options.add("Marié(e)"); options.add("Divorcé(e)"); options.add("Veuf(ve)"); return options; } public List getTypeAdhesionOptions() { List options = new ArrayList<>(); options.add("Membre actif"); options.add("Membre associé"); options.add("Membre bienfaiteur"); options.add("Membre honoraire"); return options; } public List getContactUrgenceLienOptions() { List options = new ArrayList<>(); options.add("Conjoint(e)"); options.add("Parent"); options.add("Enfant"); options.add("Frère/Sœur"); options.add("Ami(e)"); options.add("Autre"); return options; } }