Add time-based progress tracking and department-specific target calculations

- Added support for `today`, `week`, and `month` progress tracking in `GoalsCriteria`.
- Introduced `setTimeframeByName` method to manage time-based progress criteria.
- Enhanced `calculateProgressFromArray` and `calculateProgressDetailsFromArray` to include customizable timeframes.
- Updated departmental progress calculations with detailed breakdowns for multiple time periods.
- Replaced obsolete single-value progress tracking with comprehensive progress details.
This commit is contained in:
Jeppe Bundgaard
2026-02-25 14:30:03 +01:00
parent 90959c6b41
commit 49f07c40c8
2 changed files with 73 additions and 6 deletions
@@ -379,9 +379,12 @@ class goals_criteria implements goals_criteria_i
/**
* @throws \Exception
*/
public static function calculateProgressFromArray(array $criteria_array): float
public static function calculateProgressFromArray(array $criteria_array, ?string $timeframe = null): float
{
$criteria = self::fromJson(json_encode($criteria_array));
if ($timeframe) {
$criteria->setTimeframeByName($timeframe);
}
return $criteria->getProgress();
}
@@ -459,6 +462,25 @@ class goals_criteria implements goals_criteria_i
};
}
public function setTimeframeByName(string $timeframe): void
{
$now = new \DateTime();
switch ($timeframe) {
case 'today':
$this->start = (clone $now)->setTime(0, 0, 0);
$this->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);
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);
break;
}
}
/**
* Calculate revenue within the criteria filters.
* Revenue is computed as sum(price * quantity) for matching order items.
@@ -658,13 +680,58 @@ class goals_criteria implements goals_criteria_i
foreach ($department_ids as $dept_id) {
$dept_criteria = clone $this;
$dept_criteria->departments->set([(new \objects\departments_o())->select($dept_id)]);
$results[$dept_id] = $dept_criteria->getProgress();
$results[$dept_id] = [
'all' => $dept_criteria->getProgressDetails(null),
'today' => $dept_criteria->getProgressDetails('today'),
'week' => $dept_criteria->getProgressDetails('week'),
'month' => $dept_criteria->getProgressDetails('month'),
];
}
// reset the departments to original
$this->departments->set(array_map(fn($id) => (new \objects\departments_o())->select($id), $department_ids));
return $results;
}
/**
* @throws \Exception
*/
public static function calculateProgressDetailsFromArray(array $criteria_array, ?string $timeframe = null): array
{
$criteria = self::fromJson(json_encode($criteria_array));
return $criteria->getProgressDetails($timeframe);
}
public function getProgressDetails(?string $timeframe = null): array
{
if ($timeframe) {
$this->setTimeframeByName($timeframe);
}
$target = 0;
$active_dept_ids = $this->departments->listIDs();
if ($timeframe === 'today') {
foreach ($active_dept_ids as $id) {
$target += $this->department_daily_targets[$id] ?? 0;
}
} elseif ($timeframe === 'week') {
foreach ($active_dept_ids as $id) {
$target += ($this->department_daily_targets[$id] ?? 0) * 7;
}
} elseif ($timeframe === 'month') {
foreach ($active_dept_ids as $id) {
$target += ($this->department_daily_targets[$id] ?? 0) * 30;
}
} else {
$target = (int)$this->target;
}
return [
'count' => $this->getProgress(),
'target' => $target
];
}
public function withDepartmentFilter(int $department_id): goals_criteria
{
// Clone the criteria and create a fresh departments collection to avoid mutating the original
@@ -85,13 +85,13 @@ class department_goals_o extends db
'departments' => (array)$this->departments->value(),
'criteria' => (array)$this->criteria->value(),
'progress' => [
'value' => $include_progress ? goals_criteria::calculateProgressFromArray((array)$this->criteria->value()) : null,
'all' => $include_progress ? goals_criteria::calculateProgressDetailsFromArray((array)$this->criteria->value()) : null,
'departmental_distribution' => $include_progress ? goals_criteria::calculateDepartmentalProgressFromArray((array)$this->criteria->value()) : null,
// array of department_id => [ 'all' => [ 'count' => int, 'target' => int ], 'today' => [ 'count' => int, 'target' => int ], 'week' => [ 'count' => int, 'target' => int ], 'month' => [ 'count' => int, 'target' => int ] ]
// Showing progress for different time periods
'today' => $include_progress ? goals_criteria::calculateProgressFromArray((array)$this->criteria->value(), 'today') : null,
'week' => $include_progress ? goals_criteria::calculateProgressFromArray((array)$this->criteria->value(), 'week') : null,
'month' => $include_progress ? goals_criteria::calculateProgressFromArray((array)$this->criteria->value(), 'month') : null,
'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,
],
'created_at' => (string)$this->created_at->value(),
'updated_at' => (string)$this->updated_at->value(),