Pārlūkot izejas kodu

fix: Corregir cálculo de horas planificadas para slots que cruzan meses - Usar lógica de Odoo Planning nativo para calcular solo horas del período específico - Evitar contar horas completas de slots que cruzan meses

root 5 mēneši atpakaļ
vecāks
revīzija
dd7723ec1b
1 mainītis faili ar 27 papildinājumiem un 22 dzēšanām
  1. 27 22
      hr_efficiency/models/hr_efficiency.py

+ 27 - 22
hr_efficiency/models/hr_efficiency.py

@@ -400,12 +400,15 @@ class HrEfficiency(models.Model):
         """
         Calculate planned hours from planning module
         """
-        # Get planning slots for the employee in the date range
-        # Use flexible date range to capture slots that cross month boundaries
+        # Get planning slots for the employee that overlap with the date range
+        # This is the same logic as Odoo Planning's Gantt chart
+        start_datetime = datetime.combine(start_date, datetime.min.time())
+        end_datetime = datetime.combine(end_date, datetime.max.time())
+        
         planning_slots = self.env['planning.slot'].search([
             ('employee_id', '=', employee.id),
-            ('start_datetime', '<', datetime.combine(end_date + relativedelta(days=1), datetime.min.time())),
-            ('end_datetime', '>', datetime.combine(start_date - relativedelta(days=1), datetime.max.time())),
+            ('start_datetime', '<=', end_datetime),
+            ('end_datetime', '>=', start_datetime),
             # Removed state restriction to include all planning slots regardless of state
         ])
         
@@ -413,25 +416,27 @@ class HrEfficiency(models.Model):
         total_billable = 0.0
         total_non_billable = 0.0
         
+        # Get working intervals for the resource and company calendar
+        # This is the same approach as Odoo Planning's Gantt chart
+        start_utc = pytz.utc.localize(start_datetime)
+        end_utc = pytz.utc.localize(end_datetime)
+        
+        if employee.resource_id:
+            resource_work_intervals, calendar_work_intervals = employee.resource_id._get_valid_work_intervals(
+                start_utc, end_utc, calendars=employee.company_id.resource_calendar_id
+            )
+        else:
+            # Fallback to company calendar if no resource
+            calendar_work_intervals = {employee.company_id.resource_calendar_id.id: []}
+            resource_work_intervals = {}
+        
         for slot in planning_slots:
-            # Use the same logic as Odoo Planning to calculate allocated hours
-            if slot.start_datetime and slot.end_datetime and slot.resource_id:
-                # Calculate the intersection between slot and working intervals
-                start_utc = pytz.utc.localize(slot.start_datetime)
-                end_utc = pytz.utc.localize(slot.end_datetime)
-                
-                # Get working intervals for the resource
-                resource_work_intervals, calendar_work_intervals = slot.resource_id._get_valid_work_intervals(
-                    start_utc, end_utc, calendars=slot.company_id.resource_calendar_id
-                )
-                
-                # Calculate duration over working periods
-                hours = slot._get_duration_over_period(
-                    start_utc, end_utc,
-                    resource_work_intervals, calendar_work_intervals, has_allocated_hours=False
-                )
-            else:
-                hours = slot.allocated_hours or 0.0
+            # Use the same logic as Odoo Planning's Gantt chart
+            # Calculate duration only within the specified period
+            hours = slot._get_duration_over_period(
+                start_utc, end_utc,
+                resource_work_intervals, calendar_work_intervals, has_allocated_hours=False
+            )
             
             # Check if the slot is linked to a billable project
             if slot.project_id and slot.project_id.allow_billable: