added transcript report and gradesheet and some requirement changes
This commit is contained in:
parent
d672e9c566
commit
5d064a313c
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
'name': 'School_Management',
|
'name': 'School_Management',
|
||||||
'version': '1.0',
|
'version': '1.0',
|
||||||
'depends': ['base', 'web', 'mail','product','hr'],
|
'depends': ['base', 'web', 'mail', 'product', 'hr', 'hr_attendance'],
|
||||||
'license': 'LGPL-3',
|
'license': 'LGPL-3',
|
||||||
'data': [
|
'data': [
|
||||||
'security/security.xml',
|
'security/security.xml',
|
||||||
|
@ -24,7 +24,9 @@
|
||||||
'views/school_student_views.xml',
|
'views/school_student_views.xml',
|
||||||
'views/fee_structure_views.xml',
|
'views/fee_structure_views.xml',
|
||||||
'views/fee_element_views.xml',
|
'views/fee_element_views.xml',
|
||||||
|
'views/gradesheet.xml',
|
||||||
'views/menu.xml',
|
'views/menu.xml',
|
||||||
|
|
||||||
],
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'application': True,
|
'application': True,
|
||||||
|
|
|
@ -19,6 +19,8 @@ from . import school_student
|
||||||
from . import fee_structure
|
from . import fee_structure
|
||||||
from . import fee_element
|
from . import fee_element
|
||||||
from . import school_fee_structure_line
|
from . import school_fee_structure_line
|
||||||
|
from . import gradesheet
|
||||||
|
from . import gradesheet_line
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,242 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
from odoo.exceptions import ValidationError, UserError
|
||||||
|
|
||||||
|
class SchoolGradesheet(models.Model):
|
||||||
|
_name = 'school.gradesheet'
|
||||||
|
_description = 'Student Gradesheet Report'
|
||||||
|
_order = 'session, class_name, course_id'
|
||||||
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||||
|
|
||||||
|
# Filter Fields
|
||||||
|
session = fields.Char(string="Session", required=True, help="Academic Session (e.g., 2024-2025)")
|
||||||
|
# application_id = fields.Many2one('school.application', string="Application", required=True)
|
||||||
|
# student_id = fields.Many2one('res.partner', string='Student', required=True)
|
||||||
|
# roll_number = fields.Char(string="Roll Number")
|
||||||
|
obtained_marks = fields.Float(
|
||||||
|
string="Obtained Marks",
|
||||||
|
default=0.0
|
||||||
|
)
|
||||||
|
total_marks = fields.Float(
|
||||||
|
string="Total Marks",
|
||||||
|
default=100.0
|
||||||
|
)
|
||||||
|
percentage = fields.Float(
|
||||||
|
string="Percentage (%)",
|
||||||
|
compute="_compute_percentage",
|
||||||
|
store=True
|
||||||
|
)
|
||||||
|
final_grade = fields.Selection([
|
||||||
|
('A+', 'A+ (90-100%)'),
|
||||||
|
('A', 'A (80-89%)'),
|
||||||
|
('B+', 'B+ (70-79%)'),
|
||||||
|
('B', 'B (60-69%)'),
|
||||||
|
('C', 'C (50-59%)'),
|
||||||
|
('D', 'D (40-49%)'),
|
||||||
|
('F', 'F (Below 40%)')
|
||||||
|
], string="Grade", default='F')
|
||||||
|
|
||||||
|
status = fields.Selection([
|
||||||
|
('pass', 'Pass'),
|
||||||
|
('fail', 'Fail')
|
||||||
|
], string="Status", default='fail')
|
||||||
|
|
||||||
|
remarks = fields.Text(string="Remarks")
|
||||||
|
class_name = fields.Selection([
|
||||||
|
('1', 'Class 1'), ('2', 'Class 2'), ('3', 'Class 3'),
|
||||||
|
('4', 'Class 4'), ('5', 'Class 5'), ('6', 'Class 6'),
|
||||||
|
('7', 'Class 7'), ('8', 'Class 8'), ('9', 'Class 9'),
|
||||||
|
('10', 'Class 10'), ('11', 'Class 11'), ('12', 'Class 12'),
|
||||||
|
], string="Class", required=True)
|
||||||
|
|
||||||
|
course_id = fields.Many2one('school.course', string="Course", required=True)
|
||||||
|
subject_id = fields.Many2one('school.subject', string="Subject")
|
||||||
|
|
||||||
|
# Report Generation Status
|
||||||
|
state = fields.Selection([
|
||||||
|
('draft', 'Draft'),
|
||||||
|
('generated', 'Generated'),
|
||||||
|
('finalized', 'Finalized')
|
||||||
|
], string="Status", default='draft', tracking=True)
|
||||||
|
|
||||||
|
# Generated Data
|
||||||
|
student_grade_ids = fields.One2many(
|
||||||
|
'school.gradesheet.line', 'gradesheet_id', string="Student Grades"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Report Info
|
||||||
|
generated_date = fields.Datetime(string="Generated Date", readonly=True)
|
||||||
|
generated_by = fields.Many2one('res.users', string="Generated By", readonly=True)
|
||||||
|
total_students = fields.Integer(string="Total Students", compute="_compute_student_stats", store=True)
|
||||||
|
passed_students = fields.Integer(string="Passed Students", compute="_compute_student_stats", store=True)
|
||||||
|
failed_students = fields.Integer(string="Failed Students", compute="_compute_student_stats", store=True)
|
||||||
|
pass_percentage = fields.Float(string="Pass Percentage", compute="_compute_student_stats", store=True)
|
||||||
|
|
||||||
|
@api.depends('student_grade_ids', 'student_grade_ids.final_grade', 'student_grade_ids.status')
|
||||||
|
def _compute_student_stats(self):
|
||||||
|
for record in self:
|
||||||
|
total = len(record.student_grade_ids)
|
||||||
|
passed = len(record.student_grade_ids.filtered(lambda x: x.status == 'pass'))
|
||||||
|
failed = total - passed
|
||||||
|
|
||||||
|
record.total_students = total
|
||||||
|
record.passed_students = passed
|
||||||
|
record.failed_students = failed
|
||||||
|
record.pass_percentage = (passed / total * 100) if total > 0 else 0.0
|
||||||
|
|
||||||
|
@api.onchange('class_name')
|
||||||
|
def _onchange_class_name(self):
|
||||||
|
if self.class_name:
|
||||||
|
return {
|
||||||
|
'domain': {
|
||||||
|
'course_id': [('class_id.name', '=', f'Class {self.class_name}')],
|
||||||
|
'subject_id': [('class_name', '=', f'Class {self.class_name}')], #Add this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'domain': {
|
||||||
|
'course_id': [],
|
||||||
|
'subject_id': [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def action_fetch_student_marks(self):
|
||||||
|
"""Fetch student marks and generate gradesheet"""
|
||||||
|
self.ensure_one()
|
||||||
|
|
||||||
|
if not all([self.session, self.class_name, self.course_id]):
|
||||||
|
raise UserError("Please fill all required fields: Session, Class, and Course.")
|
||||||
|
|
||||||
|
# Clear existing lines
|
||||||
|
self.student_grade_ids.unlink()
|
||||||
|
|
||||||
|
# Get enrolled students for the course
|
||||||
|
enrollments = self.env['school.enrollment'].search([
|
||||||
|
('course_id', '=', self.course_id.id),
|
||||||
|
('class_name', '=', self.class_name),
|
||||||
|
('session', '=', self.session),
|
||||||
|
('status', '=', 'confirmed')
|
||||||
|
])
|
||||||
|
|
||||||
|
if not enrollments:
|
||||||
|
raise UserError(f"No enrolled students found for Class {self.class_name}, Course {self.course_id.name}, Session {self.session}")
|
||||||
|
|
||||||
|
grade_lines = []
|
||||||
|
for enrollment in enrollments:
|
||||||
|
# Get student marks (you may need to adapt this based on your marks/exam model)
|
||||||
|
student_marks = self._get_student_marks(enrollment)
|
||||||
|
|
||||||
|
grade_lines.append({
|
||||||
|
'gradesheet_id': self.id,
|
||||||
|
'student_id': enrollment.student_id.id,
|
||||||
|
'enrollment_id': enrollment.id,
|
||||||
|
'student_name': enrollment.student_id.name,
|
||||||
|
'roll_number': enrollment.application_id.roll_no if enrollment.application_id else '',
|
||||||
|
'obtained_marks': student_marks.get('obtained_marks', 0),
|
||||||
|
'total_marks': student_marks.get('total_marks', 100),
|
||||||
|
'percentage': student_marks.get('percentage', 0),
|
||||||
|
'final_grade': student_marks.get('grade', 'F'),
|
||||||
|
'status': student_marks.get('status', 'fail'),
|
||||||
|
'remarks': student_marks.get('remarks', ''),
|
||||||
|
'subject_id': self.subject_id.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
# Create grade lines
|
||||||
|
self.env['school.gradesheet.line'].create(grade_lines)
|
||||||
|
|
||||||
|
# Update gradesheet status
|
||||||
|
self.write({
|
||||||
|
'state': 'generated',
|
||||||
|
'generated_date': fields.Datetime.now(),
|
||||||
|
'generated_by': self.env.user.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.client',
|
||||||
|
'tag': 'display_notification',
|
||||||
|
'params': {
|
||||||
|
'message': f'Gradesheet generated successfully! Found {len(grade_lines)} students.',
|
||||||
|
'type': 'success',
|
||||||
|
'sticky': False,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_student_marks(self, enrollment):
|
||||||
|
"""
|
||||||
|
Get student marks from your existing marks/exam system
|
||||||
|
This is a placeholder - adapt according to your actual marks model
|
||||||
|
"""
|
||||||
|
# Example: If you have a student.marks model or exam.result model
|
||||||
|
# marks_record = self.env['student.marks'].search([
|
||||||
|
# ('student_id', '=', enrollment.student_id.id),
|
||||||
|
# ('course_id', '=', self.course_id.id),
|
||||||
|
# ('session', '=', self.session)
|
||||||
|
# ], limit=1)
|
||||||
|
|
||||||
|
# For demo purposes, generating sample marks
|
||||||
|
# Replace this with actual marks fetching logic
|
||||||
|
import random
|
||||||
|
obtained = random.randint(30, 95)
|
||||||
|
total = 100
|
||||||
|
percentage = (obtained / total) * 100
|
||||||
|
|
||||||
|
# Grade calculation
|
||||||
|
if percentage >= 90:
|
||||||
|
grade = 'A+'
|
||||||
|
status = 'pass'
|
||||||
|
elif percentage >= 80:
|
||||||
|
grade = 'A'
|
||||||
|
status = 'pass'
|
||||||
|
elif percentage >= 70:
|
||||||
|
grade = 'B+'
|
||||||
|
status = 'pass'
|
||||||
|
elif percentage >= 60:
|
||||||
|
grade = 'B'
|
||||||
|
status = 'pass'
|
||||||
|
elif percentage >= 50:
|
||||||
|
grade = 'C'
|
||||||
|
status = 'pass'
|
||||||
|
elif percentage >= 40:
|
||||||
|
grade = 'D'
|
||||||
|
status = 'pass'
|
||||||
|
else:
|
||||||
|
grade = 'F'
|
||||||
|
status = 'fail'
|
||||||
|
|
||||||
|
return {
|
||||||
|
'obtained_marks': obtained,
|
||||||
|
'total_marks': total,
|
||||||
|
'percentage': percentage,
|
||||||
|
'grade': grade,
|
||||||
|
'status': status,
|
||||||
|
'remarks': 'Good' if status == 'pass' else 'Needs Improvement'
|
||||||
|
}
|
||||||
|
|
||||||
|
def action_finalize_gradesheet(self):
|
||||||
|
"""Finalize the gradesheet"""
|
||||||
|
self.ensure_one()
|
||||||
|
if self.state != 'generated':
|
||||||
|
raise UserError("Please generate the gradesheet first.")
|
||||||
|
|
||||||
|
self.state = 'finalized'
|
||||||
|
return True
|
||||||
|
|
||||||
|
def action_reset_to_draft(self):
|
||||||
|
"""Reset gradesheet to draft"""
|
||||||
|
self.ensure_one()
|
||||||
|
self.student_grade_ids.unlink()
|
||||||
|
self.write({
|
||||||
|
'state': 'draft',
|
||||||
|
'generated_date': False,
|
||||||
|
'generated_by': False,
|
||||||
|
})
|
||||||
|
return True
|
||||||
|
|
||||||
|
def action_print_gradesheet(self):
|
||||||
|
"""Print gradesheet report"""
|
||||||
|
self.ensure_one()
|
||||||
|
if not self.student_grade_ids:
|
||||||
|
raise UserError("No student data found. Please fetch student marks first.")
|
||||||
|
|
||||||
|
return self.env.ref('school_management.report_school_gradesheet').report_action(self)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
class SchoolGradesheetLine(models.Model):
|
||||||
|
_name = 'school.gradesheet.line'
|
||||||
|
_description = 'Student Grade Line'
|
||||||
|
_order = 'student_name'
|
||||||
|
|
||||||
|
gradesheet_id = fields.Many2one('school.gradesheet', string="Gradesheet", ondelete="cascade")
|
||||||
|
application_id = fields.Many2one('school.application', string="Application", required=True)
|
||||||
|
student_id = fields.Many2one('school.application', string="Student", required=True)
|
||||||
|
student_name = fields.Char(related='student_id.name', string="Student Name", store=True)
|
||||||
|
roll_number = fields.Char(related='student_id.roll_no', string="Roll Number", store=True)
|
||||||
|
subject_id = fields.Many2one('school.subject', string="Subject")
|
||||||
|
|
||||||
|
|
||||||
|
enrollment_id = fields.Many2one(
|
||||||
|
'school.enrollment',
|
||||||
|
string="Enrollment"
|
||||||
|
)
|
||||||
|
|
||||||
|
obtained_marks = fields.Float(
|
||||||
|
string="Obtained Marks",
|
||||||
|
default=0.0
|
||||||
|
)
|
||||||
|
total_marks = fields.Float(
|
||||||
|
string="Total Marks",
|
||||||
|
default=100.0
|
||||||
|
)
|
||||||
|
percentage = fields.Float(
|
||||||
|
string="Percentage (%)",
|
||||||
|
compute="_compute_percentage",
|
||||||
|
store=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Grade Info
|
||||||
|
final_grade = fields.Selection([
|
||||||
|
('A+', 'A+ (90-100%)'),
|
||||||
|
('A', 'A (80-89%)'),
|
||||||
|
('B+', 'B+ (70-79%)'),
|
||||||
|
('B', 'B (60-69%)'),
|
||||||
|
('C', 'C (50-59%)'),
|
||||||
|
('D', 'D (40-49%)'),
|
||||||
|
('F', 'F (Below 40%)')
|
||||||
|
], string="Grade", default='F')
|
||||||
|
|
||||||
|
status = fields.Selection([
|
||||||
|
('pass', 'Pass'),
|
||||||
|
('fail', 'Fail')
|
||||||
|
], string="Status", default='fail')
|
||||||
|
|
||||||
|
remarks = fields.Text(string="Remarks")
|
||||||
|
|
||||||
|
# Compute percentage
|
||||||
|
@api.depends('obtained_marks', 'total_marks')
|
||||||
|
def _compute_percentage(self):
|
||||||
|
for record in self:
|
||||||
|
if record.total_marks > 0:
|
||||||
|
record.percentage = (record.obtained_marks / record.total_marks) * 100
|
||||||
|
else:
|
||||||
|
record.percentage = 0.0
|
||||||
|
|
||||||
|
# Auto-update grade and status on marks change
|
||||||
|
@api.onchange('obtained_marks', 'total_marks')
|
||||||
|
def _onchange_marks(self):
|
||||||
|
for record in self:
|
||||||
|
if record.total_marks > 0:
|
||||||
|
percentage = (record.obtained_marks / record.total_marks) * 100
|
||||||
|
|
||||||
|
if percentage >= 90:
|
||||||
|
record.final_grade = 'A+'
|
||||||
|
record.status = 'pass'
|
||||||
|
elif percentage >= 80:
|
||||||
|
record.final_grade = 'A'
|
||||||
|
record.status = 'pass'
|
||||||
|
elif percentage >= 70:
|
||||||
|
record.final_grade = 'B+'
|
||||||
|
record.status = 'pass'
|
||||||
|
elif percentage >= 60:
|
||||||
|
record.final_grade = 'B'
|
||||||
|
record.status = 'pass'
|
||||||
|
elif percentage >= 50:
|
||||||
|
record.final_grade = 'C'
|
||||||
|
record.status = 'pass'
|
||||||
|
elif percentage >= 40:
|
||||||
|
record.final_grade = 'D'
|
||||||
|
record.status = 'pass'
|
||||||
|
else:
|
||||||
|
record.final_grade = 'F'
|
||||||
|
record.status = 'fail'
|
||||||
|
else:
|
||||||
|
record.percentage = 0.0
|
||||||
|
record.final_grade = 'F'
|
||||||
|
record.status = 'fail'
|
||||||
|
|
||||||
|
# Validation to prevent invalid marks
|
||||||
|
@api.constrains('obtained_marks', 'total_marks')
|
||||||
|
def _check_marks(self):
|
||||||
|
for record in self:
|
||||||
|
if record.obtained_marks < 0 or record.total_marks < 0:
|
||||||
|
raise ValidationError("Marks cannot be negative.")
|
||||||
|
if record.obtained_marks > record.total_marks:
|
||||||
|
raise ValidationError("Obtained marks cannot exceed total marks.")
|
|
@ -1,6 +1,6 @@
|
||||||
from odoo import models, fields
|
# from odoo import models, fields
|
||||||
|
|
||||||
class SchoolCourseSchedule(models.Model):
|
# class SchoolCourseSchedule(models.Model):
|
||||||
_inherit = 'hr.leave' # not 'school.course.schedule'
|
# _inherit = 'hr.leave' # not 'school.course.schedule'
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from odoo import models, fields
|
from odoo import models, fields, api
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
class SchoolNotice(models.Model):
|
class SchoolNotice(models.Model):
|
||||||
_name = 'school.notice.board'
|
_name = 'school.notice.board'
|
||||||
|
@ -22,8 +23,6 @@ class SchoolReportDummy(models.Model):
|
||||||
name = fields.Char("Report Name")
|
name = fields.Char("Report Name")
|
||||||
date_generated = fields.Date("Generated On", default=fields.Date.today)
|
date_generated = fields.Date("Generated On", default=fields.Date.today)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SchoolFeesReport(models.Model):
|
class SchoolFeesReport(models.Model):
|
||||||
_name = 'school.fees.report'
|
_name = 'school.fees.report'
|
||||||
_description = 'Fees Report'
|
_description = 'Fees Report'
|
||||||
|
@ -31,12 +30,140 @@ class SchoolFeesReport(models.Model):
|
||||||
name = fields.Char("Report Name")
|
name = fields.Char("Report Name")
|
||||||
amount = fields.Float("Amount")
|
amount = fields.Float("Amount")
|
||||||
|
|
||||||
class SchoolTranscriptReport(models.Model):
|
class TranscriptReport(models.Model):
|
||||||
_name = 'school.transcript.report'
|
_name = 'school.transcript.report'
|
||||||
_description = 'Transcript Report'
|
_description = 'Transcript Report'
|
||||||
|
|
||||||
student_id = fields.Many2one('school.application', string="Student", ondelete='set null')
|
name = fields.Char(string="Report Name", default="Transcript Report", readonly=True)
|
||||||
grade = fields.Char("Grade")
|
session = fields.Selection([
|
||||||
|
('2023-24', '2023-24'),
|
||||||
|
('2024-25', '2024-25'),
|
||||||
|
('2025-26', '2025-26'),
|
||||||
|
('2026-27', '2026-27'),
|
||||||
|
], string="Session", required=True)
|
||||||
|
|
||||||
|
student_id = fields.Many2one('school.application', string="Student", required=True)
|
||||||
|
|
||||||
|
# Student Information Fields (computed from student_id)
|
||||||
|
student_name = fields.Char(related='student_id.name', string="Student Name", readonly=True)
|
||||||
|
student_address = fields.Text(related='student_id.address', string="Address", readonly=True)
|
||||||
|
student_phone = fields.Char(related='student_id.phone_no', string="Phone", readonly=True)
|
||||||
|
student_email = fields.Char(related='student_id.email', string="Email", readonly=True)
|
||||||
|
student_dob = fields.Date(related='student_id.date_of_birth', string="Date of Birth", readonly=True)
|
||||||
|
student_guardian = fields.Char(related='student_id.father_name', string="Guardian", readonly=True)
|
||||||
|
student_academic_year = fields.Char(related='student_id.academic_year', string="Academic Year", readonly=True)
|
||||||
|
student_class = fields.Selection(related='student_id.class_name', string="Class", readonly=True)
|
||||||
|
|
||||||
|
# School Information Fields
|
||||||
|
school_id = fields.Many2one('res.company', string="School", default=lambda self: self.env.company, readonly=True)
|
||||||
|
school_name = fields.Char(related='school_id.name', string="School Name", readonly=True)
|
||||||
|
school_address = fields.Text(string="School Address", compute='_compute_school_address', readonly=True)
|
||||||
|
school_state = fields.Char(related='school_id.state_id.name', string="State", readonly=True)
|
||||||
|
school_phone = fields.Char(related='school_id.phone', string="School Phone", readonly=True)
|
||||||
|
school_email = fields.Char(related='school_id.email', string="School Email", readonly=True)
|
||||||
|
school_academic_year = fields.Char(string="School Academic Year", default="2024-25", readonly=True)
|
||||||
|
school_classes = fields.Char(string="Classes", default="Class 1-12", readonly=True)
|
||||||
|
|
||||||
|
# Subject Information
|
||||||
|
subject_ids = fields.Many2many('school.subject', string="Subjects", compute='_compute_subjects', readonly=True)
|
||||||
|
subject_names = fields.Char(string="Subject Names", compute='_compute_subject_names', readonly=True)
|
||||||
|
|
||||||
|
# Report Status
|
||||||
|
report_generated = fields.Boolean(string="Report Generated", default=False)
|
||||||
|
generated_date = fields.Datetime(string="Generated Date")
|
||||||
|
|
||||||
|
@api.depends('school_id')
|
||||||
|
def _compute_school_address(self):
|
||||||
|
for record in self:
|
||||||
|
if record.school_id:
|
||||||
|
address_parts = []
|
||||||
|
if record.school_id.street:
|
||||||
|
address_parts.append(record.school_id.street)
|
||||||
|
if record.school_id.street2:
|
||||||
|
address_parts.append(record.school_id.street2)
|
||||||
|
if record.school_id.city:
|
||||||
|
address_parts.append(record.school_id.city)
|
||||||
|
if record.school_id.zip:
|
||||||
|
address_parts.append(record.school_id.zip)
|
||||||
|
record.school_address = ', '.join(address_parts)
|
||||||
|
else:
|
||||||
|
record.school_address = ''
|
||||||
|
|
||||||
|
@api.depends('student_id')
|
||||||
|
def _compute_subjects(self):
|
||||||
|
for record in self:
|
||||||
|
if record.student_id and record.student_id.class_name:
|
||||||
|
# Get subjects for the student's class
|
||||||
|
subjects = self.env['school.subject'].search([
|
||||||
|
('class_name', '=', 'Class ' + record.student_id.class_name)
|
||||||
|
])
|
||||||
|
record.subject_ids = subjects
|
||||||
|
else:
|
||||||
|
record.subject_ids = False
|
||||||
|
|
||||||
|
@api.depends('subject_ids')
|
||||||
|
def _compute_subject_names(self):
|
||||||
|
for record in self:
|
||||||
|
if record.subject_ids:
|
||||||
|
subject_names = []
|
||||||
|
for subject in record.subject_ids:
|
||||||
|
# Get the display name for the subject
|
||||||
|
subject_display = dict(subject._fields['name'].selection).get(subject.name, subject.name)
|
||||||
|
subject_names.append(subject_display)
|
||||||
|
record.subject_names = ', '.join(subject_names)
|
||||||
|
else:
|
||||||
|
record.subject_names = ''
|
||||||
|
|
||||||
|
def action_fetch_report(self):
|
||||||
|
"""Fetch and prepare the report data"""
|
||||||
|
self.ensure_one()
|
||||||
|
if not self.student_id:
|
||||||
|
raise ValidationError("Please select a student first.")
|
||||||
|
if not self.session:
|
||||||
|
raise ValidationError("Please select a session first.")
|
||||||
|
|
||||||
|
# Mark report as generated
|
||||||
|
self.report_generated = True
|
||||||
|
self.generated_date = fields.Datetime.now()
|
||||||
|
|
||||||
|
# You can add more logic here to fetch additional data
|
||||||
|
# For example: get grades, attendance, etc.
|
||||||
|
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.client',
|
||||||
|
'tag': 'display_notification',
|
||||||
|
'params': {
|
||||||
|
'type': 'success',
|
||||||
|
'message': 'Report data fetched successfully!',
|
||||||
|
'next': {'type': 'ir.actions.act_window_close'},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def action_download_report(self):
|
||||||
|
"""Download the transcript report"""
|
||||||
|
self.ensure_one()
|
||||||
|
if not self.report_generated:
|
||||||
|
raise ValidationError("Please fetch the report first before downloading.")
|
||||||
|
|
||||||
|
# Here you would typically call a report action
|
||||||
|
# For now, we'll show a notification
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.client',
|
||||||
|
'tag': 'display_notification',
|
||||||
|
'params': {
|
||||||
|
'type': 'success',
|
||||||
|
'message': 'Report download functionality will be implemented with PDF generation.',
|
||||||
|
'sticky': False,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
# Auto-generate report name with session and student info
|
||||||
|
if 'student_id' in vals and 'session' in vals:
|
||||||
|
student = self.env['school.application'].browse(vals['student_id'])
|
||||||
|
vals['name'] = f"Transcript Report - {student.name} - {vals['session']}"
|
||||||
|
return super().create(vals)
|
||||||
|
|
||||||
class SchoolScholarshipReport(models.Model):
|
class SchoolScholarshipReport(models.Model):
|
||||||
_name = 'school.scholarship.report'
|
_name = 'school.scholarship.report'
|
||||||
|
|
|
@ -34,7 +34,7 @@ class SchoolStudent(models.Model):
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'name': 'Fee Slip',
|
'name': 'Fee Slip',
|
||||||
'res_model': 'school.enrollment.fee.summary',
|
'res_model': 'school.enrollment.fee.summary',
|
||||||
'view_mode': 'tree,form',
|
'view_mode': 'list,form',
|
||||||
'domain': [('student_ref', '=', self.id)],
|
'domain': [('student_ref', '=', self.id)],
|
||||||
'target': 'current',
|
'target': 'current',
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ access_school_application,School Application,model_school_application,,1,1,1,1
|
||||||
access_school_enrollment,School Enrollment,model_school_enrollment,,1,1,1,1
|
access_school_enrollment,School Enrollment,model_school_enrollment,,1,1,1,1
|
||||||
access_school_enrollment_subject,School Enrollment Subject,model_school_enrollment_subject,,1,1,1,1
|
access_school_enrollment_subject,School Enrollment Subject,model_school_enrollment_subject,,1,1,1,1
|
||||||
access_school_enrollment_fee_summary,School Enrollment Fee Summary,model_school_enrollment_fee_summary,,1,1,1,1
|
access_school_enrollment_fee_summary,School Enrollment Fee Summary,model_school_enrollment_fee_summary,,1,1,1,1
|
||||||
access_school_class_schedule,School Class Schedule,model_school_class_schedule,,1,1,1,1
|
access_school_class_schedule,School Class Schedule,model_school_class_schedule,base.group_user,1,1,1,1
|
||||||
access_school_class,School Class,model_school_class,,1,1,1,1
|
access_school_class,School Class,model_school_class,,1,1,1,1
|
||||||
access_school_subject,School Subject,model_school_subject,,1,1,1,1
|
access_school_subject,School Subject,model_school_subject,,1,1,1,1
|
||||||
access_school_course,School Course,model_school_course,,1,1,1,1
|
access_school_course,School Course,model_school_course,,1,1,1,1
|
||||||
|
@ -23,5 +23,7 @@ access_school_report_card,Report Card,model_school_report_card,,1,1,1,1
|
||||||
access_school_student,Student,model_school_student,,1,1,1,1
|
access_school_student,Student,model_school_student,,1,1,1,1
|
||||||
access_school_fee_structure,School Fee Structure,model_school_fee_structure,,1,1,1,1
|
access_school_fee_structure,School Fee Structure,model_school_fee_structure,,1,1,1,1
|
||||||
access_school_fee_element,School Fee Element,model_school_fee_element,,1,1,1,1
|
access_school_fee_element,School Fee Element,model_school_fee_element,,1,1,1,1
|
||||||
access_school_fee_component,School Fee Component,model_school_fee_component,,1,0,0,0
|
access_school_fee_component,School Fee Component,model_school_fee_component,,1,1,1,1
|
||||||
|
access_school_gradesheet,School Gradesheet,model_school_gradesheet,,1,1,1,1
|
||||||
|
access_school_gradesheet_line,School Gradesheet Line,model_school_gradesheet_line,,1,1,1,1
|
||||||
|
|
||||||
|
|
|
|
@ -0,0 +1,394 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<!-- Gradesheet List View -->
|
||||||
|
<record id="view_school_gradesheet_list" model="ir.ui.view">
|
||||||
|
<field name="name">school.gradesheet.list</field>
|
||||||
|
<field name="model">school.gradesheet</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list string="Gradesheets" decoration-info="state=='draft'" decoration-success="state=='generated'" decoration-muted="state=='finalized'">
|
||||||
|
<field name="session"/>
|
||||||
|
<field name="class_name"/>
|
||||||
|
<field name="course_id"/>
|
||||||
|
<field name="total_students"/>
|
||||||
|
<field name="passed_students"/>
|
||||||
|
<field name="pass_percentage" widget="percentage"/>
|
||||||
|
<field name="state" widget="badge" decoration-info="state=='draft'" decoration-success="state=='generated'" decoration-muted="state=='finalized'"/>
|
||||||
|
<field name="generated_date"/>
|
||||||
|
<field name="generated_by"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Gradesheet Form View -->
|
||||||
|
<record id="view_school_gradesheet_form" model="ir.ui.view">
|
||||||
|
<field name="name">school.gradesheet.form</field>
|
||||||
|
<field name="model">school.gradesheet</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Gradesheet">
|
||||||
|
<header>
|
||||||
|
<button name="action_fetch_student_marks"
|
||||||
|
string="Fetch Marks"
|
||||||
|
type="object"
|
||||||
|
class="btn-primary"
|
||||||
|
modifiers='{"invisible": [["state", "!=", "draft"]]}'/>
|
||||||
|
|
||||||
|
<button name="action_finalize_gradesheet"
|
||||||
|
string="Finalize"
|
||||||
|
type="object"
|
||||||
|
class="btn-success"
|
||||||
|
modifiers='{"invisible": [["state", "!=", "generated"]]}'/>
|
||||||
|
|
||||||
|
<button name="action_print_gradesheet"
|
||||||
|
string="Print"
|
||||||
|
type="object"
|
||||||
|
class="btn-secondary"
|
||||||
|
modifiers='{"invisible": [["state", "==", "draft"]]}'/>
|
||||||
|
|
||||||
|
<button name="action_reset_to_draft"
|
||||||
|
string="Reset to Draft"
|
||||||
|
type="object"
|
||||||
|
class="btn-warning"
|
||||||
|
confirm="This will reset the gradesheet. Continue?"
|
||||||
|
modifiers='{"invisible": [["state", "==", "draft"]]}'/>
|
||||||
|
|
||||||
|
<field name="state" widget="statusbar" statusbar_visible="draft,generated,finalized"/>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<sheet>
|
||||||
|
<group string="Filters">
|
||||||
|
<field name="session" placeholder="e.g., 2024-2025">
|
||||||
|
<modifiers>{"readonly": [["state", "!=", "draft"]]}</modifiers>
|
||||||
|
</field>
|
||||||
|
<field name="class_name">
|
||||||
|
<modifiers>{"readonly": [["state", "!=", "draft"]]}</modifiers>
|
||||||
|
</field>
|
||||||
|
<field name="course_id" context="{'default_class_name': class_name}">
|
||||||
|
<modifiers>{"readonly": [["state", "!=", "draft"]]}</modifiers>
|
||||||
|
</field>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group string="Statistics">
|
||||||
|
<modifiers>{"invisible": [["state", "==", "draft"]]}</modifiers>
|
||||||
|
<field name="total_students"/>
|
||||||
|
<field name="passed_students"/>
|
||||||
|
<field name="failed_students"/>
|
||||||
|
<field name="pass_percentage" widget="percentage"/>
|
||||||
|
<field name="generated_date"/>
|
||||||
|
<field name="generated_by"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<notebook>
|
||||||
|
<page string="Student Grades">
|
||||||
|
<field name="student_grade_ids">
|
||||||
|
<list editable="bottom" decoration-success="status=='pass'" decoration-danger="status=='fail'">
|
||||||
|
<field name="student_id"/>
|
||||||
|
<field name="roll_number"/>
|
||||||
|
<field name="subject_id"/>
|
||||||
|
<field name="obtained_marks" sum="Total Obtained"/>
|
||||||
|
<field name="total_marks" sum="Total Max"/>
|
||||||
|
<field name="percentage" widget="percentage"/>
|
||||||
|
<field name="final_grade"/>
|
||||||
|
<field name="status" widget="badge"/>
|
||||||
|
<field name="remarks"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</sheet>
|
||||||
|
<!-- Chatter -->
|
||||||
|
<!-- <div class="oe_chatter">
|
||||||
|
<field name="message_follower_ids"/>
|
||||||
|
<field name="activity_ids"/>
|
||||||
|
<field name="message_ids"/>
|
||||||
|
</div> -->
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Gradesheet Search View -->
|
||||||
|
<record id="view_school_gradesheet_search" model="ir.ui.view">
|
||||||
|
<field name="name">school.gradesheet.search</field>
|
||||||
|
<field name="model">school.gradesheet</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="Search Gradesheets">
|
||||||
|
<field name="session"/>
|
||||||
|
<field name="class_name"/>
|
||||||
|
<field name="course_id"/>
|
||||||
|
<field name="generated_by"/>
|
||||||
|
|
||||||
|
<filter string="Draft" name="filter_draft" domain="[('state', '=', 'draft')]"/>
|
||||||
|
<filter string="Generated" name="filter_generated" domain="[('state', '=', 'generated')]"/>
|
||||||
|
<filter string="Finalized" name="filter_finalized" domain="[('state', '=', 'finalized')]"/>
|
||||||
|
|
||||||
|
<separator/>
|
||||||
|
<filter string="Current Session" name="filter_current_session" domain="[('session', 'ilike', '2024')]"/>
|
||||||
|
|
||||||
|
<group expand="0" string="Group By">
|
||||||
|
<filter string="Session" name="group_session" context="{'group_by': 'session'}"/>
|
||||||
|
<filter string="Class" name="group_class" context="{'group_by': 'class_name'}"/>
|
||||||
|
<filter string="Status" name="group_state" context="{'group_by': 'state'}"/>
|
||||||
|
<filter string="Generated By" name="group_generated_by" context="{'group_by': 'generated_by'}"/>
|
||||||
|
</group>
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Gradesheet Line List View -->
|
||||||
|
<record id="view_school_gradesheet_line_list" model="ir.ui.view">
|
||||||
|
<field name="name">school.gradesheet.line.list</field>
|
||||||
|
<field name="model">school.gradesheet.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list string="Student Grades" decoration-success="status=='pass'" decoration-danger="status=='fail'">
|
||||||
|
<field name="student_name"/>
|
||||||
|
<field name="roll_number"/>
|
||||||
|
<field name="obtained_marks"/>
|
||||||
|
<field name="total_marks"/>
|
||||||
|
<field name="percentage" widget="percentage"/>
|
||||||
|
<field name="final_grade"/>
|
||||||
|
<field name="status" widget="badge" decoration-success="status=='pass'" decoration-danger="status=='fail'"/>
|
||||||
|
<field name="remarks"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Gradesheet Kanban View -->
|
||||||
|
<record id="view_school_gradesheet_kanban" model="ir.ui.view">
|
||||||
|
<field name="name">school.gradesheet.kanban</field>
|
||||||
|
<field name="model">school.gradesheet</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<kanban class="o_kanban_small_column" default_group_by="state">
|
||||||
|
<field name="session"/>
|
||||||
|
<field name="class_name"/>
|
||||||
|
<field name="course_id"/>
|
||||||
|
<field name="total_students"/>
|
||||||
|
<field name="passed_students"/>
|
||||||
|
<field name="pass_percentage"/>
|
||||||
|
<field name="state"/>
|
||||||
|
<field name="generated_date"/>
|
||||||
|
|
||||||
|
<templates>
|
||||||
|
<t t-name="kanban-box">
|
||||||
|
<div class="oe_kanban_card oe_kanban_global_click">
|
||||||
|
<div class="oe_kanban_content">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<strong><field name="session"/></strong>
|
||||||
|
<span class="float-right">
|
||||||
|
<field name="state" widget="label_selection" options="{'classes': {'draft': 'secondary', 'generated': 'success', 'finalized': 'info'}}"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<i class="fa fa-graduation-cap"/> Class <field name="class_name"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<i class="fa fa-book" title="Gradesheet"/> <field name="course_id"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt8">
|
||||||
|
<div class="col-6">
|
||||||
|
<small>Students: <field name="total_students"/></small>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<small>Passed: <field name="passed_students"/></small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="progress" style="height: 15px;">
|
||||||
|
<div class="progress-bar bg-success" role="progressbar" t-att-style="'width: ' + record.pass_percentage.raw_value + '%'">
|
||||||
|
<t t-esc="Math.round(record.pass_percentage.raw_value)"/>%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</templates>
|
||||||
|
</kanban>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Gradesheet Pivot View -->
|
||||||
|
<record id="view_school_gradesheet_pivot" model="ir.ui.view">
|
||||||
|
<field name="name">school.gradesheet.pivot</field>
|
||||||
|
<field name="model">school.gradesheet</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<pivot string="Gradesheet Analysis">
|
||||||
|
<field name="session" type="row"/>
|
||||||
|
<field name="class_name" type="row"/>
|
||||||
|
<field name="course_id" type="col"/>
|
||||||
|
<field name="total_students" type="measure"/>
|
||||||
|
<field name="passed_students" type="measure"/>
|
||||||
|
<field name="failed_students" type="measure"/>
|
||||||
|
</pivot>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Gradesheet Graph View -->
|
||||||
|
<record id="view_school_gradesheet_graph" model="ir.ui.view">
|
||||||
|
<field name="name">school.gradesheet.graph</field>
|
||||||
|
<field name="model">school.gradesheet</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<graph string="Pass/Fail Analysis" type="bar">
|
||||||
|
<field name="class_name" type="row"/>
|
||||||
|
<field name="passed_students" type="measure"/>
|
||||||
|
<field name="failed_students" type="measure"/>
|
||||||
|
</graph>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Action for Gradesheet -->
|
||||||
|
<record id="action_school_gradesheet" model="ir.actions.act_window">
|
||||||
|
<field name="name">Gradesheets</field>
|
||||||
|
<field name="res_model">school.gradesheet</field>
|
||||||
|
<field name="view_mode">kanban,list,form,pivot,graph</field>
|
||||||
|
<field name="context">{'search_default_filter_current_session': 1}</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="o_view_nocontent_smiling_face">
|
||||||
|
Create your first Gradesheet!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Generate gradesheets for students by selecting session, class, and course.
|
||||||
|
Fetch student marks automatically from your existing data.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Action for Gradesheet Lines -->
|
||||||
|
<record id="action_school_gradesheet_line" model="ir.actions.act_window">
|
||||||
|
<field name="name">Student Grades</field>
|
||||||
|
<field name="res_model">school.gradesheet.line</field>
|
||||||
|
<field name="view_mode">list</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Gradesheet Report Template -->
|
||||||
|
<record id="report_school_gradesheet" model="ir.actions.report">
|
||||||
|
<field name="name">Gradesheet Report</field>
|
||||||
|
<field name="model">school.gradesheet</field>
|
||||||
|
<field name="report_type">qweb-pdf</field>
|
||||||
|
<field name="report_name">school_management.report_gradesheet_template</field>
|
||||||
|
<field name="report_file">school_management.report_gradesheet_template</field>
|
||||||
|
<field name="binding_model_id" ref="model_school_gradesheet"/>
|
||||||
|
<field name="binding_type">report</field>
|
||||||
|
<field name="paperformat_id" ref="base.paperformat_euro"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Report Template -->
|
||||||
|
<template id="report_gradesheet_template">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-foreach="docs" t-as="gradesheet">
|
||||||
|
<t t-call="web.external_layout">
|
||||||
|
<div class="page">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="text-center mb-4">
|
||||||
|
<h2>GRADESHEET REPORT</h2>
|
||||||
|
<h4 t-field="gradesheet.course_id.name"/>
|
||||||
|
<p>
|
||||||
|
<strong>Session:</strong> <span t-field="gradesheet.session"/> |
|
||||||
|
<strong>Class:</strong> <span t-field="gradesheet.class_name"/> |
|
||||||
|
<strong>Generated:</strong> <span t-field="gradesheet.generated_date" t-options="{'widget': 'datetime'}"/>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Statistics -->
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="card text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title" t-field="gradesheet.total_students"/>
|
||||||
|
<p class="card-text">Total Students</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="card text-center text-success">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title" t-field="gradesheet.passed_students"/>
|
||||||
|
<p class="card-text">Passed</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="card text-center text-danger">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title" t-field="gradesheet.failed_students"/>
|
||||||
|
<p class="card-text">Failed</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="card text-center text-info">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><span t-field="gradesheet.pass_percentage" t-options="{'widget': 'float', 'precision': 2}"/>%</h5>
|
||||||
|
<p class="card-text">Pass Rate</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Student Grades Table -->
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead class="table-dark">
|
||||||
|
<tr>
|
||||||
|
<th>S.No.</th>
|
||||||
|
<th>Student Name</th>
|
||||||
|
<th>Roll Number</th>
|
||||||
|
<th>Obtained Marks</th>
|
||||||
|
<th>Total Marks</th>
|
||||||
|
<th>Percentage</th>
|
||||||
|
<th>Grade</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Remarks</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr t-foreach="gradesheet.student_grade_ids" t-as="line"
|
||||||
|
t-att-class="'table-success' if line.status == 'pass' else 'table-danger'">
|
||||||
|
<td t-esc="line_index + 1"/>
|
||||||
|
<td t-field="line.student_name"/>
|
||||||
|
<td t-field="line.roll_number"/>
|
||||||
|
<td t-field="line.obtained_marks" t-options="{'widget': 'float', 'precision': 1}"/>
|
||||||
|
<td t-field="line.total_marks" t-options="{'widget': 'float', 'precision': 1}"/>
|
||||||
|
<td>
|
||||||
|
<span t-field="line.percentage" t-options="{'widget': 'float', 'precision': 2}"/>%
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-field="line.final_grade"
|
||||||
|
t-att-class="'badge badge-success' if line.status == 'pass' else 'badge badge-danger'"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span t-field="line.status"
|
||||||
|
t-att-class="'text-success' if line.status == 'pass' else 'text-danger'"
|
||||||
|
style="text-transform: uppercase; font-weight: bold;"/>
|
||||||
|
</td>
|
||||||
|
<td t-field="line.remarks"/>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<p><strong>Generated By:</strong> <span t-field="gradesheet.generated_by.name"/></p>
|
||||||
|
<p><strong>Date:</strong> <span t-field="gradesheet.generated_date" t-options="{'widget': 'date'}"/></p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<p><strong>Status:</strong> <span t-field="gradesheet.state" class="badge badge-info"/></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</odoo>
|
|
@ -103,7 +103,7 @@
|
||||||
<menuitem id="menu_school_transcript_report"
|
<menuitem id="menu_school_transcript_report"
|
||||||
name="Transcript Report"
|
name="Transcript Report"
|
||||||
parent="menu_school_reporting"
|
parent="menu_school_reporting"
|
||||||
action="action_school_transcript_report"
|
action="action_transcript_report"
|
||||||
sequence="3"/>
|
sequence="3"/>
|
||||||
|
|
||||||
<!-- 3. Scholarship Report -->
|
<!-- 3. Scholarship Report -->
|
||||||
|
@ -120,6 +120,12 @@
|
||||||
action="action_school_report_card"
|
action="action_school_report_card"
|
||||||
sequence="5"/>
|
sequence="5"/>
|
||||||
|
|
||||||
|
<!-- 4. Grade Sheet -->
|
||||||
|
<menuitem id="menu_school_gradesheet"
|
||||||
|
name="Gradesheets"
|
||||||
|
parent="menu_school_reporting"
|
||||||
|
action="action_school_gradesheet"
|
||||||
|
sequence="6"/>
|
||||||
|
|
||||||
<!-- Configuration Menu -->
|
<!-- Configuration Menu -->
|
||||||
<menuitem id="menu_school_configuration"
|
<menuitem id="menu_school_configuration"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<!-- === Action & Views: Fees Report === -->
|
<!-- === Action & Views: Fees Report === -->
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
</list>
|
</list>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_fees_report_form" model="ir.ui.view">
|
<record id="view_fees_report_form" model="ir.ui.view">
|
||||||
<field name="name">school.fees.report.form</field>
|
<field name="name">school.fees.report.form</field>
|
||||||
<field name="model">school.fees.report</field>
|
<field name="model">school.fees.report</field>
|
||||||
|
@ -26,48 +28,123 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<record id="action_school_fees_report" model="ir.actions.act_window">
|
<record id="action_school_fees_report" model="ir.actions.act_window">
|
||||||
<field name="name">Fees Report</field>
|
<field name="name">Fees Report</field>
|
||||||
<field name="res_model">school.fees.report</field>
|
<field name="res_model">school.fees.report</field>
|
||||||
<field name="view_mode">list,form</field>
|
<field name="view_mode">list,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<!-- === Action & Views: Transcript Report === -->
|
<!-- === Action & Views: Transcript Report === -->
|
||||||
<record id="view_transcript_report_list" model="ir.ui.view">
|
<record id="view_transcript_report_list" model="ir.ui.view">
|
||||||
<field name="name">school.transcript.report.list</field>
|
<field name="name">school.transcript.report.list</field>
|
||||||
<field name="model">school.transcript.report</field>
|
<field name="model">school.transcript.report</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<list>
|
<list string="Transcript Reports">
|
||||||
|
<field name="name"/>
|
||||||
<field name="student_id"/>
|
<field name="student_id"/>
|
||||||
<field name="grade"/>
|
<field name="session"/>
|
||||||
|
<field name="student_class"/>
|
||||||
|
<field name="report_generated"/>
|
||||||
|
<field name="generated_date"/>
|
||||||
</list>
|
</list>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_transcript_report_form" model="ir.ui.view">
|
<record id="view_transcript_report_form" model="ir.ui.view">
|
||||||
<field name="name">school.transcript.report.form</field>
|
<field name="name">school.transcript.report.form</field>
|
||||||
<field name="model">school.transcript.report</field>
|
<field name="model">school.transcript.report</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Transcript Report">
|
<form string="Transcript Report">
|
||||||
|
<header>
|
||||||
|
<button name="action_fetch_report"
|
||||||
|
string="Fetch Report"
|
||||||
|
type="object"
|
||||||
|
class="btn-primary"
|
||||||
|
invisible="report_generated"/>
|
||||||
|
|
||||||
|
<button name="action_download_report"
|
||||||
|
string="Download Report"
|
||||||
|
type="object"
|
||||||
|
class="btn-secondary"
|
||||||
|
invisible="not report_generated"/>
|
||||||
|
</header>
|
||||||
<sheet>
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<field name="student_id"/>
|
<h1>Transcript Report Generator</h1>
|
||||||
<field name="grade"/>
|
</group>
|
||||||
|
|
||||||
|
<!-- Selection Fields -->
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="session" options="{'no_create': True}" placeholder="Select Session..."/>
|
||||||
|
<field name="student_id" options="{'no_create': True}" placeholder="Select Student..."/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="report_generated" invisible="1"/>
|
||||||
|
<field name="generated_date" readonly="1" widget="date"
|
||||||
|
modifiers="{'invisible': [['report_generated', '=', False]]}"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!-- Report Content - Only visible after fetch -->
|
||||||
|
<group modifiers="{'invisible': [['report_generated', '=', False]]}">
|
||||||
|
|
||||||
|
<separator string="Report Details"/>
|
||||||
|
|
||||||
|
<!-- Student Information Card -->
|
||||||
|
<group string="Student Information">
|
||||||
|
<group>
|
||||||
|
<field name="student_name" readonly="1"/>
|
||||||
|
<field name="student_address" readonly="1"/>
|
||||||
|
<field name="student_phone" readonly="1"/>
|
||||||
|
<field name="student_email" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="student_dob" readonly="1"/>
|
||||||
|
<field name="student_guardian" readonly="1"/>
|
||||||
|
<field name="student_academic_year" readonly="1"/>
|
||||||
|
<field name="student_class" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="subject_names" readonly="1" string="Subjects" widget="text"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!-- School Information Card -->
|
||||||
|
<group string="School Information">
|
||||||
|
<group>
|
||||||
|
<field name="school_name" readonly="1"/>
|
||||||
|
<field name="school_address" readonly="1"/>
|
||||||
|
<field name="school_state" readonly="1"/>
|
||||||
|
<field name="school_phone" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="school_email" readonly="1"/>
|
||||||
|
<field name="school_academic_year" readonly="1"/>
|
||||||
|
<field name="school_classes" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="action_transcript_report" model="ir.actions.act_window">
|
||||||
<record id="action_school_transcript_report" model="ir.actions.act_window">
|
|
||||||
<field name="name">Transcript Report</field>
|
<field name="name">Transcript Report</field>
|
||||||
<field name="res_model">school.transcript.report</field>
|
<field name="res_model">school.transcript.report</field>
|
||||||
<field name="view_mode">list,form</field>
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="o_view_nocontent_smiling_face">
|
||||||
|
Create a transcript report
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Select a session and student to generate transcript reports.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<!-- === Action & Views: Scholarship Report === -->
|
<!-- === Action & Views: Scholarship Report === -->
|
||||||
<record id="view_scholarship_report_list" model="ir.ui.view">
|
<record id="view_scholarship_report_list" model="ir.ui.view">
|
||||||
<field name="name">school.scholarship.report.list</field>
|
<field name="name">school.scholarship.report.list</field>
|
||||||
|
@ -80,6 +157,7 @@
|
||||||
</list>
|
</list>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_scholarship_report_form" model="ir.ui.view">
|
<record id="view_scholarship_report_form" model="ir.ui.view">
|
||||||
<field name="name">school.scholarship.report.form</field>
|
<field name="name">school.scholarship.report.form</field>
|
||||||
<field name="model">school.scholarship.report</field>
|
<field name="model">school.scholarship.report</field>
|
||||||
|
@ -96,14 +174,12 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<record id="action_school_scholarship_report" model="ir.actions.act_window">
|
<record id="action_school_scholarship_report" model="ir.actions.act_window">
|
||||||
<field name="name">Scholarship Report</field>
|
<field name="name">Scholarship Report</field>
|
||||||
<field name="res_model">school.scholarship.report</field>
|
<field name="res_model">school.scholarship.report</field>
|
||||||
<field name="view_mode">list,form</field>
|
<field name="view_mode">list,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<!-- === Action & Views: Report Card === -->
|
<!-- === Action & Views: Report Card === -->
|
||||||
<record id="view_report_card_list" model="ir.ui.view">
|
<record id="view_report_card_list" model="ir.ui.view">
|
||||||
<field name="name">school.report.card.list</field>
|
<field name="name">school.report.card.list</field>
|
||||||
|
@ -116,6 +192,7 @@
|
||||||
</list>
|
</list>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_report_card_form" model="ir.ui.view">
|
<record id="view_report_card_form" model="ir.ui.view">
|
||||||
<field name="name">school.report.card.form</field>
|
<field name="name">school.report.card.form</field>
|
||||||
<field name="model">school.report.card</field>
|
<field name="model">school.report.card</field>
|
||||||
|
@ -132,7 +209,6 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<record id="action_school_report_card" model="ir.actions.act_window">
|
<record id="action_school_report_card" model="ir.actions.act_window">
|
||||||
<field name="name">Report Card</field>
|
<field name="name">Report Card</field>
|
||||||
<field name="res_model">school.report.card</field>
|
<field name="res_model">school.report.card</field>
|
||||||
|
|
Loading…
Reference in New Issue