From 9964e964ceffa393b26a7ef5d31c2ebfb4bc6df9 Mon Sep 17 00:00:00 2001 From: kenza Date: Tue, 8 Sep 2026 17:48:53 +0100 Subject: [PATCH] #406 --- .../triz/trizservice/bean/DicomPacsBean.java | 453 +++++- .../trizservice/bean/ExamenDetailBean.java | 52 +- .../triz/trizservice/bean/PatientBean.java | 727 ++++++++++ .../trizservice/bean/PatientDetailBean.java | 1126 +++++++++++++++ .../bean/TypeAlerteMedicaleConverter.java | 73 + .../bean/converter/WilayaConverter.java | 37 +- .../trizservice/modeles/AlertesMedicales.java | 13 +- .../trizservice/modeles/FichierDossier.java | 12 +- .../com/triz/trizservice/modeles/Patient.java | 31 + .../com/triz/trizservice/modeles/Queue.java | 11 +- .../triz/trizservice/service/DaoService.java | 4 + .../service/TransactionService.java | 6 + .../service/impl/DaoServiceImpl.java | 27 +- .../service/impl/TransactionServiceImpl.java | 20 +- .../db/migration/V000__main_schema.sql | 15 +- .../resources/langue/message_fr.properties | 96 +- .../webapp/WEB-INF/layout/sections/menu.xhtml | 2 +- .../WEB-INF/layout/sections/topbar.xhtml | 16 +- src/main/webapp/WEB-INF/layout/template.xhtml | 5 +- src/main/webapp/views/Examen/form.xhtml | 3 +- src/main/webapp/views/Examen/list.xhtml | 3 +- src/main/webapp/views/patient/form.xhtml | 1270 ++++++++++++++++- src/main/webapp/views/patient/list.xhtml | 665 ++++++++- 23 files changed, 4528 insertions(+), 139 deletions(-) create mode 100644 src/main/java/com/triz/trizservice/bean/PatientBean.java create mode 100644 src/main/java/com/triz/trizservice/bean/PatientDetailBean.java create mode 100644 src/main/java/com/triz/trizservice/bean/TypeAlerteMedicaleConverter.java diff --git a/src/main/java/com/triz/trizservice/bean/DicomPacsBean.java b/src/main/java/com/triz/trizservice/bean/DicomPacsBean.java index 47a1ed1..982928f 100644 --- a/src/main/java/com/triz/trizservice/bean/DicomPacsBean.java +++ b/src/main/java/com/triz/trizservice/bean/DicomPacsBean.java @@ -1,27 +1,25 @@ package com.triz.trizservice.bean; import com.triz.trizservice.modeles.Centre; +import com.triz.trizservice.modeles.Examen; import com.triz.trizservice.modeles.Machine; import com.triz.trizservice.modeles.ServiceUser; import com.triz.trizservice.modeles.TypeMachine; import com.triz.trizservice.security.impl.PingService; import com.triz.trizservice.service.TransactionService; import com.triz.util.UtilContext; -import java.io.BufferedReader; -import java.io.InputStreamReader; + import java.io.Serializable; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Date; import java.util.List; -import java.util.UUID; import javax.annotation.PostConstruct; import javax.faces.application.FacesMessage; -import javax.faces.bean.ManagedBean; -import javax.faces.bean.ViewScoped; import javax.faces.context.FacesContext; + import org.primefaces.PrimeFaces; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; @@ -33,14 +31,15 @@ public class DicomPacsBean implements Serializable { private static final long serialVersionUID = 1L; - // TODO : remplacer par l'injection du DAO réel (DaoServiceImpl / EJB) - // quand le mapping table sera défini. + // ============================================================ + // ATTRIBUTS + // ============================================================ private List machines; private Machine selectedMachine; + private Centre centre; private ServiceUser user; - private Date dernierMajOrthanc; private String etatMwlScp; private Date dernierEtudeRecu; @@ -53,141 +52,451 @@ public class DicomPacsBean implements Serializable { @Autowired private PingService pingService; + // ============================================================ + // INITIALISATION + // ============================================================ @PostConstruct public void init() { + centre = context.getCurrentEtablissement(); user = context.getCurrentUser(); + machines = new ArrayList<>(); - machines = service.getAllByCentre(Machine.class, centre); + + if (centre != null) { + machines = service.getAllByCentre(Machine.class, centre); + } + selectedMachine = new Machine(); - context.saveNewManipulation("Machine", "", "Consulter Machine", new Date(), new Date(), user, "", ""); - // Valeurs d'en-tête neutres pour l'instant (pas de source de données branchée) - dernierMajOrthanc = null; + + // -------------------------------------------------------- + // Manipulation : consultation de la liste des machines + // -------------------------------------------------------- + context.saveNewManipulation( + "Machine", + "", + "CONSULTATION Machine", + new Date(), + new Date(), + user, + "", + "" + ); + + // -------------------------------------------------------- + // Etat MWL / SCP + // -------------------------------------------------------- etatMwlScp = "Actif"; + + // -------------------------------------------------------- + // Dernière étude reçue + // -------------------------------------------------------- dernierEtudeRecu = null; + + if (centre != null) { + + Examen examen = service.getLastExamenByCentre(centre); + + if (examen != null) { + + Calendar calDate = Calendar.getInstance(); + calDate.setTime(examen.getDate()); + + Calendar calHeure = Calendar.getInstance(); + calHeure.setTime(examen.getHeureDebut()); + + calDate.set( + Calendar.HOUR_OF_DAY, + calHeure.get(Calendar.HOUR_OF_DAY) + ); + + calDate.set( + Calendar.MINUTE, + calHeure.get(Calendar.MINUTE) + ); + + calDate.set( + Calendar.SECOND, + calHeure.get(Calendar.SECOND) + ); + + calDate.set( + Calendar.MILLISECOND, + 0 + ); + + dernierEtudeRecu = calDate.getTime(); + } + } + + // -------------------------------------------------------- + // Démarrage du ping + // -------------------------------------------------------- pingService.startPingThread(); } + // ============================================================ + // NOUVELLE MACHINE + // ============================================================ public void prepareNew() { + selectedMachine = new Machine(); + + selectedMachine.setFkCentre(centre); + + PrimeFaces.current() + .ajax() + .update(":dicomPacsForm:dlgMachine"); } + // ============================================================ + // MODIFICATION MACHINE + // ============================================================ public void prepareEdit(Machine machine) { + selectedMachine = machine; - PrimeFaces.current().ajax().update(":dicomPacsForm:dlgMachine"); + + PrimeFaces.current() + .ajax() + .update(":dicomPacsForm:dlgMachine"); } + // ============================================================ + // SAUVEGARDE MACHINE + // ============================================================ public void saveMachine() { + try { - if (selectedMachine.getId() == null) { + + // IMPORTANT : + // On vérifie si elle est nouvelle AVANT le save() + boolean estNouveau = (selectedMachine.getId() == null); + + if (estNouveau) { selectedMachine.setFkCentre(centre); - machines.add(selectedMachine); - addMessage(FacesMessage.SEVERITY_INFO, "Succès", "Machine ajoutée avec succès"); } else { + selectedMachine.setLastUpdate(new Date()); - addMessage(FacesMessage.SEVERITY_INFO, "Succès", "Machine modifiée avec succès"); - } + + // ---------------------------------------------------- + // Sauvegarde + // ---------------------------------------------------- service.save(selectedMachine); - if (selectedMachine.getId() == null) { - context.saveNewManipulation("Machine", selectedMachine.getId().toString(), "Ajouter Machine", new Date(), new Date(), user, "", ""); - } else { - context.saveNewManipulation("Machine", selectedMachine.getId().toString(), "Modifier Machine", new Date(), new Date(), user, "", ""); - } + // ---------------------------------------------------- + // Recharger la liste + // ---------------------------------------------------- + machines = service.getAllByCentre( + Machine.class, + centre + ); + + // ---------------------------------------------------- + // Historique + // ---------------------------------------------------- + context.saveNewManipulation( + "Machine", + selectedMachine.getId().toString(), + estNouveau + ? "CREATION Machine" + : "MODIFICATION Machine", + new Date(), + new Date(), + user, + "", + "" + ); + + // ---------------------------------------------------- + // Message + // ---------------------------------------------------- + String message = estNouveau + ? "Machine ajoutée avec succès" + : "Machine modifiée avec succès"; + + addMessage( + FacesMessage.SEVERITY_INFO, + "Succès", + message + ); + } catch (Exception e) { - System.out.println(e.getMessage()); - addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Une erreur est survenue lors de l'enregistrement"); + + e.printStackTrace(); + + addMessage( + FacesMessage.SEVERITY_ERROR, + "Erreur", + "Une erreur est survenue lors de l'enregistrement" + ); } } + // ============================================================ + // SUPPRESSION / DESACTIVATION MACHINE + // ============================================================ public void deleteMachine() { + try { + selectedMachine.setActif(Boolean.FALSE); selectedMachine.setLastUpdate(new Date()); + + // ---------------------------------------------------- + // Sauvegarde + // ---------------------------------------------------- service.save(selectedMachine); - context.saveNewManipulation("Machine", selectedMachine.getId().toString(), "Desactiver Machine", new Date(), new Date(), user, "", ""); - addMessage(FacesMessage.SEVERITY_INFO, "Succès", "Machine supprimée avec succès"); + + // ---------------------------------------------------- + // Historique + // ---------------------------------------------------- + context.saveNewManipulation( + "Machine", + selectedMachine.getId().toString(), + "DESACTIVATION Machine", + new Date(), + new Date(), + user, + "", + "" + ); + + // ---------------------------------------------------- + // Recharger + // ---------------------------------------------------- + machines = service.getAllByCentre( + Machine.class, + centre + ); + + addMessage( + FacesMessage.SEVERITY_INFO, + "Succès", + "Machine désactivée avec succès" + ); + } catch (Exception e) { - System.out.println(e.getMessage()); - addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Une erreur est survenue lors de la suppression"); + + e.printStackTrace(); + + addMessage( + FacesMessage.SEVERITY_ERROR, + "Erreur", + "Une erreur est survenue lors de la suppression" + ); } } - private void addMessage(FacesMessage.Severity severity, String summary, String detail) { - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, summary, detail)); + // ============================================================ + // ACTIVER / DESACTIVER MACHINE + // ============================================================ + public void toggleActif() { + + try { + + boolean nouvelEtat + = !Boolean.TRUE.equals( + selectedMachine.getActif() + ); + + selectedMachine.setActif(nouvelEtat); + selectedMachine.setLastUpdate(new Date()); + + // ---------------------------------------------------- + // Sauvegarde + // ---------------------------------------------------- + service.save(selectedMachine); + + // ---------------------------------------------------- + // Historique + // ---------------------------------------------------- + context.saveNewManipulation( + "Machine", + selectedMachine.getId().toString(), + nouvelEtat + ? "ACTIVATION Machine" + : "DESACTIVATION Machine", + new Date(), + new Date(), + user, + "", + "" + ); + + // ---------------------------------------------------- + // Recharger + // ---------------------------------------------------- + machines = service.getAllByCentre( + Machine.class, + centre + ); + + // ---------------------------------------------------- + // Message + // ---------------------------------------------------- + String msg = nouvelEtat + ? "Machine réactivée avec succès" + : "Machine désactivée avec succès"; + + addMessage( + FacesMessage.SEVERITY_INFO, + "Succès", + msg + ); + + } catch (Exception e) { + + e.printStackTrace(); + + addMessage( + FacesMessage.SEVERITY_ERROR, + "Erreur", + "Une erreur est survenue" + ); + } } + // ============================================================ + // STATUTS DISPONIBLES + // ============================================================ public List getStatutsDisponibles() { - return Arrays.asList("Actif", "Inactif", "Indisponible"); + + return Arrays.asList( + "Actif", + "Inactif", + "Indisponible" + ); } + // ============================================================ + // TYPES DE MACHINE + // ============================================================ public List getTypesMachineDisponibles() { - // TODO : brancher sur le tab "Types de machines" de Paramétrage une fois l'entité TypeMachine exposée - return service.findAll(TypeMachine.class); + + return service.findAll( + TypeMachine.class + ); } - // ===== Getters / Setters ===== - public List getMachines() { - return machines; - } - - public void setMachines(List machines) { - this.machines = machines; - } - - public Machine getSelectedMachine() { - return selectedMachine; - } - - public void setSelectedMachine(Machine selectedMachine) { - this.selectedMachine = selectedMachine; - } -// Supprimer le champ dernierMajOrthanc et son setter, garder seulement ce getter : - + // ============================================================ + // DERNIERE MAJ ORTHANC + // ============================================================ public Date getDernierMajOrthanc() { + + if (machines == null) { + return null; + } + return machines.stream() - .filter(m -> "Orthanc Principal".equals(m.getNom())) + .filter(m + -> "Orthanc Principal".equals( + m.getNom() + ) + ) .map(Machine::getLastUpdate) .findFirst() .orElse(null); } + // ============================================================ + // ETAT MWL SCP + // ============================================================ public String getEtatMwlScp() { + return etatMwlScp; } public void setEtatMwlScp(String etatMwlScp) { + this.etatMwlScp = etatMwlScp; } - public java.util.Date getDernierEtudeRecu() { + // ============================================================ + // DERNIERE ETUDE RECUE + // ============================================================ + public Date getDernierEtudeRecu() { + return dernierEtudeRecu; } - public void setDernierEtudeRecu(java.util.Date dernierEtudeRecu) { + public void setDernierEtudeRecu( + Date dernierEtudeRecu) { + this.dernierEtudeRecu = dernierEtudeRecu; } - public void toggleActif() { - try { - boolean nouvelEtat = !Boolean.TRUE.equals(selectedMachine.getActif()); - selectedMachine.setActif(nouvelEtat); - selectedMachine.setLastUpdate(new Date()); - service.save(selectedMachine); - context.saveNewManipulation("Machine", selectedMachine.getId().toString(), "reactiver Machine", new Date(), new Date(), user, "", ""); - // TODO : persister le changement via le DAO réel (merge) + // ============================================================ + // ETAT GLOBAL DU PING + // ============================================================ + public boolean isActif() { - String msg = nouvelEtat ? "Machine réactivée avec succès" : "Machine désactivée avec succès"; - addMessage(FacesMessage.SEVERITY_INFO, "Succès", msg); - } catch (Exception e) { - addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Une erreur est survenue"); - } - } - - public boolean isActif() { return pingService.isActif(); } + + // ============================================================ + // MESSAGE + // ============================================================ + private void addMessage( + FacesMessage.Severity severity, + String summary, + String detail) { + + FacesContext.getCurrentInstance() + .addMessage( + null, + new FacesMessage( + severity, + summary, + detail + ) + ); + } + + // ============================================================ + // GETTERS / SETTERS + // ============================================================ + public List getMachines() { + + return machines; + } + + public void setMachines( + List machines) { + + this.machines = machines; + } + + public Machine getSelectedMachine() { + + return selectedMachine; + } + + public void setSelectedMachine( + Machine selectedMachine) { + + this.selectedMachine = selectedMachine; + } + + public Centre getCentre() { + + return centre; + } + + public void setCentre(Centre centre) { + + this.centre = centre; + } + + public ServiceUser getUser() { + + return user; + } + + public void setUser(ServiceUser user) { + + this.user = user; + } } diff --git a/src/main/java/com/triz/trizservice/bean/ExamenDetailBean.java b/src/main/java/com/triz/trizservice/bean/ExamenDetailBean.java index ab3ce9b..c8e3a92 100644 --- a/src/main/java/com/triz/trizservice/bean/ExamenDetailBean.java +++ b/src/main/java/com/triz/trizservice/bean/ExamenDetailBean.java @@ -115,6 +115,16 @@ public class ExamenDetailBean implements Serializable { .findFirst() .orElse(null); } + context.saveNewManipulation( + "Examen", + examen.getId().toString(), + "CONSULTATION Examen", + new Date(), + new Date(), + user, + "", + "" + ); } allMedecins = service.getAllMedecinByCenter(centre); } @@ -227,6 +237,16 @@ public class ExamenDetailBean implements Serializable { public void enregistrerObservation() { if (examen != null) { service.save(examen); + context.saveNewManipulation( + "Examen", + examen.getId().toString(), + "MODIFICATION Observation", + new Date(), + new Date(), + user, + "", + "" + ); } this.editObservation = false; } @@ -603,6 +623,16 @@ public class ExamenDetailBean implements Serializable { examen.setFkInterpreteurAssi(medecin); System.out.println(" examen.setFkInterpreteurAssi " + examen.getFkInterpreteurAssi()); service.save(examen); + context.saveNewManipulation( + "Examen", + examen.getId().toString(), + "MODIFICATION Interpréteur assigné", + new Date(), + new Date(), + user, + "", + "" + ); } else { selectedMedecinId = examen.getFkInterpreteurAssi() != null ? examen.getFkInterpreteurAssi().getId().toString() @@ -624,7 +654,16 @@ public class ExamenDetailBean implements Serializable { Medecin medecinCourant = service.getMedecinByUser(user); examen.setManipulateur(medecinCourant); service.save(examen); - + context.saveNewManipulation( + "Examen", + examen.getId().toString(), + "VALIDATION Examen", + new Date(), + new Date(), + user, + "", + "" + ); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "", getMsg("distribution.message.consultationValidee"))); @@ -641,7 +680,16 @@ public class ExamenDetailBean implements Serializable { examen.setAnnule(true); examen.setHeureFin(new Date()); service.save(examen); - + context.saveNewManipulation( + "Examen", + examen.getId().toString(), + "ANNULATION Examen", + new Date(), + new Date(), + user, + "", + "" + ); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "", getMsg("distribution.message.consultationAnnulee"))); diff --git a/src/main/java/com/triz/trizservice/bean/PatientBean.java b/src/main/java/com/triz/trizservice/bean/PatientBean.java new file mode 100644 index 0000000..698a6d7 --- /dev/null +++ b/src/main/java/com/triz/trizservice/bean/PatientBean.java @@ -0,0 +1,727 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package com.triz.trizservice.bean; + +import com.triz.trizservice.modeles.Centre; +import com.triz.trizservice.modeles.Examen; +import com.triz.trizservice.modeles.Patient; +import com.triz.trizservice.modeles.Queue; +import com.triz.trizservice.modeles.Wilaya; +import com.triz.trizservice.service.TransactionService; +import com.triz.util.UtilContext; +import java.io.Serializable; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.annotation.PostConstruct; +import javax.faces.application.FacesMessage; +import javax.faces.context.FacesContext; +import org.primefaces.model.StreamedContent; +import org.springframework.beans.factory.annotation.Autowired; + +import org.springframework.context.annotation.Scope; + +import org.springframework.stereotype.Component; + +// PDF (OpenPDF / com.lowagie.text) +import com.lowagie.text.Document; +import com.lowagie.text.Element; +import com.lowagie.text.Font; +import com.lowagie.text.FontFactory; +import com.lowagie.text.PageSize; +import com.lowagie.text.Paragraph; +import com.lowagie.text.Phrase; +import com.lowagie.text.pdf.PdfPCell; +import com.lowagie.text.pdf.PdfPTable; +import com.lowagie.text.pdf.PdfWriter; +import com.triz.util.UtilFile; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.Period; +import java.time.ZoneId; +import java.util.Date; +import static org.apache.commons.math3.stat.ranking.TiesStrategy.RANDOM; + +// Excel (Apache POI) +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.primefaces.PrimeFaces; +import org.primefaces.model.DefaultStreamedContent; + +@Component("patientBean") +@Scope("view") +public class PatientBean implements Serializable { + + // TODO : remplacer par votre service DAO existant (même pattern que DaoServiceImpl utilisé ailleurs) + @Autowired + private TransactionService service; + @Autowired + private UtilContext context; // TODO : remplacer par le vrai service/DAO + + // Réutilise la méthode déjà en place pour retrouver l'Examen d'une Queue + private List patientList; + private Centre centre; + + private static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + private static final SecureRandom RANDOM = new SecureRandom(); + + // Cache id patient -> a déjà un examen (évite de recalculer à chaque rendu de ligne du dataTable) + private final Map dejaExamenCache = new HashMap<>(); + + @PostConstruct + public void init() { + chargerPatients(); + } + + public void chargerPatients() { + centre = context.getCurrentEtablissement(); + patientList = service.getAllByCentre(Patient.class, centre); + dejaExamenCache.clear(); + } + + public List getPatientList() { + return patientList; + } + + /** + * Vrai si le patient a au moins une Queue déjà associée à un Examen -> + * déclenche l'indicateur orange dans la liste. + */ + public boolean isPatientADejaExamen(Patient patient) { + if (patient == null || patient.getId() == null) { + return false; + } + return dejaExamenCache.computeIfAbsent(patient.getId(), id -> { + List queues = patient.getQueueList(); + if (queues == null) { + return false; + } + for (Queue q : queues) { + Examen e = getExamenByQueue(q); + if (e != null) { + return true; + } + } + return false; + }); + } + + /** + * Classe CSS appliquée à la ligne du p:dataTable (bordure orange à gauche). + */ + public String getRowStyleClass(Patient patient) { + return isPatientADejaExamen(patient) ? "patient-row-deja-examen" : null; + } + + /** + * Conservée pour compatibilité si utilisée ailleurs (ex. lien direct vers + * un formulaire patient vierge) ; l'"Ajouter" de la liste passe désormais + * par ouvrirAjoutPatient() + le dialog, pas par cette navigation. + */ + public String ajouterPatient() { + return "/views/patient/form.xhtml?faces-redirect=true"; + } + + public String consulterPatient(Patient patient) { + return "/views/patient/form.xhtml?faces-redirect=true&patient=" + patient.getId(); + } + + public void basculerStatut(Patient patient) { + patient.setActif(!Boolean.TRUE.equals(patient.getActif())); + service.save(patient); + } + + public Examen getExamenByQueue(Queue queue) { + + List examens = service.getExamenByQueue(queue); + + if (examens == null || examens.isEmpty()) { + return null; + } + + for (Examen examen : examens) { + if (Boolean.FALSE.equals(examen.getAnnule())) { + return examen; + } + } + + return examens.get(0); + } + + // --------------------------------------------------------------- + // Ajout d'un nouveau patient (dialog "Nouveau patient") + // --------------------------------------------------------------- + private Patient nouveauPatient; + private List allWilayas; + + private static final String CODE_PATIENT_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + private static final int CODE_PATIENT_LONGUEUR = 10; + private static final int CODE_PATIENT_TENTATIVES_MAX = 5; + + public void ouvrirAjoutPatient() { + nouveauPatient = new Patient(); + nouveauPatient.setActif(true); + if (allWilayas == null) { + allWilayas = service.findAll(Wilaya.class); // TODO : adapter à la vraie méthode du service (triée par code) + } + } + + public void enregistrerNouveauPatient() { + if (nouveauPatient == null) { + return; + } + + if (patientInvalide(nouveauPatient)) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_WARN, + "Champs obligatoires manquants", + "Le nom et le prénom sont obligatoires")); + return; + } + + nouveauPatient.setCreeLe(new Date()); + nouveauPatient.setFkCentre(centre); // TODO : adapter si un autre mécanisme assigne le centre courant + + try { + sauvegarderAvecCodeUnique(nouveauPatient); + } catch (RuntimeException e) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, + "Erreur lors de la création du patient", e.getMessage())); + return; + } + + if (patientList != null) { + patientList.add(0, nouveauPatient); + } + dejaExamenCache.remove(nouveauPatient.getId()); + + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Patient créé", + nouveauPatient.getPrenom() + " " + nouveauPatient.getNom())); + + nouveauPatient = null; + } + + /** + * Génère un code_patient (contrainte unique en base) et sauvegarde, en + * réessayant avec un nouveau code en cas de collision. + * + * TODO : le catch(RuntimeException) est un filet générique — remplace-le + * par l'exception réelle de violation de contrainte unique de ta stack (ex. + * org.springframework.dao.DataIntegrityViolationException si Spring + * Data/JPA, ou l'exception équivalente levée par ton + * TransactionService.save(...)), pour ne pas masquer d'autres erreurs de + * sauvegarde sous ce même retry. + */ + private void sauvegarderAvecCodeUnique(Patient patient) { + String code = genererCodePatient(); + while (service.getPatientByCode(code) != null) { + code = genererCodePatient(); + } + patient.setCodePatient(genererCodePatient()); + + service.save(patient); + PrimeFaces.current().executeScript("PF('dlgPatient').hide();"); + + } + + public String genererCodePatient() { + StringBuilder code = new StringBuilder(); + + for (int i = 0; i < 10; i++) { + code.append(CHARS.charAt(RANDOM.nextInt(CHARS.length()))); + } + + return code.toString(); + } + + private boolean patientInvalide(Patient patient) { + + return patient == null + || patient.getNom() == null + || patient.getPrenom() == null + || patient.getDateNaissance() == null + || patient.getSexe() == null + || patient.getTelephone() == null + || patient.getAdresse() == null; + } + + public Patient getNouveauPatient() { + return nouveauPatient; + } + + public void setNouveauPatient(Patient nouveauPatient) { + this.nouveauPatient = nouveauPatient; + } + + public List getAllWilayas() { + return allWilayas; + } + + public StreamedContent exportListePatientsPdf() { + + try { + + String fileName = "Liste_Patients_" + System.currentTimeMillis() + ".pdf"; + + File file = new File( + UtilFile.getFilePath( + "PDF", + fileName + ) + ); + + file.getParentFile().mkdirs(); + + Document document = new Document(PageSize.A4.rotate()); + + PdfWriter.getInstance( + document, + new FileOutputStream(file) + ); + + document.open(); + + Font centreFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, + 16 + ); + + Font titleFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, + 14, + Font.UNDERLINE + ); + + Font infoFont = FontFactory.getFont( + FontFactory.HELVETICA, + 10 + ); + + Paragraph centreParagraph = new Paragraph( + centre != null ? centre.getName() : "", + centreFont + ); + + centreParagraph.setAlignment(Element.ALIGN_CENTER); + + document.add(centreParagraph); + + document.add(new Paragraph(" ")); + + Paragraph title = new Paragraph( + "Liste des patients", + titleFont + ); + + title.setAlignment(Element.ALIGN_CENTER); + + document.add(title); + + document.add(new Paragraph(" ")); + + Paragraph dateGeneration = new Paragraph( + "Date de génération : " + + new SimpleDateFormat("dd/MM/yyyy HH:mm") + .format(new Date()), + infoFont + ); + + dateGeneration.setAlignment(Element.ALIGN_RIGHT); + + document.add(dateGeneration); + + document.add(new Paragraph(" ")); + + PdfPTable table = new PdfPTable(9); + + table.setWidthPercentage(100); + + table.setWidths(new float[]{ + 12f, // Code + 15f, // Nom + 15f, // Prénom + 8f, // Sexe + 13f, // Date naissance + 7f, // Age + 13f, // Téléphone + 17f, // Email + 10f // Status + }); + + Font headerFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, + 10 + ); + PdfPCell cell; + + cell = new PdfPCell(new Phrase("Code", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Nom", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Prénom", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Sexe", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Date naissance", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Age", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Téléphone", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Email", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Status", headerFont)); + cell.setBorderWidth(1); + table.addCell(cell); + + Font rowFont = FontFactory.getFont( + FontFactory.HELVETICA, + 9 + ); + + SimpleDateFormat sdfDate = new SimpleDateFormat("dd/MM/yyyy"); + + for (Patient p : patientList) { + + table.addCell(new Phrase( + p.getCodePatient() != null ? p.getCodePatient() : "", + rowFont)); + + table.addCell(new Phrase( + p.getNom() != null ? p.getNom() : "", + rowFont)); + + table.addCell(new Phrase( + p.getPrenom() != null ? p.getPrenom() : "", + rowFont)); + + table.addCell(new Phrase( + p.getSexe() != null ? p.getSexe() : "", + rowFont)); + + table.addCell(new Phrase( + p.getDateNaissance() != null + ? sdfDate.format(p.getDateNaissance()) + : "", + rowFont)); + + table.addCell(new Phrase( + calculerAge(p.getDateNaissance()) != null ? String.valueOf(calculerAge(p.getDateNaissance())) : "-", + rowFont)); + + table.addCell(new Phrase( + p.getTelephone() != null ? p.getTelephone() : "", + rowFont)); + + table.addCell(new Phrase( + p.getEmail() != null ? p.getEmail() : "", + rowFont)); + + table.addCell(new Phrase( + Boolean.TRUE.equals(p.getActif()) ? "Actif" : "Inactif", + rowFont)); + } + + document.add(table); + + document.close(); + + return DefaultStreamedContent.builder() + .name(fileName) + .contentType("application/pdf") + .stream(() -> { + try { + return new FileInputStream(file); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + }) + .build(); + + } catch (Exception e) { + + e.printStackTrace(); + } + + return null; + } + + public StreamedContent exportListePatientsExcel() { + + try { + + String fileName = "Liste_Patients_" + System.currentTimeMillis() + ".xlsx"; + + File file = new File( + UtilFile.getFilePath( + "Excel", + fileName + ) + ); + + file.getParentFile().mkdirs(); + + Workbook workbook = new XSSFWorkbook(); + + Sheet sheet = workbook.createSheet("Patients"); + + sheet.addMergedRegion( + new CellRangeAddress(0, 0, 0, 8)); + + sheet.addMergedRegion( + new CellRangeAddress(2, 2, 0, 8)); + + sheet.addMergedRegion( + new CellRangeAddress(4, 4, 0, 8)); + + /* + * STYLE TITRE + */ + CellStyle titleStyle = workbook.createCellStyle(); + + org.apache.poi.ss.usermodel.Font titleFont = workbook.createFont(); + titleFont.setBold(true); + titleFont.setUnderline(org.apache.poi.ss.usermodel.Font.U_SINGLE); + titleFont.setFontHeightInPoints((short) 14); + + titleStyle.setFont(titleFont); + titleStyle.setAlignment(HorizontalAlignment.CENTER); + /* + * STYLE ENTETE + */ + CellStyle headerStyle = workbook.createCellStyle(); + + org.apache.poi.ss.usermodel.Font headerFont = workbook.createFont(); + headerFont.setBold(true); + + headerStyle.setFont(headerFont); + + headerStyle.setBorderTop(BorderStyle.THIN); + headerStyle.setBorderBottom(BorderStyle.THIN); + headerStyle.setBorderLeft(BorderStyle.THIN); + headerStyle.setBorderRight(BorderStyle.THIN); + + headerStyle.setAlignment(HorizontalAlignment.CENTER); + + /* + * STYLE DONNEES + */ + CellStyle dataStyle = workbook.createCellStyle(); + + dataStyle.setBorderTop(BorderStyle.THIN); + dataStyle.setBorderBottom(BorderStyle.THIN); + dataStyle.setBorderLeft(BorderStyle.THIN); + dataStyle.setBorderRight(BorderStyle.THIN); + + int rowNum = 0; + + Row centreRow = sheet.createRow(rowNum++); + centreRow.setHeightInPoints(25); + + Cell centreCell = centreRow.createCell(0); + + centreCell.setCellValue( + centre != null ? centre.getName() : ""); + + centreCell.setCellStyle(titleStyle); + + rowNum++; + + Row titleRow = sheet.createRow(rowNum++); + titleRow.setHeightInPoints(25); + + Cell titleCell = titleRow.createCell(0); + + titleCell.setCellValue("Liste des patients"); + + titleCell.setCellStyle(titleStyle); + + rowNum++; + + Row dateRow = sheet.createRow(rowNum++); + + Cell dateCell = dateRow.createCell(0); + + dateCell.setCellValue( + "Date de génération : " + + new SimpleDateFormat("dd/MM/yyyy HH:mm") + .format(new Date())); + + rowNum += 2; + + /* + * ENTETES + */ + Row header = sheet.createRow(rowNum++); + + String[] headers = { + "Code Patient", + "Nom", + "Prénom", + "Sexe", + "Date naissance", + "Age", + "Téléphone", + "Email", + "Status" + }; + + for (int i = 0; i < headers.length; i++) { + + Cell cell = header.createCell(i); + + cell.setCellValue(headers[i]); + + cell.setCellStyle(headerStyle); + } + + SimpleDateFormat sdfDate + = new SimpleDateFormat("dd/MM/yyyy"); + + /* + * DONNEES + */ + for (Patient p : patientList) { + + Row row = sheet.createRow(rowNum++); + + Cell c0 = row.createCell(0); + c0.setCellValue( + p.getCodePatient() != null ? p.getCodePatient() : ""); + c0.setCellStyle(dataStyle); + + Cell c1 = row.createCell(1); + c1.setCellValue( + p.getNom() != null ? p.getNom() : ""); + c1.setCellStyle(dataStyle); + + Cell c2 = row.createCell(2); + c2.setCellValue( + p.getPrenom() != null ? p.getPrenom() : ""); + c2.setCellStyle(dataStyle); + + Cell c3 = row.createCell(3); + c3.setCellValue( + p.getSexe() != null ? p.getSexe() : ""); + c3.setCellStyle(dataStyle); + + Cell c4 = row.createCell(4); + c4.setCellValue( + p.getDateNaissance() != null + ? sdfDate.format(p.getDateNaissance()) + : ""); + c4.setCellStyle(dataStyle); + + Cell c5 = row.createCell(5); + String age = calculerAge(p.getDateNaissance()); + c5.setCellValue(age != null ? age : "-"); + c5.setCellStyle(dataStyle); + + Cell c6 = row.createCell(6); + c6.setCellValue( + p.getTelephone() != null ? p.getTelephone() : ""); + c6.setCellStyle(dataStyle); + + Cell c7 = row.createCell(7); + c7.setCellValue( + p.getEmail() != null ? p.getEmail() : ""); + c7.setCellStyle(dataStyle); + + Cell c8 = row.createCell(8); + c8.setCellValue( + Boolean.TRUE.equals(p.getActif()) ? "Actif" : "Inactif"); + c8.setCellStyle(dataStyle); + } + + /* + * LARGEUR COLONNES + */ + for (int i = 0; i < headers.length; i++) { + sheet.autoSizeColumn(i); + } + + FileOutputStream fos = new FileOutputStream(file); + + workbook.write(fos); + + fos.close(); + workbook.close(); + + return DefaultStreamedContent.builder() + .name(fileName) + .contentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + .stream(() -> { + try { + return new FileInputStream(file); + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .build(); + + } catch (Exception e) { + + e.printStackTrace(); + } + + return null; + } + + public String calculerAge(Date dateNaissance) { + + if (dateNaissance == null) { + return null; + } + + LocalDate naissance; + + if (dateNaissance instanceof java.sql.Date) { + naissance = ((java.sql.Date) dateNaissance).toLocalDate(); + } else { + naissance = dateNaissance.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + } + + int age = Period.between(naissance, LocalDate.now()).getYears(); + + if (age > 0) { + return Integer.toString(age); + } else { + return "-"; + } + } +} diff --git a/src/main/java/com/triz/trizservice/bean/PatientDetailBean.java b/src/main/java/com/triz/trizservice/bean/PatientDetailBean.java new file mode 100644 index 0000000..5a34a3d --- /dev/null +++ b/src/main/java/com/triz/trizservice/bean/PatientDetailBean.java @@ -0,0 +1,1126 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package com.triz.trizservice.bean; + +import com.triz.trizservice.modeles.AlertesMedicales; +import com.triz.trizservice.modeles.Centre; +import com.triz.trizservice.modeles.Consultation; +import com.triz.trizservice.modeles.Examen; +import com.triz.trizservice.modeles.FichierDossier; +import com.triz.trizservice.modeles.Medecin; +import com.triz.trizservice.modeles.Patient; +import com.triz.trizservice.modeles.Queue; +import com.triz.trizservice.modeles.ServiceUser; +import com.triz.trizservice.modeles.TypeAlerteMedical; +import com.triz.trizservice.modeles.Wilaya; +import com.triz.trizservice.service.TransactionService; +import com.triz.util.UtilContext; +import com.triz.util.UtilFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.security.SecureRandom; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import javax.faces.application.FacesMessage; +import javax.faces.context.FacesContext; + +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.primefaces.PrimeFaces; + +import org.primefaces.event.FileUploadEvent; +import org.primefaces.model.DefaultStreamedContent; +import org.primefaces.model.StreamedContent; +import org.primefaces.model.file.UploadedFile; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import com.itextpdf.text.Document; +import com.itextpdf.text.Element; +import com.itextpdf.text.Font; +import com.itextpdf.text.FontFactory; +import com.itextpdf.text.PageSize; +import com.itextpdf.text.Paragraph; +import com.itextpdf.text.Phrase; + +import com.itextpdf.text.pdf.PdfPCell; +import com.itextpdf.text.pdf.PdfPTable; +import com.itextpdf.text.pdf.PdfWriter; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; + +import java.text.SimpleDateFormat; + +import java.util.Date; + +import javax.faces.application.FacesMessage; +import javax.faces.context.FacesContext; + +import org.primefaces.model.DefaultStreamedContent; +import org.primefaces.model.StreamedContent; + +import org.springframework.stereotype.Component; + +/** + * TODO : remplacer TransactionService par le/les vrai(s) service(s)/DAO du + * projet. AlertesMedicales et FichierDossier n'ont pas été fournies : les + * getters/setters supposés ci-dessous sont à adapter aux vrais noms. + */ +@Component("patientDetailBean") +@Scope("session") +public class PatientDetailBean implements Serializable { + + private static final long serialVersionUID = 1L; + + @Autowired + private TransactionService service; // TODO : remplacer par le vrai service/DAO + @Autowired + private UtilContext context; // TODO : remplacer par le vrai service/DAO + + // Lié à f:viewParam name="patient" (nom conservé pour rester compatible + // avec ExamenDetailBean.voirDossierPatient(...) qui construit déjà l'URL ainsi) + private String idPatient; + private Patient patient; + private String modifie; + private String nomDossier = "Patient"; + private ServiceUser user; + private Centre centre; + private List allWilayas; + private boolean editMode = false; + private AlertesMedicales selectedAlerte; + private TypeAlerteMedical selectedTypeAlerte; + private String selectedDescriptionAlerte; + private Date selectedDateAlerte; + + // Mode d'édition global (bouton unique "Modifier" en haut à droite, comme sur la maquette) + public void init() { + System.out.println("idPatient " + idPatient); + centre = context.getCurrentEtablissement(); + user = context.getCurrentUser(); + if (idPatient == null) { + return; + } + patient = service.findById(Patient.class, UUID.fromString(idPatient)); // TODO : adapter à l'appel réel du projet + System.out.println("patient " + patient); + if ("true".equals(modifie)) { + editMode = true; + } + allWilayas = service.findAll(Wilaya.class); // TODO : adapter à la vraie méthode du service, trié par code + patient.getQueueList().removeIf(queue + -> queue.getExamenList() == null + || queue.getExamenList().isEmpty() + ); + context.saveNewManipulation( + "Patient", + patient.getId().toString(), + "CONSULTATION Patient", + new Date(), + new Date(), + user, + "", + "" + ); + + } + + // --------------------------------------------------------------- + // Mode édition global + // --------------------------------------------------------------- + public void toggleEditMode() { + if (editMode) { + enregistrerPatient(); + } else { + editMode = true; + } + } + + public void enregistrerPatient() { + System.out.println("Wilaya = " + patient.getFkWilaya()); + System.out.println("NIS = " + patient.getNis()); + if (patient != null) { + + service.save(patient); // TODO : adapter à la vraie couche de persistance + context.saveNewManipulation( + "Patient", + patient.getId().toString(), + "MODIFICATION Patient", + new Date(), + new Date(), + user, + "", + "" + ); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Patient enregistré", "")); + } + editMode = false; + } + + // Recharge le patient depuis la base pour annuler les modifications non enregistrées + public void annulerEdition() { + if (idPatient != null) { + patient = service.findById(Patient.class, UUID.fromString(idPatient)); + } + editMode = false; + } + + public String retour() { + return "list.xhtml?faces-redirect=true"; + } + + // --------------------------------------------------------------- + // Champs calculés + // --------------------------------------------------------------- + public String getAge() { + if (patient == null || patient.getDateNaissance() == null) { + return null; + } + Calendar naissance = Calendar.getInstance(); + naissance.setTime(patient.getDateNaissance()); + Calendar aujourdHui = Calendar.getInstance(); + int age = aujourdHui.get(Calendar.YEAR) - naissance.get(Calendar.YEAR); + if (aujourdHui.get(Calendar.DAY_OF_YEAR) < naissance.get(Calendar.DAY_OF_YEAR)) { + age--; + } + if (age > 0) { + return Integer.toString(age); + } else { + return "-"; + } + } + + public String getStatusLabel() { + if (patient == null || patient.getActif() == null) { + return ""; + } + return patient.getActif() ? "Actif" : "Inactif"; + } + + public String getStatusBadgeClass() { + if (patient == null || patient.getActif() == null) { + return ""; + } + return patient.getActif() ? "patient-status-actif" : "patient-status-inactif"; + } + + private static final List GROUPAGES = Arrays.asList( + "A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"); + + public List getGroupages() { + return GROUPAGES; + } + + // --------------------------------------------------------------- + // Onglet Fichiers (FichierDossier) + // TODO : entité FichierDossier non fournie ; getters/setters supposés + // d'après la relation Patient.fichierDossierList (mappedBy = "fkDossierMedical") : + // id, date, heur, filePath, fkDossierMedical. Adapter si les vrais noms diffèrent. + // --------------------------------------------------------------- + private static final List EXTENSIONS_AUTORISEES + = Arrays.asList("pdf", "xls", "xlsx", "doc", "docx", "txt", "jpg", "jpeg", "png"); + + public void uploadFichierDossier(FileUploadEvent event) { + + UploadedFile uploadedFile = event.getFile(); + if (uploadedFile == null) { + return; + } + + String nomOriginal = uploadedFile.getFileName(); + String extension = extraireExtension(nomOriginal).toLowerCase(); + + if (!EXTENSIONS_AUTORISEES.contains(extension)) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, + "Type de fichier non autorisé", nomOriginal)); + return; + } + + try { + File destination = new File(UtilFile.getDirectoryName(nomDossier + "/" + nomOriginal)); + + try (InputStream in = uploadedFile.getInputStream()) { + Files.copy(in, destination.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + FichierDossier fichier = new FichierDossier(); + fichier.setDate(new Date()); + fichier.setHeur(new Date()); + fichier.setFilePath(destination.getAbsolutePath()); + fichier.setFkDossierMedical(patient); + + // TODO : adapter à la vraie couche de persistance (même mécanisme que pour le patient) + service.save(fichier); + + patient.getFichierDossierList().add(fichier); + + context.saveNewManipulation( + "Fichier Dossier", + fichier.getId().toString(), + "AJOUT Fichier", + new Date(), + new Date(), + user, + "", + "" + ); + + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Fichier ajouté", nomOriginal)); + + } catch (IOException e) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, + "Erreur lors de l'envoi du fichier", e.getMessage())); + } + } + + public StreamedContent telechargerFichierDossier(FichierDossier fichier) { + + File source = new File(fichier.getFilePath()); + + return DefaultStreamedContent.builder() + .name(new File(fichier.getFilePath()).getName()) + .contentType(determinerContentType(fichier.getFilePath())) + .stream(() -> { + try { + return new FileInputStream(source); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + }) + .build(); + } + + public void supprimerFichierDossier(FichierDossier fichier) { + + if (fichier == null) { + return; + } + + try { + File fichierPhysique = new File(fichier.getFilePath()); + if (fichierPhysique.exists()) { + fichierPhysique.delete(); + } + + service.delete(fichier); // TODO : adapter à la vraie couche de persistance + + patient.getFichierDossierList().remove(fichier); + + context.saveNewManipulation( + "Fichier Dossier", + fichier.getId().toString(), + "SUPPRESSION Fichier", + new Date(), + new Date(), + user, + "", + "" + ); + + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, + "Fichier supprimé", getNomFichier(fichier.getFilePath()))); + + } catch (Exception e) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, + "Erreur lors de la suppression", e.getMessage())); + } + } + + private String extraireExtension(String nomFichier) { + int i = nomFichier.lastIndexOf('.'); + return (i >= 0 && i < nomFichier.length() - 1) ? nomFichier.substring(i + 1) : ""; + } + + private String determinerContentType(String nomFichier) { + switch (extraireExtension(nomFichier).toLowerCase()) { + case "pdf": + return "application/pdf"; + case "xls": + return "application/vnd.ms-excel"; + case "xlsx": + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + case "doc": + return "application/msword"; + case "docx": + return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + case "txt": + return "text/plain"; + default: + return "application/octet-stream"; + } + } + + public String getNomFichier(String filePath) { + if (filePath == null || filePath.trim().isEmpty()) { + return ""; + } + return new File(filePath).getName(); + } + + // --------------------------------------------------------------- + // Onglet Alertes Médicaux (AlertesMedicales) + // TODO : entité AlertesMedicales non fournie ; getters/setters supposés : + // id, typeAlerte, description, dateHeure, fkPatient. Adapter si les vrais noms diffèrent. + // --------------------------------------------------------------- + public List getTypesAlerte() { + return service.findAll(TypeAlerteMedical.class); + } + + public void ajouterAlerte() { + selectedAlerte = null; + selectedTypeAlerte = null; + selectedDescriptionAlerte = null; + selectedDateAlerte = new Date(); + PrimeFaces.current().ajax().update(":form:dlgAlerte"); + } + + public void selectAlerte(AlertesMedicales alerte) { + selectedAlerte = alerte; + selectedTypeAlerte = alerte.getFkTypeAlerteMedical(); + selectedDescriptionAlerte = alerte.getDerscription(); + selectedDateAlerte = alerte.getDate(); + } + + public void enregistrerAlerte() { + if (patient == null) { + return; + } + boolean nouvelleAlerte = (selectedAlerte == null); + if (selectedAlerte == null) { + selectedAlerte = new AlertesMedicales(); + selectedAlerte.setFkPatient(patient); + if (patient.getAlertesMedicalesList() == null) { + patient.setAlertesMedicalesList(new ArrayList<>()); + } + patient.getAlertesMedicalesList().add(selectedAlerte); + } + selectedAlerte.setFkTypeAlerteMedical(selectedTypeAlerte); + selectedAlerte.setDerscription(selectedDescriptionAlerte); + selectedAlerte.setDate(selectedDateAlerte); + + service.save(selectedAlerte); // TODO : adapter à la vraie couche de persistance + + context.saveNewManipulation( + "Patient", + patient.getId().toString(), + nouvelleAlerte ? "AJOUT Alerte médicale" : "MODIFICATION Alerte médicale", + new Date(), + new Date(), + user, + "", + "" + ); + + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Alerte enregistrée", "")); + } + + public void supprimerAlerte() { + if (selectedAlerte == null || patient == null) { + return; + } + service.delete(selectedAlerte); // TODO : adapter à la vraie couche de persistance + patient.getAlertesMedicalesList().remove(selectedAlerte); + context.saveNewManipulation( + "Patient", + patient.getId().toString(), + "SUPPRESSION Alerte médicale", + new Date(), + new Date(), + user, + "", + "" + ); + + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Alerte supprimée", "")); + + selectedAlerte = null; + } + + public AlertesMedicales getSelectedAlerte() { + return selectedAlerte; + } + + public void setSelectedAlerte(AlertesMedicales selectedAlerte) { + this.selectedAlerte = selectedAlerte; + } + + public TypeAlerteMedical getSelectedTypeAlerte() { + return selectedTypeAlerte; + } + + public void setSelectedTypeAlerte(TypeAlerteMedical selectedTypeAlerte) { + this.selectedTypeAlerte = selectedTypeAlerte; + } + + public String getSelectedDescriptionAlerte() { + return selectedDescriptionAlerte; + } + + public void setSelectedDescriptionAlerte(String selectedDescriptionAlerte) { + this.selectedDescriptionAlerte = selectedDescriptionAlerte; + } + + public Date getSelectedDateAlerte() { + return selectedDateAlerte; + } + + public void setSelectedDateAlerte(Date selectedDateAlerte) { + this.selectedDateAlerte = selectedDateAlerte; + } + + // --------------------------------------------------------------- + // Onglet Historique de consultation (même logique que ExamenDetailBean) + // --------------------------------------------------------------- + private Consultation selectedConsultation; + + public void selectConsultation(Consultation consultation) { + this.selectedConsultation = consultation; + } + + public Consultation getSelectedConsultation() { + return selectedConsultation; + } + + public void setSelectedConsultation(Consultation selectedConsultation) { + this.selectedConsultation = selectedConsultation; + } + + public String getTypeConsultation(Consultation consultation) { + if (consultation != null) { + if (consultation.getSessionAnnule() == true) { + return "annule"; + } + if (consultation.getDefinitive() == null || consultation.getBrouillon() == null) { + return "normal"; + } + if (consultation.getDefinitive() == true) { + return "definitve"; + } else { + if (consultation.getBrouillon() == true) { + return "brouillon"; + } else { + return "normal"; + } + } + } else { + return ""; + } + } + + // --------------------------------------------------------------- + // Export Excel de la fiche patient + // --------------------------------------------------------------- + public StreamedContent exportFichePatientExcel() { + + if (patient == null) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_WARN, + "Export impossible", "Aucun patient chargé")); + return null; + } + + try { + String fileName = "Fiche_Patient_" + System.currentTimeMillis() + ".xlsx"; + File file = new File(UtilFile.getFilePath("Excel", fileName)); + file.getParentFile().mkdirs(); + + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("Fiche patient"); + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm"); + + org.apache.poi.ss.usermodel.Font titleFont = workbook.createFont(); + titleFont.setBold(true); + titleFont.setFontHeightInPoints((short) 16); + CellStyle titleStyle = workbook.createCellStyle(); + titleStyle.setFont(titleFont); + + org.apache.poi.ss.usermodel.Font sectionFont = workbook.createFont(); + sectionFont.setBold(true); + CellStyle sectionStyle = workbook.createCellStyle(); + sectionStyle.setFont(sectionFont); + sectionStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + sectionStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + CellStyle valueStyle = workbook.createCellStyle(); + valueStyle.setBorderTop(BorderStyle.THIN); + valueStyle.setBorderBottom(BorderStyle.THIN); + valueStyle.setBorderLeft(BorderStyle.THIN); + valueStyle.setBorderRight(BorderStyle.THIN); + valueStyle.setVerticalAlignment(VerticalAlignment.TOP); + valueStyle.setWrapText(true); + + int rowNum = 0; + + Row row = sheet.createRow(rowNum++); + Cell cell = row.createCell(0); + cell.setCellValue(centre != null ? centre.getName() : "Centre d'imagerie"); + cell.setCellStyle(titleStyle); + + row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue("Fiche patient"); + + row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue("Date édition : " + sdf.format(new Date())); + + rowNum++; + + row = sheet.createRow(rowNum++); + cell = row.createCell(0); + cell.setCellValue("INFORMATIONS PATIENT"); + cell.setCellStyle(sectionStyle); + + ajouterLigne(sheet, rowNum++, "Id patient", patient.getCodePatient()); + ajouterLigne(sheet, rowNum++, "Nom complet", construireNomComplet(patient.getPrenom(), patient.getNom())); + ajouterLigne(sheet, rowNum++, "Sexe", patient.getSexe()); + ajouterLigne(sheet, rowNum++, "NIN", patient.getNin()); + ajouterLigne(sheet, rowNum++, "NIS", patient.getNis()); + ajouterLigne(sheet, rowNum++, "Date de naissance", + patient.getDateNaissance() != null ? sdf.format(patient.getDateNaissance()) : ""); + ajouterLigne(sheet, rowNum++, "Téléphone", patient.getTelephone()); + ajouterLigne(sheet, rowNum++, "Téléphone relative", patient.getTelephoneRelative()); + ajouterLigne(sheet, rowNum++, "Email", patient.getEmail()); + ajouterLigne(sheet, rowNum++, "Wilaya", + patient.getFkWilaya() != null ? patient.getFkWilaya().getName() : ""); + ajouterLigne(sheet, rowNum++, "Adresse", patient.getAdresse()); + ajouterLigne(sheet, rowNum++, "Status", getStatusLabel()); + ajouterLigne(sheet, rowNum++, "Créé le", + patient.getCreeLe() != null ? sdf.format(patient.getCreeLe()) : ""); + ajouterLigne(sheet, rowNum++, "Groupage", patient.getGroupage()); + + rowNum++; + + if (patient.getAlertesMedicalesList() != null && !patient.getAlertesMedicalesList().isEmpty()) { + row = sheet.createRow(rowNum++); + cell = row.createCell(0); + cell.setCellValue("ALERTES MÉDICALES"); + cell.setCellStyle(sectionStyle); + + row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue("Type alerte"); + row.createCell(1).setCellValue("Description"); + row.createCell(2).setCellValue("Date et heure"); + + for (AlertesMedicales alerte : patient.getAlertesMedicalesList()) { + if (alerte == null) { + continue; + } + row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue( + alerte.getFkTypeAlerteMedical() != null && alerte.getFkTypeAlerteMedical().getType() != null + ? alerte.getFkTypeAlerteMedical().getType() : ""); + row.createCell(1).setCellValue(alerte.getDerscription() != null ? alerte.getDerscription() : ""); + row.createCell(2).setCellValue(alerte.getDate() != null ? sdf.format(alerte.getDate()) : ""); + } + } + + for (int i = 0; i < 6; i++) { + sheet.autoSizeColumn(i); + } + + FileOutputStream fos = new FileOutputStream(file); + workbook.write(fos); + fos.close(); + workbook.close(); + + return DefaultStreamedContent.builder() + .name(fileName) + .contentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + .stream(() -> { + try { + return new FileInputStream(file); + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .build(); + + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /** + * Concatène prénom/nom en gérant les null individuellement (évite la chaîne + * littérale "null" que produirait patient.getPrenom() + " " + + * patient.getNom() si l'un des deux champs est vide en base). + */ + private String construireNomComplet(String prenom, String nom) { + String p = prenom != null ? prenom.trim() : ""; + String n = nom != null ? nom.trim() : ""; + String complet = (p + " " + n).trim(); + return complet.isEmpty() ? "-" : complet; + } + + private void ajouterLigne(Sheet sheet, int rowNum, String label, String valeur) { + Row row = sheet.createRow(rowNum); + row.createCell(0).setCellValue(label); + row.createCell(1).setCellValue(valeur != null ? valeur : ""); + } + + // --------------------------------------------------------------- + // Getters / setters + // --------------------------------------------------------------- + public String getIdPatient() { + return idPatient; + } + + public void setIdPatient(String idPatient) { + this.idPatient = idPatient; + } + + public Patient getPatient() { + return patient; + } + + public void setPatient(Patient patient) { + this.patient = patient; + } + + public String getModifie() { + return modifie; + } + + public void setModifie(String modifie) { + this.modifie = modifie; + } + + public boolean isEditMode() { + return editMode; + } + + public void setEditMode(boolean editMode) { + this.editMode = editMode; + } + + public Centre getCentre() { + return centre; + } + + public ServiceUser getUser() { + return user; + } + + public String getTailleFichier(FichierDossier fichier) { + if (fichier == null || fichier.getFilePath() == null) { + return ""; + } + File f = new File(fichier.getFilePath()); + if (!f.exists()) { + return ""; + } + return formaterTaille(f.length()); + } + + private String formaterTaille(long bytes) { + if (bytes < 1024) { + return bytes + " o"; + } + double ko = bytes / 1024.0; + if (ko < 1024) { + return String.format("%.1f Ko", ko); + } + double mo = ko / 1024.0; + if (mo < 1024) { + return String.format("%.1f Mo", mo); + } + double go = mo / 1024.0; + return String.format("%.1f Go", go); + } + + // à appeler dans init() + public List getAllWilayas() { + return allWilayas; + } + + public String getDisplayStatus(Queue q) { + if (q == null || q.getStatus() == null) { + return ""; + } + if (getExamenByQueue(q) == null) { + return "Enregistrer"; + } + if (isAnnule(q)) { + return "Annulé"; + } + + Consultation consultation = service.getConsultationByExamen(getExamenByQueue(q)); + if (consultation != null) { + if (consultation.getFilePathSignature() == null) { + return "Préliminaire"; + } else { + return "Signé"; + } + } + if (getExamenByQueue(q).getHeureDebut() != null && getExamenByQueue(q).getHeureFin() == null && getExamenByQueue(q).getAnnule() == false) { + return "En cours"; + } + + if (getExamenByQueue(q).getHeureDebut() != null && getExamenByQueue(q).getHeureFin() != null && getExamenByQueue(q).getAnnule() == false) { + return "Terminé"; + } + + return q.getStatus(); + } + + public Examen getExamenByQueue(Queue queue) { + + List examens = service.getExamenByQueue(queue); + + if (examens == null || examens.isEmpty()) { + return null; + } + + for (Examen examen : examens) { + if (Boolean.FALSE.equals(examen.getAnnule())) { + return examen; + } + } + + return examens.get(0); + } + + private boolean isAnnule(Queue q) { + return getExamenByQueue(q) != null && Boolean.TRUE.equals(getExamenByQueue(q).getAnnule()); + } + + public String getStatusBadgeClass(Queue q) { + String status = getDisplayStatus(q); + if (status == null) { + return ""; + } + switch (status) { + case "Programmé": + return "status-programme"; + case "Enregistré": + return "status-enregistre"; + case "En cours": + return "status-encours"; + case "Terminé": + return "status-termine"; + case "Préliminaire": + return "status-preliminaire"; + case "Signé": + return "status-signe"; + case "Addenda": + return "status-addenda"; + + case "Annulé": + return "status-annule"; + case "Enregistrer": + return "status-enregister"; + default: + return "status-programme"; + } + } + + public String voirExamen(Examen exam) { + return "/views/Examen/form.xhtml?faces-redirect=true&id=" + exam.getId(); + } + + public StreamedContent exportFichePatientPdf() { + + if (patient == null) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_WARN, + "Export impossible", + "Aucun patient chargé")); + return null; + } + + try { + + String fileName = "Fiche_Patient_" + System.currentTimeMillis() + ".pdf"; + + File file = new File( + UtilFile.getFilePath("PDF", fileName) + ); + + file.getParentFile().mkdirs(); + + Document document = new Document(PageSize.A4); + + PdfWriter.getInstance( + document, + new FileOutputStream(file) + ); + + document.open(); + + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + + Font centreFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, 18); + + Font titleFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, 14); + + Font sectionFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, 11); + + Font labelFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, 10); + + Font valueFont = FontFactory.getFont( + FontFactory.HELVETICA, 10); + + // ===================================================== + // ENTETE + // ===================================================== + Paragraph centreParagraph = new Paragraph( + centre != null ? centre.getName() : "Centre d'imagerie", + centreFont); + + centreParagraph.setAlignment(Element.ALIGN_CENTER); + document.add(centreParagraph); + + document.add(new Paragraph(" ")); + + Paragraph titre = new Paragraph( + "FICHE PATIENT", + titleFont); + + titre.setAlignment(Element.ALIGN_CENTER); + + document.add(titre); + + document.add(new Paragraph(" ")); + + Paragraph edition = new Paragraph( + "Date d'édition : " + + new SimpleDateFormat("dd/MM/yyyy HH:mm") + .format(new Date()), + valueFont); + + edition.setAlignment(Element.ALIGN_RIGHT); + + document.add(edition); + + document.add(new Paragraph(" ")); + + // ===================================================== + // INFORMATIONS PATIENT + // ===================================================== + Paragraph section1 = new Paragraph( + "INFORMATIONS PATIENT", + sectionFont); + + document.add(section1); + document.add(new Paragraph(" ")); + + PdfPTable infosTable = new PdfPTable(2); + infosTable.setWidthPercentage(100); + infosTable.setWidths(new float[]{30f, 70f}); + + ajouterLignePdf(infosTable, "Code patient", patient.getCodePatient()); + ajouterLignePdf(infosTable, "Nom complet", + construireNomComplet( + patient.getPrenom(), + patient.getNom())); + + ajouterLignePdf(infosTable, "Sexe", patient.getSexe()); + + ajouterLignePdf(infosTable, "Date naissance", + patient.getDateNaissance() != null + ? sdf.format(patient.getDateNaissance()) + : ""); + + ajouterLignePdf(infosTable, "NIN", patient.getNin()); + ajouterLignePdf(infosTable, "NIS", patient.getNis()); + + ajouterLignePdf(infosTable, "Groupage", patient.getGroupage()); + + ajouterLignePdf(infosTable, "Statut", getStatusLabel()); + + document.add(infosTable); + + document.add(new Paragraph(" ")); + + // ===================================================== + // COORDONNEES + // ===================================================== + Paragraph section2 = new Paragraph( + "COORDONNÉES", + sectionFont); + + document.add(section2); + + document.add(new Paragraph(" ")); + + PdfPTable contactTable = new PdfPTable(2); + contactTable.setWidthPercentage(100); + contactTable.setWidths(new float[]{30f, 70f}); + + ajouterLignePdf(contactTable, + "Téléphone", + patient.getTelephone()); + + ajouterLignePdf(contactTable, + "Téléphone proche", + patient.getTelephoneRelative()); + + ajouterLignePdf(contactTable, + "Email", + patient.getEmail()); + + ajouterLignePdf(contactTable, + "Wilaya", + patient.getFkWilaya() != null + ? patient.getFkWilaya().getName() + : ""); + + ajouterLignePdf(contactTable, + "Adresse", + patient.getAdresse()); + + document.add(contactTable); + + document.add(new Paragraph(" ")); + + // ===================================================== + // ALERTES MEDICALES + // ===================================================== + if (patient.getAlertesMedicalesList() != null + && !patient.getAlertesMedicalesList().isEmpty()) { + + Paragraph section3 = new Paragraph( + "ALERTES MÉDICALES", + sectionFont); + + document.add(section3); + + document.add(new Paragraph(" ")); + + PdfPTable alertesTable = new PdfPTable(3); + + alertesTable.setWidthPercentage(100); + + alertesTable.setWidths(new float[]{ + 25f, + 50f, + 25f + }); + + alertesTable.addCell( + new PdfPCell( + new Phrase("Type", labelFont))); + + alertesTable.addCell( + new PdfPCell( + new Phrase("Description", labelFont))); + + alertesTable.addCell( + new PdfPCell( + new Phrase("Date", labelFont))); + + for (AlertesMedicales alerte : patient.getAlertesMedicalesList()) { + + if (alerte == null) { + continue; + } + + alertesTable.addCell( + alerte.getFkTypeAlerteMedical() != null + ? alerte.getFkTypeAlerteMedical().getType() + : ""); + + alertesTable.addCell( + alerte.getDerscription() != null + ? alerte.getDerscription() + : ""); + + alertesTable.addCell( + alerte.getDate() != null + ? sdf.format(alerte.getDate()) + : ""); + } + + document.add(alertesTable); + } + + document.add(new Paragraph(" ")); + document.add(new Paragraph(" ")); + document.add(new Paragraph( + "Document généré automatiquement par le système.", + valueFont)); + + document.close(); + + return DefaultStreamedContent.builder() + .name(fileName) + .contentType("application/pdf") + .stream(() -> { + try { + return new FileInputStream(file); + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .build(); + + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + private void ajouterLignePdf( + PdfPTable table, + String label, + String valeur) { + + Font labelFont = FontFactory.getFont( + FontFactory.HELVETICA_BOLD, + 10); + + Font valueFont = FontFactory.getFont( + FontFactory.HELVETICA, + 10); + + table.addCell( + new PdfPCell( + new Phrase(label, labelFont))); + + table.addCell( + new PdfPCell( + new Phrase( + valeur != null ? valeur : "", + valueFont))); + } +} diff --git a/src/main/java/com/triz/trizservice/bean/TypeAlerteMedicaleConverter.java b/src/main/java/com/triz/trizservice/bean/TypeAlerteMedicaleConverter.java new file mode 100644 index 0000000..14193a9 --- /dev/null +++ b/src/main/java/com/triz/trizservice/bean/TypeAlerteMedicaleConverter.java @@ -0,0 +1,73 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package com.triz.trizservice.bean; + +import com.triz.trizservice.modeles.Patient; +import com.triz.trizservice.modeles.TypeAlerteMedical; +import com.triz.trizservice.service.TransactionService; +import java.util.UUID; +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.FacesConverter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.SpringBeanAutowiringSupport; + +/** + * + * @author FORCE TECH + */ +@FacesConverter(value = "typeAlerteMedicaleConverter") +@Component +public class TypeAlerteMedicaleConverter implements Converter{ + @Autowired + private TransactionService service; + + public TypeAlerteMedicaleConverter() { + // JSF instancie ce convertisseur lui-même (new MachineConverter()), + // donc @Autowired ne se déclenche jamais tout seul. + // Cet appel va chercher le WebApplicationContext Spring actif + // et injecte manuellement les champs @Autowired de cette instance. + SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); + } + + @Override + public Object getAsObject(FacesContext fc, UIComponent uic, String value) { + + if (value == null || value.trim().isEmpty()) { + return null; + } + + try { + return service.findById(TypeAlerteMedical.class, UUID.fromString(value)); + } catch (IllegalArgumentException e) { + return null; + } + } + + @Override + public String getAsString(FacesContext fc, UIComponent uic, Object object) { + + if (object == null) { + return ""; + } + + if (object instanceof String) { + return (String) object; + } + + if (!(object instanceof TypeAlerteMedical)) { + return ""; + } + + TypeAlerteMedical patient = (TypeAlerteMedical) object; + + return patient.getId() != null + ? patient.getId().toString() + : ""; + } + +} diff --git a/src/main/java/com/triz/trizservice/bean/converter/WilayaConverter.java b/src/main/java/com/triz/trizservice/bean/converter/WilayaConverter.java index d69b196..8de3f04 100644 --- a/src/main/java/com/triz/trizservice/bean/converter/WilayaConverter.java +++ b/src/main/java/com/triz/trizservice/bean/converter/WilayaConverter.java @@ -6,6 +6,7 @@ package com.triz.trizservice.bean.converter; import com.triz.trizservice.modeles.Wilaya; import com.triz.trizservice.service.TransactionService; +import java.util.UUID; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; @@ -26,22 +27,38 @@ public class WilayaConverter implements Converter { protected transient TransactionService service; @Override - public Object getAsObject(FacesContext fc, UIComponent uic, String value) { - try { - return service.findById(Wilaya.class, value); - } catch (NumberFormatException e) { - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Wilaya n'existe pas."); + public Wilaya getAsObject(FacesContext context, UIComponent component, String value) { + + if (value == null || value.trim().isEmpty()) { + return null; } - return null; + try { + return service.findById(Wilaya.class, value); + } catch (IllegalArgumentException e) { + return null; + } } @Override public String getAsString(FacesContext fc, UIComponent uic, Object object) { - if (object != null) { - return String.valueOf(((Wilaya) object).getName()); - } else { - return null; + if (object == null) { + return ""; } + + if (object instanceof String) { + return (String) object; + } + + if (!(object instanceof Wilaya)) { + return ""; + } + + Wilaya patient = (Wilaya) object; + + return patient.getCode() != null + ? patient.getCode() + : ""; } + } diff --git a/src/main/java/com/triz/trizservice/modeles/AlertesMedicales.java b/src/main/java/com/triz/trizservice/modeles/AlertesMedicales.java index ae27289..3e2051d 100644 --- a/src/main/java/com/triz/trizservice/modeles/AlertesMedicales.java +++ b/src/main/java/com/triz/trizservice/modeles/AlertesMedicales.java @@ -6,9 +6,12 @@ package com.triz.trizservice.modeles; import java.io.Serializable; import java.util.Date; +import java.util.UUID; +import javax.annotation.Generated; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.Lob; @@ -39,9 +42,9 @@ public class AlertesMedicales implements Serializable { @Id @Basic(optional = false) @NotNull - @Lob + @GeneratedValue @Column(name = "id") - private Object id; + private UUID id; @Size(max = 2147483647) @Column(name = "derscription") private String derscription; @@ -58,15 +61,15 @@ public class AlertesMedicales implements Serializable { public AlertesMedicales() { } - public AlertesMedicales(Object id) { + public AlertesMedicales(UUID id) { this.id = id; } - public Object getId() { + public UUID getId() { return id; } - public void setId(Object id) { + public void setId(UUID id) { this.id = id; } diff --git a/src/main/java/com/triz/trizservice/modeles/FichierDossier.java b/src/main/java/com/triz/trizservice/modeles/FichierDossier.java index 50a90d7..069d21b 100644 --- a/src/main/java/com/triz/trizservice/modeles/FichierDossier.java +++ b/src/main/java/com/triz/trizservice/modeles/FichierDossier.java @@ -6,9 +6,11 @@ package com.triz.trizservice.modeles; import java.io.Serializable; import java.util.Date; +import java.util.UUID; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.Lob; @@ -40,9 +42,9 @@ public class FichierDossier implements Serializable { @Id @Basic(optional = false) @NotNull - @Lob + @GeneratedValue @Column(name = "id") - private Object id; + private UUID id; @Column(name = "date") @Temporal(TemporalType.DATE) private Date date; @@ -59,15 +61,15 @@ public class FichierDossier implements Serializable { public FichierDossier() { } - public FichierDossier(Object id) { + public FichierDossier(UUID id) { this.id = id; } - public Object getId() { + public UUID getId() { return id; } - public void setId(Object id) { + public void setId(UUID id) { this.id = id; } diff --git a/src/main/java/com/triz/trizservice/modeles/Patient.java b/src/main/java/com/triz/trizservice/modeles/Patient.java index f53b303..e11a3b3 100644 --- a/src/main/java/com/triz/trizservice/modeles/Patient.java +++ b/src/main/java/com/triz/trizservice/modeles/Patient.java @@ -108,6 +108,21 @@ public class Patient implements Serializable { private List queueList; @Column(name = "code_patient", unique = true, length = 10) private String codePatient; + @Column(name = "actif") + private Boolean actif = true; + @Column(name = "nis") + private String nis; + @JoinColumn(name = "fk_wilaya", referencedColumnName = "code") + @ManyToOne + private Wilaya fkWilaya; + + public Wilaya getFkWilaya() { + return fkWilaya; + } + + public void setFkWilaya(Wilaya fkWilaya) { + this.fkWilaya = fkWilaya; + } public Patient() { } @@ -307,4 +322,20 @@ public class Patient implements Serializable { this.codePatient = codePatient; } + public Boolean getActif() { + return actif; + } + + public void setActif(Boolean actif) { + this.actif = actif; + } + + public String getNis() { + return nis; + } + + public void setNis(String nis) { + this.nis = nis; + } + } diff --git a/src/main/java/com/triz/trizservice/modeles/Queue.java b/src/main/java/com/triz/trizservice/modeles/Queue.java index 7250656..77cf41d 100644 --- a/src/main/java/com/triz/trizservice/modeles/Queue.java +++ b/src/main/java/com/triz/trizservice/modeles/Queue.java @@ -62,7 +62,8 @@ public class Queue implements Serializable { @JoinColumn(name = "fk_queue_tips", referencedColumnName = "id") @ManyToOne private QueueTips fkQueueTips; - + @OneToMany(mappedBy = "fkQueue") + private List ExamenList; @ManyToOne @JoinColumn(name = "fk_type_examen") private TypeExamen fkTypeExamen; @@ -179,4 +180,12 @@ public class Queue implements Serializable { this.fkTypeExamen = fkTypeExamen; } + public List getExamenList() { + return ExamenList; + } + + public void setExamenList(List ExamenList) { + this.ExamenList = ExamenList; + } + } diff --git a/src/main/java/com/triz/trizservice/service/DaoService.java b/src/main/java/com/triz/trizservice/service/DaoService.java index b73e6ec..b2ce6dd 100644 --- a/src/main/java/com/triz/trizservice/service/DaoService.java +++ b/src/main/java/com/triz/trizservice/service/DaoService.java @@ -176,5 +176,9 @@ public interface DaoService { public Consultation getConsultationByExamen(Examen examen); public List getQueueByCentreByRequete(Centre centre,String requete); + + public Examen getLastExamenByCentre(Centre centre); + + public Patient getPatientByCode(String code); } diff --git a/src/main/java/com/triz/trizservice/service/TransactionService.java b/src/main/java/com/triz/trizservice/service/TransactionService.java index e47e0d3..02dbcee 100644 --- a/src/main/java/com/triz/trizservice/service/TransactionService.java +++ b/src/main/java/com/triz/trizservice/service/TransactionService.java @@ -177,4 +177,10 @@ public interface TransactionService { public Consultation getConsultationByExamen(Examen examen); public List getQueueByCentreByRequete(Centre centre,String requete); + + public Examen getLastExamenByCentre(Centre centre); + + public Patient getPatientByCode(String code); + + } diff --git a/src/main/java/com/triz/trizservice/service/impl/DaoServiceImpl.java b/src/main/java/com/triz/trizservice/service/impl/DaoServiceImpl.java index 463c166..c3e8182 100644 --- a/src/main/java/com/triz/trizservice/service/impl/DaoServiceImpl.java +++ b/src/main/java/com/triz/trizservice/service/impl/DaoServiceImpl.java @@ -446,7 +446,7 @@ public class DaoServiceImpl implements DaoService { @Override public List getExamenByQueue(Queue queue) { - return getCurrentSession().createQuery("select s from Examen s where s.fkQueue=:type ").setParameter("type", queue).list(); + return getCurrentSession().createQuery("select s from Examen s where s.fkQueue=:type ").setParameter("type", queue).list(); } @Override @@ -465,22 +465,39 @@ public class DaoServiceImpl implements DaoService { } @Override - public List getQueueByCentre(Centre centre,Date date) { + public List getQueueByCentre(Centre centre, Date date) { return getCurrentSession().createQuery("select s from Queue s where s.fkPatient.fkCentre=:centre and s.date=:date ").setParameter("centre", centre).setParameter("date", date).list(); } @Override public Medecin getMedecinByUser(ServiceUser user) { - return (Medecin) getCurrentSession().createQuery("select s from Medecin s where s.fkUser=:user ").setParameter("user", user).setMaxResults(1).uniqueResult(); + return (Medecin) getCurrentSession().createQuery("select s from Medecin s where s.fkUser=:user ").setParameter("user", user).setMaxResults(1).uniqueResult(); } @Override public Consultation getConsultationByExamen(Examen examen) { - return (Consultation) getCurrentSession().createQuery("select s from Consultation s where s.fkExamen=:examen and s.sessionAnnule=false").setParameter("examen", examen).setMaxResults(1).uniqueResult(); + return (Consultation) getCurrentSession().createQuery("select s from Consultation s where s.fkExamen=:examen and s.sessionAnnule=false").setParameter("examen", examen).setMaxResults(1).uniqueResult(); } @Override public List getQueueByCentreByRequete(Centre centre, String requete) { - return getCurrentSession().createQuery("select s from Queue s where s.fkPatient.fkCentre=:centre"+requete).setParameter("centre", centre).list(); + return getCurrentSession().createQuery("select s from Queue s where s.fkPatient.fkCentre=:centre" + requete).setParameter("centre", centre).list(); + } + + @Override + public Examen getLastExamenByCentre(Centre centre) { + List examens = getCurrentSession().createQuery( + "SELECT e FROM Examen e WHERE e.annule = false ORDER BY e.date DESC, e.heureDebut DESC", + Examen.class) + .setMaxResults(1) + .getResultList(); + + Examen dernierExamen = examens.isEmpty() ? null : examens.get(0); + return dernierExamen; + } + + @Override + public Patient getPatientByCode(String code) { + return (Patient) getCurrentSession().createQuery("select s from Patient s where s.codePatient=:code").setParameter("code", code).setMaxResults(1).uniqueResult(); } } diff --git a/src/main/java/com/triz/trizservice/service/impl/TransactionServiceImpl.java b/src/main/java/com/triz/trizservice/service/impl/TransactionServiceImpl.java index f836000..d9d9254 100644 --- a/src/main/java/com/triz/trizservice/service/impl/TransactionServiceImpl.java +++ b/src/main/java/com/triz/trizservice/service/impl/TransactionServiceImpl.java @@ -434,20 +434,20 @@ public class TransactionServiceImpl implements TransactionService { @Transactional("transactionManager") @Override - public List getQueueByCentre(Centre centre,Date date) { - return daoService.getQueueByCentre(centre,date); + public List getQueueByCentre(Centre centre, Date date) { + return daoService.getQueueByCentre(centre, date); } @Transactional("transactionManager") @Override public Medecin getMedecinByUser(ServiceUser user) { - return daoService.getMedecinByUser(user); + return daoService.getMedecinByUser(user); } @Transactional("transactionManager") @Override public Consultation getConsultationByExamen(Examen examen) { - return daoService.getConsultationByExamen(examen); + return daoService.getConsultationByExamen(examen); } @Transactional("transactionManager") @@ -455,4 +455,16 @@ public class TransactionServiceImpl implements TransactionService { public List getQueueByCentreByRequete(Centre centre, String requete) { return daoService.getQueueByCentreByRequete(centre, requete); } + + @Transactional("transactionManager") + @Override + public Examen getLastExamenByCentre(Centre centre) { + return daoService.getLastExamenByCentre(centre); + } + + @Transactional("transactionManager") + @Override + public Patient getPatientByCode(String code) { + return daoService.getPatientByCode(code); + } } diff --git a/src/main/resources/db/migration/V000__main_schema.sql b/src/main/resources/db/migration/V000__main_schema.sql index 940e56a..2243093 100644 --- a/src/main/resources/db/migration/V000__main_schema.sql +++ b/src/main/resources/db/migration/V000__main_schema.sql @@ -934,4 +934,17 @@ ALTER TABLE patient ADD COLUMN code_patient VARCHAR(10); ALTER TABLE patient -ADD CONSTRAINT uk_patient_code UNIQUE (code_patient); \ No newline at end of file +ADD CONSTRAINT uk_patient_code UNIQUE (code_patient); + +ALTER TABLE patient +ADD COLUMN actif BOOLEAN DEFAULT TRUE; + +ALTER TABLE patient +ADD COLUMN nis VARCHAR(20); + +ALTER TABLE patient +ADD COLUMN fk_wilaya varchar; +ALTER TABLE patient +ADD CONSTRAINT fk_patient_wilaya +FOREIGN KEY (fk_wilaya) +REFERENCES wilaya(code); \ No newline at end of file diff --git a/src/main/resources/langue/message_fr.properties b/src/main/resources/langue/message_fr.properties index 51c3d5b..5e79787 100644 --- a/src/main/resources/langue/message_fr.properties +++ b/src/main/resources/langue/message_fr.properties @@ -4419,4 +4419,98 @@ distribution.message.consultationValidee=Examen valid\u00e9e avec succ\u00e8s distribution.message.consultationAnnulee=Examen annul\u00e9e distribution.page.selectionner=S\u00e9lectionner distribution.page.confirmerValidation=Confirmez-vous la validation de cet examen ? -distribution.page.confirmerAnnulation=Confirmez-vous l'annulation de cet examen ? \ No newline at end of file +distribution.page.confirmerAnnulation=Confirmez-vous l'annulation de cet examen ? + +# Titre / breadcrumb +distribution.page.patients=Patients +distribution.page.patients.liste=Liste des Patients +distribution.page.patient.liste.message.non=Aucun patient trouv\u00e9 + +# L\u00e9gende de l'indicateur orange +distribution.page.patient.legende.dejaExamen=Patients qui ont d\u00e9j\u00e0 fait un examen + +# Colonnes du tableau +distribution.page.patient.code=ID Patient +distribution.page.patient.nom=Nom +distribution.page.patient.prenom=Pr\u00e9nom +distribution.page.patient.sexe=Sexe +distribution.page.patient.dateNaissance=Date de Naissance +distribution.page.patient.age=Age +distribution.page.patient.telephone=T\u00e9l\u00e9phone +distribution.page.patient.email=Email +distribution.page.status=Status + +# Action +distribution.page.consulter=Consulter + +# Panneau de filtre +distribution.filtre.dateNaissance=Date de naissance +distribution.filtre.dateDebut=Date d\u00e9but +distribution.filtre.dateFin=Date fin +distribution.filtre.rapide=Filtres rapides +distribution.filtre.patient.dejaExamen=Patients ayant d\u00e9j\u00e0 un examen +distribution.filtre.criteres=Crit\u00e8res +distribution.filtre.reinitialiser=R\u00e9initialiser +distribution.filtre.appliquer=Appliquer + +# Statuts de consultation (typeConsultation) +distribution.statut.annule=Annul\u00e9 +distribution.statut.normal=Normal +distribution.statut.definitve=D\u00e9finitive +distribution.statut.brouillon=Brouillon + +# ===================== Page d\u00e9tail Examen ===================== +distribution.page.examen.detail=D\u00e9tail examen +distribution.page.examen.ajouterSignature=Ajouter signature +distribution.page.examen.visualiser=Visualiser +distribution.page.examen.consultation=Consultation +distribution.page.valider=Valider +distribution.page.confirmerValidation=Voulez-vous vraiment valider cette consultation ? +distribution.page.confirmerAnnulation=Voulez-vous vraiment annuler cette consultation ? +distribution.page.patient.nom=Patient +distribution.page.patient.sexe=Sexe +distribution.page.priorite=Priorit\u00e9 +distribution.page.observation=Observation +distribution.page.voirPlus=Voir plus +distribution.page.voirMoins=Voir moins +distribution.page.interpreteurAssigne=Interpr\u00e8te Assign\u00e9 +distribution.page.completeLe=Compl\u00e9t\u00e9 le +distribution.page.consulteLe=Consult\u00e9 le +distribution.page.rapportCreeLe=Rapport cr\u00e9\u00e9 le +distribution.page.etudeInstanceId=Study Instance UID +distribution.page.typeExamen=Type d'examen +distribution.page.machine=Machine +distribution.page.lateralite=Lat\u00e9ralit\u00e9 +distribution.page.rapport=Rapport +distribution.page.typeConsultation=Type consultation +distribution.page.medecinConsultant=M\u00e9decin consultant +distribution.page.rapportEcritPar=Rapport \u00e9crit par +distribution.page.rapportEcrit=Rapport \u00c9crit +distribution.page.aucuneConsultation=Aucune consultation pour cet examen +distribution.page.rapportsDictes=Rapports dict\u00e9s +distribution.page.imagesCles=Images cl\u00e9s +distribution.message.aucuneImageCle=Aucune image cl\u00e9 + +# ===================== Page d\u00e9tail Patient (Dossier patients) ===================== +distribution.page.patient.detail=Fiche patient +distribution.page.patient.idPatient=Id Patient +distribution.page.patient.dateNaissance=Date de naissance +distribution.page.patient.telephone=T\u00e9l\u00e9phone +distribution.page.patient.telephoneRelative=T\u00e9l\u00e9phone Relative +distribution.page.patient.email=Email +distribution.page.patient.wilaya=Wilaya +distribution.page.patient.adresse=Adresse +distribution.page.patient.groupage=Groupage +distribution.page.patient.alertesMedicaux=Alertes M\u00e9dicaux +distribution.page.patient.aucuneAlerte=Aucune alerte m\u00e9dicale +distribution.page.patient.alerteMedicale=Alerte m\u00e9dicale +distribution.page.patient.typeAlerte=Type Alerte +distribution.page.patient.description=Description +distribution.page.patient.dateHeure=Date et heure +distribution.page.patient.modifierAlerte=Modifier Alerte +distribution.page.patient.nouvelleAlerte=Ajouter une alerte +distribution.page.patient.confirmerSuppressionAlerte=Voulez-vous vraiment supprimer cette alerte ? +distribution.page.patient.nouveauPatient=Nouveau patient +distribution.page.patient.nouveauPatientSousTitre=Cr\u00e9er une nouvelle fiche patient +distribution.page.patient.codeGenereAuto=L'identifiant patient sera g\u00e9n\u00e9r\u00e9 automatiquement \u00e0 l'enregistrement. +distribution.page.champObligatoire=champ obligatoire \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/layout/sections/menu.xhtml b/src/main/webapp/WEB-INF/layout/sections/menu.xhtml index 5750e14..b4b7020 100644 --- a/src/main/webapp/WEB-INF/layout/sections/menu.xhtml +++ b/src/main/webapp/WEB-INF/layout/sections/menu.xhtml @@ -125,7 +125,7 @@ diff --git a/src/main/webapp/WEB-INF/layout/sections/topbar.xhtml b/src/main/webapp/WEB-INF/layout/sections/topbar.xhtml index 8b7597d..037ac0e 100644 --- a/src/main/webapp/WEB-INF/layout/sections/topbar.xhtml +++ b/src/main/webapp/WEB-INF/layout/sections/topbar.xhtml @@ -37,13 +37,7 @@ transition: all 0.3s ease; } - #layoutTopbarForm .layout-topbar.custom-topbar .layout-topbar-right { - background-color: #F8FAFC !important; - height: 100% !important; - flex: 1 1 auto; - display: flex; - align-items: center; - } + #layoutTopbarForm .layout-topbar.custom-topbar .layout-menu-button { position: absolute !important; @@ -116,7 +110,7 @@ background-color: #0D1B2E !important; } #layoutTopbarForm .layout-topbar-right { - background-color: #FFFFFF !important; + background-color: #{empty topbarRightColor ? '#FFFFFF' : topbarRightColor} !important; height: 100% !important; flex: 1 1 auto; @@ -131,7 +125,7 @@ .topbar-page-title { font-weight: 700; font-size: 20px; - color: #0D1B2E; + color: #{empty topbarTextColor ? '#0D1B2E' : topbarTextColor}; font-family: 'Inter', sans-serif; margin-right: auto; margin-left: 35px; @@ -147,7 +141,7 @@ } .topbar-date { - color: #94A3B8; + color: #{empty topbarTextColor ? '#94A3B8' : topbarTextColor}; font-size: 14px; font-weight: 500; line-height: 1; @@ -186,7 +180,7 @@ .notification-button .ui-icon { font-size: 22px !important; - color: #64748B !important; + color: #{empty topbarTextColor ? '#64748B' : topbarTextColor} !important; line-height: 1 !important; } diff --git a/src/main/webapp/WEB-INF/layout/template.xhtml b/src/main/webapp/WEB-INF/layout/template.xhtml index 8f274d5..7553f3f 100644 --- a/src/main/webapp/WEB-INF/layout/template.xhtml +++ b/src/main/webapp/WEB-INF/layout/template.xhtml @@ -36,7 +36,10 @@
- + + + + diff --git a/src/main/webapp/views/Examen/form.xhtml b/src/main/webapp/views/Examen/form.xhtml index d7d3479..23d5e34 100644 --- a/src/main/webapp/views/Examen/form.xhtml +++ b/src/main/webapp/views/Examen/form.xhtml @@ -9,7 +9,8 @@ #{msg['distribution.page.examen.detail']} - + + diff --git a/src/main/webapp/views/Examen/list.xhtml b/src/main/webapp/views/Examen/list.xhtml index 5ea469c..a325340 100644 --- a/src/main/webapp/views/Examen/list.xhtml +++ b/src/main/webapp/views/Examen/list.xhtml @@ -9,7 +9,8 @@ #{msg['distribution.page.examen']} - + + diff --git a/src/main/webapp/views/patient/form.xhtml b/src/main/webapp/views/patient/form.xhtml index 2f6b0f8..e13fc14 100644 --- a/src/main/webapp/views/patient/form.xhtml +++ b/src/main/webapp/views/patient/form.xhtml @@ -1,11 +1,1263 @@ - - - Facelet Title - - - Hello from Facelets - - + + + #{msg['distribution.page.patient.detail']} + + + + + + + + + + + + + + + + #{patientDetailBean.init()} +
+ + +
+ + + + + + +
+
+
+ + + +
+ + + + +
+
+ +
+ +
+ #{msg['distribution.page.patient.idPatient']} + #{patientDetailBean.patient.codePatient} +
+ +
+ #{msg['distribution.page.patient.nom']} + + + + + + + + + + + + + +
+ +
+ #{msg['distribution.page.patient.sexe']} + + + + + + + + + +
+ +
+ NIN + + + + + + +
+ +
+ NIS + + + + + + +
+ +
+ Age + #{patientDetailBean.age} +
+ +
+ #{msg['distribution.page.patient.dateNaissance']} + + + + + + + + + +
+ +
+ #{msg['distribution.page.patient.telephone']} + + + + + +
+ +
+ #{msg['distribution.page.patient.telephoneRelative']} + + + + + +
+ +
+ #{msg['distribution.page.patient.email']} + + + + + +
+ +
+ #{msg['distribution.page.patient.wilaya']} + + + + + + + + + + + + + + +
+ +
+ #{msg['distribution.page.patient.adresse']} + + + + + +
+ +
+ #{msg['distribution.page.status']} + + + #{patientDetailBean.statusLabel} + + + + +
+ +
+ #{msg['distribution.page.creeLe']} + + + + + +
+ +
+ #{msg['distribution.page.patient.groupage']} + + + #{patientDetailBean.patient.groupage} + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ #{msg['distribution.page.patient.alertesMedicaux']} +
+ + + + + + + +
+
+ + + + + + + +
+ #{msg['distribution.page.patient.alertesMedicaux']} +
+ + +
+
+ + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+
+ + + + + + +
+ #{msg['distribution.page.fichiers']} + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + #{patientDetailBean.getNomFichier(f.filePath)} + #{patientDetailBean.getTailleFichier(f)} + + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ + + + + + + + + + + + + #{patientDetailBean.selectedAlerte ne null + ? msg['distribution.page.patient.modifierAlerte'] + : msg['distribution.page.patient.nouvelleAlerte']} + + + #{patientDetailBean.patient.prenom} #{patientDetailBean.patient.nom} + + + + + + + + +
+ + + + + +
+ +
+ + +
+ +
+ + +
+
+ + + + +
+ + +
+
+
\ No newline at end of file diff --git a/src/main/webapp/views/patient/list.xhtml b/src/main/webapp/views/patient/list.xhtml index 2f6b0f8..6832d77 100644 --- a/src/main/webapp/views/patient/list.xhtml +++ b/src/main/webapp/views/patient/list.xhtml @@ -1,11 +1,658 @@ - - - Facelet Title - - - Hello from Facelets - - + + + #{msg['distribution.page.patients']} + + + + + + + + + + + + + + + +
+ #{patientBean.init()} + +
+ + + +
+
+ #{msg['distribution.page.patients.liste']} +
+ + #{msg['distribution.page.patient.legende.dejaExamen']} +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + + + + + + + + + + #{msg['distribution.page.patient.nouveauPatient']} + #{msg['distribution.page.patient.nouveauPatientSousTitre']} + + + + + + + +
+ +
+ + #{msg['distribution.page.patient.codeGenereAuto']} +
+ +
+ + +
+
+ + +
+ +
+ + + + + + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + + + + + +
+ +
+ + +
+ +
+ + + + + + + + + + + + +
+
+ +
+ +
+
+ +
+
+ + + + +
+
+
+
\ No newline at end of file