Files
api/services/nginx/app/tests/Unit/Goals/GoalsCriteriaTargetMathTest.php
T

118 lines
4.1 KiB
PHP

<?php
app_require('modules/goals/classes/goals_criteria.php');
app_require('modules/goals/helpers/goals_criteria_target_duration.php');
app_require('modules/goals/helpers/goals_criteria_type.php');
use goals\classes\goals_criteria;
use goals\helpers\goals_criteria_target_duration as TargetDuration;
use goals\helpers\goals_criteria_type as CriteriaType;
function goals_test_department(int $id): object
{
$department = new stdClass();
$department->id = $id;
return $department;
}
it('computes weekly target using touched ISO weeks for March 2026', function (): void {
$criteria = new goals_criteria();
$criteria->type = CriteriaType::NONE;
$criteria->target = 10;
$criteria->target_duration = TargetDuration::WEEKS;
$criteria->target_duration_every = 1;
$criteria->start = new DateTime('2026-03-01 00:00:00');
$criteria->end = new DateTime('2026-03-31 23:59:59');
$criteria->departments->set([goals_test_department(12)]);
$criteria->validateAndSanitize();
$target = $criteria->calculateTargetForRange(
new DateTime('2026-03-01 00:00:00'),
new DateTime('2026-03-31 23:59:59')
);
expect($target)->toBe(60.0);
});
it('applies target_duration_every for weekly cadence', function (): void {
$criteria = new goals_criteria();
$criteria->type = CriteriaType::NONE;
$criteria->target = 10;
$criteria->target_duration = TargetDuration::WEEKS;
$criteria->target_duration_every = 2;
$criteria->start = new DateTime('2026-03-01 00:00:00');
$criteria->end = new DateTime('2026-03-31 23:59:59');
$criteria->departments->set([goals_test_department(12)]);
$criteria->validateAndSanitize();
$target = $criteria->calculateTargetForRange(
new DateTime('2026-03-01 00:00:00'),
new DateTime('2026-03-31 23:59:59')
);
expect($target)->toBe(30.0);
});
it('prorates ENTIRE_DURATION target by overlap days', function (): void {
$criteria = new goals_criteria();
$criteria->type = CriteriaType::NONE;
$criteria->target = 310;
$criteria->target_duration = TargetDuration::ENTIRE_DURATION;
$criteria->start = new DateTime('2026-01-01 00:00:00');
$criteria->end = new DateTime('2026-01-31 23:59:59');
$criteria->departments->set([goals_test_department(12)]);
$criteria->validateAndSanitize();
$target = $criteria->calculateTargetForRange(
new DateTime('2026-01-01 00:00:00'),
new DateTime('2026-01-07 23:59:59')
);
expect($target)->toBe(70.0);
});
it('splits advanced target by override weights per department', function (): void {
$criteria = new goals_criteria();
$criteria->type = CriteriaType::NONE;
$criteria->target = 10;
$criteria->target_duration = TargetDuration::WEEKS;
$criteria->target_duration_every = 1;
$criteria->start = new DateTime('2026-03-01 00:00:00');
$criteria->end = new DateTime('2026-03-31 23:59:59');
$criteria->departments->set([goals_test_department(12), goals_test_department(15)]);
$criteria->department_daily_targets = [12 => 3, 15 => 1];
$criteria->validateAndSanitize();
$dept12 = $criteria->calculateTargetForRange(
new DateTime('2026-03-01 00:00:00'),
new DateTime('2026-03-31 23:59:59'),
12,
[12, 15]
);
$dept15 = $criteria->calculateTargetForRange(
new DateTime('2026-03-01 00:00:00'),
new DateTime('2026-03-31 23:59:59'),
15,
[12, 15]
);
expect($dept12)->toBe(45.0);
expect($dept15)->toBe(15.0);
});
it('preserves legacy target behavior when target_duration is missing', function (): void {
$criteria = new goals_criteria();
$criteria->type = CriteriaType::NONE;
$criteria->target = 70;
$criteria->start = new DateTime('first day of this month 00:00:00');
$criteria->end = new DateTime('now');
$criteria->departments->set([goals_test_department(12)]);
$criteria->validateAndSanitize();
$monthProgress = $criteria->getProgressDetails('month');
$allProgress = $criteria->getProgressDetails();
expect((float)$monthProgress['target'])->toBe(0.0);
expect((float)$allProgress['target'])->toBe(70.0);
});