From 16bcc3a00c7004caef86ebc968d78a934fcda96a Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Mon, 9 Mar 2026 09:58:48 +0100 Subject: [PATCH] Add custom monthly target calculation in `goals_progress_alert_renderer` for specific periods. --- .../goals_progress_alert_renderer.php | 64 ++++++++++++++----- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/services/nginx/app/modules/goals/services/goals_progress_alert_renderer.php b/services/nginx/app/modules/goals/services/goals_progress_alert_renderer.php index 5c131b12..9b7c224b 100644 --- a/services/nginx/app/modules/goals/services/goals_progress_alert_renderer.php +++ b/services/nginx/app/modules/goals/services/goals_progress_alert_renderer.php @@ -219,6 +219,7 @@ class goals_progress_alert_renderer ]; foreach ($periods as $idx => $period) { + $isMonthPeriod = ($idx === 2); $label = (string)$period['label']; [$ps, $pe] = $period['range']; $range = self::clampToCriteriaWindow($criteria, $ps, $pe); @@ -246,13 +247,17 @@ class goals_progress_alert_renderer $total_period_count += $count; if ($includeTargets && isset($criteria->target)) { - // Set the target to (operating days in period) * (daily target) - $target = self::getTargetForDepartmentInTimeframe( - $criteria, - $rs, - $re, - (int)$deptId - ); + if ($isMonthPeriod) { + $target = self::getMonthlyTargetForDepartment($criteria, (int)$deptId, $departments); + } else { + // Set the target to (operating days in period) * (daily target) + $target = self::getTargetForDepartmentInTimeframe( + $criteria, + $rs, + $re, + (int)$deptId + ); + } $percent = $target > 0 ? round(($count / max(1, $target)) * 100, 2) : 0.0; // If the $department is set and matches the current department, make the related line stand out (*text here*) $line = $deptData['highlight'] @@ -269,14 +274,18 @@ class goals_progress_alert_renderer // Total line for the period if ($includeTargets && isset($criteria->target)) { // Sum per-department targets to account for overrides - $total_target = 0; - foreach ($departments as $deptData) { - $total_target += self::getTargetForDepartmentInTimeframe( - $criteria, - $rs, - $re, - (int)$deptData['id'] - ); + if ($isMonthPeriod) { + $total_target = max(0, (int)round((float)($criteria->target ?? 0))); + } else { + $total_target = 0; + foreach ($departments as $deptData) { + $total_target += self::getTargetForDepartmentInTimeframe( + $criteria, + $rs, + $re, + (int)$deptData['id'] + ); + } } $total_percent = $total_target > 0 ? round(($total_period_count / max(1, $total_target)) * 100, 2) : 0.0; $outLines[] = sprintf($label . ': %d ud af %d (%.2f%%)', @@ -382,6 +391,31 @@ class goals_progress_alert_renderer return (int)round($dailyTarget * $operatingDays); } + private static function getMonthlyTargetForDepartment(goals_criteria $criteria, int $departmentId, array $departments): int + { + $totalMonthlyTarget = max(0, (int)round((float)($criteria->target ?? 0))); + if ($totalMonthlyTarget <= 0) { + return 0; + } + + $deptIds = array_map(fn($deptData) => (int)$deptData['id'], $departments); + sort($deptIds); + $countDepts = max(1, count($deptIds)); + + if ($countDepts === 1) { + return $totalMonthlyTarget; + } + + $base = intdiv($totalMonthlyTarget, $countDepts); + $remainder = $totalMonthlyTarget % $countDepts; + $index = array_search($departmentId, $deptIds, true); + if ($index === false) { + return $base; + } + + return $base + ($index < $remainder ? 1 : 0); + } + private static function getDailyTargetForDepartment(goals_criteria $criteria, ?int $departmentId): float { // If explicit per-department daily targets are provided, honor them