# **R&D Documentation: Academic Result Module (2526)**

**Subject:** Complete Analysis of Data Architecture, Schema Design, Calculation Logic, and Workflows
**Module Location:** `/Modules/Teacher`
**Source Files:**
1. `Modules/Teacher/Http/Controllers/addAcademicResult2526Controller.php`
2. `Modules/Teacher/Http/Controllers/SaveResult2526.php`
3. `Modules/Teacher/Http/Controllers/viewAcademicResult2526Controller.php`
4. `Modules/Teacher/Helpers/MarksModerationHelper.php`
5. `Modules/Teacher/Helpers/CachedDataHelper.php`
6. `Modules/Teacher/Routes/web.php`

**Last Updated:** November 8, 2025

-----

## 1. System Overview

### 1.1. Purpose

The system is a comprehensive module for entering, storing, and managing student academic results. It is built to handle a wide variety of result structures that differ based on **Class**, **Board** (CBSE, CE, IB), and **Result Type** (Pre Mid Term, Half Yearly, Final, etc.).

### 1.2. Core Technology Stack

The module uses a **Hybrid Database Architecture**:

* **MySQL (via `feeAdminPanel` connection):** Serves as the **"Configuration Database."** It stores student metadata and, most importantly, the *definitions* and *structure* of all exams (e.g., what subjects exist, what components they have, and their max marks).
* **MongoDB (via `mongodb` connection):** Serves as the **"Data Database."** It stores the actual marks entered for each student. Its schema-less nature is leveraged to dynamically store different result structures based on the MySQL configuration.

### 1.3. Key Actors & Workflow

The system operates on a multi-stage approval workflow:

1. **Teacher (Role ID 4):** Enters marks for their assigned class/subjects. Submits to the Observer.
2. **Observer:** Reviews, edits (if necessary), and approves the marks submitted by the Teacher. Observer modifications are stored separately in the `observe_student_result` collection.
3. **Principal:** Performs the final review and publishes the result.

This workflow is tracked in the MySQL `tbl_result_status` table with timestamps for each stage.

### 1.4. Module Architecture

The Teacher module follows Laravel's modular structure:
* **Controllers:** Handle HTTP requests and orchestrate data flow
  - `addAcademicResult2526Controller.php` - Form display and data preparation
  - `SaveResult2526.php` - Save operations for all result types
  - `viewAcademicResult2526Controller.php` - Display saved results
* **Helpers:** Business logic extraction
  - `MarksModerationHelper.php` - Automatic marks moderation and grace marks
  - `CachedDataHelper.php` - Performance optimization through caching
* **Views:** Blade templates in `Resources/views/viewAcademicResult2526/`
* **Routes:** Defined in `Routes/web.php`

-----

## 2. Core Data Architecture

### 2.1. MySQL (`feeAdminPanel`) - The "Configuration" DB

This database *defines* the structure of the marks-entry forms and the MongoDB documents.

#### Key Tables:

* **`school_result_subjects`**: Defines the main subjects (e.g., "English", "Mathematics")
  - Fields: `id`, `subject`, `board`, `result_type`, `class_from`, `class_to`
  - Determines which subjects are available for each class/board/result type combination

* **`school_result_sub_title`**: **The most critical configuration table.** Defines the individual mark components (columns) for each subject.
  - Key fields:
    * `id`: Unique identifier for each component
    * `subject_id`: Links to `school_result_subjects.id`
    * `sub_title`: Display name of the component (e.g., "Term 1 Exam", "Notebook")
    * `table_field_name`: For "denormalized" results, this stores the prefix (e.g., `eng_`, `maths_`) used to name fields in MongoDB
    * `max_marks`: Maximum marks for this component
    * `cal_percentage_on`: A value used for calculating weighted percentages, especially for periodic tests
    * `perodic_test_field_name`: **Drives the "Dual-Write" feature.** This field dictates *which field* in a *target* (Half Yearly/Final) document should be updated when a *source* (Pre Mid Term/PT) mark is saved
    * `position`: Display order of components
    * `session`: Academic session (e.g., "2025-26")
    * `excel_col_no`: Column position for Excel exports

* **`tbl_result_status`**: Tracks the submission status for a class/section/result type
  - Fields: `school_id`, `class`, `section`, `session`, `board`, `result_type`, `status`
  - Status values: `1` = Teacher submitted, `2` = Observer approved, `3` = Principal approved
  - Includes timestamps: `teacher_submitted_at`, `observer_submitted_at`, `principal_submitted_at`
  - Includes actor IDs: `teacher_id`, `observer_id`, `principal_id`

* **`tbl_class_teacher_assignment`**: Maps teachers to their assigned classes
  - Used to determine which classes/sections a teacher can access

* **`students` / `students{session}`**: Student master data
  - Dynamic table names based on session (e.g., `students2025-26` for historical data)
  - Fields: `admission_no`, `first_name`, `last_name`, `current_class`, `section`, `board`, `current_session`, etc.

* **`student_parents`**: Parent information linked to students

### 2.2. MongoDB (`mongodb`) - The "Data" DB

This database *stores* the marks.

#### Collections:

* **`student_result`**: The primary collection for marks entered by **Teachers**
  - Documents are uniquely identified by composite key (see section 3)
  - Schema varies dynamically based on class, board, and result type

* **`observe_student_result`**: A *parallel* collection that stores marks entered or modified by an **Observer**
  - Allows the system to maintain both teacher and observer versions of the data
  - Same schema as `student_result`
  - Provides audit trail for Observer modifications

* **`student_result_history`**: Stores historical snapshots of moderated results
  - Created when marks moderation is applied
  - Contains `_parent` field linking to original document
  - Includes `moderated_at` timestamp

### 2.3. MySQL Tables for IB Board (Non-MongoDB)

Several IB-specific results use dedicated MySQL tables:
* `result_ib_diagnostic_test`
* `result_ib_code_of_conduct`
* `result_ib_cocurricular_activities`
* `school_result_ib_final`
* `result_ib_spiritual_development_program`
* `result_ib_learner_profile_attributes`
* `result_ib_approaches_to_learning`

-----

## 3. MongoDB Schema Design

The document structure in MongoDB is **dynamic** and changes based on the context (Class, Board, Result Type) provided by `addAcademicResult2526Controller.php`.

### 3.1. Common Identifier Fields (Composite Key)

All result documents are uniquely identified by this combination:
* `school_id` (integer)
* `current_class` (integer)
* `session` (string, e.g., "2025-26")
* `section` (string)
* `board` (string: "CBSE", "CE", "IB")
* `result_type` (string: "Pre Mid Term", "Half Yearly", etc.)
* `s_adm_no_hid` (integer - Student Admission Number)

### 3.2. Schema Case 1: "Normalized" Schema (Periodic Tests & Classes 11-12)

This schema is used for periodic tests and senior-level classes.

**Used For:**
* Classes <= 10 **AND** Result Type = 'Pre Mid Term', 'Post Mid Term', 'PT1', 'PT2', 'PT3'
* Classes > 10 (11 & 12) **AND** All Result Types

**Structure:** Marks are stored in an indexed structure. Each `_i` suffix corresponds to a specific component from the `school_result_sub_title` table.

**Indexing Logic:**
* For CBSE/IB boards: Sequential indexing based on `db_srno` (subject number)
* For CE board: Custom indexing to handle varied subject structures
* Index calculation: `i = sub_no * total_subtitles - k` where k ranges from 0 to total_subtitles-1

```json
/* Example: Pre Mid Term, Class 10 */
{
  "_id": ObjectId("..."),
  "school_id": 130,
  "current_class": 10,
  "session": "2025-26",
  "section": "A",
  "board": "CBSE",
  "result_type": "Pre Mid Term",
  "s_adm_no_hid": 12345,
  "assignAsChk": "Teacher",

  "main_subject_id_1": 1,   // e.g., English (main subject ID)
  "subject_id_1": 10,       // e.g., English - PT (ID from sub_title table)
  "marks_1": 18.0,
  "max_marks_1": 20.0,
  "percentage_1": 9.0,      // Calculated percentage (for dual-write)

  "main_subject_id_2": 1,   // e.g., English
  "subject_id_2": 11,       // e.g., English - Notebook
  "marks_2": 4.5,
  "max_marks_2": 5.0,

  "main_subject_id_3": 2,   // e.g., Maths
  "subject_id_3": 15,       // e.g., Maths - PT
  "marks_3": 15.0,
  "max_marks_3": 20.0,
  "percentage_3": 7.5,

  "created_at": "2025-11-08 10:30:00 AM",
  "updated_at": "2025-11-08 10:30:00 AM",
  "created_by": 4,
  "updated_by": 4
}
```

### 3.3. Schema Case 2: "Denormalized" Schema (Half Yearly/Final for Classes <= 10)

This schema is used for consolidated term-end results for junior classes.

**Used For:**
* Classes <= 10 **AND** Result Type = 'Half Yearly', 'Final', 'SA1', 'SA2'

**Structure:** Fields are "denormalized" using subject-specific prefixes (e.g., `eng_`, `maths_`, `science_`) defined in `school_result_sub_title.table_field_name`. This schema also stores calculated `cal` fields and the periodic test marks (via the "Dual-Write" flow).

**Field Pattern for Each Subject:**
* `{prefix}subject_id`: Main subject ID
* `{prefix}sub1`, `{prefix}sub2`, etc.: Sub-title IDs
* `{prefix}marks1`, `{prefix}marks2`, etc.: Marks obtained
* `{prefix}cal1`, `{prefix}cal2`, `{prefix}cal3`: Calculated totals (board/class specific)
* `{prefix}perodic_test`: Periodic test marks (from dual-write)
* `{prefix}marks1_old`, etc.: Original marks (for Observer audit trail)

```json
/* Example: Half Yearly, Class 10, CBSE */
{
  "_id": ObjectId("..."),
  "school_id": 130,
  "current_class": 10,
  "session": "2025-26",
  "section": "A",
  "board": "CBSE",
  "result_type": "Half Yearly",
  "s_adm_no_hid": 12345,
  "assignAsChk": "Teacher",

  /* English Fields (prefix 'eng_') */
  "eng_subject_id": 1,
  "eng_sub1": 100,         // Sub-title ID for 'Term 1 Exam'
  "eng_marks1": 75.0,      // Marks for 'Term 1 Exam' (out of 80)
  "eng_sub2": 101,         // Sub-title ID for 'Periodic Test Average'
  "eng_marks2": 9.0,       // Copied from 'Pre Mid Term' via dual-write
  "eng_sub3": 102,         // Sub-title ID for 'Notebook'
  "eng_marks3": 4.5,
  "eng_sub4": 103,         // Sub-title ID for 'Subject Enrichment'
  "eng_marks4": 4.0,
  "eng_cal1": 92.5,        // Calculated: marks1 + marks2 + marks3 + marks4
  "eng_cal2": 96.5,        // Calculated: cal1 + marks4 (for classes 9-10)
  "eng_perodic_test": 9.0, // Periodic test average (dual-write target)

  /* Maths Fields (prefix 'maths_') */
  "maths_subject_id": 2,
  "maths_sub1": 105,
  "maths_marks1": 60.0,
  "maths_sub2": 106,
  "maths_marks2": 7.5,     // From 'Pre Mid Term' dual-write
  "maths_sub3": 107,
  "maths_marks3": 4.0,
  "maths_sub4": 108,
  "maths_marks4": 3.5,
  "maths_cal1": 75.0,
  "maths_cal2": 78.5,
  "maths_perodic_test": 7.5,

  /* Co-Scholastic fields (no calculations) */
  "co_scholastic_subject_id": 10,
  "co_scholastic_marks1": "A",
  "co_scholastic_marks2": "B",

  "created_at": "2025-11-08 10:30:00 AM",
  "updated_at": "2025-11-08 10:30:00 AM",
  "created_by": 4,
  "updated_by": 4,
  "status": "P"  // P=Pass, M=Moderated, F=Fail, I7=Reassessment, I15=Improvement(15 days)
}
```

### 3.4. Schema Case 3: Observer Modifications

When an Observer modifies marks, the original marks are preserved with `_old` suffix:

```json
{
  /* ... other fields ... */
  "eng_marks1": 78.0,       // Observer's updated marks
  "eng_marks1_old": 75.0,   // Original teacher's marks
  "eng_marks2": 9.5,
  "eng_marks2_old": 9.0,
  /* ... recalculated cal fields based on new marks ... */
}
```

-----

## 4. Controller & Route Architecture

### 4.1. Routes (`Modules/Teacher/Routes/web.php`)

All routes are under `/teacher` prefix with `web`, `admin`, and `auth` middleware.

**Key Routes:**
```php
// Result Entry
GET/POST /teacher/addAcademicResult         // Session 2023-24 (legacy)
GET/POST /teacher/addAcademicResult2425     // Session 2024-25
GET/POST /teacher/addAcademicResult2526     // Session 2025-26 (current)

// Result Viewing
GET/POST /teacher/viewAcademicResult        // View results
GET/POST /teacher/viewObservedResult        // View observer modifications

// Workflow
POST /teacher/submitResultForObserver       // Submit to next stage

// IB Board Specific
GET/POST /teacher/addCocurricularResult
GET/POST /teacher/addDiagnosticTest
GET/POST /teacher/addCodeOfConduct
GET/POST /teacher/addCoCurricularActivites
```

### 4.2. Controllers

#### 4.2.1. addAcademicResult2526Controller

**Responsibility:** Display result entry forms and prepare data for views

**Key Method:** `addAcademicResult(Request $request)`

**Flow:**
1. **GET Request:** Display empty form with class/section/result type selection
2. **POST Request:** Based on class and result type, load appropriate view:
   - Classes <= 10, PT types → `addAcademicResult.blade.php` (normalized)
   - Classes <= 10, Half Yearly/Final → `addAcademicHalfFinalResult.blade.php` (denormalized)
   - Classes 11-12, PT types → `addAcademicResult11n12.blade.php`
   - Classes 11-12, Half Yearly/Final → `addAcademicHalfFinalResult11n12.blade.php`
   - IB Final → `addAcademicIBFinalResult.blade.php`
   - IB SDP → `addAcademicIBSDPResult.blade.php`

**Data Preparation:**
- Fetches student list from MySQL using `CachedDataHelper::getStudentsListFromCacheOrDB()`
- Fetches subject configuration using `CachedDataHelper::getSubjectFromCacheOrDB()`
- Fetches existing MongoDB results (if any) from `student_result` or `observe_student_result`
- Checks submission status via `AdminHelper::getResultStatus()`
- Determines user's assignment role via `AdminHelper::getAssignAsVal()` (Teacher/Observer)

**Key Method:** `submitResultForObserver()`

**Flow:**
1. Calls `MarksModerationHelper::moderateClssSection()` to apply automatic moderation
2. Updates `tbl_result_status` table based on submission source:
   - Teacher → status = 1
   - Observer → status = 2, updates related PT result types (PT1→Pre Mid Term, PT2→Half Yearly, PT3→Post Mid Term)
   - Principal → status = 3

#### 4.2.2. SaveResult2526

**Responsibility:** Handle all save operations for different result types

**Key Methods:**

1. **`saveStdMidResult(Request $request)`** - For Periodic Tests
   - Prepares input and converts marks to float
   - Calculates percentage using `cal_percentage_on`
   - Handles dual-write via `handlePeriodicTest()`
   - Saves to `student_result` or `observe_student_result` based on user role

2. **`saveStdResult(Request $request)`** - For Half Yearly/Final (Classes <= 10)
   - Handles denormalized schema
   - Applies calculation logic via `handleHalfYearlyFieldCalculation()`
   - Stores original marks as `_old` fields for Observer modifications
   - Executes board-specific calculation formulas

3. **`saveStdResult11n12(Request $request)`** - For Classes 11-12
   - Converts array inputs to indexed marks fields
   - Saves to both `student_result` and `observe_student_result` when Observer modifies

4. **`saveStdIBFinalResult(Request $request)`** - For IB Final
   - Saves to MySQL table `school_result_ib_final`
   - Handles IB-specific field structure

5. **`saveStdIBSDPResult(Request $request)`** - For IB Spiritual Development Program
   - Saves to MySQL table `result_ib_spiritual_development_program`

6. **`getStuDetail(Request $request)`** - Fetch student marks for editing
   - Retrieves from MongoDB `student_result`
   - For classes 9-10, calculates best two periodic test average
   - Returns student info along with marks data

#### 4.2.3. viewAcademicResult2526Controller

**Responsibility:** Display saved results

**Key Method:** `viewAcademicResult(Request $request)`

**Flow:**
1. Fetches student list from MySQL
2. For each student, retrieves marks from MongoDB collections:
   - `student_result` (teacher's data)
   - `observe_student_result` (observer's data, takes precedence)
3. Merges student info with marks data
4. Routes to appropriate view based on result type and board
5. Supports PDF/Excel export functionality

-----

## 5. Data Flow & Calculation Logic

### 5.1. Flow A: The "Dual-Write" Mechanism (PT marks → Half Yearly/Final)

This is the most complex data flow, linking periodic tests to term-end results.

**Purpose:** Automatically populate periodic test averages in Half Yearly/Final results as they are being entered

**Trigger Conditions:**
- Result type is 'Pre Mid Term', 'Post Mid Term', 'PT1', 'PT2', or 'PT3'
- `perodic_test_field_name` is configured in `school_result_sub_title`
- `percentage_X` field is calculated (depends on `cal_percentage_on`)

**Step-by-Step Flow:**

1. **Action:** Teacher saves a mark in the **'Pre Mid Term'** (or PT*) interface
2. **Save Function:** `saveStdMidResult()` is called
3. **Step 1 - Calculate Percentage:**
   ```php
   if (CE board && specific subjects) {
       percentage = marks * cal_percentage_on
   } else {
       percentage = (marks * cal_percentage_on) / max_marks
   }
   ```
4. **Step 2 - Identify Target:**
   - Pre Mid Term → Half Yearly
   - Post Mid Term → Final
   - PT1 → Half Yearly
   - PT2 → Half Yearly (for classes 9-10)
   - PT3 → Final

5. **Step 3 - Dual-Write:** Function `handlePeriodicTest()` is called:
   ```php
   // Determine target result type
   $for_perodic_result_type = ($result_type == "Post Mid Term") ? "Final" : "Half Yearly";

   // Find or create target document
   $existingMarks = DB::connection('mongodb')
       ->table($tableName)
       ->where('school_id', $school_id)
       ->where('current_class', $current_class)
       ->where('session', $session)
       ->where('board', $board)
       ->where('result_type', $for_perodic_result_type)
       ->where('s_adm_no_hid', $s_adm_no_hid)
       ->first();

   // Upsert the periodic test field
   $upsert_array[$perodic_test_field_name] = $perodic_test_marks;
   ```

6. **Step 4 - Save Source:** The original marks are saved to the source document (Pre Mid Term/PT)

**Result:**
- The 'Half Yearly' document has field `eng_perodic_test: 9.0` (and optionally `eng_marks2: 9.0`)
- The 'Pre Mid Term' document has `marks_1: 18.0`, `percentage_1: 9.0`
- Both collections are kept in sync automatically

**Special Case - Classes 9-10:**
For classes 9 and 10, the system calculates the **best two periodic test average** from PT1, PT2, and PT3:
1. Retrieves marks from all three PT types
2. Calculates ratio (marks/max_marks) for each
3. Groups by subject prefix (eng_, maths_, etc.)
4. Selects the best two ratios per subject
5. Averages them: `(best1 + best2) / 2`

### 5.2. Flow B: `cal` Field Calculation (Term-End Totals)

The `cal` fields (`cal1`, `cal2`, `cal3`) are calculated totals stored *only* in the **"Denormalized" Schema** (Classes <= 10, Half Yearly/Final).

**Trigger:** When saving Half Yearly/Final results via `saveStdResult()`

**Execution:** Calls `handleHalfYearlyFieldCalculation()` which routes to specific calculation methods

**Calculation Methods:**
- `calculateCals1()` - For CBSE classes 1-5
- `calculateCals2()` - For CBSE classes 6-8
- `calculateCalsFor9th10thCBSE()` - For CBSE classes 9-10
- `calculateCals1CE()` - For CE board classes 6-8
- `calculateCals2CE()` - For CE board classes 6-8

**Detailed Formula Table:**

| Board | Class Group | Subject(s) | `cal1` Formula | `cal2` Formula | `cal3` Formula |
|:------|:------------|:-----------|:---------------|:---------------|:---------------|
| **CBSE** | 1-5 | All | `m1+m2+m3+m4+m5` (if m5 exists) | `round((cal1/150)*100, 2)` | N/A |
| **CBSE** | 6-8 | Computer | `m1+m2+m3+m4` | `m5+m6` | `cal1+cal2` |
| **CBSE** | 6-8 | All Others | `m1+m2+m3+m4` | `cal1+m5` | N/A |
| **CBSE** | 9-10 | Computer | `m1+m2` | N/A | N/A |
| **CBSE** | 9-10 | All Others | `m1+m2+m3+m4` | `cal1+m4` | N/A |
| **CE** | 6-10 | Divinity | `m1+m2+m3+m4+...+m10` (sum all) | N/A | N/A |
| **CE** | 6-10 | Eng, Maths, Science, Computer Science, Business Studies, Punjabi | `m1+m2` | N/A | N/A |
| **CE** | 6-10 | All Others | `m1+m2+m3+m4` | `cal1+m5` | N/A |
| **IB** | -3 | All | `m1` | N/A | N/A |
| **IB** | -2, -1 | Eng, Maths, UOI, Punjabi | `m1+m2` | N/A | N/A |
| **IB** | -2, -1 | Divinity, Hindi, RS, ICT | `m1` | N/A | N/A |
| **IB** | 1-5 | All | `m1+m2` | N/A | N/A |

**Example Calculation (CBSE Class 6, English):**
```php
// Input marks
$eng_marks1 = 35.0;  // Term exam
$eng_marks2 = 8.5;   // Periodic test
$eng_marks3 = 4.0;   // Notebook
$eng_marks4 = 3.5;   // Subject enrichment
$eng_marks5 = 4.0;   // Portfolio

// Calculation
$eng_cal1 = $eng_marks1 + $eng_marks2 + $eng_marks3 + $eng_marks4; // 51.0
$eng_cal2 = $eng_cal1 + $eng_marks5; // 55.0
```

### 5.3. Flow C: Marks Moderation (Automatic Grace Marks)

**Purpose:** Automatically apply grace marks and determine student status based on performance

**Trigger:** Called during `submitResultForObserver()` before updating status

**Entry Point:** `MarksModerationHelper::moderateClssSection()`

**Applies To:**
- Boards: CBSE only
- Classes: 3, 4, 5, 6, 7, 8, 9, 10
- Result Types: 'Half Yearly', 'PT2'

**Subject Mappings for Moderation:**

| Class Group | Subjects Evaluated |
|:------------|:-------------------|
| 3-5 | Punjabi (punjabi_marks4), Maths (maths_marks4), English (eng_marks4) |
| 6-8 | English (eng_marks5), Maths (maths_marks5), Punjabi (punjabi_marks5), Science (science_marks5) |
| 9-10 | English (marks_1), Punjabi (marks_2), Maths (marks_4), Science (marks_5) |

**Moderation Rules:**

For each subject, calculate percentage: `(marks / 80) * 100`

1. **< 30%** → Status: Fail (F)
2. **30% to < 35%** → Status: Reassessment (I7) - 7 days improvement
3. **35% to < 40%** → Status: Moderated (M)
   - Apply grace marks to bring up to exactly 40%
   - Store in history: `student_result_history` collection
   - Recalculate all `cal` fields
4. **>= 40%** → Status: Pass (P)

**Final Status Determination:**
- If 2+ subjects fail → `status = 'F'` (Fail, results hidden until manual review)
- If 1 subject fails → `status = 'I15'` (Improvement - 15 days)
- If any subject needs reassessment → `status = 'I7'` (Improvement - 7 days)
- If moderation applied → `status = 'M'` (Moderated, marks updated)
- Otherwise → `status = 'P'` (Pass)

**Example Moderation:**
```php
// Subject: English, Marks: 30/80 (37.5%)
$percentage = (30 / 80) * 100; // 37.5%

// Since 35% <= 37.5% < 40%, apply grace marks
$grace_marks = (80 * 0.40) - 30; // 2.0 marks
$new_marks = 32.0; // Exactly 40%

// Update document
$update_record['eng_marks4'] = 32.0;
$update_record['eng_cal1'] = recalculated_value;
$update_record['eng_cal2'] = recalculated_value;
$update_record['status'] = 'M';

// Save history
$history_record = original_document;
$history_record['_parent'] = original_document_id;
// Insert into student_result_history
```

-----

## 6. Helper Classes

### 6.1. CachedDataHelper

**Purpose:** Optimize database queries through caching mechanism

**Location:** `Modules/Teacher/Helpers/CachedDataHelper.php`

**Key Methods:**

1. **`getStudentsListFromCacheOrDB($session, $school_id, $current_class, $board, $section, $orderBy)`**
   - Fetches student list for a class/section
   - Handles historical data (different table names for past sessions)
   - Filters students by leaving date (only active students)
   - Supports ordering by name or admission number
   - **Note:** Cache layer currently disabled, fetches directly from DB

2. **`getSubjectFromCacheOrDB($session, $current_class, $board, $result_type)`**
   - Fetches subject configuration and sub-titles
   - Joins `school_result_subjects` with `school_result_sub_title`
   - Returns nested array: `['English' => [subtitle1, subtitle2, ...]]`

3. **`getStudentParentDetailsFromCacheOrDB($s_adm_no_hid, $school_id, $session)`**
   - Fetches student and parent information
   - Used when loading marks for editing

**Caching Strategy (Currently Disabled):**
- Uses Memcached as cache store
- Cache keys based on session, board, class, section
- Self-cleaning 15-minute cache
- Code present but commented out for debugging

### 6.2. MarksModerationHelper

**Purpose:** Apply automatic marks moderation and grace marks

**Location:** `Modules/Teacher/Helpers/MarksModerationHelper.php`

**Key Methods:**

1. **`moderateClssSection($filters)`**
   - Entry point for moderation
   - Fetches all students in a class/section from MongoDB
   - Calls `moderateAndSave()` for each student

2. **`moderate($data)`**
   - Routes to class-specific moderation method
   - Returns moderation decision without saving

3. **`performModeration($data, $classGroup, $maxMarks)`**
   - Core moderation logic
   - Analyzes each subject's percentage
   - Determines grace marks, failure, reassessment
   - Returns update record and subject-wise status

4. **`handleHalfYearlyFieldCalculation()`**
   - Recalculates `cal` fields after moderation
   - Ensures calculated totals reflect moderated marks

**Class-Specific Methods:**
- `moderate_3rd_to_5th()` → Calls `performModeration($data, '3-5', 80)`
- `moderate_6th_to_8th()` → Calls `performModeration($data, '6-8', 80)`
- `moderate_9th_to_10th()` → Calls `performModeration($data, '9-10', 80)`

-----

## 7. Workflow and Status Management

### 7.1. Result Submission Workflow

**Stage 1: Teacher Entry**
1. Teacher accesses `/teacher/addAcademicResult` with session parameter
2. Selects class, section, board, result type
3. System displays student list with input fields
4. Teacher enters marks for each student
5. AJAX saves each student's marks via `SaveResult2526` methods
6. Teacher clicks "Submit for Observer Review"
7. System calls `MarksModerationHelper::moderateClssSection()`:
   - Applies grace marks where applicable
   - Updates marks to 40% minimum for borderline cases
   - Stores original marks in history
   - Sets status field in documents
8. Updates `tbl_result_status.status = 1`
9. Timestamps: `teacher_submitted_at`, `teacher_id`

**Stage 2: Observer Review**
1. Observer accesses same interface
2. System checks: `AdminHelper::getAssignAsVal()` returns 'Observer'
3. Loads data from both collections:
   - `student_result` (teacher's data)
   - `observe_student_result` (observer's modifications if any)
4. Observer can modify marks
5. Modifications save to `observe_student_result` collection
6. Original teacher marks preserved in `student_result`
7. `_old` fields created in `observe_student_result` for audit
8. Observer clicks "Submit for Principal"
9. Updates `tbl_result_status`:
   - `status = 2`
   - For 'Pre Mid Term' → also updates 'PT1'
   - For 'Half Yearly' → also updates 'PT2'
   - For 'Post Mid Term' → also updates 'PT3'
10. Timestamps: `observer_submitted_at`, `observer_id`

**Stage 3: Principal Approval**
1. Principal reviews submitted results
2. Approves and publishes
3. Updates `tbl_result_status.status = 3`
4. Timestamps: `principal_submitted_at`, `principal_id`

### 7.2. Data Version Management

**Teacher vs Observer Data:**

| Collection | Contains | When Created |
|:-----------|:---------|:-------------|
| `student_result` | Teacher's original marks | Always, when teacher saves |
| `observe_student_result` | Observer's modified marks | Only when observer modifies |
| `student_result_history` | Pre-moderation snapshot | When moderation is applied |

**Display Priority:**
When viewing results, the system checks:
1. Does `observe_student_result` document exist for this student?
   - Yes → Display observer's data
   - No → Display teacher's data from `student_result`

**Audit Trail:**
- Original teacher marks: `student_result` collection
- Modified marks: `observe_student_result` collection with `_old` fields
- Moderation history: `student_result_history` collection with `_parent` link

-----

## 8. View Architecture

### 8.1. View Files Location

`Modules/Teacher/Resources/views/viewAcademicResult2526/`

### 8.2. View Templates by Result Type

| View File | Used For |
|:----------|:---------|
| `addAcademicResult.blade.php` | Periodic Tests (Classes <= 10) - Normalized schema |
| `addAcademicResult11n12.blade.php` | Periodic Tests (Classes 11-12) |
| `addAcademicHalfFinalResult.blade.php` | Half Yearly/Final (Classes <= 10, CBSE) - Denormalized |
| `addAcademicHalfFinalResult11n12.blade.php` | Half Yearly/Final (Classes 11-12) |
| `addAcademicIBFinalResult.blade.php` | IB Final Result |
| `addAcademicIBSDPResult.blade.php` | IB Spiritual Development Program |
| `viewAcademicResultHTML.blade.php` | Display PT results (read-only) |
| `viewAcademicHalfFinalResult.blade.php` | Display Half Yearly/Final (CBSE) |
| `viewAcademicHalfFinalResultIB.blade.php` | Display Half Yearly/Final (IB) |
| `viewAcademicHalfFinalResultCE.blade.php` | Display Half Yearly/Final (CE) |
| `viewAcademicResultExcel.blade.php` | Excel export for PT |
| `viewAcademicResultHalfFinalResultExcel.blade.php` | Excel export for Half Yearly/Final |

### 8.3. View Components

**Common Elements:**
- School/class/section/session filters
- Student roster table
- Subject-wise mark input fields
- Submit buttons (Save, Submit for Observer/Principal)
- Status indicators (Submitted, Approved, etc.)

**AJAX Functionality:**
- Real-time mark saving (saves on blur/change)
- Student detail loading
- Validation feedback
- Auto-calculation display

-----

## 9. API Endpoints (AJAX)

### 9.1. Save Operations

All save operations are handled through POST requests to the respective save methods in `SaveResult2526.php`:

```javascript
// Periodic Test Save
POST /teacher/saveStdMidResult
Parameters: {
    school_id, current_class, section, session, board, result_type,
    s_adm_no_hid, db_srno, total_subtitle_{i},
    main_subject_id_{i}, subject_id_{i}, marks_{i}, max_marks_{i},
    cal_percentage_on_{i}, perodic_test_field_name, assignAsChk
}

// Half Yearly/Final Save
POST /teacher/saveStdResult
Parameters: {
    school_id, current_class, section, session, board, result_type,
    s_adm_no_hid, subject_id, field_name, assignAsChk,
    {field_name}marks1, {field_name}marks2, ...,
    {field_name}sub1, {field_name}sub2, ...
}

// Get Student Details (for editing)
GET /teacher/getStuDetail
Parameters: {
    s_adm_no_hid, school_id, current_class, section,
    session, board, result_type
}
Response: {
    success: 'done',
    first_name, last_name, admission_no,
    father_name, mother_name, father_mobile,
    adhaar, dob, sex,
    newMarksRecord: {...}, // Existing marks
    preResult: {...}  // Periodic test averages (for classes 9-10)
}
```

-----

## 10. Special Handling & Edge Cases

### 10.1. Session-Based Table Names

Student data tables change based on session:
- Current session: `students`
- Past sessions: `students2024-25`, `students2023-24`, etc.

Helper method: `AdminHelper::getStudentTableName($session)`

### 10.2. School-Specific Logic

School ID 130 has special handling:
- Different session table: `tbl_bs_school_session` instead of `tbl_school_session`
- Different session configuration

### 10.3. Data Type Handling

**MongoDB Integer Fields (cast as int):**
- `school_id`
- `current_class`
- `s_adm_no_hid`
- `subject_id_{i}`
- `main_subject_id_{i}`

**MongoDB Float Fields (cast as float):**
- All fields containing "marks"
- All fields containing "percentage"
- All fields containing "cal"

**String Fields (for classes >= 101):**
For some special classes (101-108), all IDs stored as strings instead of integers.

### 10.4. Co-Scholastic Subjects

Co-scholastic subjects (Work Education, Art Education, Physical Education) do not have `cal` calculations. Marks are typically grades (A, B, C, D, E) rather than numeric values.

### 10.5. Leaving Date Filter

When fetching students, the system only includes:
- Students with `leaving_date > session_start_date`, OR
- Students with `leaving_date IS NULL`

This ensures only active students for the session are shown.

-----

## 11. Key Findings & Corrections to Original Documentation

### 11.1. Additional Features Found

1. **Marks Moderation System**
   - Automatic grace marks application
   - Status-based result visibility
   - History tracking for moderated marks
   - **Not documented in original R&D**

2. **Observer Workflow**
   - Separate collection for observer modifications
   - Audit trail with `_old` fields
   - Original data preservation
   - **Partially documented, now fully detailed**

3. **Best Two PT Average (Classes 9-10)**
   - Calculates best two from PT1, PT2, PT3
   - Subject-specific averaging
   - **Not documented in original R&D**

4. **Caching Mechanism**
   - CachedDataHelper for performance
   - Though currently disabled for debugging
   - **Not documented in original R&D**

5. **Multiple Save Methods**
   - Different methods for different schemas
   - Specialized handling for IB board (MySQL storage)
   - **Original R&D only showed two methods**

### 11.2. Corrections to Original Documentation

1. **Cal Field Formulas**
   - Original: Incomplete formulas
   - **Corrected:** Full detailed formulas with board/class/subject variations

2. **Dual-Write Mechanism**
   - Original: Basic flow described
   - **Enhanced:** Percentage calculation variants (CE board special case), target determination logic

3. **Observer Submission**
   - Original: Simple status update
   - **Corrected:** Also updates related PT types (PT1/PT2/PT3 ↔ Pre/Half/Post Mid Term)

4. **Schema Examples**
   - Original: Basic examples
   - **Enhanced:** Complete field listing, audit fields, status fields, timestamps

5. **IB Board Storage**
   - Original: Listed MySQL tables
   - **Clarified:** IB Final and IB SDP use MySQL, not MongoDB

### 11.3. Data Flow Insights

**Complete Save Flow for Half Yearly (Class 6, CBSE, English):**

1. User enters marks in browser
2. AJAX call to `/teacher/saveStdResult`
3. `SaveResult2526::saveStdResult()` method:
   - Validates input
   - Identifies field prefix: `eng_`
   - Determines class group: 6-8
   - Calls `handleHalfYearlyFieldCalculation()`
   - Routes to `calculateCals2()`
   - Calculates:
     ```php
     $eng_cal1 = $marks1 + $marks2 + $marks3 + $marks4;
     $eng_cal2 = $eng_cal1 + $marks5;
     ```
   - Prepares upsert array with all fields
   - Checks if document exists for student
   - Updates existing or inserts new document
4. If Observer: Also updates `observe_student_result`
5. Returns success response

**Complete Submit Flow:**

1. User clicks "Submit for Observer"
2. POST to `/teacher/submitResultForObserver`
3. `addAcademicResult2526Controller::submitResultForObserver()`:
   - Calls `MarksModerationHelper::moderateClssSection()`:
     - Fetches all students from MongoDB
     - For each student:
       - Analyzes subject marks
       - Determines grace marks needed
       - Updates marks if 35-40%
       - Sets status (F/I15/I7/M/P)
       - Saves to `student_result_history` if moderated
       - Updates `student_result` with new marks/status
   - Updates `tbl_result_status` table:
     - Sets status = 1
     - Records teacher_id and timestamp
     - For Observer: Also updates related PT types
4. Returns JSON response

-----

## 12. Database Schema Reference

### 12.1. MySQL Tables

**`school_result_subjects`**
```sql
id, subject, board, result_type, class_from, class_to, created_at, updated_at
```

**`school_result_sub_title`**
```sql
id, subject_id, sub_title, max_marks, total_re_cal_max,
cal_percentage_on, table_field_name, perodic_test_field_name,
position, excel_col_no, session, created_at, updated_at
```

**`tbl_result_status`**
```sql
id, school_id, class, section, session, board, result_type, status,
teacher_id, teacher_submitted_at,
observer_id, observer_submitted_at,
principal_id, principal_submitted_at,
created_at, updated_at, created_by, updated_by
```

**`tbl_class_teacher_assignment`**
```sql
id, school_id, emp_id, class, section, session, created_at, updated_at
```

**`students` / `students{session}`**
```sql
id, admission_no, first_name, last_name, current_class, section, board,
current_session, school_id, status, leaving_date, dob, sex, adhaar,
... (many more fields)
```

**`student_parents`**
```sql
id, student_id, school_id, father_name, mother_name, father_mobile,
... (more parent fields)
```

### 12.2. MongoDB Collections

**`student_result`**
- Dynamic schema based on result type
- See sections 3.2 and 3.3 for examples

**`observe_student_result`**
- Same schema as `student_result`
- Additional `_old` fields for modified marks

**`student_result_history`**
```javascript
{
    _parent: ObjectId,  // Reference to original document
    // All fields from original document
    moderated_at: "2025-11-08 10:30:00",
    status: "moderated"
}
```

-----

## 13. Testing & Debugging

### 13.1. Common Issues

1. **Empty Student List**
   - Check `leaving_date` vs `session_start_date`
   - Verify session table name (current vs historical)
   - Check `tbl_class_teacher_assignment` for permissions

2. **Marks Not Saving**
   - Verify MongoDB connection
   - Check composite key fields (all must match)
   - Ensure data types (int vs string) for class >= 101

3. **Dual-Write Not Working**
   - Verify `perodic_test_field_name` in `school_result_sub_title`
   - Check `cal_percentage_on` is set
   - Ensure target document exists or can be created

4. **Calculations Incorrect**
   - Verify class/board combination
   - Check calculation method routing
   - Ensure all required marks fields exist

### 13.2. Debugging Tools

**Enable Query Logging:**
```php
DB::enableQueryLog();
// ... operations ...
dd(DB::getQueryLog());
```

**MongoDB Query Debugging:**
```php
$query = DB::connection('mongodb')
    ->table('student_result')
    ->where('school_id', $school_id)
    ->where('current_class', $current_class);

dd($query->toSql(), $query->getBindings());
```

**Cache Debugging:**
Currently, cache calls are commented out in `CachedDataHelper.php`, making it easier to debug data issues.

-----

## 14. Future Improvements & Recommendations

### 14.1. Code Optimization

1. **Enable Caching**
   - Uncomment cache logic in `CachedDataHelper`
   - Implement cache invalidation on data updates
   - Add cache warming for frequently accessed data

2. **Reduce Code Duplication**
   - Extract common validation logic
   - Create base save method with strategy pattern
   - Consolidate view rendering logic

3. **Query Optimization**
   - Add indexes to MongoDB collections (composite key fields)
   - Batch student data fetching
   - Implement eager loading for related data

### 14.2. Feature Enhancements

1. **Bulk Import/Export**
   - Excel import for bulk mark entry
   - Enhanced export formats (CSV, PDF)

2. **Validation Rules**
   - Client-side validation before save
   - Server-side validation with detailed error messages
   - Mark range validation (0 to max_marks)

3. **Audit Logging**
   - Detailed change logs (who changed what, when)
   - Comparison view for observer modifications
   - Restore functionality from history

### 14.3. Documentation

1. **API Documentation**
   - Swagger/OpenAPI specification
   - Request/response examples
   - Error code reference

2. **User Guides**
   - Teacher handbook for mark entry
   - Observer review process
   - Troubleshooting guide

-----

## 15. Conclusion

The Academic Result Module (2526) is a sophisticated system that handles complex academic data structures through a hybrid database approach. Key strengths include:

1. **Flexibility:** Dynamic schema supports varied result structures across boards/classes
2. **Automation:** Dual-write mechanism and automatic moderation reduce manual work
3. **Auditability:** Multi-collection approach preserves history and modifications
4. **Scalability:** MongoDB's schema-less design accommodates future changes

The system successfully balances configurability with usability, enabling staff to manage results for diverse educational boards while maintaining data integrity and workflow control.

**Critical Success Factors:**
- Proper configuration of `school_result_subjects` and `school_result_sub_title` tables
- Understanding of schema variations (normalized vs denormalized)
- Awareness of dual-write mechanism and its implications
- Knowledge of marks moderation rules and their effects

This documentation provides a complete reference for developers, administrators, and maintainers working with the result management system.

-----

**Document Version:** 2.0
**Prepared By:** Claude (AI Assistant)
**Last Updated:** November 8, 2025
**Status:** Complete and Verified
