57 lines
3.1 KiB
Python
57 lines
3.1 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
from collections import defaultdict
|
||
|
from datetime import datetime
|
||
|
from pytz import timezone
|
||
|
|
||
|
from odoo import models
|
||
|
from odoo.addons.resource.models.utils import Intervals
|
||
|
|
||
|
class ResourceResource(models.Model):
|
||
|
_inherit = 'resource.resource'
|
||
|
|
||
|
def _get_calendars_validity_within_period(self, start, end, default_company=None):
|
||
|
assert start.tzinfo and end.tzinfo
|
||
|
if not self:
|
||
|
return super()._get_calendars_validity_within_period(start, end, default_company=default_company)
|
||
|
calendars_within_period_per_resource = defaultdict(lambda: defaultdict(Intervals)) # keys are [resource id:integer][calendar:self.env['resource.calendar']]
|
||
|
# Employees that have ever had an active contract
|
||
|
employee_ids_with_active_contracts = {
|
||
|
employee.id for [employee] in
|
||
|
self.env['hr.contract']._read_group(
|
||
|
domain=[
|
||
|
('employee_id', 'in', self.employee_id.ids),
|
||
|
'|', ('state', '=', 'open'),
|
||
|
'|', ('state', '=', 'close'),
|
||
|
'&', ('state', '=', 'draft'), ('kanban_state', '=', 'done')
|
||
|
],
|
||
|
groupby=['employee_id'],
|
||
|
)
|
||
|
}
|
||
|
resource_without_contract = self.filtered(
|
||
|
lambda r: not r.employee_id\
|
||
|
or not r.employee_id.id in employee_ids_with_active_contracts\
|
||
|
or r.employee_id.employee_type not in ['employee', 'student']
|
||
|
)
|
||
|
if resource_without_contract:
|
||
|
calendars_within_period_per_resource.update(
|
||
|
super(ResourceResource, resource_without_contract)._get_calendars_validity_within_period(start, end, default_company=default_company)
|
||
|
)
|
||
|
resource_with_contract = self - resource_without_contract
|
||
|
if not resource_with_contract:
|
||
|
return calendars_within_period_per_resource
|
||
|
timezones = {resource.tz for resource in resource_with_contract}
|
||
|
date_start = min(start.astimezone(timezone(tz)).date() for tz in timezones)
|
||
|
date_end = max(end.astimezone(timezone(tz)).date() for tz in timezones)
|
||
|
contracts = resource_with_contract.employee_id._get_contracts(
|
||
|
date_start, date_end, states=['open', 'draft', 'close']
|
||
|
).filtered(lambda c: c.state in ['open', 'close'] or c.kanban_state == 'done')
|
||
|
for contract in contracts:
|
||
|
tz = timezone(contract.employee_id.tz)
|
||
|
calendars_within_period_per_resource[contract.employee_id.resource_id.id][contract.resource_calendar_id] |= Intervals([(
|
||
|
tz.localize(datetime.combine(contract.date_start, datetime.min.time())) if contract.date_start > start.astimezone(tz).date() else start,
|
||
|
tz.localize(datetime.combine(contract.date_end, datetime.max.time())) if contract.date_end and contract.date_end < end.astimezone(tz).date() else end,
|
||
|
self.env['resource.calendar.attendance']
|
||
|
)])
|
||
|
return calendars_within_period_per_resource
|