diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3b66410 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.ignoreLimitWarning": true +} \ No newline at end of file diff --git a/__manifest__.py b/__manifest__.py index 4082d64..2ffdbff 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,10 +1,10 @@ { 'name': 'School_Management', 'version': '1.0', - 'depends': ['base', 'web', 'mail'], + 'depends': ['base', 'web', 'mail','product'], 'license': 'LGPL-3', 'data': [ - 'security/security.xml', + 'security/security.xml', 'security/ir.model.access.csv', 'views/schedule.xml', 'views/class.xml', @@ -19,9 +19,11 @@ 'views/timeoff_views.xml', 'views/teacher_attendance_view.xml', 'views/school_misc_views.xml', - 'views/school_reporting_views.xml', - 'views/menu.xml', - + 'views/school_reporting_views.xml', + 'views/school_student_views.xml', + 'views/fee_structure_views.xml', + 'views/fee_element_views.xml', + 'views/menu.xml', ], 'installable': True, 'application': True, diff --git a/__pycache__/__init__.cpython-310.pyc b/__pycache__/__init__.cpython-310.pyc index 6741cf0..08b7bb9 100644 Binary files a/__pycache__/__init__.cpython-310.pyc and b/__pycache__/__init__.cpython-310.pyc differ diff --git a/models/__init__.py b/models/__init__.py index 873b274..f65f0e8 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -15,5 +15,11 @@ from . import school_subject_lesson from . import school_subject_teacher_info from . import teacher_attendance from . import school_misc_menus +from . import school_student +from . import fee_structure +from . import fee_element +from . import school_fee_structure_line + + diff --git a/models/__pycache__/__init__.cpython-310.pyc b/models/__pycache__/__init__.cpython-310.pyc index c92e7ab..eecf7aa 100644 Binary files a/models/__pycache__/__init__.cpython-310.pyc and b/models/__pycache__/__init__.cpython-310.pyc differ diff --git a/models/__pycache__/application.cpython-310.pyc b/models/__pycache__/application.cpython-310.pyc index 0528151..e53371b 100644 Binary files a/models/__pycache__/application.cpython-310.pyc and b/models/__pycache__/application.cpython-310.pyc differ diff --git a/models/__pycache__/enrollment.cpython-310.pyc b/models/__pycache__/enrollment.cpython-310.pyc index 9ac326e..f73d4b5 100644 Binary files a/models/__pycache__/enrollment.cpython-310.pyc and b/models/__pycache__/enrollment.cpython-310.pyc differ diff --git a/models/__pycache__/enrollment_fee_summary.cpython-310.pyc b/models/__pycache__/enrollment_fee_summary.cpython-310.pyc index d39457a..3a99eb4 100644 Binary files a/models/__pycache__/enrollment_fee_summary.cpython-310.pyc and b/models/__pycache__/enrollment_fee_summary.cpython-310.pyc differ diff --git a/models/__pycache__/enrollment_subject.cpython-310.pyc b/models/__pycache__/enrollment_subject.cpython-310.pyc index 1edcf72..7c82cbc 100644 Binary files a/models/__pycache__/enrollment_subject.cpython-310.pyc and b/models/__pycache__/enrollment_subject.cpython-310.pyc differ diff --git a/models/__pycache__/fee_element.cpython-310.pyc b/models/__pycache__/fee_element.cpython-310.pyc new file mode 100644 index 0000000..750b47d Binary files /dev/null and b/models/__pycache__/fee_element.cpython-310.pyc differ diff --git a/models/__pycache__/fee_structure.cpython-310.pyc b/models/__pycache__/fee_structure.cpython-310.pyc new file mode 100644 index 0000000..c8ed105 Binary files /dev/null and b/models/__pycache__/fee_structure.cpython-310.pyc differ diff --git a/models/__pycache__/schedule.cpython-310.pyc b/models/__pycache__/schedule.cpython-310.pyc index 8c22f01..7e16979 100644 Binary files a/models/__pycache__/schedule.cpython-310.pyc and b/models/__pycache__/schedule.cpython-310.pyc differ diff --git a/models/__pycache__/school_class.cpython-310.pyc b/models/__pycache__/school_class.cpython-310.pyc index 5e4594c..81cf391 100644 Binary files a/models/__pycache__/school_class.cpython-310.pyc and b/models/__pycache__/school_class.cpython-310.pyc differ diff --git a/models/__pycache__/school_course.cpython-310.pyc b/models/__pycache__/school_course.cpython-310.pyc index 01c5d1f..33b0f0d 100644 Binary files a/models/__pycache__/school_course.cpython-310.pyc and b/models/__pycache__/school_course.cpython-310.pyc differ diff --git a/models/__pycache__/school_course_attendance.cpython-310.pyc b/models/__pycache__/school_course_attendance.cpython-310.pyc index 4593303..e41a523 100644 Binary files a/models/__pycache__/school_course_attendance.cpython-310.pyc and b/models/__pycache__/school_course_attendance.cpython-310.pyc differ diff --git a/models/__pycache__/school_course_schedule.cpython-310.pyc b/models/__pycache__/school_course_schedule.cpython-310.pyc index 2af8bdd..d9b0ae2 100644 Binary files a/models/__pycache__/school_course_schedule.cpython-310.pyc and b/models/__pycache__/school_course_schedule.cpython-310.pyc differ diff --git a/models/__pycache__/school_course_student.cpython-310.pyc b/models/__pycache__/school_course_student.cpython-310.pyc index d1694f4..3b05131 100644 Binary files a/models/__pycache__/school_course_student.cpython-310.pyc and b/models/__pycache__/school_course_student.cpython-310.pyc differ diff --git a/models/__pycache__/school_fee_structure_line.cpython-310.pyc b/models/__pycache__/school_fee_structure_line.cpython-310.pyc new file mode 100644 index 0000000..6e13022 Binary files /dev/null and b/models/__pycache__/school_fee_structure_line.cpython-310.pyc differ diff --git a/models/__pycache__/school_student.cpython-310.pyc b/models/__pycache__/school_student.cpython-310.pyc new file mode 100644 index 0000000..e84bf7a Binary files /dev/null and b/models/__pycache__/school_student.cpython-310.pyc differ diff --git a/models/__pycache__/school_subject.cpython-310.pyc b/models/__pycache__/school_subject.cpython-310.pyc index 108693c..2dffe32 100644 Binary files a/models/__pycache__/school_subject.cpython-310.pyc and b/models/__pycache__/school_subject.cpython-310.pyc differ diff --git a/models/__pycache__/school_subject_teacher_info.cpython-310.pyc b/models/__pycache__/school_subject_teacher_info.cpython-310.pyc index e3725f4..1ae5d3b 100644 Binary files a/models/__pycache__/school_subject_teacher_info.cpython-310.pyc and b/models/__pycache__/school_subject_teacher_info.cpython-310.pyc differ diff --git a/models/__pycache__/teacher_attendance.cpython-310.pyc b/models/__pycache__/teacher_attendance.cpython-310.pyc index 2b00848..7f5b1fa 100644 Binary files a/models/__pycache__/teacher_attendance.cpython-310.pyc and b/models/__pycache__/teacher_attendance.cpython-310.pyc differ diff --git a/models/application.py b/models/application.py index 5983490..c6819e5 100644 --- a/models/application.py +++ b/models/application.py @@ -9,15 +9,29 @@ class SchoolApplication(models.Model): _description = 'Student Application' _order = 'name' _rec_name = 'name' - - # _inherit = ['mail.thread', 'mail.activity.mixin'] + _inherit = ['mail.thread', 'mail.activity.mixin'] name = fields.Char(string="Student Name", required=True,) email = fields.Char(string="Email", ) phone_no = fields.Char(string="Phone Number") image = fields.Binary("Profile Photo", store=True) address = fields.Text(string="Address") - class_name = fields.Char(string="Class") + 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) + + academic_year = fields.Char(string="Academic Year") gender = fields.Selection([ ('male', 'Male'), ('female', 'Female'), @@ -74,18 +88,31 @@ class SchoolApplication(models.Model): if not re.fullmatch(r'\d{10}', record.phone_no or ''): raise ValidationError("Phone number must contain exactly 10 digits.") - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) + def action_show_id_card(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': 'ID Card', + 'view_mode': 'form', + 'res_model': 'school.application', + 'res_id': self.id, + 'view_id': self.env.ref('school_management.view_school_id_card_form').id, + 'target': 'new', # or 'current' for full page + } - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) + + @api.depends('application_id') + def _compute_student_id(self): + for rec in self: + rec.student_id = str(rec.application_id.id) if rec.application_id else '' - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) - - # def get_default_image(self): - # with open('/path/to/sample.jpg', 'rb') as f: - # return base64.b64encode(f.read()) \ No newline at end of file + # def action_open_id_card_wizard(self): + # return { + # 'type': 'ir.actions.act_window', + # 'name': 'Generate ID Card', + # 'res_model': 'wizard.generate.id.card', + # 'view_mode': 'form', + # 'target': 'new', + # 'context': {'default_application_id': self.id}, + # } + \ No newline at end of file diff --git a/models/enrollment.py b/models/enrollment.py index 51281aa..8d4e73a 100644 --- a/models/enrollment.py +++ b/models/enrollment.py @@ -1,14 +1,32 @@ -from odoo import models, fields -from odoo.exceptions import UserError +from odoo import models, fields, api +_inherit = ['mail.thread', 'mail.activity.mixin'] + class SchoolEnrollment(models.Model): _name = 'school.enrollment' _description = 'Enrollment' + + + application_id = fields.Many2one('school.application', string="Student", required=True) + school_id = fields.Many2one('res.company', string="School", default=lambda self: self.env.company) + student_id = fields.Char(string="Student ID", compute='_compute_student_id', store=True) + student_name = fields.Many2one('school.application', string="Student", ondelete='set null') + image = fields.Binary("Profile Photo", store=True) + 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) - student_id = fields.Many2one('school.application', string="Student", ondelete='set null') - image = fields.Binary(string="Profile Photo") - school_name = fields.Char(string="School") - class_name = fields.Char(string="Class") course = fields.Char(string="Course") session = fields.Char(string="Session") academic_year = fields.Char(string="Academic Year") @@ -34,14 +52,7 @@ class SchoolEnrollment(models.Model): course_id = fields.Many2one('school.course', string='Course', ondelete='cascade', required=True) student_id = fields.Many2one('res.partner', string='Student', required=True) - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + @api.depends('application_id') + def _compute_student_id(self): + for rec in self: + rec.student_id = str(rec.application_id.id) if rec.application_id else '' \ No newline at end of file diff --git a/models/enrollment_fee_summary.py b/models/enrollment_fee_summary.py index dfbd60c..66f7e14 100644 --- a/models/enrollment_fee_summary.py +++ b/models/enrollment_fee_summary.py @@ -6,6 +6,7 @@ class EnrollmentFeeSummary(models.Model): _description = 'Fee Summary Line' enrollment_id = fields.Many2one('school.enrollment', string="Enrollment") + student_ref = fields.Many2one('school.student', string="Student") total_fees = fields.Float(string="Total Fees") paid_fees = fields.Float(string="Paid Fees") fee_slip_amount = fields.Float(string="Fee Slip Amount") diff --git a/models/enrollment_subject.py b/models/enrollment_subject.py index 6cde80b..5989691 100644 --- a/models/enrollment_subject.py +++ b/models/enrollment_subject.py @@ -8,7 +8,21 @@ class EnrollmentSubject(models.Model): enrollment_id = fields.Many2one('school.enrollment', string="Enrollment") subject_id = fields.Many2one('school.subject', string="Subject Name", required=True) subject_name = fields.Char(string="Subject Name") - class_name = fields.Char(string="Class") + 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) + academic_year = fields.Char(string="Academic Year") status = fields.Selection([ ('active', 'Active'), diff --git a/models/fee_element.py b/models/fee_element.py new file mode 100644 index 0000000..1879c44 --- /dev/null +++ b/models/fee_element.py @@ -0,0 +1,8 @@ +from odoo import models, fields + +class FeeElement(models.Model): + _name = 'school.fee.element' + _description = 'Fee Element' + + name = fields.Char("Fee Component", required=True) + description = fields.Text("Description") diff --git a/models/fee_structure.py b/models/fee_structure.py new file mode 100644 index 0000000..4c270da --- /dev/null +++ b/models/fee_structure.py @@ -0,0 +1,66 @@ +from odoo import models, fields, api + +class SchoolFeeStructure(models.Model): + _name = 'school.fee.structure' + _description = 'Fee Structure' + + name = fields.Char(string="Structure Name", compute='_compute_name', store=True) + 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) + + tuition_fee = fields.Float(string="Tuition Fees") + admission_fee = fields.Float(string="Admission Charges") + annual_charge = fields.Float(string="Annual Charges") + total_fee = fields.Float(string="Total Fee", compute="_compute_total_fee", store=True) + + component_line_ids = fields.One2many('school.fee.component', 'structure_id', string="Fee Components", readonly=True) + + @api.depends('class_name') + def _compute_name(self): + for rec in self: + rec.name = f"Fee Structure for Class {rec.class_name}" if rec.class_name else "" + + @api.depends('tuition_fee', 'admission_fee', 'annual_charge') + def _compute_total_fee(self): + for rec in self: + rec.total_fee = (rec.tuition_fee or 0) + (rec.admission_fee or 0) + (rec.annual_charge or 0) + + @api.onchange('class_name') + def _onchange_class_name(self): + fee_data = { + '1': {'admission_fee': 5000, 'tuition_fee': 72000, 'annual_charge': 1000}, + '2': {'admission_fee': 6000, 'tuition_fee': 84000, 'annual_charge': 1000}, + '3': {'admission_fee': 6500, 'tuition_fee': 90000, 'annual_charge': 1000}, + '4': {'admission_fee': 7000, 'tuition_fee': 96000, 'annual_charge': 1000}, + '5': {'admission_fee': 7500, 'tuition_fee': 100000, 'annual_charge': 1000}, + '6': {'admission_fee': 8000, 'tuition_fee': 105000, 'annual_charge': 1000}, + '7': {'admission_fee': 8500, 'tuition_fee': 110000, 'annual_charge': 1000}, + '8': {'admission_fee': 9000, 'tuition_fee': 115000, 'annual_charge': 1000}, + '9': {'admission_fee': 9500, 'tuition_fee': 120000, 'annual_charge': 1000}, + '10': {'admission_fee': 10000, 'tuition_fee': 125000, 'annual_charge': 1000}, + '11': {'admission_fee': 11000, 'tuition_fee': 130000, 'annual_charge': 1000}, + '12': {'admission_fee': 12000, 'tuition_fee': 135000, 'annual_charge': 1000}, + } + + if self.class_name: + values = fee_data.get(self.class_name, {}) + self.admission_fee = values.get('admission_fee', 0) + self.tuition_fee = values.get('tuition_fee', 0) + self.annual_charge = values.get('annual_charge', 0) + + self.component_line_ids = [(5, 0, 0)] # Clear + self.component_line_ids = [(0, 0, {'component_name': 'Admission Charges', 'amount': self.admission_fee}), + (0, 0, {'component_name': 'Tuition Fees', 'amount': self.tuition_fee}), + (0, 0, {'component_name': 'Annual Charges', 'amount': self.annual_charge})] diff --git a/models/schedule.py b/models/schedule.py index b0e5f5c..b835cde 100644 --- a/models/schedule.py +++ b/models/schedule.py @@ -1,12 +1,27 @@ from odoo import models, fields from odoo.exceptions import UserError +_inherit = ['mail.thread', 'mail.activity.mixin'] class SchoolClassSchedule(models.Model): _name = 'school.class.schedule' _description = 'Class Schedule' title = fields.Char(string="Title", required=True) - class_name = fields.Char(string="Class") + 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) + subject = fields.Char(string="Subject") teacher = fields.Char(string="Teacher") secondary_teacher = fields.Char(string="Secondary Teacher") diff --git a/models/school_class.py b/models/school_class.py index d8d0c9a..577a7b5 100644 --- a/models/school_class.py +++ b/models/school_class.py @@ -1,25 +1,52 @@ -from odoo import models, fields -from odoo.exceptions import UserError -import base64 +from odoo import models, fields, api class SchoolClass(models.Model): _name = 'school.class' _description = 'Class' - name = fields.Char(string='Class Name', required=True) + related_subject_ids = fields.One2many('school.subject', 'class_name', string='Subjects') + name = fields.Selection([ + ('Class 1', 'Class 1'), + ('Class 2', 'Class 2'), + ('Class 3', 'Class 3'), + ('Class 4', 'Class 4'), + ('Class 5', 'Class 5'), + ('Class 6', 'Class 6'), + ('Class 7', 'Class 7'), + ('Class 8', 'Class 8'), + ('Class 9', 'Class 9'), + ('Class 10', 'Class 10'), + ('Class 11', 'Class 11'), + ('Class 12', 'Class 12'), + ], string="Class Name", required=True) + subject_ids = fields.Many2many('school.subject', string='Subjects') - school = fields.Char(string='School') + school = fields.Many2one('res.company', string="School", default=lambda self: self.env.company) is_optional = fields.Boolean(string='Optional') class_teacher = fields.Many2one('res.users', string='Class Teacher') - - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) + @api.onchange('name') + def _onchange_name_set_subjects(self): + if not self.name: + self.subject_ids = False + return + + subject_map = { + 'Class 1': ['math', 'english', 'science', 'mil'], + 'Class 2': ['math', 'english', 'science', 'drawing', 'mil'], + 'Class 3': ['math', 'english', 'science', 'odia', 'drawing', 'english_grammar'], + 'Class 4': ['math', 'english', 'science', 'odia', 'drawing', 'english_grammar'], + 'Class 5': ['math', 'english', 'science', 'odia', 'history', 'drawing', 'english_grammar'], + 'Class 6': ['math', 'english', 'science', 'geography', 'mil', 'english_grammar'], + 'Class 7': ['math', 'english', 'science', 'political_science', 'mil', 'english_grammar', 'history', 'geography'], + 'Class 8': ['math', 'english', 'science', 'political_science', 'mil', 'english_grammar', 'history', 'geography'], + 'Class 9': ['math', 'english', 'physical_science', 'life_science', 'english_grammar', 'economic_science', 'history', 'geography'], + 'Class 10': ['math', 'english', 'physical_science', 'life_science', 'english_grammar', 'economic_science', 'history', 'geography'], + 'Class 11': ['physics', 'chemistry', 'math', 'biology', 'english', 'english_grammar', 'computer_science', 'mil', 'economic_science'], + 'Class 12': ['physics', 'chemistry', 'math', 'biology', 'computer_science', 'english_grammar', 'english', 'mil', 'economic_science'], + } + + subject_codes = subject_map.get(self.name, []) + subjects = self.env['school.subject'].search([('name', 'in', subject_codes)]) + self.subject_ids = [(6, 0, subjects.ids)] # This sets all - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file diff --git a/models/school_course.py b/models/school_course.py index 3f69791..af31434 100644 --- a/models/school_course.py +++ b/models/school_course.py @@ -1,14 +1,15 @@ from odoo import models, fields -from odoo.exceptions import UserError class SchoolCourse(models.Model): _name = 'school.course' _description = 'Course' - + + application_id = fields.Many2one('school.application', string="Student", required=True) name = fields.Char(string='Course Name', required=True) class_id = fields.Many2one('school.class', string='Class') teacher = fields.Many2one('res.users', string='Teacher') + student_name = fields.Char(related='application_id.name', string="Student Name", store=True) start_date = fields.Date(string='Started On') end_date = fields.Date(string='End Date') total_capacity = fields.Integer(string='Total Capacity') @@ -21,14 +22,4 @@ class SchoolCourse(models.Model): - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + \ No newline at end of file diff --git a/models/school_course_attendance.py b/models/school_course_attendance.py index aa7cc37..01a74e2 100644 --- a/models/school_course_attendance.py +++ b/models/school_course_attendance.py @@ -1,25 +1,15 @@ from odoo import models, fields -from odoo.exceptions import UserError + class SchoolCourseAttendance(models.Model): _name = 'school.course.attendance' _description = 'Course Attendance' - + + application_id = fields.Many2one('school.application', string="Student", required=True) course_id = fields.Many2one('school.course', string='Course', ondelete='cascade') - student_id = fields.Many2one('res.partner', string='Student') + student_name = fields.Char(related='application_id.name', string="Student Name", store=True) is_present = fields.Boolean(string='Present') class_id = fields.Many2one('school.class', string='Class') - - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + \ No newline at end of file diff --git a/models/school_course_schedule.py b/models/school_course_schedule.py index 3197b4b..decf9ce 100644 --- a/models/school_course_schedule.py +++ b/models/school_course_schedule.py @@ -1,5 +1,6 @@ from odoo import models, fields from odoo.exceptions import UserError +_inherit = ['mail.thread', 'mail.activity.mixin'] class SchoolCourseSchedule(models.Model): _name = 'school.course.schedule' diff --git a/models/school_course_student.py b/models/school_course_student.py index 6f31215..88ffe7f 100644 --- a/models/school_course_student.py +++ b/models/school_course_student.py @@ -3,6 +3,8 @@ from odoo import models, fields class SchoolCourseStudent(models.Model): _name = 'school.course.student' _description = 'Enrolled Student' - + + application_id = fields.Many2one('school.application', string="Student", required=True) course_id = fields.Many2one('school.course', string='Course', ondelete='cascade') student_id = fields.Many2one('res.partner', string='Student') + student_name = fields.Char(related='application_id.name', string="Student Name", store=True) \ No newline at end of file diff --git a/models/school_fee_structure_line.py b/models/school_fee_structure_line.py new file mode 100644 index 0000000..d3f3967 --- /dev/null +++ b/models/school_fee_structure_line.py @@ -0,0 +1,10 @@ +from odoo import models, fields, api + +class SchoolFeeComponent(models.Model): + _name = 'school.fee.component' + _description = 'Fee Component' + + structure_id = fields.Many2one('school.fee.structure', string="Fee Structure") + component_name = fields.Char(string="Component") + amount = fields.Float(string="Amount") + diff --git a/models/school_student.py b/models/school_student.py new file mode 100644 index 0000000..7a328bd --- /dev/null +++ b/models/school_student.py @@ -0,0 +1,52 @@ +from odoo import models, fields, api +from odoo.exceptions import UserError + +class SchoolStudent(models.Model): + _name = 'school.student' + _description = 'Student' + + application_id = fields.Many2one('school.application', string="Application", required=True) + + # Use computed char field instead of invalid related field + student_id = fields.Char(string="Student ID", compute='_compute_student_id', store=True) + + profile_photo = fields.Binary(related='application_id.image', string="Profile Photo", store=True) + student_name = fields.Char(related='application_id.name', string="Student Name", store=True) + school_id = fields.Many2one('res.company', string="School", default=lambda self: self.env.company) + enrollment_date = fields.Date(string="Enrollment Date") + 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) + academic_year = fields.Char(string="Academic Year") + session_status = fields.Selection([ + ('active', 'Active'), + ('completed', 'Completed'), + ('suspended', 'Suspended') + ], string="Session Status") + payment_term = fields.Char(string="Payment Term") + + def action_generate_payment_slip(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'Fee Slip', + 'res_model': 'school.enrollment.fee.summary', + 'view_mode': 'tree,form', + 'domain': [('student_ref', '=', self.id)], + 'target': 'current', + } + + @api.depends('application_id') + def _compute_student_id(self): + for rec in self: + rec.student_id = str(rec.application_id.id) if rec.application_id else '' diff --git a/models/school_subject.py b/models/school_subject.py index c6b5106..814d930 100644 --- a/models/school_subject.py +++ b/models/school_subject.py @@ -1,27 +1,87 @@ -from odoo import models, fields +from odoo import models, fields, api from odoo.exceptions import UserError -import base64 class SchoolSubject(models.Model): _name = 'school.subject' _description = 'Subject' - name = fields.Char(string='Subject Name', required=True) - class_id = fields.Many2one('school.class', string='Class') + name = fields.Selection([ + ('math', 'Math'), + ('english', 'English'), + ('science', 'Science'), + ('physical_science', 'Physical Science'), + ('life_science', 'Life Science'), + ('geography', 'Geography'), + ('history', 'History'), + ('political_science', 'Political Science'), + ('economic_science', 'Economic Science'), + ('physics', 'Physics'), + ('chemistry', 'Chemistry'), + ('biology', 'Biology'), + ('it', 'IT'), + ('computer_science', 'Computer Science'), + ('mil', 'MIL'), + ('odia', 'Odia'), + ('english_grammar', 'English Grammar'), + ('drawing', 'Drawing'), + ('odia_grammar', 'Odia Grammar'), + ], string="Subject", required=True) + + class_name = fields.Selection([ + ('Class 1', 'Class 1'), + ('Class 2', 'Class 2'), + ('Class 3', 'Class 3'), + ('Class 4', 'Class 4'), + ('Class 5', 'Class 5'), + ('Class 6', 'Class 6'), + ('Class 7', 'Class 7'), + ('Class 8', 'Class 8'), + ('Class 9', 'Class 9'), + ('Class 10', 'Class 10'), + ('Class 11', 'Class 11'), + ('Class 12', 'Class 12'), + ], string="Class Name", required=True) + lesson_plan = fields.Text(string='Lesson Plan') teacher = fields.Many2one('res.users', string='Teacher') lesson_plan_line_ids = fields.One2many('school.subject.lesson', 'subject_id', string='Lesson Plans') teacher_info_line_ids = fields.One2many('school.subject.teacher.info', 'subject_id', string="Teacher Info") - - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.name) + @api.depends('class_name') + def _compute_subjects(self): + subject_mapping = { + 'Class 1': ['Math', 'English', 'Science', 'MIL'], + 'Class 2': ['Math', 'English', 'Science', 'Drawing', 'MIL'], + 'Class 3': ['Math', 'English', 'Science', 'Odia', 'Drawing', 'English Grammar'], + 'Class 4': ['Math', 'English', 'Science', 'Odia', 'Drawing', 'English Grammar'], + 'Class 5': ['Math', 'English', 'Science', 'Odia', 'History', 'Drawing', 'English Grammar'], + 'Class 6': ['Math', 'English', 'Science', 'Geography', 'MIL', 'English Grammar'], + 'Class 7': ['Math', 'English', 'Science', 'Political Science', 'MIL', 'English Grammar', 'History', 'Geography'], + 'Class 8': ['Math', 'English', 'Science', 'Political Science', 'MIL', 'English Grammar', 'History', 'Geography'], + 'Class 9': ['Math', 'English', 'Physical Science', 'Life Science', 'English Grammar', 'Economic Science', 'History', 'Geography'], + 'Class 10': ['Math', 'English', 'Physical Science', 'Life Science', 'English Grammar', 'Economic Science', 'History', 'Geography'], + 'Class 11': ['Physics', 'Chemistry', 'Math', 'Biology', 'English', 'English Grammar', 'Computer Science', 'MIL', 'Economic Science'], + 'Class 12': ['Physics', 'Chemistry', 'Math', 'Biology', 'Computer Science', 'English Grammar', 'English', 'MIL', 'Economic Science'], + } + for rec in self: + rec.subject_list = ', '.join(subject_mapping.get(rec.class_name, [])) + def action_generate_subjects(self): + if not self.class_name: + raise UserError("Please select a class name first.") - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.name) + existing_subjects = self.search([ + ('class_name', '=', self.class_name) + ]).mapped('name') - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.name) \ No newline at end of file + subject_list = self.get_subjects_by_class().get(self.class_name, []) + + new_subjects = [sub for sub in subject_list if sub not in existing_subjects] + + for subject in new_subjects: + self.create({ + 'class_name': self.class_name, + 'name': subject, + }) + + if not new_subjects: + raise UserError("All subjects for this class already exist.") diff --git a/models/school_subject_teacher_info.py b/models/school_subject_teacher_info.py index cc27f90..1949564 100644 --- a/models/school_subject_teacher_info.py +++ b/models/school_subject_teacher_info.py @@ -1,34 +1,34 @@ -from odoo import models, fields -from odoo.exceptions import UserError +from odoo import models, fields, api class SchoolSubjectTeacherInfo(models.Model): _name = 'school.subject.teacher.info' _description = 'Subject Teacher Info' subject_id = fields.Many2one('school.subject', string='Subject', required=True, ondelete='cascade') - employee_name = fields.Char(string='Teacher Name') - phone = fields.Char(string='Phone') - email = fields.Char(string='Email') + + # Related fields to auto-fetch from related subject's teacher (res.users) + teacher_user_id = fields.Many2one(related='subject_id.teacher', string="Teacher User", store=True) + employee_name = fields.Char(string='Teacher Name', compute="_compute_teacher_fields", store=True) + phone = fields.Char(string='Phone', compute="_compute_teacher_fields", store=True) + email = fields.Char(string='Email', compute="_compute_teacher_fields", store=True) + profile_photo = fields.Binary(string="Profile Photo", compute="_compute_teacher_fields", store=True) + + # Editable fields for extra info activity = fields.Char(string='Activity') activity_deadline = fields.Date(string='New Activity Deadline') department = fields.Char(string='Department') job_position = fields.Char(string='Job Position') manager = fields.Char(string='Manager') - profile_photo = fields.Binary(string="Profile Photo", attachment=True) address = fields.Text(string="Address") experience = fields.Integer(string="Experience (Years)") date_of_birth = fields.Date(string="Date of Birth") join_date = fields.Date(string="Join Date") - - def action_send_message(self): - for record in self: - raise UserError("Send Message clicked for %s" % record.employee_name) - - def action_log_note(self): - for record in self: - raise UserError("Log Note clicked for %s" % record.employee_name) - - def action_schedule_activity(self): - for record in self: - raise UserError("Activity clicked for %s" % record.employee_name) + @api.depends('subject_id.teacher') + def _compute_teacher_fields(self): + for rec in self: + user = rec.subject_id.teacher + rec.employee_name = user.name if user else '' + rec.email = user.email if user else '' + rec.phone = user.phone if user else '' + rec.profile_photo = user.image_1920 if user else False diff --git a/models/teacher_attendance.py b/models/teacher_attendance.py index 080edfc..455ff0e 100644 --- a/models/teacher_attendance.py +++ b/models/teacher_attendance.py @@ -6,7 +6,7 @@ class TeacherAttendance(models.Model): _description = 'Teacher Attendance' _order = 'date desc' - teacher_id = fields.Many2one('school.subject.teacher.info', string='Teacher', required=True) + teacher_id = fields.Many2one('res.partner', string='Student') date = fields.Date(string='Date', required=True, default=fields.Date.today) attendance_status = fields.Selection([ ('present', 'Present'), diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index dc9143f..018e9b8 100644 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -22,4 +22,9 @@ access_school_config_settings,School Config Settings,model_school_config_setting access_school_fees_report,Fees Report,model_school_fees_report,,1,1,1,1 access_school_transcript_report,Transcript Report,model_school_transcript_report,,1,1,1,1 access_school_scholarship_report,Scholarship Report,model_school_scholarship_report,,1,1,1,1 -access_school_report_card,Report Card,model_school_report_card,,1,1,1,1 \ No newline at end of file +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_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_component,School Fee Component,model_school_fee_component,,1,0,0,0 + diff --git a/views/application.xml b/views/application.xml index fb4e3c9..c9c66a9 100644 --- a/views/application.xml +++ b/views/application.xml @@ -24,12 +24,6 @@
- -
@@ -54,6 +48,12 @@ + +
diff --git a/views/course.xml b/views/course.xml index 4196b8c..28770b2 100644 --- a/views/course.xml +++ b/views/course.xml @@ -36,7 +36,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -75,11 +75,6 @@ -
-
diff --git a/views/course_attendance.xml b/views/course_attendance.xml index 1392767..562f381 100644 --- a/views/course_attendance.xml +++ b/views/course_attendance.xml @@ -5,7 +5,7 @@ school.course.attendance - + @@ -19,15 +19,10 @@
- + -
-
diff --git a/views/enrollment.xml b/views/enrollment.xml index 94fd5c9..27ab32f 100644 --- a/views/enrollment.xml +++ b/views/enrollment.xml @@ -7,7 +7,7 @@ - + @@ -33,8 +33,8 @@ - - + + @@ -89,7 +89,7 @@ - + @@ -101,12 +101,12 @@
- +
-
Class:
+
Course:
Fees:
Session:
diff --git a/views/fee_element_views.xml b/views/fee_element_views.xml new file mode 100644 index 0000000..b1fbd1c --- /dev/null +++ b/views/fee_element_views.xml @@ -0,0 +1,33 @@ + + + fee.element.form + school.fee.element + +
+ + + + + + +
+
+
+ + + fee.element.list + school.fee.element + + + + + + + + + + Fee Element + school.fee.element + list,form + +
diff --git a/views/fee_structure_views.xml b/views/fee_structure_views.xml new file mode 100644 index 0000000..45a5b06 --- /dev/null +++ b/views/fee_structure_views.xml @@ -0,0 +1,56 @@ + + + + fee.structure.form + school.fee.structure + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + fee.structure.list + school.fee.structure + + + + + + + + + + + + + + + Fee Structure + school.fee.structure + list,form + +
diff --git a/views/lesson_views.xml b/views/lesson_views.xml index 5f2d71a..bed84ac 100644 --- a/views/lesson_views.xml +++ b/views/lesson_views.xml @@ -31,11 +31,6 @@ -
-
diff --git a/views/menu.xml b/views/menu.xml index 84b2502..d3f3f56 100644 --- a/views/menu.xml +++ b/views/menu.xml @@ -12,27 +12,27 @@ name="Applications" parent="menu_school_root" action="action_school_application" - sequence="30"/> + sequence="10"/> + sequence="20"/> + sequence="40"/> + sequence="30"/> - + + + + + + + + + diff --git a/views/schedule.xml b/views/schedule.xml index 6326a49..0387595 100644 --- a/views/schedule.xml +++ b/views/schedule.xml @@ -46,11 +46,6 @@ -
-
@@ -82,12 +77,34 @@ + + school.class.schedule.activity + school.class.schedule + + + + + +
+
+
+ Class:
+ Subject:
+ Teacher:
+
+
+
+
+
+
+
+ Class Schedule school.class.schedule - list,form,kanban + list,form,kanban,activity diff --git a/views/school_student_views.xml b/views/school_student_views.xml new file mode 100644 index 0000000..2a09118 --- /dev/null +++ b/views/school_student_views.xml @@ -0,0 +1,105 @@ + + + + + + school.student.list + school.student + + + + + + + + + + + + + + + school.student.form + school.student + +
+ +

Student Information

+ + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + + school.student.kanban + school.student + + + + + + + +
+
+
+ +
+
+
+ Class: +
+
+
+
+
+
+
+
+ + + + All Students + school.student + list,form,kanban + +

Create and manage your students here.

+
+
+ + + + + + +
diff --git a/views/school_subject_teacher_views.xml b/views/school_subject_teacher_views.xml index b5b7e2a..aca0cb0 100644 --- a/views/school_subject_teacher_views.xml +++ b/views/school_subject_teacher_views.xml @@ -45,11 +45,6 @@ -
-
diff --git a/views/subject.xml b/views/subject.xml index 622250b..311f597 100644 --- a/views/subject.xml +++ b/views/subject.xml @@ -1,69 +1,87 @@ + + + Generate Subjects + + code + + form + +action = env['school.subject'].create_subjects_for_class(record.class_name) + + + + school.subject.list school.subject - + - + + school.subject.form school.subject -
+ +
+
- + - - - - - - - - - - - - - - - - - - - - - - - - - -
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ - Subject + Subjects school.subject list,form diff --git a/views/teacher_attendance_view.xml b/views/teacher_attendance_view.xml index a78e149..c5d6bdb 100644 --- a/views/teacher_attendance_view.xml +++ b/views/teacher_attendance_view.xml @@ -31,6 +31,18 @@ + + school.teacher.attendance.calendar + school.teacher.attendance + + + + + + + + + Teacher Attendance school.teacher.attendance