|
|
@@ -0,0 +1,67 @@
|
|
|
+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)
|
|
|
+ last_day = calendar.monthrange(start_datetime.year, start_datetime.month)[1]
|
|
|
+ last_day_of_month = datetime(start_datetime.year, start_datetime.month, last_day)
|
|
|
+
|
|
|
+ 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)
|
|
|
+ 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']
|