# -*- 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