mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Add rounding to tasks
This commit is contained in:
parent
4a627be02c
commit
aa649ac625
@ -503,7 +503,13 @@ class CompanySettings extends BaseSettings
|
||||
|
||||
public $enable_rappen_rounding = false;
|
||||
|
||||
public bool $task_round_up = true;
|
||||
|
||||
public int $task_round_to_nearest = 1;
|
||||
|
||||
public static $casts = [
|
||||
'task_round_up' => 'bool',
|
||||
'task_round_to_nearest' => 'int',
|
||||
'e_quote_type' => 'string',
|
||||
'enable_rappen_rounding' => 'bool',
|
||||
'use_unapplied_payment' => 'string',
|
||||
|
@ -27,6 +27,10 @@ class TaskRepository extends BaseRepository
|
||||
|
||||
private $completed = true;
|
||||
|
||||
private bool $task_round_up = true;
|
||||
|
||||
private int $task_round_to_nearest = 1;
|
||||
|
||||
/**
|
||||
* Saves the task and its contacts.
|
||||
*
|
||||
@ -44,6 +48,8 @@ class TaskRepository extends BaseRepository
|
||||
$task->fill($data);
|
||||
$task->saveQuietly();
|
||||
|
||||
$this->init($task);
|
||||
|
||||
if ($this->new_task && ! $task->status_id) {
|
||||
$task->status_id = $this->setDefaultStatus($task);
|
||||
}
|
||||
@ -105,6 +111,11 @@ class TaskRepository extends BaseRepository
|
||||
$key_values = array_column($time_log, 0);
|
||||
array_multisort($key_values, SORT_ASC, $time_log);
|
||||
|
||||
foreach($time_log as $key => $value)
|
||||
{
|
||||
$time_log[$key][1] = $this->roundTimeLog($time_log[$key][1]);
|
||||
}
|
||||
|
||||
if (isset($data['action'])) {
|
||||
if ($data['action'] == 'start') {
|
||||
$task->is_running = true;
|
||||
@ -126,8 +137,6 @@ class TaskRepository extends BaseRepository
|
||||
|
||||
$task->time_log = json_encode($time_log);
|
||||
|
||||
|
||||
|
||||
$task->saveQuietly();
|
||||
|
||||
if (array_key_exists('documents', $data)) {
|
||||
@ -243,14 +252,27 @@ class TaskRepository extends BaseRepository
|
||||
return $task;
|
||||
}
|
||||
|
||||
public function roundTimeLog(int $end_time): int
|
||||
{
|
||||
if($this->task_round_to_nearest == 1)
|
||||
return $end_time;
|
||||
|
||||
if($this->task_round_up)
|
||||
return (int)ceil($end_time/$this->task_round_to_nearest)*$this->task_round_to_nearest;
|
||||
|
||||
return (int)floor($end_time/$this->task_round_to_nearest) * $this->task_round_to_nearest;
|
||||
}
|
||||
|
||||
public function stop(Task $task)
|
||||
{
|
||||
$this->init($task);
|
||||
|
||||
$log = json_decode($task->time_log, true);
|
||||
|
||||
$last = end($log);
|
||||
|
||||
if (is_array($last) && $last[1] === 0) {
|
||||
$last[1] = time();
|
||||
$last[1] = $this->roundTimeLog(time());
|
||||
|
||||
array_pop($log);
|
||||
$log = array_merge($log, [$last]);//check at this point, it may be prepending here.
|
||||
@ -275,6 +297,15 @@ class TaskRepository extends BaseRepository
|
||||
return $task;
|
||||
}
|
||||
|
||||
private function init(Task $task): self
|
||||
{
|
||||
|
||||
$this->task_round_up = $task->client ? $task->client->getSetting('task_round_up') : $task->company->getSetting('task_round_up');
|
||||
$this->task_round_to_nearest = $task->client ? $task->client->getSetting('task_round_to_nearest') : $task->company->getSetting('task_round_to_nearest');
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
private function trySaving(Task $task)
|
||||
{
|
||||
|
@ -104,6 +104,64 @@ class TaskApiTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testRoundingViaApi()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'description' => 'Test Task',
|
||||
'time_log' => '[[1681165417,1681165432,"sumtin",true],[1681165446,0]]',
|
||||
'assigned_user' => [],
|
||||
'project' => [],
|
||||
'user' => [],
|
||||
// 'status' => [],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson("/api/v1/tasks", $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
}
|
||||
|
||||
public function testRoundingToNearestXXX()
|
||||
{
|
||||
|
||||
$time = 1680036807;
|
||||
|
||||
$round_up_to_next_minute = ceil($time / 60) * 60;
|
||||
$round_down_to_next_minute = floor($time / 60) * 60;
|
||||
$this->assertEquals(1680036840, $round_up_to_next_minute);
|
||||
$this->assertEquals(1680036780, $round_down_to_next_minute);
|
||||
|
||||
$round_up_to_next_minute = ceil($round_up_to_next_minute / 3600) * 3600;
|
||||
$round_down_to_next_minute = floor($round_down_to_next_minute / 3600) * 3600;
|
||||
$this->assertEquals(1680037200, $round_up_to_next_minute);
|
||||
$this->assertEquals(1680033600, $round_down_to_next_minute);
|
||||
|
||||
}
|
||||
|
||||
public function testKsortPerformance()
|
||||
{
|
||||
$logs = [
|
||||
[1680035007,1680036807,"",true],
|
||||
[1681156840,1681158000,"",true],
|
||||
[1680302433,1680387960,"",true],
|
||||
[1680715620,1680722820,"",true],
|
||||
[1,1680737460,"",true]
|
||||
];
|
||||
|
||||
$key_values = array_column($logs, 0);
|
||||
array_multisort($key_values, SORT_ASC, $logs);
|
||||
|
||||
$start = $logs[0];
|
||||
|
||||
$this->assertEquals(1, $start[0]);
|
||||
|
||||
}
|
||||
|
||||
public function testRequestRuleParsing()
|
||||
{
|
||||
|
||||
@ -393,26 +451,6 @@ class TaskApiTest extends TestCase
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testKsortPerformance()
|
||||
{
|
||||
$logs = [
|
||||
[1680035007,1680036807,"",true],
|
||||
[1681156840,1681158000,"",true],
|
||||
[1680302433,1680387960,"",true],
|
||||
[1680715620,1680722820,"",true],
|
||||
[1,1680737460,"",true]
|
||||
];
|
||||
|
||||
$key_values = array_column($logs, 0);
|
||||
array_multisort($key_values, SORT_ASC, $logs);
|
||||
|
||||
$start = $logs[0];
|
||||
|
||||
$this->assertEquals(1, $start[0]);
|
||||
|
||||
}
|
||||
|
||||
public function testStartStopSanity()
|
||||
{
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user