############################################################################### # # OpenEduCat Inc # Copyright (C) 2009-TODAY OpenEduCat Inc(). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # ############################################################################### import calendar import pytz from odoo import _, api, fields, models from odoo.exceptions import ValidationError week_days = [(calendar.day_name[0], (calendar.day_name[0])), (calendar.day_name[1], (calendar.day_name[1])), (calendar.day_name[2], (calendar.day_name[2])), (calendar.day_name[3], (calendar.day_name[3])), (calendar.day_name[4], (calendar.day_name[4])), (calendar.day_name[5], (calendar.day_name[5])), (calendar.day_name[6], (calendar.day_name[6]))] class OpSession(models.Model): _name = "op.session" _inherit = ["mail.thread"] _description = "Sessions" name = fields.Char(compute='_compute_name', string='Name', store=True) timing_id = fields.Many2one( 'op.timing', 'Timing', tracking=True) start_datetime = fields.Datetime( 'Start Time', required=True, default=lambda self: fields.Datetime.now()) end_datetime = fields.Datetime( 'End Time', required=True) course_id = fields.Many2one( 'op.course', 'Course', required=True) faculty_id = fields.Many2one( 'op.faculty', 'Faculty', required=True) batch_id = fields.Many2one( 'op.batch', 'Batch', required=True) subject_id = fields.Many2one( 'op.subject', 'Subject', required=True) classroom_id = fields.Many2one( 'op.classroom', 'Classroom') color = fields.Integer('Color Index') type = fields.Char(compute='_compute_day', string='Day', store=True) state = fields.Selection( [('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Canceled')], string='Status', default='draft') user_ids = fields.Many2many( 'res.users', compute='_compute_batch_users', store=True, string='Users') active = fields.Boolean(default=True) company_id = fields.Many2one( 'res.company', string='Company', default=lambda self: self.env.user.company_id) days = fields.Selection([ ('monday', 'Monday'), ('tuesday', 'Tuesday'), ('wednesday', 'Wednesday'), ('thursday', 'Thursday'), ('friday', 'Friday'), ('saturday', 'Saturday'), ('sunday', 'Sunday')], 'Days', group_expand='_expand_groups', store=True ) timing = fields.Char(compute='_compute_timing', string='Session timing') @api.depends('start_datetime', 'end_datetime') def _compute_timing(self): tz = pytz.timezone(self.env.user.tz) for session in self: session.timing = str( session.start_datetime.astimezone(tz).strftime('%I:%M%p') ) + ' - ' + str(session.end_datetime.astimezone( tz).strftime('%I:%M%p')) @api.model def _expand_groups(self, days, domain, order=None): weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] return [day for day in weekdays if day in days] @api.depends('start_datetime') def _compute_day(self): days = {0: 'monday', 1: 'tuesday', 2: 'wednesday', 3: 'thursday', 4: 'friday', 5: 'saturday', 6: 'sunday'} for record in self: record.type = days.get(record.start_datetime.weekday()).capitalize() record.days = days.get(record.start_datetime.weekday()) @api.depends('faculty_id', 'subject_id', 'start_datetime', 'end_datetime') def _compute_name(self): tz = pytz.timezone(self.env.user.tz) for session in self: if session.faculty_id and session.subject_id \ and session.start_datetime and session.end_datetime: session.name = \ session.faculty_id.name + ':' + \ session.subject_id.name + ':' + str( session.start_datetime.astimezone(tz).strftime('%I:%M%p')) + '-' + str( # noqa session.end_datetime.astimezone(tz).strftime('%I:%M%p')) # For record rule on student and faculty dashboard @api.depends('batch_id', 'faculty_id', 'user_ids.child_ids') def _compute_batch_users(self): student_obj = self.env['op.student'] users_obj = self.env['res.users'] for session in self: student_ids = student_obj.search( [('course_detail_ids.batch_id', '=', session.batch_id.id)]) user_list = [student_id.user_id.id for student_id in student_ids if student_id.user_id] if session.faculty_id.user_id: user_list.append(session.faculty_id.user_id.id) user_ids = users_obj.search([('child_ids', 'in', user_list)]) if user_ids: user_list.extend(user_ids.ids) session.user_ids = user_list def lecture_draft(self): self.state = 'draft' def lecture_confirm(self): self.state = 'confirm' def lecture_done(self): self.state = 'done' def lecture_cancel(self): self.state = 'cancel' @api.constrains('start_datetime', 'end_datetime') def _check_date_time(self): for rec in self: if rec.start_datetime > rec.end_datetime: raise ValidationError(_( 'End Time cannot be set before Start Time.')) @api.constrains('faculty_id', 'start_datetime', 'end_datetime', 'classroom_id', 'batch_id', 'subject_id') def check_timetable_fields(self): res_param = self.env['ir.config_parameter'].sudo() faculty_constraint = res_param.search([ ('key', '=', 'timetable.is_faculty_constraint')]) classroom_constraint = res_param.search([ ('key', '=', 'timetable.is_classroom_constraint')]) batch_and_subject_constraint = res_param.search([ ('key', '=', 'timetable.is_batch_and_subject_constraint')]) batch_constraint = res_param.search([ ('key', '=', 'timetable.is_batch_constraint')]) is_faculty_constraint = faculty_constraint.value is_classroom_constraint = classroom_constraint.value is_batch_and_subject_constraint = batch_and_subject_constraint.value is_batch_constraint = batch_constraint.value sessions = self.env['op.session'].search([]) for session in sessions: for rec in self: if rec.id != session.id: if is_faculty_constraint: if rec.faculty_id.id == session.faculty_id.id and \ rec.start_datetime.date() == session.start_datetime.date() and ( # noqa session.start_datetime.time() < rec.start_datetime.time() < session.end_datetime.time() or # noqa session.start_datetime.time() < rec.end_datetime.time() < session.end_datetime.time() or # noqa rec.start_datetime.time() <= session.start_datetime.time() < rec.end_datetime.time() or # noqa rec.start_datetime.time() < session.end_datetime.time() <= rec.end_datetime.time()): # noqa raise ValidationError(_( 'You cannot create a session' ' with same faculty on same date ' 'and time')) if is_classroom_constraint: if rec.classroom_id.id == session.classroom_id.id and \ rec.start_datetime.date() == session.start_datetime.date() and ( # noqa session.start_datetime.time() < rec.start_datetime.time() < session.end_datetime.time() or # noqa session.start_datetime.time() < rec.end_datetime.time() < session.end_datetime.time() or # noqa rec.start_datetime.time() <= session.start_datetime.time() < rec.end_datetime.time() or # noqa rec.start_datetime.time() < session.end_datetime.time() <= rec.end_datetime.time()): # noqa raise ValidationError(_( 'You cannot create a session ' 'with same classroom on same date' ' and time')) if is_batch_and_subject_constraint: if rec.batch_id.id == session.batch_id.id and \ rec.start_datetime.date() == session.start_datetime.date() and ( # noqa session.start_datetime.time() < rec.start_datetime.time() < session.end_datetime.time() or # noqa session.start_datetime.time() < rec.end_datetime.time() < session.end_datetime.time() or # noqa rec.start_datetime.time() <= session.start_datetime.time() < rec.end_datetime.time() or # noqa rec.start_datetime.time() < session.end_datetime.time() <= rec.end_datetime.time()) and rec.subject_id.id == session.subject_id.id: # noqa raise ValidationError(_( 'You cannot create a session ' 'for the same batch on same time ' 'and for same subject')) if is_batch_constraint: if rec.batch_id.id == session.batch_id.id and \ rec.start_datetime.date() == session.start_datetime.date() and ( # noqa session.start_datetime.time() < rec.start_datetime.time() < session.end_datetime.time() or # noqa session.start_datetime.time() < rec.end_datetime.time() < session.end_datetime.time() or # noqa rec.start_datetime.time() <= session.start_datetime.time() < rec.end_datetime.time() or # noqa rec.start_datetime.time() < session.end_datetime.time() <= rec.end_datetime.time()): # noqa raise ValidationError(_( 'You cannot create a session for ' 'the same batch on same time ' 'even if it is different subject')) @api.model_create_multi def create(self, values): records = super(OpSession, self).create(values) for record in records: mfids = record.message_follower_ids partner_val = [] partner_ids = [] for val in mfids: partner_val.append(val.partner_id.id) if record.faculty_id and record.faculty_id.user_id: partner_ids.append(record.faculty_id.user_id.partner_id.id) if record.batch_id and record.course_id: course_val = self.env['op.student.course'].search([ ('batch_id', '=', record.batch_id.id), ('course_id', '=', record.course_id.id) ]) for val in course_val: if val.student_id.user_id: partner_ids.append(val.student_id.user_id.partner_id.id) subtype_id = self.env['mail.message.subtype'].sudo().search([ ('name', '=', 'Discussions')]) if partner_ids and subtype_id: mail_followers = self.env['mail.followers'].sudo() for partner in list(set(partner_ids)): if partner in partner_val: continue mail_followers.create({ 'res_model': record._name, 'res_id': record.id, 'partner_id': partner, 'subtype_ids': [[6, 0, [subtype_id[0].id]]] }) return records @api.onchange('course_id') def onchange_course(self): self.batch_id = False if self.course_id: subject_ids = self.env['op.course'].search([ ('id', '=', self.course_id.id)]).subject_ids return {'domain': {'subject_id': [('id', 'in', subject_ids.ids)]}} def notify_user(self): for session in self: template = self.env.ref( 'openeducat_timetable.session_details_changes', raise_if_not_found=False) template.send_mail(session.id) def get_emails(self, follower_ids): email_ids = '' for user in follower_ids: if email_ids: email_ids = email_ids + ',' + str(user.sudo().partner_id.email) else: email_ids = str(user.sudo().partner_id.email) return email_ids def get_subject(self): return 'Lecture of ' + self.faculty_id.name + \ ' for ' + self.subject_id.name + ' is ' + self.state def write(self, vals): data = super(OpSession, self.with_context(check_move_validity=False)).write(vals) for session in self: if session.state not in ('draft', 'done'): session.notify_user() return data @api.model def get_import_templates(self): return [{ 'label': _('Import Template for Sessions'), 'template': '/openeducat_timetable/static/xls/op_session.xls' }]