Release 1.19.4 (#3255)
* login redirects to homepage if already being logged-in * fix budget check for entries that were moved to another moth * invoice: fix amount should be decimal if decimal template is used * added new month grouped by project/activity/user report
This commit is contained in:
@@ -190,66 +190,72 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
{
|
||||
return [
|
||||
// activity: violations ----------------------------------------------------------------------
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'a_a' => [1230, null, null, null, null, null, 3600, null, null, null, null, null, '00:20', '00:39', '01:00', 'activity', '+3600 seconds'],
|
||||
'a_b' => [null, 1001.0, null, null, null, null, null, 1000.0, null, null, null, null, '€1,001.00', '€0.00', '€1,000.00', 'activity', '+3600 seconds'],
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'a_a' => [1230, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '00:20', '00:39', '01:00', 'activity', '+3600 seconds'],
|
||||
'a_b' => [null, 1001.0, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, '€1,001.00', '€0.00', '€1,000.00', 'activity', '+3600 seconds'],
|
||||
|
||||
// activity: no violations
|
||||
'a_c' => [1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'a_d' => [null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'a_e' => [1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'a_c' => [1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'a_d' => [null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'a_e' => [1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'a_f1' => [1320, null, null, null, null, null, 3600, null, null, null, null, null, '00:22', '00:38', '01:00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'a_h1' => [7200, null, null, null, null, null, 7200, null, null, null, null, null, '02:00', '00:00', '02:00', 'activity', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'a_h2' => [3601, null, null, null, null, null, 3600, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'a_g0' => [null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, '1,002.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'a_g1' => [null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'a_f1' => [1320, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '00:22', '00:38', '01:00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'a_h1' => [7200, null, null, null, null, null, null, 7200, null, null, null, null, null, null, null, '02:00', '00:00', '02:00', 'activity', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'a_h2' => [3601, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'a_g0' => [null, 1002.0, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, '1,002.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'a_g1' => [null, 1002.0, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
// nothing changed => no violation
|
||||
'a_x1' => [3600, 1000.0, null, null, null, null, 3600, 1000.0, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600], new Rate(1000.0, 0.00)],
|
||||
'a_x1' => [3600, 1000.0, null, null, null, null, null, 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600], new Rate(1000.0, 0.00)],
|
||||
// date changed => violation
|
||||
'a_x2' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, '1,000.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 999.0, 'duration' => 3599, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => true], new Rate(1000.0, 0.00)],
|
||||
// date changed but not violation was raised
|
||||
'a_x3' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 999.0, 'duration' => 3599, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => false], new Rate(1000.0, 0.00)],
|
||||
'a_x4' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => true], new Rate(1000.0, 0.00)],
|
||||
'a_x5' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => false], new Rate(1000.0, 0.00)],
|
||||
|
||||
// project: violations ----------------------------------------------------------------------
|
||||
'p_j' => [null, null, 1230, null, null, null, null, null, 3600, null, null, null, '00:20', '00:39', '01:00', 'project', '+3600 seconds'],
|
||||
'p_k' => [null, null, null, 1001.0, null, null, null, null, null, 1000.0, null, null, '€1,001.00', '€0.00', '€1,000.00', 'project', '+3600 seconds'],
|
||||
'p_j' => [null, null, 1230, null, null, null, null, null, null, null, 3600, null, null, null, null, '00:20', '00:39', '01:00', 'project', '+3600 seconds'],
|
||||
'p_k' => [null, null, null, 1001.0, null, null, null, null, null, null, null, 1000.0, null, null, null, '€1,001.00', '€0.00', '€1,000.00', 'project', '+3600 seconds'],
|
||||
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'p_f1' => [null, null, 1320, null, null, null, null, null, 3600, null, null, null, '00:22', '00:38', '01:00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'p_h1' => [null, null, 7200, null, null, null, null, null, 7200, null, null, null, '02:00', '00:00', '02:00', 'project', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'p_h2' => [null, null, 3601, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'p_g0' => [null, null, null, 1002.0, null, null, null, null, null, 1000.0, null, null, '1,002.00', '0.00', '1,000.00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'p_g1' => [null, null, null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'p_f1' => [null, null, 1320, null, null, null, null, null, null, null, 3600, null, null, null, null, '00:22', '00:38', '01:00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'p_h1' => [null, null, 7200, null, null, null, null, null, null, null, 7200, null, null, null, null, '02:00', '00:00', '02:00', 'project', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'p_h2' => [null, null, 3601, null, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'p_g0' => [null, null, null, 1002.0, null, null, null, null, null, null, null, 1000.0, null, null, null, '1,002.00', '0.00', '1,000.00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'p_g1' => [null, null, null, 1002.0, null, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
|
||||
// project: no violations
|
||||
'p_n' => [null, null, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_o' => [null, null, null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_p' => [null, null, 1230, 1001, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_n' => [null, null, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_o' => [null, null, null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_p' => [null, null, 1230, 1001, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
|
||||
'p_q' => [1230, null, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_r' => [1230, 1001.0, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_s' => [null, 1001.0, null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_t' => [null, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_u' => [1230, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_q' => [1230, null, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_r' => [1230, 1001.0, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_s' => [null, 1001.0, null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_t' => [null, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_u' => [1230, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
|
||||
// customer: violations ----------------------------------------------------------------------
|
||||
'c_v' => [null, null, null, null, 1230, null, null, null, null, null, 3600, null, '00:20', '00:39', '01:00', 'customer', '+3600 seconds'],
|
||||
'c_w' => [null, null, null, null, null, 1001.0, null, null, null, null, null, 1000.0, '€1,001.00', '€0.00', '€1,000.00', 'customer', '+3600 seconds'],
|
||||
'c_v' => [null, null, null, null, 1230, null, null, null, null, null, null, null, null, 3600, null, '00:20', '00:39', '01:00', 'customer', '+3600 seconds'],
|
||||
'c_w' => [null, null, null, null, null, 1001.0, null, null, null, null, null, null, null, null, 1000.0, '€1,001.00', '€0.00', '€1,000.00', 'customer', '+3600 seconds'],
|
||||
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'c_f1' => [null, null, null, null, 1320, null, null, null, null, null, 3600, null, '00:22', '00:38', '01:00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'c_h1' => [null, null, null, null, 7200, null, null, null, null, null, 7200, null, '02:00', '00:00', '02:00', 'customer', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'c_h2' => [null, null, null, null, 3601, null, null, null, null, null, 3600, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'c_g0' => [null, null, null, null, null, 1002.0, null, null, null, null, null, 1000.0, '1,002.00', '0.00', '1,000.00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'c_g1' => [null, null, null, null, null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'c_f1' => [null, null, null, null, 1320, null, null, null, null, null, null, null, null, 3600, null, '00:22', '00:38', '01:00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'c_h1' => [null, null, null, null, 7200, null, null, null, null, null, null, null, null, 7200, null, '02:00', '00:00', '02:00', 'customer', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'c_h2' => [null, null, null, null, 3601, null, null, null, null, null, null, null, null, 3600, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'c_g0' => [null, null, null, null, null, 1002.0, null, null, null, null, null, null, null, null, 1000.0, '1,002.00', '0.00', '1,000.00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'c_g1' => [null, null, null, null, null, 1002.0, null, null, null, null, null, null, null, null, 1000.0, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
|
||||
// customer: no violations
|
||||
'c_z' => [null, null, null, null, 1230, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_1' => [null, null, null, null, null, 1001.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_2' => [null, null, null, null, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_3' => [1230, null, 1230, null, 1230, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_4' => [1230, 1001.0, 1230, null, null, 1001.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_5' => [null, 1001.0, null, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_6' => [null, 1001.0, 1230, 1001.0, 1230, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_7' => [1230, 1001.0, 1230, 1001.0, null, 1001.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_z' => [null, null, null, null, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_1' => [null, null, null, null, null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_2' => [null, null, null, null, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_3' => [1230, null, 1230, null, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_4' => [1230, 1001.0, 1230, null, null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_5' => [null, 1001.0, null, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_6' => [null, 1001.0, 1230, 1001.0, 1230, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'c_7' => [1230, 1001.0, 1230, 1001.0, null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -263,10 +269,13 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
?float $projectRate,
|
||||
?int $customerDuration,
|
||||
?float $customerRate,
|
||||
?string $activityBudgetType,
|
||||
?int $activityTimeBudget,
|
||||
?float $activityBudget,
|
||||
?string $projectBudgetType,
|
||||
?int $projectTimeBudget,
|
||||
?float $projectBudget,
|
||||
?string $customerBudgetType,
|
||||
?int $customerTimeBudget,
|
||||
?float $customerBudget,
|
||||
?string $used,
|
||||
@@ -334,9 +343,19 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
if (!\array_key_exists('duration', $rawData)) {
|
||||
$rawData['duration'] = 0;
|
||||
}
|
||||
if (!\array_key_exists('begin', $rawData)) {
|
||||
$rawData['begin'] = clone $begin;
|
||||
}
|
||||
if (!\array_key_exists('end', $rawData)) {
|
||||
$rawData['end'] = clone $end;
|
||||
}
|
||||
$activity = $this->createMock(Activity::class);
|
||||
$activity->method('getId')->willReturn($rawData['activity']);
|
||||
$activity->method('isMonthlyBudget')->willReturn(false);
|
||||
if ($activityBudgetType !== null) {
|
||||
$activity->method('getBudgetType')->willReturn($activityBudgetType);
|
||||
$activity->method('isMonthlyBudget')->willReturn($activityBudgetType === 'month');
|
||||
}
|
||||
if ($activityTimeBudget !== null) {
|
||||
$activity->method('getTimeBudget')->willReturn($activityTimeBudget);
|
||||
$activity->method('hasTimeBudget')->willReturn(true);
|
||||
@@ -351,6 +370,10 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
$customer = $this->createMock(Customer::class);
|
||||
$customer->method('getId')->willReturn($rawData['customer']);
|
||||
$customer->method('isMonthlyBudget')->willReturn(false);
|
||||
if ($customerBudgetType !== null) {
|
||||
$customer->method('getBudgetType')->willReturn($customerBudgetType);
|
||||
$customer->method('isMonthlyBudget')->willReturn($customerBudgetType === 'month');
|
||||
}
|
||||
if ($customerTimeBudget !== null) {
|
||||
$customer->method('getTimeBudget')->willReturn($customerTimeBudget);
|
||||
$customer->method('hasTimeBudget')->willReturn(true);
|
||||
@@ -366,6 +389,10 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
$project->method('getId')->willReturn($rawData['project']);
|
||||
$project->method('getCustomer')->willReturn($customer);
|
||||
$project->method('isMonthlyBudget')->willReturn(false);
|
||||
if ($projectBudgetType !== null) {
|
||||
$project->method('getBudgetType')->willReturn($projectBudgetType);
|
||||
$project->method('isMonthlyBudget')->willReturn($projectBudgetType === 'month');
|
||||
}
|
||||
if ($projectTimeBudget !== null) {
|
||||
$project->method('getTimeBudget')->willReturn($projectTimeBudget);
|
||||
$project->method('hasTimeBudget')->willReturn(true);
|
||||
@@ -376,7 +403,6 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
$project->method('hasBudget')->willReturn(true);
|
||||
$project->method('hasBudgets')->willReturn(true);
|
||||
}
|
||||
|
||||
$timesheet = $this->createMock(Timesheet::class);
|
||||
$timesheet->method('getId')->willReturn(1);
|
||||
$timesheet->method('getRate')->willReturn($rawData['rate']);
|
||||
|
||||
Reference in New Issue
Block a user