import calendar from collections import defaultdict from datetime import date, datetime, timedelta, time from dateutil.relativedelta import relativedelta import logging import pytz import uuid from math import modf from random import randint from odoo import api, fields, models, _ from odoo.addons.resource.models.resource import Intervals, sum_intervals, string_to_datetime from odoo.addons.resource.models.resource_mixin import timezone_datetime from odoo.exceptions import UserError, AccessError from odoo.osv import expression from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_utils, format_datetime _logger = logging.getLogger(__name__) class PlanningSlot(models.Model): _inherit = 'planning.slot' real_working_days_count = fields.Float( string='Real Working Days', compute='_compute_real_working_days_count', store=True, ) @api.depends('start_datetime', 'end_datetime', 'resource_id') def _compute_real_working_days_count(self): slots_per_calendar = defaultdict(set) planned_dates_per_calendar_id = defaultdict(lambda: (datetime.max, datetime.min)) for slot in self: if not slot.employee_id: slot.real_working_days_count = 0 continue slots_per_calendar[slot.resource_id.calendar_id].add(slot.id) datetime_begin, datetime_end = planned_dates_per_calendar_id[slot.resource_id.calendar_id.id] start_datetime = slot.start_datetime first_day_of_month = datetime(start_datetime.year, start_datetime.month, 1, 0, 0, 0) last_day = calendar.monthrange(start_datetime.year, start_datetime.month)[1] last_day_of_month = datetime(start_datetime.year, start_datetime.month, last_day, 23, 59, 59) datetime_begin = min(datetime_begin, first_day_of_month) datetime_end = max(datetime_end, last_day_of_month) planned_dates_per_calendar_id[slot.resource_id.calendar_id.id] = datetime_begin, datetime_end for calendar_slot, slot_ids in slots_per_calendar.items(): slots = self.env['planning.slot'].browse(list(slot_ids)) if not calendar_slot: slots.real_working_days_count = 0 continue datetime_begin, datetime_end = planned_dates_per_calendar_id[calendar_slot.id] datetime_begin = timezone_datetime(datetime_begin) datetime_end = timezone_datetime(datetime_end) resources = slots.resource_id day_total = calendar_slot._get_resources_day_total(datetime_begin, datetime_end, resources) _logger.info('DAY TOTAL %s', day_total) intervals = calendar_slot._work_intervals_batch(datetime_begin, datetime_end, resources) for slot in slots: slot.real_working_days_count = calendar_slot._get_days_data( intervals[slot.resource_id.id] & Intervals([( timezone_datetime(first_day_of_month), timezone_datetime(last_day_of_month), self.env['resource.calendar.attendance'] )]), day_total[slot.resource_id.id] )['days']