feat(ticketing): add service and command for converting validity times to UTC

This commit is contained in:
2026-09-21 16:05:18 -03:00
parent 3e3b3bfac0
commit 969e99b3ae
4 changed files with 213 additions and 1 deletions

View File

@@ -0,0 +1,74 @@
<?php
namespace Tests\Feature\Ticket;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class ConvertValidityTimesToUtcTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
Schema::create('validity_times', function (Blueprint $table): void {
$table->id();
$table->string('type');
$table->time('start_time')->nullable();
$table->time('end_time')->nullable();
$table->dateTime('fixed_starts_at')->nullable();
$table->dateTime('fixed_expires_at')->nullable();
});
DB::table('validity_times')->insert([
['id' => 1, 'type' => 'fixed_window', 'fixed_starts_at' => '2026-09-21 07:00:00', 'fixed_expires_at' => '2026-09-23 23:59:00'],
['id' => 2, 'type' => 'fixed_window', 'fixed_starts_at' => null, 'fixed_expires_at' => '2026-09-24 23:59:00'],
]);
DB::table('validity_times')->insert(['id' => 3, 'type' => 'time_window', 'start_time' => '07:00:00', 'end_time' => '10:00:00']);
}
public function test_preview_does_not_modify_data(): void
{
$this->artisan('tickets:convert-validity-times-to-utc', ['--all' => true])->assertSuccessful();
$this->assertDatabaseHas('validity_times', ['id' => 1, 'fixed_starts_at' => '2026-09-21 07:00:00']);
}
public function test_explicit_conversion_preserves_multiple_days_nulls_and_time_windows(): void
{
$this->artisan('tickets:convert-validity-times-to-utc', ['--ids' => '1,2', '--apply' => true])->assertSuccessful();
$this->assertDatabaseHas('validity_times', [
'id' => 1, 'fixed_starts_at' => '2026-09-21 10:00:00', 'fixed_expires_at' => '2026-09-24 02:59:00',
]);
$this->assertDatabaseHas('validity_times', ['id' => 2, 'fixed_starts_at' => null, 'fixed_expires_at' => '2026-09-25 02:59:00']);
$this->assertDatabaseHas('validity_times', ['id' => 3, 'start_time' => '07:00:00', 'end_time' => '10:00:00']);
}
public function test_all_converts_every_fixed_window_without_a_migration(): void
{
$this->artisan('tickets:convert-validity-times-to-utc', ['--all' => true, '--apply' => true])->assertSuccessful();
$this->assertDatabaseHas('validity_times', ['id' => 1, 'fixed_starts_at' => '2026-09-21 10:00:00', 'fixed_expires_at' => '2026-09-24 02:59:00']);
$this->assertDatabaseHas('validity_times', ['id' => 2, 'fixed_starts_at' => null, 'fixed_expires_at' => '2026-09-25 02:59:00']);
$this->assertDatabaseHas('validity_times', ['id' => 3, 'start_time' => '07:00:00', 'end_time' => '10:00:00']);
}
public function test_ids_leave_unselected_fixed_windows_unchanged(): void
{
$this->artisan('tickets:convert-validity-times-to-utc', ['--ids' => '1', '--apply' => true])->assertSuccessful();
$this->assertDatabaseHas('validity_times', ['id' => 2, 'fixed_expires_at' => '2026-09-24 23:59:00']);
}
public function test_invalid_scope_is_rejected_before_any_write(): void
{
foreach ([[], ['--all' => true, '--ids' => '1'], ['--ids' => '1,999'], ['--ids' => '1,3'], ['--ids' => 'bad'], ['--ids' => '1', '--source-timezone' => 'bad']] as $options) {
$this->artisan('tickets:convert-validity-times-to-utc', $options + ['--apply' => true])->assertFailed();
}
$this->assertDatabaseHas('validity_times', ['id' => 1, 'fixed_starts_at' => '2026-09-21 07:00:00']);
}
public function test_failure_rolls_back_all_updates(): void
{
DB::statement("CREATE TRIGGER prevent_second_update BEFORE UPDATE ON validity_times WHEN OLD.id = 2 BEGIN SELECT RAISE(ABORT, 'test failure'); END");
$this->artisan('tickets:convert-validity-times-to-utc', ['--ids' => '1,2', '--apply' => true])->assertFailed();
$this->assertDatabaseHas('validity_times', ['id' => 1, 'fixed_starts_at' => '2026-09-21 07:00:00']);
}
}