Detect time entries with a task but no project in consistency check

The comparison used != which evaluates to NULL when the time entry has no
project, so entries that kept their task after the project was removed
were not reported.
This commit is contained in:
Constantin Graf
2026-10-09 10:37:44 +02:00
committed by Gregor Vostrak
parent e82c601449
commit b73cdc4bb5
2 changed files with 21 additions and 1 deletions

View File

@@ -39,7 +39,7 @@ class SelfHostDatabaseConsistency extends Command
$problems = DB::table('time_entries') $problems = DB::table('time_entries')
->select(['time_entries.id as id']) ->select(['time_entries.id as id'])
->join('tasks', 'time_entries.task_id', '=', 'tasks.id') ->join('tasks', 'time_entries.task_id', '=', 'tasks.id')
->where('tasks.project_id', '!=', DB::raw('time_entries.project_id')) ->whereRaw('tasks.project_id is distinct from time_entries.project_id')
->get(); ->get();
$this->logProblems($problems, 'Time entries have a task that does not belong to the project of the time entry', $hadAProblem); $this->logProblems($problems, 'Time entries have a task that does not belong to the project of the time entry', $hadAProblem);

View File

@@ -39,6 +39,26 @@ class SelfHostDatabaseConsistencyCommandTest extends TestCaseWithDatabase
$this->assertSame("Consistency problem: Time entries have a task that does not belong to the project of the time entry\n - ".$timeEntry->getKey()."\n", $output); $this->assertSame("Consistency problem: Time entries have a task that does not belong to the project of the time entry\n - ".$timeEntry->getKey()."\n", $output);
} }
public function test_checks_that_task_need_to_be_part_of_project_in_time_entries_with_no_project_in_time_entry(): void
{
// Arrange
$user = $this->createUserWithRole(Role::Owner);
$project = Project::factory()->forOrganization($user->organization)->create();
$task = Task::factory()->forOrganization($user->organization)->forProject($project)->create();
$timeEntry = TimeEntry::factory()->forMember($user->member)->forTask($task)->create([
'project_id' => null,
'client_id' => null,
]);
// Act
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
// Assert
$this->assertSame(Command::FAILURE, $exitCode);
$output = Artisan::output();
$this->assertSame("Consistency problem: Time entries have a task that does not belong to the project of the time entry\n - ".$timeEntry->getKey()."\n", $output);
}
public function test_checks_that_client_id_is_the_client_id_of_the_project(): void public function test_checks_that_client_id_is_the_client_id_of_the_project(): void
{ {
// Arrange // Arrange