from odoo import fields, http from odoo.http import request from odoo.addons.portal.controllers.portal import CustomerPortal class DanceCustomerPortal(CustomerPortal): def _prepare_home_portal_values(self, counters): values = super()._prepare_home_portal_values(counters) if "dance_student_count" in counters: values["dance_student_count"] = request.env["res.partner"].sudo().search_count( self._get_portal_student_domain() ) return values def _get_portal_student_domain(self): partner = request.env.user.partner_id return [ ("is_student", "=", True), "|", ("guardian_id", "=", partner.id), ("guardian_ids", "in", [partner.id]), ] def _get_portal_student(self, student_id): student = request.env["res.partner"].sudo().browse(student_id) if not student.exists() or not student.is_student: return request.env["res.partner"] if student in request.env["res.partner"].sudo().search(self._get_portal_student_domain()): return student return request.env["res.partner"] def _get_student_portal_values(self, student): today = fields.Date.context_today(request.env.user) attendance = request.env["dance.attendance"].sudo().search( [("student_id", "=", student.id)], order="date desc, id desc", ) invoices = request.env["account.move"].sudo().search( [ ("move_type", "=", "out_invoice"), ("state", "!=", "cancel"), "|", ("dance_student_id", "=", student.id), ("partner_id", "=", student.id), ], order="invoice_date desc, id desc", ) enrollments = request.env["dance.enrollment"].sudo().search( [("student_id", "=", student.id)], order="enrollment_date desc, id desc", ) active_batches = enrollments.filtered(lambda enrollment: enrollment.status == "active").mapped("batch_id") upcoming_sessions = request.env["dance.session"].sudo().search( [ ("batch_id", "in", active_batches.ids), ("date", ">=", today), ("status", "=", "scheduled"), ], order="date asc, start_time asc, id asc", limit=20, ) upcoming_events = request.env["dance.event.performance"].sudo().search( [ ("student_id", "=", student.id), ("event_id.date", ">=", today), ("event_id.state", "!=", "cancelled"), ], order="id asc", limit=20, ).sorted(lambda performance: (performance.event_id.date, performance.sequence, performance.id)) upcoming_rehearsals = request.env["dance.rehearsal"].sudo().search( [ ("event_id.performance_ids.student_id", "=", student.id), ("date", ">=", today), ("status", "=", "scheduled"), ], order="date asc, start_time asc, id asc", limit=20, ) total_sessions = len(attendance) present_sessions = len(attendance.filtered(lambda line: line.status != "absent")) attendance_percent = ( round((present_sessions / total_sessions) * 100, 2) if total_sessions else 0.0 ) return { "page_name": "dance_student", "student": student, "attendance": attendance, "attendance_percent": attendance_percent, "absent_count": len(attendance.filtered(lambda line: line.status == "absent")), "invoices": invoices, "enrollments": enrollments, "upcoming_sessions": upcoming_sessions, "upcoming_events": upcoming_events, "upcoming_rehearsals": upcoming_rehearsals, } @http.route(["/my/students"], type="http", auth="user", website=True) def portal_my_students(self, **kwargs): students = request.env["res.partner"].sudo().search( self._get_portal_student_domain(), order="name", ) values = self._prepare_portal_layout_values() values.update( { "page_name": "dance_students", "students": students, } ) return request.render("dance_portal.portal_my_students", values) @http.route(["/my/students/"], type="http", auth="user", website=True) def portal_my_student_detail(self, student_id, **kwargs): student = self._get_portal_student(student_id) if not student: return request.redirect("/my/students") values = self._prepare_portal_layout_values() values.update(self._get_student_portal_values(student)) return request.render("dance_portal.portal_my_student_detail", values)