mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 21:47:32 -05: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