File size: 10,695 Bytes
f3ad136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# pages/generate_reports.py
import streamlit as st
import pandas as pd
import io
import zipfile
from modules.database import Session, Student, AcademicTerm, ReportDesign, ENGINE, log_audit
from modules.pdf_generator import generate_pdf_report
from modules.grading import get_grade

def show():
    st.header("πŸ“„ Generate Student Reports")
    session = Session()
    
    students = pd.read_sql("SELECT * FROM students ORDER BY class_name, name", ENGINE)
    terms = pd.read_sql("SELECT * FROM academic_terms ORDER BY year DESC, term_number DESC", ENGINE)
    
    if students.empty or terms.empty:
        st.warning("Need students and terms to generate reports")
        session.close()
        st.stop()
    
    design = session.query(ReportDesign).first()
    
    st.subheader("Select Report Generation Options")
    
    report_mode = st.radio("Generate reports for:", ["Individual Student", "Whole Class"], horizontal=True)
    
    selected_term = st.selectbox("Select Term", terms['term_name'].tolist())
    term_data = terms[terms['term_name'] == selected_term].iloc[0]
    
    if report_mode == "Individual Student":
        selected_student = st.selectbox("Select Student", students['name'].tolist())
        student_data = students[students['name'] == selected_student].iloc[0]
        
        # Get marks
        marks_query = f"""
            SELECT m.*, u.name as teacher_name 
            FROM marks m
            JOIN users u ON m.submitted_by = u.id
            WHERE m.student_id = {student_data['id']} AND m.term_id = {term_data['id']}
            ORDER BY m.subject
        """
        marks = pd.read_sql(marks_query, ENGINE)
        
        # Get behavior data
        behavior_query = f"""
            SELECT punctuality, attendance, manners, general_behavior, 
                   organisational_skills, adherence_to_uniform, leadership_skills,
                   commitment_to_school, cooperation_with_peers, cooperation_with_staff,
                   participation_in_lessons, completion_of_homework
            FROM classroom_behavior
            WHERE student_id = {student_data['id']} AND term_id = {term_data['id']}
        """
        behavior_result = pd.read_sql(behavior_query, ENGINE)
        
        behavior_data = None
        if not behavior_result.empty:
            behavior_data = behavior_result.iloc[0].to_dict()
        
        # Get decision data (only for term 3)
        decision_data = None
        if term_data['term_number'] == 3:
            decision_query = f"""
                SELECT decision, notes
                FROM student_decisions
                WHERE student_id = {student_data['id']} AND term_id = {term_data['id']}
            """
            decision_result = pd.read_sql(decision_query, ENGINE)
            if not decision_result.empty:
                decision_data = decision_result.iloc[0].to_dict()
        
        if not marks.empty:
            st.subheader(f"Results Preview for {selected_student}")
            
            display_df = marks[[
                'subject', 'coursework_out_of_20', 'midterm_out_of_20', 
                'endterm_out_of_60', 'total', 'grade', 'comment', 'teacher_name'
            ]].copy()
            
            display_df.columns = ['Subject', 'CW/20', 'MOT/20', 'EOT/60', 'Total', 'Grade', 'Comment', 'Teacher']
            st.dataframe(display_df, use_container_width=True)
            
            overall_avg = marks['total'].mean()
            overall_grade = get_grade(overall_avg)
            
            avg_comments = {
                "A*": "Outstanding Performance",
                "A": "Excellent Performance",
                "B": "Good Performance",
                "C": "Satisfactory Performance",
                "D": "Needs Improvement",
                "E": "Poor Performance",
                "U": "Unsatisfactory Performance"
            }
            avg_comment = avg_comments.get(overall_grade, "")
            
            col3, col4 = st.columns(2)
            with col3:
                st.metric("Overall Average", f"{overall_avg:.0f}/100")
            with col4:
                st.metric("Overall Grade", f"{overall_grade} - {avg_comment}")
            
            if term_data['term_number'] == 3 and decision_data:
                st.metric("Decision", decision_data.get('decision', 'Pending'))
            
            if st.button("πŸ“„ Generate PDF Report", use_container_width=True):
                try:
                    pdf_data = generate_pdf_report(student_data, term_data, marks, design, behavior_data, decision_data)
                    
                    st.download_button(
                        "⬇️ Download PDF Report",
                        pdf_data,
                        f"{selected_student}_{selected_term}_report.pdf",
                        "application/pdf",
                        use_container_width=True
                    )
                    log_audit(session, st.session_state.user_id, "generate_report", 
                             f"Individual: {selected_student} - {selected_term}")
                    st.success("βœ… PDF generated successfully!")
                except Exception as e:
                    st.error(f"❌ Error generating PDF: {str(e)}")
        else:
            st.info(f"❌ No marks found for {selected_student} in {selected_term}")
            st.info(f"Debug: Student ID = {student_data['id']}, Term ID = {term_data['id']}")
            
            any_marks = pd.read_sql(f"SELECT COUNT(*) as count FROM marks WHERE student_id = {student_data['id']}", ENGINE)
            st.info(f"This student has {any_marks['count'].iloc[0]} marks in total across all terms")
    
    else:  # Whole Class
        classes = pd.read_sql("SELECT DISTINCT class_name FROM students ORDER BY class_name", ENGINE)
        selected_class = st.selectbox("Select Class", classes['class_name'].tolist())
        
        class_students = students[students['class_name'] == selected_class]
        
        st.info(f"πŸ“Š Found {len(class_students)} students in {selected_class}")
        
        students_with_marks = []
        students_without_marks = []
        
        for _, student in class_students.iterrows():
            marks = pd.read_sql(f"""
                SELECT m.*, u.name as teacher_name 
                FROM marks m
                JOIN users u ON m.submitted_by = u.id
                WHERE m.student_id = {student['id']} AND m.term_id = {term_data['id']}
            """, ENGINE)
            
            if not marks.empty:
                students_with_marks.append(student['name'])
            else:
                students_without_marks.append(student['name'])
        
        col5, col6 = st.columns(2)
        with col5:
            st.success(f"βœ… {len(students_with_marks)} students with marks")
        with col6:
            if students_without_marks:
                st.warning(f"⚠️ {len(students_without_marks)} students without marks")
        
        if students_without_marks:
            with st.expander("⚠️ Students without marks"):
                st.write(", ".join(students_without_marks))
        
        if students_with_marks:
            if st.button(f"πŸ“„ Generate All Reports for {selected_class}", use_container_width=True):
                zip_buffer = io.BytesIO()
                with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
                    for student_name in students_with_marks:
                        student_data = class_students[class_students['name'] == student_name].iloc[0]
                        
                        marks = pd.read_sql(f"""
                            SELECT m.*, u.name as teacher_name 
                            FROM marks m
                            JOIN users u ON m.submitted_by = u.id
                            WHERE m.student_id = {student_data['id']} AND m.term_id = {term_data['id']}
                        """, ENGINE)
                        
                        behavior_query = f"""
                            SELECT punctuality, attendance, manners, general_behavior, 
                                   organisational_skills, adherence_to_uniform, leadership_skills,
                                   commitment_to_school, cooperation_with_peers, cooperation_with_staff,
                                   participation_in_lessons, completion_of_homework
                            FROM classroom_behavior
                            WHERE student_id = {student_data['id']} AND term_id = {term_data['id']}
                        """
                        behavior_result = pd.read_sql(behavior_query, ENGINE)
                        
                        behavior_data = None
                        if not behavior_result.empty:
                            behavior_data = behavior_result.iloc[0].to_dict()
                        
                        decision_data = None
                        if term_data['term_number'] == 3:
                            decision_query = f"""
                                SELECT decision, notes
                                FROM student_decisions
                                WHERE student_id = {student_data['id']} AND term_id = {term_data['id']}
                            """
                            decision_result = pd.read_sql(decision_query, ENGINE)
                            if not decision_result.empty:
                                decision_data = decision_result.iloc[0].to_dict()
                        
                        if not marks.empty:
                            pdf_data = generate_pdf_report(student_data, term_data, marks, design, behavior_data, decision_data)
                            filename = f"{student_name}_{selected_term}_report.pdf"
                            zip_file.writestr(filename, pdf_data)
                
                zip_buffer.seek(0)
                
                st.download_button(
                    f"⬇️ Download All {len(students_with_marks)} Reports (ZIP)",
                    zip_buffer.getvalue(),
                    f"{selected_class}_{selected_term}_reports.zip",
                    "application/zip",
                    use_container_width=True
                )
                
                log_audit(session, st.session_state.user_id, "generate_reports", 
                         f"Bulk: {selected_class} - {selected_term} - {len(students_with_marks)} reports")
                st.success(f"βœ… Generated {len(students_with_marks)} reports!")
        else:
            st.warning("No students in this class have marks for the selected term")
    
    session.close()