hunk.code_window:         if not self._context.get('mail_notify_author', False) and self_sudo.author_id:
               partners = partners - self_sudo.author_id
           # update message
           self.write({'channel_ids': [(6, 0, channels.ids)], 'needaction_partner_ids': [(6, 0, partners.ids)]})
           # notify partners and channels
           partners._notify(self, force_send=force_send, send_after_commit=send_after_commit, user_signature=user_signature)
           channels._notify(self)
  
hunk.labels: keep keep keep replace replace keep keep keep keep keep
hunk.after_edit:         # update message, with maybe custom values
           message_values = {
               'channel_ids': [(6, 0, channels.ids)],
               'needaction_partner_ids': [(6, 0, partners.ids)]
           }
           if self.model and self.res_id and hasattr(self.env[self.model], 'message_get_message_notify_values'):
               message_values.update(self.env[self.model].browse(self.res_id).message_get_message_notify_values(self, message_values))
           self.write(message_values)
  
hunk.file_path: addons/mail/models/mail_message.py
hunk.type: replace
file: # -*- coding: utf-8 -*-
  # Part of Odoo. See LICENSE file for full copyright and licensing details.
  
  from datetime import datetime
  
  from odoo import models, fields, api, exceptions, _
  from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
  
  
  class HrAttendance(models.Model):
      _name = "hr.attendance"
      _description = "Attendance"
      _order = "check_in desc"
  
      def _default_employee(self):
          return self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
  
      employee_id = fields.Many2one('hr.employee', string="Employee", default=_default_employee, required=True, ondelete='cascade', index=True)
      department_id = fields.Many2one('hr.department', string="Department", related="employee_id.department_id")
      check_in = fields.Datetime(string="Check In", default=fields.Datetime.now, required=True)
      check_out = fields.Datetime(string="Check Out")
      worked_hours = fields.Float(string='Worked Hours', compute='_compute_worked_hours', store=True, readonly=True)
  
      @api.multi
      def name_get(self):
          result = []
          for attendance in self:
              if not attendance.check_out:
                  result.append((self.id, _("%(empl_name)s from %(check_in)s") % {
                      'empl_name': self.employee_id.name_related,
                      'check_in': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(self.check_in))),
                  }))
              else:
                  result.append((self.id, _("%(empl_name)s from %(check_in)s to %(check_out)s") % {
                      'empl_name': self.employee_id.name_related,
                      'check_in': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(self.check_in))),
                      'check_out': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(self.check_out))),
                  }))
          return result
  
      @api.depends('check_in', 'check_out')
      def _compute_worked_hours(self):
          for attendance in self:
              if attendance.check_out:
                  delta = datetime.strptime(attendance.check_out, DEFAULT_SERVER_DATETIME_FORMAT) - datetime.strptime(
                      attendance.check_in, DEFAULT_SERVER_DATETIME_FORMAT)
                  attendance.worked_hours = delta.total_seconds() / 3600.0
  
      @api.constrains('check_in', 'check_out')
      def _check_validity_check_in_check_out(self):
          """ verifies if check_in is earlier than check_out. """
          for attendance in self:
              if attendance.check_in and attendance.check_out:
                  if attendance.check_out < attendance.check_in:
                      raise exceptions.ValidationError(_('"Check Out" time cannot be earlier than "Check In" time.'))
  
      @api.constrains('check_in', 'check_out', 'employee_id')
      def _check_validity(self):
          """ Verifies the validity of the attendance record compared to the others from the same employee.
              For the same employee we must have :
                  * maximum 1 "open" attendance record (without check_out)
                  * no overlapping time slices with previous employee records
          """
          for attendance in self:
              # we take the latest attendance before our check_in time and check it doesn't overlap with ours
              last_attendance_before_check_in = self.env['hr.attendance'].search([
                  ('employee_id', '=', attendance.employee_id.id),
                  ('check_in', '<=', attendance.check_in),
                  ('id', '!=', attendance.id),
              ], order='check_in desc', limit=1)
              if last_attendance_before_check_in and last_attendance_before_check_in.check_out and last_attendance_before_check_in.check_out >= attendance.check_in:
                  raise exceptions.ValidationError(_("Cannot create new attendance record for %(empl_name)s, the employee was already checked in on %(datetime)s") % {
                      'empl_name': attendance.employee_id.name_related,
                      'datetime': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(attendance.check_in))),
                  })
  
              if not attendance.check_out:
                  # if our attendance is "open" (no check_out), we verify there is no other "open" attendance
                  no_check_out_attendances = self.env['hr.attendance'].search([
                      ('employee_id', '=', attendance.employee_id.id),
                      ('check_out', '=', False),
                      ('id', '!=', attendance.id),
                  ])
                  if no_check_out_attendances:
                      raise exceptions.ValidationError(_("Cannot create new attendance record for %(empl_name)s, the employee hasn't checked out since %(datetime)s") % {
                          'empl_name': attendance.employee_id.name_related,
                          'datetime': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(no_check_out_attendances.check_in))),
                      })
              else:
                  # we verify that the latest attendance with check_in time before our check_out time
                  # is the same as the one before our check_in time computed before, otherwise it overlaps
                  last_attendance_before_check_out = self.env['hr.attendance'].search([
                      ('employee_id', '=', attendance.employee_id.id),
                      ('check_in', '<=', attendance.check_out),
                      ('id', '!=', attendance.id),
                  ], order='check_in desc', limit=1)
                  if last_attendance_before_check_out and last_attendance_before_check_in != last_attendance_before_check_out:
                      raise exceptions.ValidationError(_("Cannot create new attendance record for %(empl_name)s, the employee was already checked in on %(datetime)s") % {
                          'empl_name': attendance.employee_id.name_related,
                          'datetime': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(last_attendance_before_check_out.check_in))),
                      })
  
      @api.multi
      def copy(self):
          raise exceptions.UserError(_('You cannot duplicate an attendance.'))
  