This commit adds methods to easily obtain calendar validity per resource for a given search period and get the work intervals per resource, taking into account the validity of their calendars. In hr, the create and departure date of an employee are taken into account to compute the calendars validity. In hr_contract, it looks for every contract of human resources with employee of type student or employee existing in the search period and consider the specific calendar of the contract as valid during the contract-lifetime. PR: #77362 task-2646630
40 lines
2.4 KiB
Python
40 lines
2.4 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.resource 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']]
|
|
resource_without_contract = self.filtered(lambda r: not r.employee_id 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
|