Enhance departmental goal tracking by adding yearly and to-date progress calculations

This commit is contained in:
Jeppe Bundgaard
2026-02-27 00:31:24 +01:00
parent ece9f5108a
commit ea7633a908
2 changed files with 62 additions and 20 deletions
@@ -465,28 +465,53 @@ class goals_criteria implements goals_criteria_i
public function setTimeframeByName(string $timeframe): void
{
$now = new \DateTime();
$goal_start = $this->start ? clone $this->start : null;
$goal_end = $this->end ? clone $this->end : null;
$timeframe_start = null;
$timeframe_end = null;
switch ($timeframe) {
case 'today':
$this->start = (clone $now)->setTime(0, 0, 0);
$this->end = (clone $now)->setTime(23, 59, 59);
$timeframe_start = (clone $now)->setTime(0, 0, 0);
$timeframe_end = (clone $now)->setTime(23, 59, 59);
break;
case 'week':
$this->start = (clone $now)->modify('monday this week')->setTime(0, 0, 0);
$this->end = (clone $now)->setTime(23, 59, 59);
$timeframe_start = (clone $now)->modify('monday this week')->setTime(0, 0, 0);
$timeframe_end = (clone $now)->setTime(23, 59, 59);
break;
case 'month':
$this->start = (clone $now)->modify('first day of this month')->setTime(0, 0, 0);
$this->end = (clone $now)->setTime(23, 59, 59);
$timeframe_start = (clone $now)->modify('first day of this month')->setTime(0, 0, 0);
$timeframe_end = (clone $now)->setTime(23, 59, 59);
break;
case 'year':
$this->start = (clone $now)->modify('first day of January this year')->setTime(0, 0, 0);
$this->end = (clone $now)->setTime(23, 59, 59);
$timeframe_start = (clone $now)->modify('first day of January this year')->setTime(0, 0, 0);
$timeframe_end = (clone $now)->setTime(23, 59, 59);
break;
case 'to_date':
$this->start = null; // no start limit
$this->end = (clone $now)->setTime(23, 59, 59);
$timeframe_start = $goal_start ? clone $goal_start : null;
$timeframe_end = (clone $now)->setTime(23, 59, 59);
break;
default:
return;
}
if ($goal_start instanceof \DateTimeInterface) {
if (!($timeframe_start instanceof \DateTimeInterface) || $timeframe_start < $goal_start) {
$timeframe_start = clone $goal_start;
}
}
if ($goal_end instanceof \DateTimeInterface) {
if (!($timeframe_end instanceof \DateTimeInterface) || $timeframe_end > $goal_end) {
$timeframe_end = clone $goal_end;
}
}
if (($timeframe_start instanceof \DateTimeInterface) && ($timeframe_end instanceof \DateTimeInterface) && $timeframe_end < $timeframe_start) {
$timeframe_end = clone $timeframe_start;
}
$this->start = $timeframe_start;
$this->end = $timeframe_end;
}
/**
@@ -693,6 +718,8 @@ class goals_criteria implements goals_criteria_i
'today' => $dept_criteria->getProgressDetails('today'),
'week' => $dept_criteria->getProgressDetails('week'),
'month' => $dept_criteria->getProgressDetails('month'),
'year' => $dept_criteria->getProgressDetails('year'),
'to_date' => $dept_criteria->getProgressDetails('to_date'),
];
}
// reset the departments to original
@@ -719,27 +746,29 @@ class goals_criteria implements goals_criteria_i
$active_dept_ids = $this->departments->listIDs();
if ($timeframe === 'today') {
$days = $this->getTimeframeDayCount();
foreach ($active_dept_ids as $id) {
$target += (float)($this->department_daily_targets[$id] ?? 0);
$target += (float)($this->department_daily_targets[$id] ?? 0) * $days;
}
} elseif ($timeframe === 'week') {
$days = $this->getTimeframeDayCount();
foreach ($active_dept_ids as $id) {
$target += (float)($this->department_daily_targets[$id] ?? 0) * 7;
$target += (float)($this->department_daily_targets[$id] ?? 0) * $days;
}
} elseif ($timeframe === 'month') {
$days = $this->getTimeframeDayCount();
foreach ( $active_dept_ids as $id ) {
$target += (float)($this->department_daily_targets[$id] ?? 0) * 30;
$target += (float)($this->department_daily_targets[$id] ?? 0) * $days;
}
} elseif ($timeframe === 'year') {
$days = $this->getTimeframeDayCount();
foreach ( $active_dept_ids as $id ) {
$target += (float)($this->department_daily_targets[$id] ?? 0) * 365;
$target += (float)($this->department_daily_targets[$id] ?? 0) * $days;
}
} elseif ($timeframe === 'to_date') {
$now = new \DateTime();
$start_of_year = (clone $now)->setDate((int)$now->format('Y'), 1, 1)->setTime(0, 0, 0);
$days_passed = (int)$start_of_year->diff($now)->format('%a') + 1; // +1 to include today
$days = $this->getTimeframeDayCount();
foreach ($active_dept_ids as $id) {
$target += (float)($this->department_daily_targets[$id] ?? 0) * $days_passed;
$target += (float)($this->department_daily_targets[$id] ?? 0) * $days;
}
} else {
$target = (float)$this->target;
@@ -751,6 +780,17 @@ class goals_criteria implements goals_criteria_i
];
}
private function getTimeframeDayCount(): int
{
if (!($this->start instanceof \DateTimeInterface) || !($this->end instanceof \DateTimeInterface)) {
return 0;
}
if ($this->end < $this->start) {
return 0;
}
return (int)$this->start->diff($this->end)->format('%a') + 1;
}
public function withDepartmentFilter(int $department_id): goals_criteria
{
// Clone the criteria and create a fresh departments collection to avoid mutating the original
@@ -770,4 +810,4 @@ class goals_criteria implements goals_criteria_i
}
return $alert_days;
}
}
}
@@ -92,9 +92,11 @@ class department_goals_o extends db
'today' => $include_progress ? goals_criteria::calculateProgressDetailsFromArray((array)$this->criteria->value(), 'today') : null,
'week' => $include_progress ? goals_criteria::calculateProgressDetailsFromArray((array)$this->criteria->value(), 'week') : null,
'month' => $include_progress ? goals_criteria::calculateProgressDetailsFromArray((array)$this->criteria->value(), 'month') : null,
'year' => $include_progress ? goals_criteria::calculateProgressDetailsFromArray((array)$this->criteria->value(), 'year') : null,
'to_date' => $include_progress ? goals_criteria::calculateProgressDetailsFromArray((array)$this->criteria->value(), 'to_date') : null,
],
'created_at' => (string)$this->created_at->value(),
'updated_at' => (string)$this->updated_at->value(),
];
}
}
}