hr_holidays.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo import api, fields, models, _
  4. from odoo.exceptions import ValidationError
  5. class HolidaysType(models.Model):
  6. _inherit = "hr.leave.type"
  7. def _default_project_id(self):
  8. company = self.company_id if self.company_id else self.env.company
  9. return company.internal_project_id.id
  10. def _default_task_id(self):
  11. company = self.company_id if self.company_id else self.env.company
  12. return company.leave_timesheet_task_id.id
  13. timesheet_generate = fields.Boolean(
  14. 'Generate Timesheet', compute='_compute_timesheet_generate', store=True, readonly=False,
  15. help="If checked, when validating a time off, timesheet will be generated in the Vacation Project of the company.")
  16. timesheet_project_id = fields.Many2one('project.project', string="Project", default=_default_project_id, domain="[('company_id', '=', company_id)]")
  17. timesheet_task_id = fields.Many2one(
  18. 'project.task', string="Task", compute='_compute_timesheet_task_id',
  19. store=True, readonly=False, default=_default_task_id,
  20. domain="[('project_id', '=', timesheet_project_id),"
  21. "('project_id', '!=', False),"
  22. "('company_id', '=', company_id)]")
  23. @api.depends('timesheet_task_id', 'timesheet_project_id')
  24. def _compute_timesheet_generate(self):
  25. for leave_type in self:
  26. leave_type.timesheet_generate = leave_type.timesheet_task_id and leave_type.timesheet_project_id
  27. @api.depends('timesheet_project_id')
  28. def _compute_timesheet_task_id(self):
  29. for leave_type in self:
  30. company = leave_type.company_id if leave_type.company_id else self.env.company
  31. default_task_id = company.leave_timesheet_task_id
  32. if default_task_id and default_task_id.project_id == leave_type.timesheet_project_id:
  33. leave_type.timesheet_task_id = default_task_id
  34. else:
  35. leave_type.timesheet_task_id = False
  36. @api.constrains('timesheet_generate', 'timesheet_project_id', 'timesheet_task_id')
  37. def _check_timesheet_generate(self):
  38. for holiday_status in self:
  39. if holiday_status.timesheet_generate:
  40. if not holiday_status.timesheet_project_id or not holiday_status.timesheet_task_id:
  41. raise ValidationError(_("Both the internal project and task are required to "
  42. "generate a timesheet for the time off %s. If you don't want a timesheet, you should "
  43. "leave the internal project and task empty.") % (holiday_status.name))
  44. class Holidays(models.Model):
  45. _inherit = "hr.leave"
  46. timesheet_ids = fields.One2many('account.analytic.line', 'holiday_id', string="Analytic Lines")
  47. def _validate_leave_request(self):
  48. """ Timesheet will be generated on leave validation only if a timesheet_project_id and a
  49. timesheet_task_id are set on the corresponding leave type. The generated timesheet will
  50. be attached to this project/task.
  51. """
  52. holidays = self.filtered(
  53. lambda l: l.holiday_type == 'employee' and
  54. l.holiday_status_id.timesheet_project_id and
  55. l.holiday_status_id.timesheet_task_id and
  56. l.holiday_status_id.timesheet_project_id.sudo().company_id == (l.holiday_status_id.company_id or self.env.company))
  57. # Unlink previous timesheets do avoid doublon (shouldn't happen on the interface but meh)
  58. old_timesheets = holidays.sudo().timesheet_ids
  59. if old_timesheets:
  60. old_timesheets.holiday_id = False
  61. old_timesheets.unlink()
  62. # create the timesheet on the vacation project
  63. holidays._timesheet_create_lines()
  64. return super()._validate_leave_request()
  65. def _timesheet_create_lines(self):
  66. vals_list = []
  67. for leave in self:
  68. if not leave.employee_id:
  69. continue
  70. work_hours_data = leave.employee_id.list_work_time_per_day(
  71. leave.date_from,
  72. leave.date_to)
  73. for index, (day_date, work_hours_count) in enumerate(work_hours_data):
  74. vals_list.append(leave._timesheet_prepare_line_values(index, work_hours_data, day_date, work_hours_count))
  75. return self.env['account.analytic.line'].sudo().create(vals_list)
  76. def _timesheet_prepare_line_values(self, index, work_hours_data, day_date, work_hours_count):
  77. self.ensure_one()
  78. return {
  79. 'name': _("Time Off (%s/%s)", index + 1, len(work_hours_data)),
  80. 'project_id': self.holiday_status_id.timesheet_project_id.id,
  81. 'task_id': self.holiday_status_id.timesheet_task_id.id,
  82. 'account_id': self.holiday_status_id.timesheet_project_id.analytic_account_id.id,
  83. 'unit_amount': work_hours_count,
  84. 'user_id': self.employee_id.user_id.id,
  85. 'date': day_date,
  86. 'holiday_id': self.id,
  87. 'employee_id': self.employee_id.id,
  88. 'company_id': self.holiday_status_id.timesheet_task_id.company_id.id or self.holiday_status_id.timesheet_project_id.company_id.id,
  89. }
  90. def action_refuse(self):
  91. """ Remove the timesheets linked to the refused holidays """
  92. result = super(Holidays, self).action_refuse()
  93. timesheets = self.sudo().mapped('timesheet_ids')
  94. timesheets.write({'holiday_id': False})
  95. timesheets.unlink()
  96. return result
  97. def _action_user_cancel(self, reason):
  98. res = super()._action_user_cancel(reason)
  99. timesheets = self.sudo().timesheet_ids
  100. timesheets.write({'holiday_id': False})
  101. timesheets.unlink()
  102. return res