This commit is contained in:
kenza 2026-09-08 17:48:53 +01:00
parent e008933a01
commit 9964e964ce
23 changed files with 4528 additions and 139 deletions

View File

@ -1,27 +1,25 @@
package com.triz.trizservice.bean; package com.triz.trizservice.bean;
import com.triz.trizservice.modeles.Centre; import com.triz.trizservice.modeles.Centre;
import com.triz.trizservice.modeles.Examen;
import com.triz.trizservice.modeles.Machine; import com.triz.trizservice.modeles.Machine;
import com.triz.trizservice.modeles.ServiceUser; import com.triz.trizservice.modeles.ServiceUser;
import com.triz.trizservice.modeles.TypeMachine; import com.triz.trizservice.modeles.TypeMachine;
import com.triz.trizservice.security.impl.PingService; import com.triz.trizservice.security.impl.PingService;
import com.triz.trizservice.service.TransactionService; import com.triz.trizservice.service.TransactionService;
import com.triz.util.UtilContext; import com.triz.util.UtilContext;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Serializable; import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage; import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext; import javax.faces.context.FacesContext;
import org.primefaces.PrimeFaces; import org.primefaces.PrimeFaces;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
@ -33,14 +31,15 @@ public class DicomPacsBean implements Serializable {
private static final long serialVersionUID = 1L; 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<Machine> machines; private List<Machine> machines;
private Machine selectedMachine; private Machine selectedMachine;
private Centre centre; private Centre centre;
private ServiceUser user; private ServiceUser user;
private Date dernierMajOrthanc;
private String etatMwlScp; private String etatMwlScp;
private Date dernierEtudeRecu; private Date dernierEtudeRecu;
@ -53,141 +52,451 @@ public class DicomPacsBean implements Serializable {
@Autowired @Autowired
private PingService pingService; private PingService pingService;
// ============================================================
// INITIALISATION
// ============================================================
@PostConstruct @PostConstruct
public void init() { public void init() {
centre = context.getCurrentEtablissement(); centre = context.getCurrentEtablissement();
user = context.getCurrentUser(); user = context.getCurrentUser();
machines = new ArrayList<>(); machines = new ArrayList<>();
machines = service.getAllByCentre(Machine.class, centre);
if (centre != null) {
machines = service.getAllByCentre(Machine.class, centre);
}
selectedMachine = new Machine(); 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"; etatMwlScp = "Actif";
// --------------------------------------------------------
// Dernière étude reçue
// --------------------------------------------------------
dernierEtudeRecu = null; 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(); pingService.startPingThread();
} }
// ============================================================
// NOUVELLE MACHINE
// ============================================================
public void prepareNew() { public void prepareNew() {
selectedMachine = new Machine(); selectedMachine = new Machine();
selectedMachine.setFkCentre(centre);
PrimeFaces.current()
.ajax()
.update(":dicomPacsForm:dlgMachine");
} }
// ============================================================
// MODIFICATION MACHINE
// ============================================================
public void prepareEdit(Machine machine) { public void prepareEdit(Machine machine) {
selectedMachine = machine; selectedMachine = machine;
PrimeFaces.current().ajax().update(":dicomPacsForm:dlgMachine");
PrimeFaces.current()
.ajax()
.update(":dicomPacsForm:dlgMachine");
} }
// ============================================================
// SAUVEGARDE MACHINE
// ============================================================
public void saveMachine() { public void saveMachine() {
try { 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); selectedMachine.setFkCentre(centre);
machines.add(selectedMachine);
addMessage(FacesMessage.SEVERITY_INFO, "Succès", "Machine ajoutée avec succès");
} else { } else {
selectedMachine.setLastUpdate(new Date()); selectedMachine.setLastUpdate(new Date());
addMessage(FacesMessage.SEVERITY_INFO, "Succès", "Machine modifiée avec succès");
} }
// ----------------------------------------------------
// Sauvegarde
// ----------------------------------------------------
service.save(selectedMachine); 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) { } 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() { public void deleteMachine() {
try { try {
selectedMachine.setActif(Boolean.FALSE); selectedMachine.setActif(Boolean.FALSE);
selectedMachine.setLastUpdate(new Date()); selectedMachine.setLastUpdate(new Date());
// ----------------------------------------------------
// Sauvegarde
// ----------------------------------------------------
service.save(selectedMachine); 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) { } 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<String> getStatutsDisponibles() { public List<String> getStatutsDisponibles() {
return Arrays.asList("Actif", "Inactif", "Indisponible");
return Arrays.asList(
"Actif",
"Inactif",
"Indisponible"
);
} }
// ============================================================
// TYPES DE MACHINE
// ============================================================
public List<TypeMachine> getTypesMachineDisponibles() { public List<TypeMachine> 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<Machine> getMachines() { // DERNIERE MAJ ORTHANC
return machines; // ============================================================
}
public void setMachines(List<Machine> 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 :
public Date getDernierMajOrthanc() { public Date getDernierMajOrthanc() {
if (machines == null) {
return null;
}
return machines.stream() return machines.stream()
.filter(m -> "Orthanc Principal".equals(m.getNom())) .filter(m
-> "Orthanc Principal".equals(
m.getNom()
)
)
.map(Machine::getLastUpdate) .map(Machine::getLastUpdate)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
// ============================================================
// ETAT MWL SCP
// ============================================================
public String getEtatMwlScp() { public String getEtatMwlScp() {
return etatMwlScp; return etatMwlScp;
} }
public void setEtatMwlScp(String etatMwlScp) { public void setEtatMwlScp(String etatMwlScp) {
this.etatMwlScp = etatMwlScp; this.etatMwlScp = etatMwlScp;
} }
public java.util.Date getDernierEtudeRecu() { // ============================================================
// DERNIERE ETUDE RECUE
// ============================================================
public Date getDernierEtudeRecu() {
return dernierEtudeRecu; return dernierEtudeRecu;
} }
public void setDernierEtudeRecu(java.util.Date dernierEtudeRecu) { public void setDernierEtudeRecu(
Date dernierEtudeRecu) {
this.dernierEtudeRecu = dernierEtudeRecu; this.dernierEtudeRecu = dernierEtudeRecu;
} }
public void toggleActif() { // ============================================================
try { // ETAT GLOBAL DU PING
boolean nouvelEtat = !Boolean.TRUE.equals(selectedMachine.getActif()); // ============================================================
selectedMachine.setActif(nouvelEtat); public boolean isActif() {
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)
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(); 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<Machine> getMachines() {
return machines;
}
public void setMachines(
List<Machine> 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;
}
} }

View File

@ -115,6 +115,16 @@ public class ExamenDetailBean implements Serializable {
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
context.saveNewManipulation(
"Examen",
examen.getId().toString(),
"CONSULTATION Examen",
new Date(),
new Date(),
user,
"",
""
);
} }
allMedecins = service.getAllMedecinByCenter(centre); allMedecins = service.getAllMedecinByCenter(centre);
} }
@ -227,6 +237,16 @@ public class ExamenDetailBean implements Serializable {
public void enregistrerObservation() { public void enregistrerObservation() {
if (examen != null) { if (examen != null) {
service.save(examen); service.save(examen);
context.saveNewManipulation(
"Examen",
examen.getId().toString(),
"MODIFICATION Observation",
new Date(),
new Date(),
user,
"",
""
);
} }
this.editObservation = false; this.editObservation = false;
} }
@ -603,6 +623,16 @@ public class ExamenDetailBean implements Serializable {
examen.setFkInterpreteurAssi(medecin); examen.setFkInterpreteurAssi(medecin);
System.out.println(" examen.setFkInterpreteurAssi " + examen.getFkInterpreteurAssi()); System.out.println(" examen.setFkInterpreteurAssi " + examen.getFkInterpreteurAssi());
service.save(examen); service.save(examen);
context.saveNewManipulation(
"Examen",
examen.getId().toString(),
"MODIFICATION Interpréteur assigné",
new Date(),
new Date(),
user,
"",
""
);
} else { } else {
selectedMedecinId = examen.getFkInterpreteurAssi() != null selectedMedecinId = examen.getFkInterpreteurAssi() != null
? examen.getFkInterpreteurAssi().getId().toString() ? examen.getFkInterpreteurAssi().getId().toString()
@ -624,7 +654,16 @@ public class ExamenDetailBean implements Serializable {
Medecin medecinCourant = service.getMedecinByUser(user); Medecin medecinCourant = service.getMedecinByUser(user);
examen.setManipulateur(medecinCourant); examen.setManipulateur(medecinCourant);
service.save(examen); service.save(examen);
context.saveNewManipulation(
"Examen",
examen.getId().toString(),
"VALIDATION Examen",
new Date(),
new Date(),
user,
"",
""
);
FacesContext.getCurrentInstance().addMessage(null, FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "", new FacesMessage(FacesMessage.SEVERITY_INFO, "",
getMsg("distribution.message.consultationValidee"))); getMsg("distribution.message.consultationValidee")));
@ -641,7 +680,16 @@ public class ExamenDetailBean implements Serializable {
examen.setAnnule(true); examen.setAnnule(true);
examen.setHeureFin(new Date()); examen.setHeureFin(new Date());
service.save(examen); service.save(examen);
context.saveNewManipulation(
"Examen",
examen.getId().toString(),
"ANNULATION Examen",
new Date(),
new Date(),
user,
"",
""
);
FacesContext.getCurrentInstance().addMessage(null, FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_WARN, "", new FacesMessage(FacesMessage.SEVERITY_WARN, "",
getMsg("distribution.message.consultationAnnulee"))); getMsg("distribution.message.consultationAnnulee")));

View File

@ -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<Patient> 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<UUID, Boolean> dejaExamenCache = new HashMap<>();
@PostConstruct
public void init() {
chargerPatients();
}
public void chargerPatients() {
centre = context.getCurrentEtablissement();
patientList = service.getAllByCentre(Patient.class, centre);
dejaExamenCache.clear();
}
public List<Patient> 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<Queue> 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<Examen> 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<Wilaya> 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<Wilaya> 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 "-";
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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()
: "";
}
}

View File

@ -6,6 +6,7 @@ package com.triz.trizservice.bean.converter;
import com.triz.trizservice.modeles.Wilaya; import com.triz.trizservice.modeles.Wilaya;
import com.triz.trizservice.service.TransactionService; import com.triz.trizservice.service.TransactionService;
import java.util.UUID;
import javax.faces.application.FacesMessage; import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent; import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext; import javax.faces.context.FacesContext;
@ -26,22 +27,38 @@ public class WilayaConverter implements Converter {
protected transient TransactionService service; protected transient TransactionService service;
@Override @Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) { public Wilaya getAsObject(FacesContext context, UIComponent component, String value) {
try {
return service.findById(Wilaya.class, value); if (value == null || value.trim().isEmpty()) {
} catch (NumberFormatException e) { return null;
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Wilaya n'existe pas.");
} }
return null; try {
return service.findById(Wilaya.class, value);
} catch (IllegalArgumentException e) {
return null;
}
} }
@Override @Override
public String getAsString(FacesContext fc, UIComponent uic, Object object) { public String getAsString(FacesContext fc, UIComponent uic, Object object) {
if (object != null) { if (object == null) {
return String.valueOf(((Wilaya) object).getName()); return "";
} else {
return null;
} }
if (object instanceof String) {
return (String) object;
}
if (!(object instanceof Wilaya)) {
return "";
}
Wilaya patient = (Wilaya) object;
return patient.getCode() != null
? patient.getCode()
: "";
} }
} }

View File

@ -6,9 +6,12 @@ package com.triz.trizservice.modeles;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.UUID;
import javax.annotation.Generated;
import javax.persistence.Basic; import javax.persistence.Basic;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.Lob; import javax.persistence.Lob;
@ -39,9 +42,9 @@ public class AlertesMedicales implements Serializable {
@Id @Id
@Basic(optional = false) @Basic(optional = false)
@NotNull @NotNull
@Lob @GeneratedValue
@Column(name = "id") @Column(name = "id")
private Object id; private UUID id;
@Size(max = 2147483647) @Size(max = 2147483647)
@Column(name = "derscription") @Column(name = "derscription")
private String derscription; private String derscription;
@ -58,15 +61,15 @@ public class AlertesMedicales implements Serializable {
public AlertesMedicales() { public AlertesMedicales() {
} }
public AlertesMedicales(Object id) { public AlertesMedicales(UUID id) {
this.id = id; this.id = id;
} }
public Object getId() { public UUID getId() {
return id; return id;
} }
public void setId(Object id) { public void setId(UUID id) {
this.id = id; this.id = id;
} }

View File

@ -6,9 +6,11 @@ package com.triz.trizservice.modeles;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.UUID;
import javax.persistence.Basic; import javax.persistence.Basic;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.Lob; import javax.persistence.Lob;
@ -40,9 +42,9 @@ public class FichierDossier implements Serializable {
@Id @Id
@Basic(optional = false) @Basic(optional = false)
@NotNull @NotNull
@Lob @GeneratedValue
@Column(name = "id") @Column(name = "id")
private Object id; private UUID id;
@Column(name = "date") @Column(name = "date")
@Temporal(TemporalType.DATE) @Temporal(TemporalType.DATE)
private Date date; private Date date;
@ -59,15 +61,15 @@ public class FichierDossier implements Serializable {
public FichierDossier() { public FichierDossier() {
} }
public FichierDossier(Object id) { public FichierDossier(UUID id) {
this.id = id; this.id = id;
} }
public Object getId() { public UUID getId() {
return id; return id;
} }
public void setId(Object id) { public void setId(UUID id) {
this.id = id; this.id = id;
} }

View File

@ -108,6 +108,21 @@ public class Patient implements Serializable {
private List<Queue> queueList; private List<Queue> queueList;
@Column(name = "code_patient", unique = true, length = 10) @Column(name = "code_patient", unique = true, length = 10)
private String codePatient; 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() { public Patient() {
} }
@ -307,4 +322,20 @@ public class Patient implements Serializable {
this.codePatient = codePatient; 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;
}
} }

View File

@ -62,7 +62,8 @@ public class Queue implements Serializable {
@JoinColumn(name = "fk_queue_tips", referencedColumnName = "id") @JoinColumn(name = "fk_queue_tips", referencedColumnName = "id")
@ManyToOne @ManyToOne
private QueueTips fkQueueTips; private QueueTips fkQueueTips;
@OneToMany(mappedBy = "fkQueue")
private List<Examen> ExamenList;
@ManyToOne @ManyToOne
@JoinColumn(name = "fk_type_examen") @JoinColumn(name = "fk_type_examen")
private TypeExamen fkTypeExamen; private TypeExamen fkTypeExamen;
@ -179,4 +180,12 @@ public class Queue implements Serializable {
this.fkTypeExamen = fkTypeExamen; this.fkTypeExamen = fkTypeExamen;
} }
public List<Examen> getExamenList() {
return ExamenList;
}
public void setExamenList(List<Examen> ExamenList) {
this.ExamenList = ExamenList;
}
} }

View File

@ -177,4 +177,8 @@ public interface DaoService {
public List<Queue> getQueueByCentreByRequete(Centre centre,String requete); public List<Queue> getQueueByCentreByRequete(Centre centre,String requete);
public Examen getLastExamenByCentre(Centre centre);
public Patient getPatientByCode(String code);
} }

View File

@ -177,4 +177,10 @@ public interface TransactionService {
public Consultation getConsultationByExamen(Examen examen); public Consultation getConsultationByExamen(Examen examen);
public List<Queue> getQueueByCentreByRequete(Centre centre,String requete); public List<Queue> getQueueByCentreByRequete(Centre centre,String requete);
public Examen getLastExamenByCentre(Centre centre);
public Patient getPatientByCode(String code);
} }

View File

@ -446,7 +446,7 @@ public class DaoServiceImpl implements DaoService {
@Override @Override
public List<Examen> getExamenByQueue(Queue queue) { public List<Examen> 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 @Override
@ -465,22 +465,39 @@ public class DaoServiceImpl implements DaoService {
} }
@Override @Override
public List<Queue> getQueueByCentre(Centre centre,Date date) { public List<Queue> 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(); 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 @Override
public Medecin getMedecinByUser(ServiceUser user) { 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 @Override
public Consultation getConsultationByExamen(Examen examen) { 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 @Override
public List<Queue> getQueueByCentreByRequete(Centre centre, String requete) { public List<Queue> 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<Examen> 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();
} }
} }

View File

@ -434,20 +434,20 @@ public class TransactionServiceImpl implements TransactionService {
@Transactional("transactionManager") @Transactional("transactionManager")
@Override @Override
public List<Queue> getQueueByCentre(Centre centre,Date date) { public List<Queue> getQueueByCentre(Centre centre, Date date) {
return daoService.getQueueByCentre(centre,date); return daoService.getQueueByCentre(centre, date);
} }
@Transactional("transactionManager") @Transactional("transactionManager")
@Override @Override
public Medecin getMedecinByUser(ServiceUser user) { public Medecin getMedecinByUser(ServiceUser user) {
return daoService.getMedecinByUser(user); return daoService.getMedecinByUser(user);
} }
@Transactional("transactionManager") @Transactional("transactionManager")
@Override @Override
public Consultation getConsultationByExamen(Examen examen) { public Consultation getConsultationByExamen(Examen examen) {
return daoService.getConsultationByExamen(examen); return daoService.getConsultationByExamen(examen);
} }
@Transactional("transactionManager") @Transactional("transactionManager")
@ -455,4 +455,16 @@ public class TransactionServiceImpl implements TransactionService {
public List<Queue> getQueueByCentreByRequete(Centre centre, String requete) { public List<Queue> getQueueByCentreByRequete(Centre centre, String requete) {
return daoService.getQueueByCentreByRequete(centre, 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);
}
} }

View File

@ -935,3 +935,16 @@ ADD COLUMN code_patient VARCHAR(10);
ALTER TABLE patient ALTER TABLE patient
ADD CONSTRAINT uk_patient_code UNIQUE (code_patient); 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);

View File

@ -4420,3 +4420,97 @@ distribution.message.consultationAnnulee=Examen annul\u00e9e
distribution.page.selectionner=S\u00e9lectionner distribution.page.selectionner=S\u00e9lectionner
distribution.page.confirmerValidation=Confirmez-vous la validation de cet examen ? distribution.page.confirmerValidation=Confirmez-vous la validation de cet examen ?
distribution.page.confirmerAnnulation=Confirmez-vous l'annulation de cet examen ? 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

View File

@ -125,7 +125,7 @@
<p:menuitem id="m_dossier_patients" <p:menuitem id="m_dossier_patients"
value="Dossier patients" value="Dossier patients"
icon="pi pi-id-card" icon="pi pi-id-card"
url="#{request.contextPath}/views/client/listeClient.xhtml?idpage=Suivis_flotte" url="#{request.contextPath}/views/patient/list.xhtml?idpage=Suivis_flotte"
rendered="#{utilControleAccess.isshowPrivilegeAdd('dossier')}" /> rendered="#{utilControleAccess.isshowPrivilegeAdd('dossier')}" />
</p:submenu> </p:submenu>

View File

@ -37,13 +37,7 @@
transition: all 0.3s ease; 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 { #layoutTopbarForm .layout-topbar.custom-topbar .layout-menu-button {
position: absolute !important; position: absolute !important;
@ -116,7 +110,7 @@
background-color: #0D1B2E !important; background-color: #0D1B2E !important;
} }
#layoutTopbarForm .layout-topbar-right { #layoutTopbarForm .layout-topbar-right {
background-color: #FFFFFF !important; background-color: #{empty topbarRightColor ? '#FFFFFF' : topbarRightColor} !important;
height: 100% !important; height: 100% !important;
flex: 1 1 auto; flex: 1 1 auto;
@ -131,7 +125,7 @@
.topbar-page-title { .topbar-page-title {
font-weight: 700; font-weight: 700;
font-size: 20px; font-size: 20px;
color: #0D1B2E; color: #{empty topbarTextColor ? '#0D1B2E' : topbarTextColor};
font-family: 'Inter', sans-serif; font-family: 'Inter', sans-serif;
margin-right: auto; margin-right: auto;
margin-left: 35px; margin-left: 35px;
@ -147,7 +141,7 @@
} }
.topbar-date { .topbar-date {
color: #94A3B8; color: #{empty topbarTextColor ? '#94A3B8' : topbarTextColor};
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
line-height: 1; line-height: 1;
@ -186,7 +180,7 @@
.notification-button .ui-icon { .notification-button .ui-icon {
font-size: 22px !important; font-size: 22px !important;
color: #64748B !important; color: #{empty topbarTextColor ? '#64748B' : topbarTextColor} !important;
line-height: 1 !important; line-height: 1 !important;
} }

View File

@ -36,7 +36,10 @@
<h:body styleClass="#{app.bodyClass}" > <h:body styleClass="#{app.bodyClass}" >
<div class="layout-wrapper #{app.layoutClass}"> <div class="layout-wrapper #{app.layoutClass}">
<ui:include src="./sections/topbar.xhtml" /> <ui:include src="./sections/topbar.xhtml">
<ui:param name="topbarRightColor" value="#{topbarRightColor}" />
<ui:param name="topbarTextColor" value="#{topbarTextColor}" />
</ui:include>
<ui:include src="./sections/rightmenu.xhtml" /> <ui:include src="./sections/rightmenu.xhtml" />
<ui:include src="./sections/menu.xhtml" /> <ui:include src="./sections/menu.xhtml" />

View File

@ -9,7 +9,8 @@
<ui:define name="title"> <ui:define name="title">
#{msg['distribution.page.examen.detail']} #{msg['distribution.page.examen.detail']}
</ui:define> </ui:define>
<ui:param name="topbarRightColor" value="#0088FF" />
<ui:param name="topbarTextColor" value="#FFFFFF" />
<ui:define name="breadcrumb"> <ui:define name="breadcrumb">
<f:metadata> <f:metadata>
<f:viewParam name="id" value="#{examenDetailBean.idExamen}" /> <f:viewParam name="id" value="#{examenDetailBean.idExamen}" />

View File

@ -9,7 +9,8 @@
<ui:define name="title"> <ui:define name="title">
#{msg['distribution.page.examen']} #{msg['distribution.page.examen']}
</ui:define> </ui:define>
<ui:param name="topbarRightColor" value="#0088FF" />
<ui:param name="topbarTextColor" value="#FFFFFF" />
<ui:define name="breadcrumb"> <ui:define name="breadcrumb">
<f:metadata> <f:metadata>
<f:viewParam name="homeOutcome" value="/favorites/dashboard" /> <f:viewParam name="homeOutcome" value="/favorites/dashboard" />

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,658 @@
<?xml version='1.0' encoding='UTF-8' ?> <?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"> xmlns:h="http://java.sun.com/jsf/html"
<h:head> xmlns:f="http://java.sun.com/jsf/core"
<title>Facelet Title</title> xmlns:ui="http://java.sun.com/jsf/facelets"
</h:head> xmlns:p="http://primefaces.org/ui"
<h:body> template="/WEB-INF/layout/template.xhtml">
Hello from Facelets <ui:define name="title">
</h:body> #{msg['distribution.page.patients']}
</html> </ui:define>
<ui:param name="topbarRightColor" value="#0D1B2E" />
<ui:param name="topbarTextColor" value="#FFFFFF" />
<ui:define name="breadcrumb">
<f:metadata>
<f:viewParam name="homeOutcome" value="/favorites/dashboard" />
<f:viewParam name="value" value="Dossier patients" />
</f:metadata>
</ui:define>
<ui:define name="content">
<style>
.card .ui-datatable-tablewrapper table td,
.card .ui-datatable-tablewrapper table th {
vertical-align: middle !important;
}
.card .ui-datatable-tablewrapper table td {
padding-top: 14px !important;
padding-bottom: 14px !important;
}
.page-center-wrapper {
display: flex;
align-items: center;
justify-content: center;
min-height: calc(100vh - 160px);
}
.page-center-wrapper .card {
width: 100%;
}
.table-header-title {
font-weight: 700;
font-size: 1.05rem;
color: #343a40;
}
.table-header-legend {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #6B6B63;
margin-top: 4px;
}
.legend-dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 2px;
background-color: #F5821F;
}
.btn-green-outline,
.btn-green-outline.ui-button {
background-color: #ffffff !important;
border: 1px solid #0D9488 !important;
color: #0D9488 !important;
}
.btn-green-outline:hover {
background-color: #e6f5f4 !important;
}
.btn-view-green,
.btn-view-green.ui-button {
background-color: #0D9488 !important;
border-color: #0D9488 !important;
color: #ffffff !important;
}
.btn-view-green:hover {
background-color: #0b7d73 !important;
}
.btn-export {
background-color: #ffffff !important;
border: 1px solid #dee2e6 !important;
color: #0D9488 !important;
}
.btn-export:hover {
background-color: #e6f5f4 !important;
border-color: #0D9488 !important;
}
.status-badge {
display: inline-block;
padding: 4px 14px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
color: #FFFFFF;
text-align: center;
min-width: 100px;
}
.status-actif {
background-color: #0D9488;
}
.status-inactif {
background-color: #F16B77;
}
/* Bordure orange gauche pour les patients ayant déjà un examen */
.ui-datatable-tablewrapper table tbody tr.patient-row-deja-examen {
border-left: 4px solid #F5821F;
}
.patient-filter-panel.ui-overlaypanel {
border-radius: 8px;
border: 0.5px solid #B4B2A9;
font-family: 'DM Sans', sans-serif;
width: 380px !important;
}
.patient-filter-grid {
display: flex;
flex-direction: column;
gap: 10px;
padding: 8px 4px;
}
.filter-section-title {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 600;
color: #6B6B63;
margin-top: 6px;
}
.filter-date-range {
display: flex;
gap: 8px;
}
.filter-date-range .ui-calendar {
width: 100%;
}
.filter-checkbox-row {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
}
.filter-select.ui-selectonemenu {
width: 100%;
box-sizing: border-box;
}
.filter-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 12px;
padding-top: 12px;
border-top: 0.5px solid #B4B2A9;
}
.patient-filter-panel .ui-overlaypanel-close {
background-color: #0D9488 !important;
border-color: #0D9488 !important;
color: #ffffff !important;
}
.patient-filter-panel .ui-overlaypanel-close:hover {
background-color: #0b7d73 !important;
border-color: #0b7d73 !important;
}
.patient-filter-panel .ui-overlaypanel-close .pi,
.patient-filter-panel .ui-overlaypanel-close .ui-icon-closethick {
color: #ffffff !important;
}
/* ===================== Dialog Nouveau patient ===================== */
.ui-dialog.patient-dialog {
border-radius: 12px;
border: none;
font-family: 'DM Sans', sans-serif;
overflow: hidden;
box-shadow: 0 16px 40px rgba(13, 27, 46, 0.18);
}
.ui-dialog.patient-dialog .ui-dialog-titlebar {
display: none;
}
.ui-dialog.patient-dialog .ui-dialog-content {
padding: 0 !important;
box-sizing: border-box !important;
overflow: visible !important;
}
.patient-dialog-header {
display: flex;
align-items: center;
gap: 12px;
width: 100%;
padding: 20px 24px;
border-bottom: 0.5px solid #EFEDE7;
box-sizing: border-box;
}
.patient-dialog-icon {
width: 38px;
height: 38px;
border-radius: 50%;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(13, 148, 136, 0.12);
color: #0D9488;
font-size: 1rem;
}
.patient-dialog-header-text {
flex: 1;
min-width: 0;
}
.patient-dialog-title {
display: block;
font-size: 15px;
font-weight: 700;
color: #0D1B2E;
line-height: 1.3;
}
.patient-dialog-subtitle {
display: block;
font-size: 12px;
color: #94A3AA;
margin-top: 1px;
}
.patient-dialog-close {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
color: #94A3AA;
cursor: pointer;
flex-shrink: 0;
transition: background-color 0.15s ease, color 0.15s ease;
}
.patient-dialog-close:hover {
background-color: rgba(148, 163, 170, 0.15);
color: #343a40;
}
.patient-dialog-body {
padding: 22px 24px 24px 24px;
box-sizing: border-box;
overflow-x: hidden;
background-color: #FCFCFB;
max-height: 60vh;
overflow-y: auto;
}
.patient-dialog-footer {
background-color: #F1EFE8;
padding: 14px 24px;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
}
.dialog-confirm-btn.ui-button {
background-color: #378ADD !important;
border-color: #378ADD !important;
border-radius: 7px !important;
color: #fff !important;
font-weight: 600;
padding: 0 16px !important;
}
.dialog-confirm-btn.ui-button:hover {
background-color: #2f79c4 !important;
}
.dialog-secondary-btn,
.dialog-secondary-btn.ui-button {
background-color: #ffffff !important;
border: 1px solid #DCE0E5 !important;
color: #495057 !important;
border-radius: 7px !important;
}
.dialog-secondary-btn:hover {
background-color: #F8F9FA !important;
}
/* Grille 2 colonnes pour le formulaire */
.dialog-field-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px 20px;
}
.dialog-field-grid .dialog-field {
margin-bottom: 16px;
}
.dialog-field-full {
grid-column: 1 / -1;
}
.dialog-field-hint {
grid-column: 1 / -1;
font-size: 12px;
color: #94A3AA;
background-color: rgba(13, 148, 136, 0.06);
border: 1px dashed rgba(13, 148, 136, 0.3);
border-radius: 8px;
padding: 8px 12px;
margin-bottom: 18px;
display: flex;
align-items: center;
gap: 8px;
}
.dialog-field {
display: flex;
flex-direction: column;
gap: 7px;
width: 100%;
box-sizing: border-box;
}
.dialog-field-label {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.6px;
font-weight: 700;
color: #0D9488;
}
.dialog-field-input {
width: 100% !important;
max-width: 100% !important;
box-sizing: border-box !important;
}
.dialog-field-input.ui-inputtext,
.dialog-field-input.ui-inputtextarea {
border: 1px solid #DCE0E5 !important;
border-radius: 8px !important;
box-shadow: none !important;
font-family: 'DM Sans', sans-serif;
font-size: 14px;
background-color: #ffffff;
padding: 9px 12px !important;
transition: border-color 0.15s ease;
}
.dialog-field-input.ui-inputtext:focus,
.dialog-field-input.ui-inputtextarea:focus {
border-color: #0D9488 !important;
}
.ui-selectonemenu.dialog-field-input {
height: 40px !important;
display: flex !important;
align-items: center;
border: 1px solid #DCE0E5 !important;
border-radius: 8px !important;
background-color: #ffffff !important;
box-shadow: none !important;
}
.ui-selectonemenu.dialog-field-input .ui-selectonemenu-label {
border: none !important;
background: transparent !important;
padding: 0 12px !important;
line-height: 38px !important;
font-family: 'DM Sans', sans-serif;
font-size: 14px;
color: #343a40;
}
.ui-selectonemenu.dialog-field-input .ui-selectonemenu-label.ui-placeholder {
color: #B4B2A9;
}
.ui-selectonemenu.dialog-field-input .ui-selectonemenu-trigger {
background: transparent !important;
border: none !important;
border-left: 1px solid #DCE0E5 !important;
width: 34px !important;
flex-shrink: 0;
color: #94A3AA !important;
}
.ui-calendar.dialog-field-input input.ui-inputtext {
width: 100% !important;
box-sizing: border-box !important;
border: 1px solid #DCE0E5 !important;
border-radius: 8px !important;
box-shadow: none !important;
font-family: 'DM Sans', sans-serif;
font-size: 14px;
padding: 9px 12px !important;
}
.dialog-field-checkbox {
display: flex;
align-items: center;
gap: 8px;
height: 40px;
}
</style>
<h:form id="form">
<div class="page-center-wrapper">
#{patientBean.init()}
<p:growl id="growlMessages" showDetail="true" life="4000" />
<div class="card">
<p:dataTable id="dataTable" var="p"
rows="30" paginator="true" draggableColumns="true"
value="#{patientBean.patientList}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="20,30,40,60,80,100"
emptyMessage="#{msg['distribution.page.patient.liste.message.non']}"
selectionMode="single"
rowKey="#{p.id}"
rowStyleClass="#{patientBean.getRowStyleClass(p)}">
<f:facet name="header">
<div class="flex justify-content-between align-items-center">
<div>
<span class="table-header-title">#{msg['distribution.page.patients.liste']}</span>
<div class="table-header-legend">
<span class="legend-dot" />
<span>#{msg['distribution.page.patient.legende.dejaExamen']}</span>
</div>
</div>
<div>
<p:commandButton id="xlsExport" styleClass="mr-2 mb-2 btn-export"
icon="pi pi-file-excel" title="Excel" ajax="false">
<p:fileDownload value="#{patientBean.exportListePatientsExcel()}" />
</p:commandButton>
<p:commandButton id="pdfExport" styleClass="mr-2 mb-2 btn-export"
ajax="false" icon="pi pi-file-pdf" title="PDF">
<p:fileDownload value="#{patientBean.exportListePatientsPdf()}" />
</p:commandButton>
<p:commandButton id="toggler" styleClass="mr-2 mb-2 btn-green-outline"
type="button" value="Columns" icon="pi pi-align-justify"/>
<p:columnToggler datasource="dataTable" trigger="toggler" />
<p:commandButton value="Ajouter" icon="pi pi-plus" styleClass="mr-2 mb-2 btn-view-green"
actionListener="#{patientBean.ouvrirAjoutPatient}"
update=":dlg:dlgAjoutPatient"
oncomplete="PF('ajoutPatientDialog').show()"
process="@this" />
</div>
</div>
</f:facet>
<!-- ID Patient -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.code']}"
filterBy="#{p.codePatient}" filterMatchMode="contains" sortBy="#{p.codePatient}">
<h:outputText value="#{p.codePatient}" />
</p:column>
<!-- Nom -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.nom']}"
filterBy="#{p.nom}" filterMatchMode="contains" sortBy="#{p.nom}">
<h:outputText value="#{p.nom}" />
</p:column>
<!-- Prénom -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.prenom']}"
filterBy="#{p.prenom}" filterMatchMode="contains" sortBy="#{p.prenom}">
<h:outputText value="#{p.prenom}" />
</p:column>
<!-- Sexe -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.sexe']}"
filterBy="#{p.sexe}" filterMatchMode="contains" sortBy="#{p.sexe}">
<h:outputText value="#{p.sexe}" />
</p:column>
<!-- Date de naissance -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.dateNaissance']}"
sortBy="#{p.dateNaissance}">
<h:outputText value="#{p.dateNaissance}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</p:column>
<!-- Age -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.age']}"
sortBy="#{patientBean.calculerAge(p.dateNaissance)}">
<h:outputText value="#{patientBean.calculerAge(p.dateNaissance)}" />
</p:column>
<!-- Téléphone -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.telephone']}"
filterBy="#{p.telephone}" filterMatchMode="contains" sortBy="#{p.telephone}">
<h:outputText value="#{p.telephone}" />
</p:column>
<!-- Email -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.patient.email']}"
filterBy="#{p.email}" filterMatchMode="contains" sortBy="#{p.email}">
<h:outputText value="#{p.email}" />
</p:column>
<!-- Status -->
<p:column style="text-align: center;" headerText="#{msg['distribution.page.status']}"
sortBy="#{p.actif}">
<h:panelGroup styleClass="status-badge #{p.actif ? 'status-actif' : 'status-inactif'}">
<h:outputText value="#{p.actif ? 'Actif' : 'Inactif'}" />
</h:panelGroup>
</p:column>
<!-- Action -->
<p:column style="width:100px; text-align: center;" exportable="false"
draggable="false" toggleable="false" headerText="Action">
<p:commandButton id="buttonConsulter" styleClass="btn-view-green"
style="height:30px; text-align: center"
action="#{patientBean.consulterPatient(p)}"
icon="pi pi-search" title="#{msg['distribution.page.consulter']}" />
</p:column>
</p:dataTable>
</div>
</div>
</h:form>
<h:form id="dlg">
<!-- ============================ -->
<!-- Dialog Nouveau patient -->
<!-- ============================ -->
<p:dialog widgetVar="ajoutPatientDialog" modal="true" resizable="false" id="dlgAjoutPatient"
showEffect="fade" hideEffect="fade" closable="true"
styleClass="patient-dialog" width="620">
<h:panelGroup layout="block" styleClass="patient-dialog-header">
<span class="patient-dialog-icon">
<i class="pi pi-user-plus"></i>
</span>
<h:panelGroup layout="block" styleClass="patient-dialog-header-text">
<span class="patient-dialog-title">#{msg['distribution.page.patient.nouveauPatient']}</span>
<span class="patient-dialog-subtitle">#{msg['distribution.page.patient.nouveauPatientSousTitre']}</span>
</h:panelGroup>
<span class="patient-dialog-close" onclick="PF('ajoutPatientDialog').hide();">
<i class="pi pi-times"></i>
</span>
</h:panelGroup>
<h:panelGroup id="panel" layout="block" styleClass="patient-dialog-body">
<div class="dialog-field-grid">
<div class="dialog-field-hint">
<i class="pi pi-info-circle"></i>
<span>#{msg['distribution.page.patient.codeGenereAuto']}</span>
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.prenom']}<span class="required-mark">*</span></label>
<p:inputText value="#{patientBean.nouveauPatient.prenom}" styleClass="dialog-field-input"
required="true" requiredMessage="#{msg['distribution.page.patient.prenom']} : #{msg['distribution.page.champObligatoire']}" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.nom']}<span class="required-mark">*</span></label>
<p:inputText value="#{patientBean.nouveauPatient.nom}" styleClass="dialog-field-input"
required="true" requiredMessage="#{msg['distribution.page.patient.nom']} : #{msg['distribution.page.champObligatoire']}" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.sexe']}<span class="required-mark">*</span></label>
<p:selectOneMenu value="#{patientBean.nouveauPatient.sexe}" styleClass="dialog-field-input"
required="true" requiredMessage="#{msg['distribution.page.patient.sexe']} : #{msg['distribution.page.champObligatoire']}">
<f:selectItem itemLabel="#{msg['distribution.page.selectionner']}" itemValue="" noSelectionOption="true" />
<f:selectItem itemLabel="Homme" itemValue="Homme" />
<f:selectItem itemLabel="Femme" itemValue="Femme" />
</p:selectOneMenu>
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.dateNaissance']}<span class="required-mark">*</span></label>
<p:calendar value="#{patientBean.nouveauPatient.dateNaissance}" pattern="dd/MM/yyyy"
placeholder="jj/mm/aaaa" styleClass="dialog-field-input"
required="true" requiredMessage="#{msg['distribution.page.patient.dateNaissance']} : #{msg['distribution.page.champObligatoire']}" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">NIN</label>
<p:inputText value="#{patientBean.nouveauPatient.nin}" styleClass="dialog-field-input" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">NIS</label>
<p:inputText value="#{patientBean.nouveauPatient.nis}" styleClass="dialog-field-input" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.telephone']}<span class="required-mark">*</span></label>
<p:inputText value="#{patientBean.nouveauPatient.telephone}" styleClass="dialog-field-input"
required="true" requiredMessage="#{msg['distribution.page.patient.telephone']} : #{msg['distribution.page.champObligatoire']}" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.telephoneRelative']}<span class="required-mark">*</span></label>
<p:inputText value="#{patientBean.nouveauPatient.telephoneRelative}" styleClass="dialog-field-input"
required="true" requiredMessage="#{msg['distribution.page.patient.telephoneRelative']} : #{msg['distribution.page.champObligatoire']}" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.email']}</label>
<p:inputText value="#{patientBean.nouveauPatient.email}" styleClass="dialog-field-input" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.wilaya']}<span class="required-mark">*</span></label>
<p:selectOneMenu value="#{patientBean.nouveauPatient.fkWilaya}" styleClass="dialog-field-input"
filter="true" filterMatchMode="contains" converter="wilayaConverter"
required="true" requiredMessage="#{msg['distribution.page.patient.wilaya']} : #{msg['distribution.page.champObligatoire']}">
<f:converter binding="#{wilayaConverter}" />
<f:selectItem itemLabel="#{msg['distribution.page.selectionner']}" itemValue="#{null}" noSelectionOption="true" />
<f:selectItems value="#{patientBean.allWilayas}" var="w" itemLabel="#{w.code}:#{w.name}" itemValue="#{w}" />
</p:selectOneMenu>
</div>
<div class="dialog-field dialog-field-full">
<label class="dialog-field-label">#{msg['distribution.page.patient.adresse']}<span class="required-mark">*</span></label>
<p:inputText value="#{patientBean.nouveauPatient.adresse}" styleClass="dialog-field-input"
required="true" requiredMessage="#{msg['distribution.page.patient.adresse']} : #{msg['distribution.page.champObligatoire']}" />
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.patient.groupage']}</label>
<p:selectOneMenu value="#{patientBean.nouveauPatient.groupage}" styleClass="dialog-field-input">
<f:selectItem itemLabel="#{msg['distribution.page.selectionner']}" itemValue="" noSelectionOption="true" />
<f:selectItem itemLabel="A+" itemValue="A+" />
<f:selectItem itemLabel="A-" itemValue="A-" />
<f:selectItem itemLabel="B+" itemValue="B+" />
<f:selectItem itemLabel="B-" itemValue="B-" />
<f:selectItem itemLabel="AB+" itemValue="AB+" />
<f:selectItem itemLabel="AB-" itemValue="AB-" />
<f:selectItem itemLabel="O+" itemValue="O+" />
<f:selectItem itemLabel="O-" itemValue="O-" />
</p:selectOneMenu>
</div>
<div class="dialog-field">
<label class="dialog-field-label">#{msg['distribution.page.status']}</label>
<div class="dialog-field-checkbox">
<p:selectBooleanCheckbox value="#{patientBean.nouveauPatient.actif}" itemLabel="Actif" />
</div>
</div>
</div>
</h:panelGroup>
<f:facet name="footer">
<div class="patient-dialog-footer">
<p:commandButton value="#{msg['distribution.page.annuler']}" icon="pi pi-times" type="button"
styleClass="dialog-secondary-btn"
onclick="PF('ajoutPatientDialog').hide();" />
<p:commandButton
value="#{msg['distribution.page.enregistrer']}"
icon="pi pi-check"
action="#{patientBean.enregistrerNouveauPatient}"
update=":form:dataTable :form:growlMessages :dlg:panel" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>