Prevent time entries with end before start

Partial updates of time entries only validated end against start if both
were part of the payload. Start and end are now also validated against the
persisted value if only one of them is sent (fixes #1189).

The importers now fail if the end of a time entry is before the start and
the database consistency check reports such time entries.
This commit is contained in:
Constantin Graf
2026-10-09 13:23:51 +02:00
committed by Constantin Graf
parent 9a845bad8f
commit fd008dd4a8
14 changed files with 300 additions and 0 deletions

View File

@@ -15,7 +15,9 @@ use App\Service\Import\Importers\SolidtimeImporter;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Str;
use PHPUnit\Framework\Attributes\CoversClass;
use ZipArchive;
#[CoversClass(SolidtimeImporter::class)]
#[CoversClass(ImportException::class)]
@@ -199,4 +201,32 @@ class SolidtimeImporterTest extends ImporterTestAbstract
Queue::assertPushed(RecalculateSpentTimeForProject::class, 1);
Queue::assertPushed(RecalculateSpentTimeForTask::class, 1);
}
public function test_import_fails_if_end_of_time_entry_is_before_start(): void
{
// Arrange
$organization = Organization::factory()->create();
$timezone = 'Europe/Vienna';
$zipPath = $this->createTestZip('solidtime_import_test_1');
$zip = new ZipArchive;
$zip->open($zipPath);
$timeEntries = $zip->getFromName('time_entries.csv');
$timeEntries = Str::replaceFirst(',2024-03-04T09:23:52Z,2024-03-04T09:23:52Z,', ',2024-03-04T09:23:52Z,2024-03-04T08:23:52Z,', $timeEntries);
$zip->addFromString('time_entries.csv', $timeEntries);
$zip->close();
$importer = new SolidtimeImporter;
$importer->init($organization);
$data = file_get_contents($zipPath);
// Act
try {
$importer->importData($data, $timezone);
} catch (ImportException $e) {
// Assert
$this->assertSame('End date ("2024-03-04T08:23:52Z") is before start date ("2024-03-04T09:23:52Z")', $e->getMessage());
return;
}
$this->fail();
}
}