# -*- coding: utf-8 -*-
"""
Application de Gestion de Cabinet Dentaire - Cameroun
Développé pour les chirurgiens-dentistes
Auteur: Assistant IA
Date: 2024
"""
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import sqlite3
from datetime import datetime, date
import os
class ApplicationGestionDentaire:
def __init__(self, root):
[Link] = root
[Link]("Gestion Cabinet Dentaire - Cameroun")
[Link]("1200x700")
[Link](bg='#f0f8ff')
# Initialisation de la base de données
self.initialiser_bdd()
# Création de l'interface
self.creer_interface()
# Charger les données initiales
self.actualiser_liste_patients()
def initialiser_bdd(self):
"""Initialise la base de données SQLite avec les tables nécessaires"""
try:
[Link] = [Link]('cabinet_dentaire.db')
[Link] = [Link]()
# Table Patients
[Link]('''
CREATE TABLE IF NOT EXISTS patients (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nom TEXT NOT NULL,
prenom TEXT NOT NULL,
date_naissance TEXT,
genre TEXT,
telephone TEXT,
email TEXT,
antecedents TEXT,
date_creation TEXT
''')
# Table Rendez-vous
[Link]('''
CREATE TABLE IF NOT EXISTS rendez_vous (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER,
date_rdv TEXT,
heure_rdv TEXT,
statut TEXT,
notes TEXT,
FOREIGN KEY (patient_id) REFERENCES patients (id)
''')
# Table Consultations
[Link]('''
CREATE TABLE IF NOT EXISTS consultations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER,
date_consultation TEXT,
observations TEXT,
diagnostic TEXT,
soins_effectues TEXT,
ordonnances TEXT,
FOREIGN KEY (patient_id) REFERENCES patients (id)
''')
# Table Factures
[Link]('''
CREATE TABLE IF NOT EXISTS factures (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER,
consultation_id INTEGER,
date_facture TEXT,
actes TEXT,
total REAL,
statut_paiement TEXT,
FOREIGN KEY (patient_id) REFERENCES patients (id),
FOREIGN KEY (consultation_id) REFERENCES consultations (id)
''')
[Link]()
print("Base de données initialisée avec succès!")
except [Link] as e:
[Link]("Erreur BDD", f"Erreur lors de l'initialisation: {e}")
def creer_interface(self):
"""Crée l'interface graphique principale"""
# Frame principal
main_frame = [Link]([Link], padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# Configuration du grid
[Link](0, weight=1)
[Link](0, weight=1)
main_frame.columnconfigure(1, weight=1)
main_frame.rowconfigure(1, weight=1)
# Titre
titre = [Link](main_frame, text="🏥 Gestion du Cabinet Dentaire",
font=("Arial", 16, "bold"), bg='#f0f8ff', fg='#2c3e50')
[Link](row=0, column=0, columnspan=2, pady=(0, 20))
# Menu latéral
self.creer_menu_lateral(main_frame)
# Zone de contenu principal
self.creer_zone_principale(main_frame)
def creer_menu_lateral(self, parent):
"""Crée le menu latéral avec les boutons de navigation"""
menu_frame = [Link](parent, text="Navigation", padding="10")
menu_frame.grid(row=1, column=0, sticky=(tk.N, tk.S, tk.W), padx=(0, 10))
menu_frame.columnconfigure(0, weight=1)
# Boutons de navigation
boutons = [
("👥 Gestion Patients", self.afficher_gestion_patients),
("📅 Rendez-vous", self.afficher_rendez_vous),
("🏥 Consultations", self.afficher_consultations),
("💰 Facturation", self.afficher_facturation),
("📊 Tableau de Bord", self.afficher_tableau_bord)
for i, (texte, commande) in enumerate(boutons):
btn = [Link](menu_frame, text=texte, command=commande,
bg='#3498db', fg='white', font=("Arial", 10),
width=20, height=2, relief='flat')
[Link](row=i, column=0, pady=5, sticky=(tk.W, tk.E))
# Bouton Quitter
btn_quitter = [Link](menu_frame, text="🚪 Quitter",
command=self.quitter_application,
bg='#e74c3c', fg='white', font=("Arial", 10),
width=20, height=2, relief='flat')
btn_quitter.grid(row=len(boutons), column=0, pady=5, sticky=(tk.W, tk.E))
def creer_zone_principale(self, parent):
"""Crée la zone de contenu principal"""
self.content_frame = [Link](parent)
self.content_frame.grid(row=1, column=1, sticky=(tk.W, tk.E, tk.N, tk.S))
self.content_frame.columnconfigure(0, weight=1)
self.content_frame.rowconfigure(1, weight=1)
# Afficher la gestion des patients par défaut
self.afficher_gestion_patients()
def afficher_gestion_patients(self):
"""Affiche l'interface de gestion des patients"""
self.effacer_contenu()
titre = [Link](self.content_frame, text="Gestion des Patients",
font=("Arial", 14, "bold"))
[Link](row=0, column=0, columnspan=2, pady=(0, 20))
# Frame pour les boutons d'action
frame_actions = [Link](self.content_frame)
frame_actions.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
# Boutons d'action
btn_nouveau = [Link](frame_actions, text="Nouveau Patient",
command=self.ajouter_patient,
bg='#27ae60', fg='white')
btn_nouveau.grid(row=0, column=0, padx=(0, 10))
btn_modifier = [Link](frame_actions, text="Modifier Patient",
command=self.modifier_patient,
bg='#f39c12', fg='white')
btn_modifier.grid(row=0, column=1, padx=(0, 10))
btn_rechercher = [Link](frame_actions, text="Rechercher",
command=self.rechercher_patient,
bg='#3498db', fg='white')
btn_rechercher.grid(row=0, column=2, padx=(0, 10))
# Barre de recherche
self.recherche_var = [Link]()
entry_recherche = [Link](frame_actions, textvariable=self.recherche_var, width=30)
entry_recherche.grid(row=0, column=3, padx=(0, 10))
entry_recherche.bind('<Return>', lambda e: self.rechercher_patient())
# Liste des patients
frame_liste = [Link](self.content_frame, text="Liste des Patients",
padding="10")
frame_liste.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S))
frame_liste.columnconfigure(0, weight=1)
frame_liste.rowconfigure(0, weight=1)
# Treeview pour afficher les patients
colonnes = ('ID', 'Nom', 'Prénom', 'Téléphone', 'Email', 'Date Naissance')
self.tree_patients = [Link](frame_liste, columns=colonnes, show='headings',
height=15)
# Définition des en-têtes
for col in colonnes:
self.tree_patients.heading(col, text=col)
self.tree_patients.column(col, width=100)
# Scrollbar
scrollbar = [Link](frame_liste, orient=[Link],
command=self.tree_patients.yview)
self.tree_patients.configure(yscrollcommand=[Link])
self.tree_patients.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
[Link](row=0, column=1, sticky=(tk.N, tk.S))
def afficher_rendez_vous(self):
"""Affiche l'interface de gestion des rendez-vous"""
self.effacer_contenu()
# Interface similaire à afficher_gestion_patients mais pour les rendez-vous
# [Code similaire pour la cohérence...]
label = [Link](self.content_frame, text="Interface Rendez-vous - En développement")
[Link](pady=50)
def afficher_consultations(self):
"""Affiche l'interface de gestion des consultations"""
self.effacer_contenu()
label = [Link](self.content_frame, text="Interface Consultations - En développement")
[Link](pady=50)
def afficher_facturation(self):
"""Affiche l'interface de facturation"""
self.effacer_contenu()
label = [Link](self.content_frame, text="Interface Facturation - En développement")
[Link](pady=50)
def afficher_tableau_bord(self):
"""Affiche le tableau de bord"""
self.effacer_contenu()
label = [Link](self.content_frame, text="Tableau de Bord - En développement")
[Link](pady=50)
def effacer_contenu(self):
"""Efface le contenu de la zone principale"""
for widget in self.content_frame.winfo_children():
[Link]()
def ajouter_patient(self):
"""Ouvre une fenêtre pour ajouter un nouveau patient"""
self.fenetre_patient = [Link]([Link])
self.fenetre_patient.title("Nouveau Patient")
self.fenetre_patient.geometry("500x600")
self.fenetre_patient.transient([Link])
self.fenetre_patient.grab_set()
# Variables pour les champs
self.nom_var = [Link]()
self.prenom_var = [Link]()
self.telephone_var = [Link]()
self.email_var = [Link]()
self.date_naissance_var = [Link]()
self.genre_var = [Link](value="M")
self.antecedents_var = [Link]()
# Formulaire
[Link](self.fenetre_patient, text="Nom *:").grid(row=0, column=0, sticky=tk.W,
padx=10, pady=5)
[Link](self.fenetre_patient, textvariable=self.nom_var, width=30).grid(row=0,
column=1, padx=10, pady=5)
[Link](self.fenetre_patient, text="Prénom *:").grid(row=1, column=0, sticky=tk.W,
padx=10, pady=5)
[Link](self.fenetre_patient, textvariable=self.prenom_var, width=30).grid(row=1,
column=1, padx=10, pady=5)
[Link](self.fenetre_patient, text="Date Naissance (JJ/MM/AAAA):").grid(row=2,
column=0, sticky=tk.W, padx=10, pady=5)
[Link](self.fenetre_patient, textvariable=self.date_naissance_var,
width=30).grid(row=2, column=1, padx=10, pady=5)
[Link](self.fenetre_patient, text="Genre:").grid(row=3, column=0, sticky=tk.W,
padx=10, pady=5)
[Link](self.fenetre_patient, textvariable=self.genre_var,
values=["M", "F"], state="readonly", width=27).grid(row=3, column=1, padx=10,
pady=5)
[Link](self.fenetre_patient, text="Téléphone:").grid(row=4, column=0, sticky=tk.W,
padx=10, pady=5)
[Link](self.fenetre_patient, textvariable=self.telephone_var, width=30).grid(row=4,
column=1, padx=10, pady=5)
[Link](self.fenetre_patient, text="Email:").grid(row=5, column=0, sticky=tk.W,
padx=10, pady=5)
[Link](self.fenetre_patient, textvariable=self.email_var, width=30).grid(row=5,
column=1, padx=10, pady=5)
[Link](self.fenetre_patient, text="Antécédents médicaux:").grid(row=6, column=0,
sticky=tk.W, padx=10, pady=5)
text_antecedents = [Link](self.fenetre_patient, width=30, height=10)
text_antecedents.grid(row=6, column=1, padx=10, pady=5)
self.text_antecedents = text_antecedents
# Boutons
frame_boutons = [Link](self.fenetre_patient)
frame_boutons.grid(row=7, column=0, columnspan=2, pady=20)
[Link](frame_boutons, text="Enregistrer",
command=lambda: self.enregistrer_patient(text_antecedents.get("1.0",
[Link]))).grid(row=0, column=0, padx=10)
[Link](frame_boutons, text="Annuler",
command=self.fenetre_patient.destroy).grid(row=0, column=1, padx=10)
def enregistrer_patient(self, antecedents):
"""Enregistre un nouveau patient dans la base de données"""
if not self.nom_var.get() or not self.prenom_var.get():
[Link]("Erreur", "Le nom et le prénom sont obligatoires!")
return
try:
# Validation de la date
date_naissance = None
if self.date_naissance_var.get():
try:
[Link](self.date_naissance_var.get(), '%d/%m/%Y')
date_naissance = self.date_naissance_var.get()
except ValueError:
[Link]("Erreur", "Format de date invalide! Utilisez
JJ/MM/AAAA")
return
[Link]('''
INSERT INTO patients (nom, prenom, date_naissance, genre, telephone, email,
antecedents, date_creation)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (self.nom_var.get(), self.prenom_var.get(), date_naissance,
self.genre_var.get(), self.telephone_var.get(), self.email_var.get(),
antecedents, [Link]().strftime('%d/%m/%Y %H:%M')))
[Link]()
[Link]("Succès", "Patient enregistré avec succès!")
self.fenetre_patient.destroy()
self.actualiser_liste_patients()
except [Link] as e:
[Link]("Erreur BDD", f"Erreur lors de l'enregistrement: {e}")
def actualiser_liste_patients(self):
"""Actualise la liste des patients dans le Treeview"""
# Vider le Treeview
for item in self.tree_patients.get_children():
self.tree_patients.delete(item)
# Récupérer les patients
[Link]('''
SELECT id, nom, prenom, telephone, email, date_naissance
FROM patients ORDER BY nom, prenom
''')
patients = [Link]()
# Ajouter au Treeview
for patient in patients:
self.tree_patients.insert('', [Link], values=patient)
def modifier_patient(self):
"""Modifie le patient sélectionné"""
selection = self.tree_patients.selection()
if not selection:
[Link]("Attention", "Veuillez sélectionner un patient à modifier!")
return
# Récupérer l'ID du patient sélectionné
item = self.tree_patients.item(selection[0])
patient_id = item['values'][0]
# Ouvrir une fenêtre de modification similaire à ajouter_patient
# [Code similaire à ajouter_patient mais avec pré-remplissage des données...]
[Link]("Information", f"Modification du patient ID: {patient_id}")
def rechercher_patient(self):
"""Recherche des patients selon le critère"""
recherche = self.recherche_var.get().strip()
if not recherche:
self.actualiser_liste_patients()
return
# Vider le Treeview
for item in self.tree_patients.get_children():
self.tree_patients.delete(item)
# Rechercher dans la base
[Link]('''
SELECT id, nom, prenom, telephone, email, date_naissance
FROM patients
WHERE nom LIKE ? OR prenom LIKE ? OR telephone LIKE ?
ORDER BY nom, prenom
''', (f'%{recherche}%', f'%{recherche}%', f'%{recherche}%'))
patients = [Link]()
for patient in patients:
self.tree_patients.insert('', [Link], values=patient)
def quitter_application(self):
"""Ferme l'application proprement"""
if [Link]("Quitter", "Voulez-vous vraiment quitter l'application?"):
try:
[Link]()
except:
pass
[Link]()
def main():
"""Fonction principale pour lancer l'application"""
root = [Link]()
app = ApplicationGestionDentaire(root)
[Link]()
if __name__ == "__main__":
main()
-- Script SQL pour la base de données cabinet_dentaire.db
-- Ce script est exécuté automatiquement par l'application
-- Table Patients
CREATE TABLE IF NOT EXISTS patients (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nom TEXT NOT NULL,
prenom TEXT NOT NULL,
date_naissance TEXT,
genre TEXT,
telephone TEXT,
email TEXT,
antecedents TEXT,
date_creation TEXT
);
-- Table Rendez-vous
CREATE TABLE IF NOT EXISTS rendez_vous (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER,
date_rdv TEXT,
heure_rdv TEXT,
statut TEXT,
notes TEXT,
FOREIGN KEY (patient_id) REFERENCES patients (id)
);
-- Table Consultations
CREATE TABLE IF NOT EXISTS consultations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER,
date_consultation TEXT,
observations TEXT,
diagnostic TEXT,
soins_effectues TEXT,
ordonnances TEXT,
FOREIGN KEY (patient_id) REFERENCES patients (id)
);
-- Table Factures
CREATE TABLE IF NOT EXISTS factures (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER,
consultation_id INTEGER,
date_facture TEXT,
actes TEXT,
total REAL,
statut_paiement TEXT,
FOREIGN KEY (patient_id) REFERENCES patients (id),
FOREIGN KEY (consultation_id) REFERENCES consultations (id)
);