Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#ameliore se code avec tes changements
import tkinter as tk
from tkinter import ttk
import pymysql
from fpdf import FPDF
from time import strftime
import os
from tkinter import messagebox
 
 
# Database connection
maBase = pymysql.connect(host="localhost", user="root", password="", database="ecoledb")
cursor = maBase.cursor()
annee = None
periode = None
classe = None
 
# Window setup
window = tk.Tk()
window.title('Student Report Card Generator')
 
# Function to get student information
def get_student_info(matricule):
    cursor.execute("""
        SELECT nom, prenom, classe
        FROM eleve
        WHERE matricule = %s  
    """, (matricule))
    student_info = cursor.fetchone()
    return student_info
 
# Fonction pour récupérer toutes les matières d'une classe
def get_all_subjects(classe):
    cursor.execute("""
        SELECT *
        FROM matiere
        WHERE classe = %s
    """, (classe,))
    subject_data = cursor.fetchall()
    return subject_data
 
# Function to get student information for a given class
def get_class_students(classe, annee, periode):
    cursor.execute("""
        SELECT eleve.matricule, eleve.nom, eleve.prenom, eleve.classe
        FROM eleve
        INNER JOIN note ON eleve.matricule = note.matricule
        WHERE note.classe = %s AND note.annee = %s AND note.periode = %s
        GROUP BY eleve.matricule
    """, (classe, annee, periode))
    student_data = cursor.fetchall()
    return student_data
 
# Function to get subject information for a student
def get_subject_info(matricule):
    cursor.execute("""
        SELECT *
        FROM note
        WHERE matricule = %s
    """, (matricule,))
    subject_info = cursor.fetchall()
    return subject_info
 
 
 
# Function to calculate total marks, average, and rank
def calculate_total_and_average_and_rank(subject_info, student_data, classe, annee, periode):
    total_marks = {}
    total_coef = {}
    average = {}
    ranks = {}
 
    # Calculate total marks, average, and coefficients for each student
    for student in student_data:
        matricule = student[0]
        student_subject_info = get_subject_info(matricule)
        total_marks[matricule] = 0
        total_coef[matricule] = 0
        for subject in student_subject_info:
            total_marks[matricule] += float(subject[11]) * int(subject[7])
            total_coef[matricule] += int(subject[7])
        if total_coef[matricule] != 0:
            average[matricule] = round(total_marks[matricule] / total_coef[matricule], 2)
        else:
            average[matricule] = 0.00
 
    # Calculate ranks based on average
    all_averages = sorted(average.items(), key=lambda x: x[1], reverse=True)
    rank = 1
    for matricule, avg in all_averages:
        if matricule in ranks:
            continue  # Handle students with the same average
        ranks[matricule] = rank
        rank += 1
 
 
    # Calcul de la moyenne générale pondérée
    total_pondere = 0
    total_coef_pondere = 0
    for matricule in average:
        total_pondere += average[matricule] * total_coef[matricule]
        total_coef_pondere += total_coef[matricule]
    if total_coef_pondere != 0:
        moyenne_generale_ponderee = round(total_pondere / total_coef_pondere, 2)
    else:
        moyenne_generale_ponderee = 0.00
 
    # Return results (including all subjects with handled missing notes)
    return total_marks, average, ranks,moyenne_generale_ponderee
 
 
 
 
# Function to generate appreciation
def generate_appreciation(average):
    if average >= 18:
        appreciation = "Excellent"
    elif average >= 16:
        appreciation = "Très Bien"
    elif average >= 14:
        appreciation = "Bien"
    elif average >= 12:
        appreciation = "Assez Bien"
    else:
        appreciation = "Insuffisant"
    return appreciation
 
# Fonction pour générer les bulletins de tous les élèves d'une classe
def generate_class_report_cards(classe, annee, periode):
    students = get_class_students(classe, annee, periode)
    all_student_data = students  # Stocker tous les élèves pour le calcul des rangs
 
 
 
    for student in students:
        matricule = student[0]
#        student_info = next(item for item in all_student_data if item[0] == matricule)  # Extract info for current student
        subject_info = get_subject_info(student[0])   # Filter by matricule
        total_marks, average, ranks,moyenne_generale_ponderee = calculate_total_and_average_and_rank(subject_info, all_student_data, classe, annee, periode)
        student_average = average.get(matricule, 0.00)  # Handle potential missing average
        appreciation = generate_appreciation(student_average)
        generate_pdf_report_card(student, subject_info, total_marks[matricule], student_average, ranks[matricule], appreciation, all_student_data,moyenne_generale_ponderee)
 
 
# Function to generate PDF report card
def generate_pdf_report_card(student_info, subject_info, total_marks, average, rank, appreciation, student_data, moyenne_generale_ponderee):
#    periode = entry_periode.get()
    pdf = FPDF('P', 'mm', 'Letter')
    pdf.add_page()
 
 
    # En-tête personnalisé (adaptez les textes et les couleurs)
    pdf.set_font('Arial', 'B', 10)
    pdf.cell(180, 10, "République du Cameroun", 0, 1, 'C')  # Titre centré
    pdf.set_font('Arial', '', 8)
    pdf.cell(90, 10, "Ministry of Secondary Education", 0, 0, 'L')  # Alignement gauche
    pdf.cell(90, 10, "Ministère des enseignements secondaires", 0, 1, 'R')  # Alignement droit
 
    # Titre du bulletin
    pdf.ln(10)
    pdf.set_font('Arial', 'B', 10)
    pdf.cell(0, 10, f"Bulletin de notes de {subject_info[0][4]}", 0, 1, 'C')  # Title centered
#    pdf.set_font('Arial', 'B', 10)
#    for subject in subject_info:
#            pdf.cell(0, 10, f'Bulletin des notes de {subject[4]}', 0, 1, 'C')  # Titre centré
 
 
 
    # Bande grise avec informations de l'élève
    pdf.set_fill_color(220, 220, 220)
    pdf.rect(x=10, y=pdf.get_y(), w=180, h=10, style='F')
    pdf.set_text_color(0, 0, 0)
    pdf.set_font('Arial', '', 10)
    pdf.cell(40, 10, f'Nom: {student_info[1]}', 0, 0, 'L')
    pdf.cell(40, 10, f'Prénom: {student_info[2]}', 0, 0, 'L')
    pdf.cell(40, 10, f'Classe: {student_info[3]}', 0, 1, 'L')
 
    # Tableau des notes (ajustement des largeurs de colonnes)
    pdf.set_fill_color(135, 206, 250)
    pdf.rect(x=10, y=pdf.get_y(), w=180, h=10, style='F')
    pdf.set_font('Arial', 'B', 12)
    pdf.cell(30, 10, 'Matière', 1, 0, 'C')
    pdf.cell(20, 10, 'Note', 1, 0, 'C')
    pdf.cell(20, 10, 'Coef.', 1, 0, 'C')
    pdf.cell(40, 10, 'Note Finale', 1, 0, 'C')
    pdf.cell(40, 10, 'Enseignant', 1, 0, 'C')
    pdf.cell(30, 10, 'Appréciation', 1, 1, 'C')  # Added column for appreciation
 
 
    pdf.set_font('Arial', '', 10)
    pdf.set_fill_color(255, 255, 204)
    # Check if subject_info is empty before iterating
 
    if subject_info:
        for subject in subject_info:
            if float(subject[11]) >= 10:
                appreciation_for_subject="bon travail"
 
            matiere = subject[6]  # Remplacer 0 par l'indice correct pour la matière
            note = subject[11]  # Remplacer 1 par l'indice correct pour la note
            coef = subject[7]
            professeur = subject[5]
 
            pdf.cell(30, 10, matiere, 1, 0, 'L')
            pdf.cell(20, 10, str(note), 1, 0, 'L')
            pdf.cell(20, 10, str(coef), 1, 0, 'C')
            final_mark = float(subject[11]) * int(subject[7])
            pdf.cell(40, 10, str(final_mark), 1, 0, 'C')
            pdf.cell(40, 10, professeur, 1, 0, 'C')
        #        appreciation_for_subject = generate_appreciation(subject[11])  # Pass final_mark for per-subject appreciation
            pdf.cell(30, 10, appreciation_for_subject, 1, 1, 'C')
 
 
 
 
        print("Données de subject_info dans generate_pdf_report_card:")
        print(f"Type de subject_info: {type(subject_info)}")
        print(f"Longueur de subject_info: {len(subject_info)}")
        for i, subject in enumerate(subject_info):
            print(subject) 
 
            # Total, moyenne et appréciation (mise en forme améliorée)
        pdf.ln()
        pdf.set_fill_color(220, 220, 220)
        pdf.rect(x=10, y=pdf.get_y(), w=80, h=12, style='B')
        pdf.set_text_color(0, 0, 0)
        pdf.set_font('Arial', 'B', 11)
        pdf.cell(w=60, h=12, txt='Total des notes:', align='L', border=0)
        pdf.set_font('Arial', 'B', 11)
        pdf.cell(w=15, h=12, txt=f"{str(total_marks)}", align='R', border=0)
 
        pdf.ln()
        pdf.set_fill_color(220, 220, 220)
        pdf.rect(x=10, y=pdf.get_y(), w=80, h=12, style='B')
        pdf.set_text_color(0, 0, 0)
        pdf.set_font('Arial', 'B', 11)
        pdf.cell(w=60, h=12, txt='Moyenne:', align='L', border=0)
        pdf.set_font('Arial', 'B', 11)
        pdf.cell(w=15, h=12, txt=f"{str(average)}/20", align='R', border=0)
 
        pdf.ln()
        pdf.set_fill_color(220, 220, 220)
        pdf.rect(x=10, y=pdf.get_y(), w=80, h=12, style='B')
        pdf.set_text_color(0, 0, 0)
        pdf.set_font('Arial', 'B', 11)
        pdf.cell(w=70, h=12, txt='Appréciation Generale:', align='L', border=0)
        pdf.set_font('Arial', '', 11)
        pdf.cell(w=5, h=12, txt=f"{appreciation}", align='R', border=0)
 
            # Ajouter le rang de l'élève
        pdf.ln()
        pdf.set_fill_color(220, 220, 220)
        pdf.rect(x=10, y=pdf.get_y(), w=80, h=12, style='B')
        pdf.set_text_color(0, 0, 0)
        pdf.set_font('Arial', 'B', 11)
        pdf.cell(w=70, h=12, txt='Rang:', align='L', border=0)
        pdf.set_font('Arial', '', 11)
        pdf.cell(w=5, h=12, txt=f"{rank}e /{len(student_data)}", align='R', border=0)
 
        # Ajouter la moyenne generale de la classe
        pdf.ln()
        pdf.set_fill_color(220, 220, 220)
        pdf.rect(x=10, y=pdf.get_y(), w=80, h=12, style='B')
        pdf.set_text_color(0, 0, 0)
        pdf.set_font('Arial', 'B', 11)
        pdf.cell(w=70, h=12, txt='Moyenne générale pondérée:', align='L', border=0)
        pdf.set_font('Arial', '', 11)
        pdf.cell(w=5, h=12, txt=f"{moyenne_generale_ponderee}/20", align='R', border=0)
 
 
 
 
            # Espaces pour signatures
        pdf.ln(20)
        pdf.set_font('Arial', 'B', 10)
        pdf.cell(90, 10, 'Visa de l\'établissement', 0, 0, 'L')
        pdf.cell(90, 10, 'Visa du tuteur', 0, 1, 'L')
 
            # Enregistrer et ouvrir le PDF
        pdf_filename = f"bulletin de {student_info[1]}-{student_info[2]}.pdf"
        pdf.output(pdf_filename)
        os.startfile(pdf_filename)
 
    else:
        messagebox.showerror("Erreur", "Aucune note enregistrée pour cet élève.")
 
 #   else:
      #      pdf.cell(0, 10, "Aucune note enregistrée pour cet élève.", 1, 1, 'C')
# Main window GUI
label_id_el = tk.Label(window, text="ID Élève:")
label_id_el.grid(row=0, column=0, padx=5, pady=5)
entry_id_el = tk.Entry(window)
entry_id_el.grid(row=0, column=1, padx=5, pady=5)
 
label_annee = tk.Label(window, text="Année:")
label_annee.grid(row=1, column=0, padx=5, pady=5)
entry_annee = tk.Entry(window)
entry_annee.grid(row=1, column=1, padx=5, pady=5)
 
label_trimestre = tk.Label(window, text="Trimestre:")
label_trimestre.grid(row=2, column=0, padx=5, pady=5)
entry_periode = tk.Entry(window)
entry_periode.grid(row=2, column=1, padx=5, pady=5)
 
label_classe = tk.Label(window, text="Classe:")
label_classe.grid(row=3, column=0, padx=5, pady=5)
 
label_classe.grid(row=3, column=0, padx=5, pady=5)
entry_classe = tk.Entry(window)
entry_classe.grid(row=3, column=1, padx=5, pady=5)
 
 
 
def generate_report(is_class=False):
    """Fonction générique pour générer un bulletin, soit pour un élève, soit pour toute une classe."""
    if  is_class:
        classe = entry_classe.get()
        annee = entry_annee.get()
        periode = entry_periode.get()
#        subject_info = get_subject_info(classe, annee, periode)  # Get subject info for all students
        generate_class_report_cards(classe, annee, periode) # Pass subject_info as argument
    else:
        matricule = entry_id_el.get()
        classe = entry_classe.get()
        annee = entry_annee.get()
        periode = entry_periode.get()
        # Vérification si le matricule est un entier avant de continuer
        try:
            matricule = int(matricule)
        except ValueError:
            messagebox.showerror("Erreur", "Veuillez entrer un identifiant d'élève valide (un nombre entier).")
            return
        students = get_class_students(classe, annee, periode)
        all_student_data = students  # Stocker tous les élèves pour le calcul des rangs
        subject_info = get_subject_info(matricule)
        student_info = next(item for item in all_student_data if item[0] == matricule)
#        total_marks, average, ranks = calculate_total_and_average_and_rank(subject_info, all_student_data, classe, annee, periode)
        total_marks, average, rank,moyenne_generale_ponderee = calculate_total_and_average_and_rank(subject_info, all_student_data, classe, annee, periode)
        appreciation = generate_appreciation(average[matricule])  # Accéder à l'average de l'élève spécifique
 
        generate_pdf_report_card(student_info, subject_info, total_marks[matricule], average[matricule], rank[matricule], appreciation, all_student_data,moyenne_generale_ponderee)
 
generate_button = tk.Button(window, text="Générer Bulletin", command=lambda: generate_report(False))  # Pass selected_classe_value
generate_button.grid(row=4, column=0, columnspan=2, padx=5, pady=5)
 
generate_class_button = tk.Button(window, text="Générer Bulletins de la Classe", command=lambda: generate_report(True))
generate_class_button.grid(row=5, column=0, columnspan=2, padx=5, pady=5)
 
 
window.mainloop()
jai une bd ecoledb. les tables eleves(matricule,nom,prenom,classe...), matiere(mid,matiere,classe,salle,coef,enseignant),note(nid,annee,classe,salle,sequence,trimestre,professeur,matiere,coef,matricule,note_1,note_2,note). pour l'instant mon code ne gener que les bulletins avec la sequence auquel les notes sont enregistrer. et j voudrais qu'il gener aussi a la fois pour le trimestre sachant que il ya 3 trimestre(1er trimestre, 2eme trimestre, 3eme trimestre) et que pour avoir la note d'une matiere lors d'un trimestre on fait la somme des notes des sequence correspondant puis on divise par 2. pour le 1er trimestre c 1e et 2e sequence, pour le 2eme trimestre c 3e et 4e sequence et pour le 3eme trimestre c la 5e et 6e sequence