This traceback arises when the user tries to remove the start date Steps to produce 1. Install 'resource' 2. Open 'Settings/Technical/resource/Resource Time Off' 3. Create a new record and remove start date AttributeError 'bool' object has no attribute 'tzinfo' when the user tries to remove the start date, an error will be produced because _compute_date_to seems to be computing the date_to based on the date_from field. when removing the date_from from calculations on empty or none which leads to traceback from here https://github.com/odoo/odoo/blob/322e7ea19b7c069fdb92d3b86e5615c55489ca21/addons/resource/models/resource_calendar_leaves.py#L54-L59 This commit solves the above issue by computing `date_to` for records that have `date_from`. Apart from that, this commit also removes `# -*- coding: utf-8 -*-` from the first line of the modified file. sentry-4983497879 closes odoo/odoo#163311 X-original-commit: 5032a8ffed10bfbd619c85a266092f129716ceca Signed-off-by: Bertrand Dossogne (bedo) <bedo@odoo.com>
80 lines
4.0 KiB
Python
80 lines
4.0 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import datetime, time
|
|
from dateutil.relativedelta import relativedelta
|
|
from pytz import timezone, utc
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class ResourceCalendarLeaves(models.Model):
|
|
_name = "resource.calendar.leaves"
|
|
_description = "Resource Time Off Detail"
|
|
_order = "date_from"
|
|
|
|
def default_get(self, fields_list):
|
|
res = super().default_get(fields_list)
|
|
if 'date_from' in fields_list and 'date_to' in fields_list and not res.get('date_from') and not res.get('date_to'):
|
|
# Then we give the current day and we search the begin and end hours for this day in resource.calendar of the current company
|
|
today = fields.Datetime.now()
|
|
user_tz = timezone(self.env.user.tz or self._context.get('tz') or self.company_id.resource_calendar_id.tz or 'UTC')
|
|
date_from = user_tz.localize(datetime.combine(today, time.min))
|
|
date_to = user_tz.localize(datetime.combine(today, time.max))
|
|
intervals = self.env.company.resource_calendar_id._work_intervals_batch(date_from.replace(tzinfo=utc), date_to.replace(tzinfo=utc))[False]
|
|
if intervals: # Then we stop and return the dates given in parameter
|
|
list_intervals = [(start, stop) for start, stop, records in intervals] # Convert intervals in interval list
|
|
date_from = list_intervals[0][0] # We take the first date in the interval list
|
|
date_to = list_intervals[-1][1] # We take the last date in the interval list
|
|
res.update(
|
|
date_from=date_from.astimezone(utc).replace(tzinfo=None),
|
|
date_to=date_to.astimezone(utc).replace(tzinfo=None)
|
|
)
|
|
return res
|
|
|
|
name = fields.Char('Reason')
|
|
company_id = fields.Many2one(
|
|
'res.company', string="Company", readonly=True, store=True,
|
|
default=lambda self: self.env.company, compute='_compute_company_id')
|
|
calendar_id = fields.Many2one('resource.calendar', 'Working Hours', domain="[('company_id', 'in', [company_id, False])]", check_company=True, index=True)
|
|
date_from = fields.Datetime('Start Date', required=True)
|
|
date_to = fields.Datetime('End Date', compute="_compute_date_to", readonly=False, required=True, store=True)
|
|
resource_id = fields.Many2one(
|
|
"resource.resource", 'Resource', index=True,
|
|
help="If empty, this is a generic time off for the company. If a resource is set, the time off is only for this resource")
|
|
time_type = fields.Selection([('leave', 'Time Off'), ('other', 'Other')], default='leave',
|
|
help="Whether this should be computed as a time off or as work time (eg: formation)")
|
|
|
|
@api.depends('calendar_id')
|
|
def _compute_company_id(self):
|
|
for leave in self:
|
|
leave.company_id = leave.calendar_id.company_id or self.env.company
|
|
|
|
@api.depends('date_from')
|
|
def _compute_date_to(self):
|
|
user_tz = timezone(self.env.user.tz or self._context.get('tz') or self.company_id.resource_calendar_id.tz or 'UTC')
|
|
for leave in self:
|
|
if not leave.date_from:
|
|
continue
|
|
date_to_tz = user_tz.localize(leave.date_from) + relativedelta(hour=23, minute=59, second=59)
|
|
leave.date_to = date_to_tz.astimezone(utc).replace(tzinfo=None)
|
|
|
|
@api.constrains('date_from', 'date_to')
|
|
def check_dates(self):
|
|
if self.filtered(lambda leave: leave.date_from > leave.date_to):
|
|
raise ValidationError(_('The start date of the time off must be earlier than the end date.'))
|
|
|
|
@api.onchange('resource_id')
|
|
def onchange_resource(self):
|
|
if self.resource_id:
|
|
self.calendar_id = self.resource_id.calendar_id
|
|
|
|
def _copy_leave_vals(self):
|
|
self.ensure_one()
|
|
return {
|
|
'name': self.name,
|
|
'date_from': self.date_from,
|
|
'date_to': self.date_to,
|
|
'time_type': self.time_type,
|
|
}
|