forked from Mapan/odoo17e
91 lines
5.0 KiB
Python
91 lines
5.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
from odoo import api, fields, models
|
|
from odoo.addons.appointment.utils import interval_from_events, intervals_overlap
|
|
from odoo.addons.resource.models.utils import Intervals, timezone_datetime
|
|
|
|
|
|
class CalendarEvent(models.Model):
|
|
_inherit = "calendar.event"
|
|
|
|
partners_on_leave = fields.Many2many('res.partner', string='Unavailable Partners', compute='_compute_partners_on_leave')
|
|
|
|
@api.depends('start', 'stop', 'partner_ids')
|
|
def _compute_partners_on_leave(self):
|
|
self.partners_on_leave = False
|
|
user_events = self.filtered(lambda event: event.appointment_type_id.schedule_based_on == 'users')
|
|
if not user_events:
|
|
return
|
|
|
|
calendar_ids = user_events.partner_ids.user_ids.employee_ids.resource_calendar_id
|
|
calendar_to_employees = user_events.partner_ids.user_ids.employee_ids.grouped('resource_calendar_id')
|
|
|
|
for start, stop, events in interval_from_events(user_events):
|
|
group_calendars = calendar_ids.filtered(lambda calendar: calendar in events.partner_ids.user_ids.employee_ids.resource_calendar_id)
|
|
calendar_to_unavailabilities = {
|
|
calendar: calendar._unavailable_intervals_batch(
|
|
timezone_datetime(start), timezone_datetime(stop), calendar_to_employees[calendar].resource_id
|
|
) for calendar in group_calendars
|
|
}
|
|
|
|
events_by_partner_id = events.partner_ids._get_calendar_events(start, stop)
|
|
|
|
for event in events:
|
|
partner_employees = event.partner_ids.user_ids.employee_ids
|
|
event_partners_on_leave = self.env['res.partner']
|
|
for employee in partner_employees:
|
|
if not employee.resource_calendar_id or not employee.resource_id:
|
|
continue
|
|
unavailabilities = calendar_to_unavailabilities.get(employee.resource_calendar_id, {}).get(employee.resource_id.id, [])
|
|
if any(intervals_overlap(unavailability, (event.start, event.stop)) for unavailability in unavailabilities):
|
|
event_partners_on_leave += employee.user_partner_id
|
|
# TODO RETH on master move this field to base appointment as it's relevant there too
|
|
for partner in event.partner_ids:
|
|
if any(intervals_overlap((event.start, event.stop), (other_event.start, other_event.stop))
|
|
for other_event in events_by_partner_id.get(partner.id, []) if other_event != event):
|
|
event_partners_on_leave += partner
|
|
event.partners_on_leave = event_partners_on_leave
|
|
|
|
@api.model
|
|
def gantt_unavailability(self, start_date, end_date, scale, group_bys=None, rows=None):
|
|
# skip if not dealing with appointments
|
|
rows = super().gantt_unavailability(start_date, end_date, scale, group_bys=group_bys, rows=rows)
|
|
partner_ids = [row['resId'] for row in rows if row.get('resId')] # remove empty rows
|
|
if not group_bys or group_bys[0] != 'partner_ids' or not partner_ids:
|
|
return rows
|
|
|
|
start_datetime = timezone_datetime(fields.Datetime.from_string(start_date))
|
|
end_datetime = timezone_datetime(fields.Datetime.from_string(end_date))
|
|
|
|
partners = self.env['res.partner'].browse(partner_ids)
|
|
users = partners.user_ids
|
|
users_from_partner_id = users.grouped(lambda user: user.partner_id.id)
|
|
|
|
calendars = users.employee_id.resource_calendar_id
|
|
employee_by_calendar = users.employee_id.grouped('resource_calendar_id')
|
|
unavailabilities_by_calendar = {
|
|
calendar: calendar._unavailable_intervals_batch(
|
|
start_datetime, end_datetime,
|
|
resources=employee_by_calendar[calendar].resource_id
|
|
) for calendar in calendars
|
|
}
|
|
|
|
event_unavailabilities = self._gantt_unavailabilities_events(start_datetime, end_datetime, partners)
|
|
for row in rows:
|
|
attendee_users = users_from_partner_id.get(row['resId'], self.env['res.users'])
|
|
attendee = partners.filtered(lambda partner: partner.id == row['resId'])
|
|
|
|
# calendar leaves
|
|
unavailabilities = Intervals([
|
|
(unavailability['start'], unavailability['stop'], self.env['res.partner'])
|
|
for unavailability in row.get('unavailabilities', [])
|
|
])
|
|
unavailabilities |= event_unavailabilities.get(attendee.id, Intervals([]))
|
|
for user in attendee_users.filtered('employee_resource_calendar_id'):
|
|
calendar_leaves = unavailabilities_by_calendar[user.employee_resource_calendar_id]
|
|
unavailabilities |= Intervals([
|
|
(start, end, attendee)
|
|
for start, end in calendar_leaves.get(user.employee_id.resource_id.id, [])])
|
|
row['unavailabilities'] = [{'start': start, 'stop': stop} for start, stop, _ in unavailabilities]
|
|
return rows
|