160 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
| # Copyright 2017-2018 Tecnativa - Pedro M. Baeza
 | |
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
 | |
| 
 | |
| from odoo import api, fields, models
 | |
| from datetime import time
 | |
| from dateutil import tz
 | |
| 
 | |
| 
 | |
| class HrHolidays(models.Model):
 | |
|     _inherit = 'hr.holidays'
 | |
| 
 | |
|     def _default_from_full_day(self):
 | |
|         """Detect if we have select full day in calendar and return the
 | |
|         full day option accordingly.
 | |
|         """
 | |
|         context = self.env.context
 | |
|         if context.get('default_date_from'):
 | |
|             dt = fields.Datetime.from_string(
 | |
|                 context['default_date_from']
 | |
|             ).replace(tzinfo=tz.gettz(self.env.user.tz)).astimezone(tz.tzutc())
 | |
|             return dt.hour == 5 and dt.minute == 0 and dt.second == 0
 | |
|         return False
 | |
| 
 | |
|     def _default_to_full_day(self):
 | |
|         """Detect if we have select full day in calendar and return the
 | |
|         full day option accordingly.
 | |
|         """
 | |
|         context = self.env.context
 | |
|         if context.get('default_date_to'):
 | |
|             dt = fields.Datetime.from_string(
 | |
|                 context['default_date_to']
 | |
|             ).replace(tzinfo=tz.gettz(self.env.user.tz)).astimezone(tz.tzutc())
 | |
|             return dt.hour == 17 and dt.minute == 0 and dt.second == 0
 | |
|         return False
 | |
| 
 | |
|     from_full_day = fields.Boolean(
 | |
|         default=lambda self: self._default_from_full_day(),
 | |
|         readonly=True,
 | |
|         copy=False,
 | |
|         states={
 | |
|             'draft': [('readonly', False)],
 | |
|             'confirm': [('readonly', False)]
 | |
|         },
 | |
|     )
 | |
|     to_full_day = fields.Boolean(
 | |
|         default=lambda self: self._default_to_full_day(),
 | |
|         readonly=True,
 | |
|         copy=False,
 | |
|         states={
 | |
|             'draft': [('readonly', False)],
 | |
|             'confirm': [('readonly', False)]
 | |
|         },
 | |
|     )
 | |
|     date_from_full = fields.Date(
 | |
|         compute="_compute_date_from_full",
 | |
|         inverse="_inverse_date_from_full",
 | |
|         readonly=True,
 | |
|         states={
 | |
|             'draft': [('readonly', False)],
 | |
|             'confirm': [('readonly', False)]
 | |
|         },
 | |
|     )
 | |
|     date_to_full = fields.Date(
 | |
|         compute="_compute_date_to_full",
 | |
|         inverse="_inverse_date_to_full",
 | |
|         readonly=True,
 | |
|         states={
 | |
|             'draft': [('readonly', False)],
 | |
|             'confirm': [('readonly', False)]
 | |
|         },
 | |
|     )
 | |
|     # Supporting field for avoiding limitation on storing readonly fields
 | |
|     number_of_days_temp_related = fields.Float(
 | |
|         related="number_of_days_temp", readonly=True,
 | |
|     )
 | |
| 
 | |
|     @api.depends('date_from')
 | |
|     def _compute_date_from_full(self):
 | |
|         """Put day in employee's user timezone, or user timezone as fallback"""
 | |
|         for record in self.filtered('date_from'):
 | |
|             tz_name = record.employee_id.user_id.tz or record.env.user.tz
 | |
|             dt = fields.Datetime.from_string(record.date_from).replace(
 | |
|                 tzinfo=tz.tzutc(),
 | |
|             ).astimezone(tz.gettz(tz_name)).date()
 | |
|             record.date_from_full = fields.Date.to_string(dt)
 | |
| 
 | |
|     @api.depends('date_to')
 | |
|     def _compute_date_to_full(self):
 | |
|         """Put day in employee's user timezone, or user timezone as fallback"""
 | |
|         for record in self.filtered('date_to'):
 | |
|             tz_name = record.employee_id.user_id.tz or record.env.user.tz
 | |
|             dt = fields.Datetime.from_string(record.date_to).replace(
 | |
|                 tzinfo=tz.tzutc(),
 | |
|             ).astimezone(tz.gettz(tz_name)).date()
 | |
|             record.date_to_full = fields.Date.to_string(dt)
 | |
| 
 | |
|     def _inverse_date_from_full(self):
 | |
|         """Put start of the day in employee's user timezone, or user timezone
 | |
|         as fallback.
 | |
|         """
 | |
|         for record in self.filtered('from_full_day'):
 | |
|             tz_name = record.employee_id.user_id.tz or record.env.user.tz
 | |
|             dt = fields.Datetime.from_string(record.date_from_full).replace(
 | |
|                 hour=0, minute=0, second=0, microsecond=0,
 | |
|                 tzinfo=tz.gettz(tz_name),
 | |
|             ).astimezone(tz.tzutc())
 | |
|             record.date_from = fields.Datetime.to_string(dt)
 | |
| 
 | |
|     def _inverse_date_to_full(self):
 | |
|         """Put end of the day in employee's user timezone, or user timezone
 | |
|         as fallback.
 | |
|         """
 | |
|         for record in self.filtered('to_full_day'):
 | |
|             tz_name = record.employee_id.user_id.tz or record.env.user.tz
 | |
|             dt = fields.Datetime.from_string(record.date_to_full).replace(
 | |
|                 hour=23, minute=59, second=59, microsecond=999999,
 | |
|                 tzinfo=tz.gettz(tz_name),
 | |
|             ).astimezone(tz.tzutc())
 | |
|             record.date_to = fields.Datetime.to_string(dt)
 | |
| 
 | |
|     @api.onchange('date_from_full', 'from_full_day')
 | |
|     def _onchange_date_from_full(self):
 | |
|         """As inverse methods only works on save, we have to add an onchange"""
 | |
|         self._inverse_date_from_full()
 | |
| 
 | |
|     @api.onchange('date_to_full', 'to_full_day')
 | |
|     def _onchange_date_to_full(self):
 | |
|         """As inverse methods only works on save, we have to add an onchange"""
 | |
|         self._inverse_date_to_full()
 | |
| 
 | |
|     def _onchange_data_hr_holidays_compute_days(self):
 | |
|         """Trigger the number of days computation also when you change the
 | |
|         employee or the leave type.
 | |
|         """
 | |
|         self._onchange_date_to()
 | |
| 
 | |
|     def _get_number_of_days(self, date_from, date_to, employee_id):
 | |
|         """Pass context variable for including rest days or change passed dates
 | |
|         when computing full days.
 | |
|         """
 | |
|         obj = self.with_context(
 | |
|             include_rest_days=not self.holiday_status_id.exclude_rest_days,
 | |
|         )
 | |
|         if self.holiday_status_id.compute_full_days:
 | |
|             dt_from = fields.Datetime.from_string(date_from)
 | |
|             date_from = fields.Datetime.to_string(
 | |
|                 dt_from.combine(
 | |
|                     dt_from.date(), time(hour=0, minute=0, second=0),
 | |
|                 ),
 | |
|             )
 | |
|             dt_to = fields.Datetime.from_string(date_to)
 | |
|             date_to = fields.Datetime.to_string(
 | |
|                 dt_to.combine(
 | |
|                     dt_to.date(), time(hour=23, minute=59, second=59),
 | |
|                 ),
 | |
|             )
 | |
|         return super(HrHolidays, obj)._get_number_of_days(
 | |
|             date_from, date_to, employee_id,
 | |
|         )
 |