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_working_days_count', store=True, help='Number of working days available in the month, regardless of slot start and end dates' ) @api.depends('start_datetime', 'end_datetime', 'resource_id', 'company_id') def _compute_working_days_count(self): for slot in self: if not slot.start_datetime: slot.real_working_days_count = 0 continue # Obtener el primer día del mes start_of_month = slot.start_datetime.replace(day=1, hour=0, minute=0, second=0) # Obtener el último día del mes end_of_month = (start_of_month + relativedelta(months=1, days=-1)).replace(hour=23, minute=59, second=59) # Obtener el calendario de trabajo calendar = slot.resource_id.calendar_id or slot.company_id.resource_calendar_id if not calendar: slot.real_working_days_count = 0 continue # Calcular los días laborables del mes completo real_working_days = calendar.get_work_duration_data( timezone_datetime(start_of_month), timezone_datetime(end_of_month), compute_leaves=True ) # El resultado viene en horas, lo convertimos a días slot.real_working_days_count = real_working_days['hours'] / calendar.hours_per_day