Skip to main content

Overview

The Bulletin System generates comprehensive academic reports showing student grades, calculated averages, and pass/fail status. Students can view their own bulletins, while administrators can generate bulletins for any student.

Academic Reports

Complete grade reports with all course results

Average Calculation

Automatic calculation of overall academic average

Pass/Fail Status

Determination of VALIDÉ or NON VALIDÉ status

Role-Based Access

Students see own bulletin, admins see all students

What is a Bulletin?

A bulletin (also called academic transcript or report card) is a formal document showing:
  • Student information (name, email)
  • All courses with grades
  • Teacher names for each course
  • Calculated overall average
  • Academic status (passed or failed)
Grading System:
  • Numerical scale (typically 0-20 in French academic systems)
  • Passing grade: 10.00 or higher
  • VALIDÉ: Average ≥ 10.00 (passed)
  • NON VALIDÉ: Average < 10.00 (failed)

Bulletin Architecture

Data Flow

Student

Enrollments → Courses → Subjects
  ↓                ↓
Grades          Teachers

Bulletin Calculation:
  • Subject names
  • Teacher names  
  • Grade values
  • Average (sum/count)
  • Status (VALIDÉ/NON VALIDÉ)
The bulletin aggregates data from multiple tables to create a comprehensive academic report.

Controller Implementation

Listing Students (Admin)

Admins can select which student’s bulletin to view:
// BulletinController.php - index()
public function index()
{
    Auth::admin(); // Only admins can access student list

    $students = $this->userModel->getAllStudents();
    require __DIR__ . '/../views/bulletin/index.php';
}
// User.php - getAllStudents()
public function getAllStudents()
{
    $stmt = $this->db->query(
        "SELECT id, name, email FROM users WHERE role = 'student'"
    );
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
This provides a list for admins to select a student and view their bulletin.

Generating Bulletin

Unified bulletin generation for both students and admins:
// BulletinController.php - show()
public function show()
{
    Auth::check(); // Must be authenticated

    // Determine student ID based on role
    if ($_SESSION['user']['role'] === 'student') {
        // Students can only view their own bulletin
        $student_id = $_SESSION['user']['id'];
    } else {
        // Admin/Teacher must provide student_id parameter
        if (!isset($_GET['student_id'])) {
            die("Student ID is required");
        }
        $student_id = $_GET['student_id'];
    }

    // Get student information
    $student = $this->userModel->findById($student_id);
    
    // Get all grades with course and teacher details
    $grades = $this->gradeModel->getBulletinData($student_id);

    // Calculate average
    $total = 0;
    $count = count($grades);

    foreach ($grades as $g) {
        $total += $g['grade'];
    }

    $average = $count > 0 ? round($total / $count, 2) : 0;
    $status = $average >= 10 ? 'VALIDÉ' : 'NON VALIDÉ';

    require __DIR__ . '/../views/bulletin/show.php';
}
For Students:
  • Use logged-in user’s ID from session
  • Cannot specify different student_id
  • Can only view own bulletin
For Admins/Teachers:
  • Must provide student_id as URL parameter
  • Can view any student’s bulletin
  • Access: /bulletin/show?student_id=5
Security:
  • Auth::check() ensures user is logged in
  • Students automatically restricted to own data
  • URL parameter required for admin access

Grade Data Retrieval

Getting Bulletin Data

Retrieve all necessary information for the bulletin:
// Grade.php - getBulletinData()
public function getBulletinData($student_id)
{
    $sql = "
        SELECT 
            subjects.name AS subject,
            users.name AS teacher,
            grades.grade
        FROM grades
        JOIN courses ON grades.course_id = courses.id
        JOIN subjects ON courses.subject_id = subjects.id
        JOIN users ON courses.teacher_id = users.id
        WHERE grades.student_id = ?
    ";

    $stmt = $this->db->prepare($sql);
    $stmt->execute([$student_id]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
JOINs:
  1. grades → courses: Link grade to course
  2. courses → subjects: Get subject name
  3. courses → teachers → users: Get teacher name
Filters:
  • WHERE grades.student_id = ?: Only this student’s grades
Result columns:
  • subject: Course subject name (e.g., “Mathematics”)
  • teacher: Teacher’s full name (e.g., “Mr. Smith”)
  • grade: Numerical grade (e.g., 16.50)
Important Note: Only courses with recorded grades appear. If a student is enrolled but has no grade yet, that course won’t show in the bulletin.
Example Data:
[
    [
        'subject' => 'Mathematics',
        'teacher' => 'Mr. Smith',
        'grade' => '16.50'
    ],
    [
        'subject' => 'Physics',
        'teacher' => 'Dr. Johnson',
        'grade' => '14.00'
    ],
    [
        'subject' => 'English',
        'teacher' => 'Ms. Williams',
        'grade' => '18.00'
    ]
]

Average Calculation

Calculation Algorithm

Simple arithmetic mean of all grades:
// From BulletinController.php - show()
$total = 0;
$count = count($grades);

foreach ($grades as $g) {
    $total += $g['grade'];
}

$average = $count > 0 ? round($total / $count, 2) : 0;
Step-by-step:
  1. Initialize total to 0
  2. Count number of grades
  3. Sum all grade values
  4. Divide total by count
  5. Round to 2 decimal places
  6. If no grades, return 0

Example Calculation

// Student has 3 grades
$grades = [
    ['subject' => 'Math', 'teacher' => 'Mr. Smith', 'grade' => 16.50],
    ['subject' => 'Physics', 'teacher' => 'Dr. Johnson', 'grade' => 14.00],
    ['subject' => 'English', 'teacher' => 'Ms. Williams', 'grade' => 18.00]
];

$total = 0;
$total += 16.50; // = 16.50
$total += 14.00; // = 30.50
$total += 18.00; // = 48.50

$count = 3;
$average = round(48.50 / 3, 2); // = 16.17
Calculation Notes:
  • All courses weighted equally (no credit hours)
  • Simple arithmetic mean
  • Rounded to 2 decimal places for display
  • Empty grade list results in 0.00 average

Status Determination

Pass/Fail Logic

$status = $average >= 10 ? 'VALIDÉ' : 'NON VALIDÉ';
Rules:
  • VALIDÉ (Passed): Average ≥ 10.00
  • NON VALIDÉ (Failed): Average < 10.00
Examples:
  • Average 16.17 → VALIDÉ ✅
  • Average 10.00 → VALIDÉ ✅ (exactly 10 passes)
  • Average 9.99 → NON VALIDÉ ❌
  • Average 0.00 → NON VALIDÉ ❌ (no grades)
Academic Standard: The 10.00 threshold is common in French academic systems where:
  • 0-20 is the grading scale
  • 10/20 represents 50% (minimum passing)
  • 10.00+ is considered satisfactory performance

Complete Bulletin Controller

// BulletinController.php - Full implementation
class BulletinController
{
    private $gradeModel;
    private $userModel;

    public function __construct()
    {
        $this->gradeModel = new Grade();
        $this->userModel = new User();
    }

    // Admin: List all students for bulletin selection
    public function index()
    {
        Auth::admin();

        $students = $this->userModel->getAllStudents();
        require __DIR__ . '/../views/bulletin/index.php';
    }

    // Generate bulletin (student sees own, admin selects student)
    public function show()
    {
        Auth::check();

        // Determine student ID based on role
        if ($_SESSION['user']['role'] === 'student') {
            $student_id = $_SESSION['user']['id'];
        } else {
            if (!isset($_GET['student_id'])) {
                die("Student ID is required");
            }
            $student_id = $_GET['student_id'];
        }

        // Get student info and grades
        $student = $this->userModel->findById($student_id);
        $grades = $this->gradeModel->getBulletinData($student_id);

        // Calculate average
        $total = 0;
        $count = count($grades);

        foreach ($grades as $g) {
            $total += $g['grade'];
        }

        $average = $count > 0 ? round($total / $count, 2) : 0;
        $status = $average >= 10 ? 'VALIDÉ' : 'NON VALIDÉ';

        require __DIR__ . '/../views/bulletin/show.php';
    }
}

API Endpoints

MethodEndpointAccessDescription
GET/bulletinAdminList all students
GET/bulletin/showStudentView own bulletin
GET/bulletin/show?student_id={id}AdminView any student’s bulletin

Use Cases

Context: John Doe wants to check his academic performanceFlow:
  1. John logs in as student
  2. Navigates to Bulletin section
  3. System detects role: ‘student’
  4. Uses session ID: $student_id = john_id
  5. Retrieves: $student = findById(john_id)
  6. Retrieves: $grades = getBulletinData(john_id)
    • Result:
      • Mathematics (Mr. Smith): 16.50
      • Physics (Dr. Johnson): 14.00
      • English (Ms. Williams): 18.00
  7. Calculates:
    • Total: 48.50
    • Count: 3
    • Average: 16.17
    • Status: VALIDÉ (16.17 ≥ 10)
  8. Displays bulletin:
    Student: John Doe ([email protected])
    
    Courses:
    - Mathematics | Mr. Smith | 16.50
    - Physics | Dr. Johnson | 14.00  
    - English | Ms. Williams | 18.00
    
    Average: 16.17
    Status: VALIDÉ
    
Context: Admin needs to review Jane Smith’s academic recordFlow:
  1. Admin navigates to /bulletin
  2. System shows list of all students
  3. Admin clicks on “Jane Smith” (id: 8)
  4. Redirects to: /bulletin/show?student_id=8
  5. System detects role: ‘admin’
  6. Extracts: $student_id = $_GET['student_id'] = 8
  7. Retrieves: $student = findById(8)
  8. Retrieves: $grades = getBulletinData(8)
    • Result:
      • Mathematics: 12.00
      • Chemistry: 8.50
  9. Calculates:
    • Total: 20.50
    • Count: 2
    • Average: 10.25
    • Status: VALIDÉ (10.25 ≥ 10)
  10. Displays Jane’s bulletin with all details
Context: Student has low gradesFlow:
  1. Student views bulletin
  2. Grades retrieved:
    • Mathematics: 8.00
    • Physics: 7.50
    • English: 9.00
  3. Calculation:
    • Total: 24.50
    • Count: 3
    • Average: 8.17
    • Status: NON VALIDÉ (8.17 < 10)
  4. Bulletin displays:
    • All grades shown
    • Average: 8.17
    • Status: NON VALIDÉ (highlighted/styled differently)
  5. Student sees they need to improve grades
Context: New student with no recorded gradesFlow:
  1. Student views bulletin
  2. Query: getBulletinData(student_id)
  3. Result: Empty array [] (no grades in database)
  4. Calculation:
    • Total: 0
    • Count: 0
    • Average: 0.00 (count > 0 check prevents division by zero)
    • Status: NON VALIDÉ (0.00 < 10)
  5. Bulletin displays:
    • No courses listed
    • Average: 0.00
    • Status: NON VALIDÉ
    • Message: “No grades recorded yet”

Bulletin Display Example

Sample Bulletin Output

╔════════════════════════════════════════════════╗
║           ACADEMIC BULLETIN                    ║
╠════════════════════════════════════════════════╣
║ Student: John Doe                              ║
║ Email: [email protected]
╠════════════════════════════════════════════════╣
║                                                ║
║ COURSES AND GRADES:                            ║
║                                                ║
║ Mathematics                                    ║
║ Teacher: Mr. Smith                             ║
║ Grade: 16.50                                   ║
║                                                ║
║ Physics                                        ║
║ Teacher: Dr. Johnson                           ║
║ Grade: 14.00                                   ║
║                                                ║
║ English Literature                             ║
║ Teacher: Ms. Williams                          ║
║ Grade: 18.00                                   ║
║                                                ║
╠════════════════════════════════════════════════╣
║ OVERALL AVERAGE: 16.17                         ║
║ STATUS: VALIDÉ ✓                               ║
╚════════════════════════════════════════════════╝

Data Dependencies

Bulletin Generation Requires:
  ├─ User data (student info)
  ├─ Grades (student performance)
  │   └─ Courses (subject & teacher links)
  │       ├─ Subjects (course names)
  │       └─ Teachers → Users (instructor names)
  └─ Calculation logic (average & status)
Important Dependency: Bulletins only show courses with recorded grades. A student enrolled in 5 courses but with grades in only 3 will see a bulletin with 3 courses. This is intentional - it shows actual academic performance, not just enrollment.

Best Practices

Accuracy

  • Use precise decimal calculations
  • Round only for display (2 decimals)
  • Handle zero-grade edge cases
  • Maintain calculation transparency

Security

  • Enforce role-based access
  • Students see only own data
  • Validate student_id parameter
  • Require authentication

Data Quality

  • Show only courses with grades
  • Include teacher attribution
  • Display complete student info
  • Handle empty grade lists gracefully

User Experience

  • Clear pass/fail indication
  • Organized grade presentation
  • Easy-to-read average display
  • Professional bulletin format

Grading Scale Reference

RangeInterpretationStatus
18-20ExcellentVALIDÉ
16-17.99Very GoodVALIDÉ
14-15.99GoodVALIDÉ
12-13.99SatisfactoryVALIDÉ
10-11.99PassingVALIDÉ
8-9.99InsufficientNON VALIDÉ
6-7.99PoorNON VALIDÉ
0-5.99Very PoorNON VALIDÉ
Passing Threshold: 10.00 (50% of maximum 20)
The bulletin system provides a comprehensive academic report while maintaining security, accuracy, and user-friendly presentation. It serves as the primary tool for students to monitor their academic progress and for administrators to assess student performance.

Build docs developers (and LLMs) love