Add optional per-department weekly targets and update related calculations
This commit is contained in:
@@ -82,6 +82,11 @@ class goals_criteria implements goals_criteria_i
|
||||
* @var array<int,float>
|
||||
*/
|
||||
public array $department_daily_targets;
|
||||
/**
|
||||
* Optional per-department custom weekly targets (department_id => weekly_target)
|
||||
* @var array<int,float>
|
||||
*/
|
||||
public array $department_weekly_targets;
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@@ -96,6 +101,8 @@ class goals_criteria implements goals_criteria_i
|
||||
$this->progress_alert_destination = goals_criteria_progress_alert_destination::NONE;
|
||||
$this->progress_alert_progress_type = goals_criteria_progress_alert_progress_type::NONE;
|
||||
$this->progress_alert_style = goals_criteria_progress_alert_style::NONE;
|
||||
$this->department_daily_targets = [];
|
||||
$this->department_weekly_targets = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,6 +278,28 @@ class goals_criteria implements goals_criteria_i
|
||||
}
|
||||
$criteria->department_daily_targets = $targets;
|
||||
}
|
||||
// Parse department weekly targets (expects object with department_id => target)
|
||||
if (isset($data['department_weekly_targets']) && is_array($data['department_weekly_targets'])) {
|
||||
$targets = [];
|
||||
foreach ($data['department_weekly_targets'] as $deptId => $target) {
|
||||
if (is_numeric($deptId) && is_numeric($target)) {
|
||||
$id = (int)$deptId;
|
||||
$t = max(0.0, (float)$target);
|
||||
$targets[$id] = $t;
|
||||
}
|
||||
}
|
||||
$criteria->department_weekly_targets = $targets;
|
||||
} elseif (isset($data['departmentWeeklyTargets']) && is_array($data['departmentWeeklyTargets'])) {
|
||||
$targets = [];
|
||||
foreach ($data['departmentWeeklyTargets'] as $deptId => $target) {
|
||||
if (is_numeric($deptId) && is_numeric($target)) {
|
||||
$id = (int)$deptId;
|
||||
$t = max(0.0, (float)$target);
|
||||
$targets[$id] = $t;
|
||||
}
|
||||
}
|
||||
$criteria->department_weekly_targets = $targets;
|
||||
}
|
||||
// Parse timeframe with validation
|
||||
if (isset($data['start']) && is_string($data['start'])) {
|
||||
try {
|
||||
@@ -431,7 +460,8 @@ class goals_criteria implements goals_criteria_i
|
||||
'progress_alert_format' => $this->progress_alert_format,
|
||||
'progress_alert_weekdays' => array_map(fn($e) => ($e instanceof goals_criteria_progress_alert_weekday) ? $e->name : (string)$e, $this->progress_alert_weekdays ?? []),
|
||||
'progress_alert_time_of_day' => $this->progress_alert_time_of_day,
|
||||
'department_daily_targets' => $this->department_daily_targets
|
||||
'department_daily_targets' => $this->department_daily_targets,
|
||||
'department_weekly_targets' => $this->department_weekly_targets
|
||||
];
|
||||
}
|
||||
|
||||
@@ -591,6 +621,16 @@ class goals_criteria implements goals_criteria_i
|
||||
}
|
||||
}
|
||||
$this->department_daily_targets = $normalized;
|
||||
// Normalize custom weekly targets map: ints and non-negative; filter to selected departments
|
||||
$normalizedWeekly = [];
|
||||
foreach ($this->department_weekly_targets as $k => $v) {
|
||||
if (!is_numeric($k) || !is_numeric($v)) { continue; }
|
||||
$dk = (int)$k; $dv = (float)$v;
|
||||
if ($dk > 0 && $dv >= 0 && in_array($dk, $deptIds)) {
|
||||
$normalizedWeekly[$dk] = $dv;
|
||||
}
|
||||
}
|
||||
$this->department_weekly_targets = $normalizedWeekly;
|
||||
// Ensure target is non-negative
|
||||
if ($this->target < 0) {
|
||||
$this->target = 0;
|
||||
@@ -701,6 +741,7 @@ class goals_criteria implements goals_criteria_i
|
||||
}
|
||||
|
||||
$this->department_daily_targets = array_filter($this->department_daily_targets, fn($v) => is_numeric($v) && $v >= 0);
|
||||
$this->department_weekly_targets = array_filter($this->department_weekly_targets, fn($v) => is_numeric($v) && $v >= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -752,27 +793,27 @@ class goals_criteria implements goals_criteria_i
|
||||
if ($timeframe === 'today') {
|
||||
$days = $criteria->getTimeframeDayCount();
|
||||
foreach ($active_dept_ids as $id) {
|
||||
$target += (float)($criteria->department_daily_targets[$id] ?? 0) * $days;
|
||||
$target += $criteria->getDailyTargetForDepartment((int)$id) * $days;
|
||||
}
|
||||
} elseif ($timeframe === 'week') {
|
||||
$days = $criteria->getTimeframeDayCount();
|
||||
foreach ($active_dept_ids as $id) {
|
||||
$target += (float)($criteria->department_daily_targets[$id] ?? 0) * $days;
|
||||
$target += $criteria->getDailyTargetForDepartment((int)$id) * $days;
|
||||
}
|
||||
} elseif ($timeframe === 'month') {
|
||||
$days = $criteria->getTimeframeDayCount();
|
||||
foreach ( $active_dept_ids as $id ) {
|
||||
$target += (float)($criteria->department_daily_targets[$id] ?? 0) * $days;
|
||||
$target += $criteria->getDailyTargetForDepartment((int)$id) * $days;
|
||||
}
|
||||
} elseif ($timeframe === 'year') {
|
||||
$days = $criteria->getTimeframeDayCount();
|
||||
foreach ( $active_dept_ids as $id ) {
|
||||
$target += (float)($criteria->department_daily_targets[$id] ?? 0) * $days;
|
||||
$target += $criteria->getDailyTargetForDepartment((int)$id) * $days;
|
||||
}
|
||||
} elseif ($timeframe === 'to_date') {
|
||||
$days = $criteria->getTimeframeDayCount();
|
||||
foreach ($active_dept_ids as $id) {
|
||||
$target += (float)($criteria->department_daily_targets[$id] ?? 0) * $days;
|
||||
$target += $criteria->getDailyTargetForDepartment((int)$id) * $days;
|
||||
}
|
||||
} else {
|
||||
$target = (float)$criteria->target;
|
||||
@@ -797,6 +838,27 @@ class goals_criteria implements goals_criteria_i
|
||||
return (int)$this->start->diff($this->end)->format('%a') + 1;
|
||||
}
|
||||
|
||||
private function getOperatingDaysPerWeek(): int
|
||||
{
|
||||
$days = $this->operating_days_of_week ?? [1, 2, 3, 4, 5];
|
||||
if (!is_array($days)) {
|
||||
return 5;
|
||||
}
|
||||
$days = array_values(array_unique(array_filter(array_map('intval', $days), fn($d) => $d >= 1 && $d <= 7)));
|
||||
return max(1, count($days));
|
||||
}
|
||||
|
||||
private function getDailyTargetForDepartment(int $departmentId): float
|
||||
{
|
||||
if (isset($this->department_daily_targets[$departmentId])) {
|
||||
return max(0.0, (float)$this->department_daily_targets[$departmentId]);
|
||||
}
|
||||
if (isset($this->department_weekly_targets[$departmentId])) {
|
||||
return max(0.0, (float)$this->department_weekly_targets[$departmentId]) / $this->getOperatingDaysPerWeek();
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public function withDepartmentFilter(int $department_id): goals_criteria
|
||||
{
|
||||
// Clone the criteria and create a fresh departments collection to avoid mutating the original
|
||||
|
||||
Reference in New Issue
Block a user