feat: complete administration and reporting
This commit is contained in:
141
tests/Feature/AdminReservationPolicyTest.php
Normal file
141
tests/Feature/AdminReservationPolicyTest.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
use App\Domain\Administration\Services\ReservationPolicy;
|
||||
use App\Domain\Identity\Enums\RoleName;
|
||||
use App\Domain\Identity\Models\Role;
|
||||
use App\Domain\Inventory\Models\SnipeAsset;
|
||||
use App\Domain\Reservations\Enums\ReservationItemStatus;
|
||||
use App\Domain\Reservations\Enums\ReservationStatus;
|
||||
use App\Domain\Reservations\Models\Reservation;
|
||||
use App\Domain\Reservations\Services\AvailabilityService;
|
||||
use App\Domain\Reservations\Services\ReservationService;
|
||||
use App\Models\User;
|
||||
use Carbon\CarbonImmutable;
|
||||
|
||||
function policyAdministrator(): User
|
||||
{
|
||||
$administrator = User::factory()->create();
|
||||
$role = Role::firstOrCreate(['name' => RoleName::Administrator->value]);
|
||||
$administrator->roles()->attach($role);
|
||||
|
||||
return $administrator;
|
||||
}
|
||||
|
||||
/** @return array<string, int> */
|
||||
function policyValues(array $overrides = []): array
|
||||
{
|
||||
return array_replace([
|
||||
'reservation.min_notice_hours' => 0,
|
||||
'reservation.max_duration_hours' => 168,
|
||||
'reservation.turnaround_minutes' => 0,
|
||||
'reservation.approval_deadline_hours' => 48,
|
||||
'reservation.max_assets' => 10,
|
||||
], $overrides);
|
||||
}
|
||||
|
||||
it('permite ao administrador alterar políticas com auditoria', function () {
|
||||
$administrator = policyAdministrator();
|
||||
$values = policyValues([
|
||||
'reservation.min_notice_hours' => 24,
|
||||
'reservation.turnaround_minutes' => 30,
|
||||
]);
|
||||
|
||||
$this->actingAs($administrator)
|
||||
->put('/administracao/regras', $values)
|
||||
->assertRedirect()
|
||||
->assertSessionHas('success');
|
||||
|
||||
expect(app(ReservationPolicy::class)->integer('reservation.min_notice_hours'))->toBe(24)
|
||||
->and(app(ReservationPolicy::class)->integer('reservation.turnaround_minutes'))->toBe(30);
|
||||
$this->assertDatabaseHas('portal_settings', [
|
||||
'key' => 'reservation.min_notice_hours',
|
||||
'updated_by' => $administrator->id,
|
||||
]);
|
||||
$this->assertDatabaseHas('audit_logs', ['event' => 'settings.reservation_policy_updated']);
|
||||
});
|
||||
|
||||
it('rejeita períodos fora da antecedência e duração configuradas', function () {
|
||||
$administrator = policyAdministrator();
|
||||
app(ReservationPolicy::class)->update(policyValues([
|
||||
'reservation.min_notice_hours' => 24,
|
||||
'reservation.max_duration_hours' => 4,
|
||||
]), $administrator);
|
||||
$requester = User::factory()->create();
|
||||
$asset = SnipeAsset::factory()->create();
|
||||
|
||||
$this->actingAs($requester)
|
||||
->from('/requisicoes/nova')
|
||||
->post('/requisicoes', [
|
||||
'purpose' => 'Atividade audiovisual com duração demasiado longa.',
|
||||
'usage_location' => 'Auditório',
|
||||
'starts_at' => now()->addHours(2)->toDateTimeString(),
|
||||
'ends_at' => now()->addHours(8)->toDateTimeString(),
|
||||
'asset_ids' => [$asset->id],
|
||||
'terms_accepted' => true,
|
||||
])
|
||||
->assertRedirect('/requisicoes/nova')
|
||||
->assertSessionHasErrors(['starts_at', 'ends_at']);
|
||||
|
||||
$this->assertDatabaseCount('reservations', 0);
|
||||
});
|
||||
|
||||
it('aplica margem temporal na consulta e na garantia de conflito', function () {
|
||||
$administrator = policyAdministrator();
|
||||
app(ReservationPolicy::class)->update(policyValues([
|
||||
'reservation.turnaround_minutes' => 60,
|
||||
]), $administrator);
|
||||
$requester = User::factory()->create();
|
||||
$asset = SnipeAsset::factory()->create();
|
||||
$reservation = Reservation::create([
|
||||
'reference' => 'REQ-POLICY-MARGIN',
|
||||
'requester_id' => $requester->id,
|
||||
'purpose' => 'Reserva existente para validar a margem.',
|
||||
'usage_location' => 'Estúdio',
|
||||
'starts_at' => '2026-09-10 09:00:00',
|
||||
'ends_at' => '2026-09-10 11:00:00',
|
||||
'status' => ReservationStatus::Approved,
|
||||
]);
|
||||
$reservation->items()->create([
|
||||
'snipe_asset_id' => $asset->id,
|
||||
'starts_at' => '2026-09-10 09:00:00',
|
||||
'ends_at' => '2026-09-10 11:00:00',
|
||||
'buffer_starts_at' => '2026-09-10 09:00:00',
|
||||
'buffer_ends_at' => '2026-09-10 11:00:00',
|
||||
'status' => ReservationItemStatus::Reserved,
|
||||
]);
|
||||
|
||||
$availability = app(AvailabilityService::class);
|
||||
expect($availability->isAvailable(
|
||||
$asset,
|
||||
new DateTimeImmutable('2026-09-10 11:30:00'),
|
||||
new DateTimeImmutable('2026-09-10 12:30:00'),
|
||||
))->toBeFalse()
|
||||
->and($availability->isAvailable(
|
||||
$asset,
|
||||
new DateTimeImmutable('2026-09-10 12:00:00'),
|
||||
new DateTimeImmutable('2026-09-10 13:00:00'),
|
||||
))->toBeTrue();
|
||||
});
|
||||
|
||||
it('grava buffers e prazo de aprovação definidos pela política', function () {
|
||||
$administrator = policyAdministrator();
|
||||
app(ReservationPolicy::class)->update(policyValues([
|
||||
'reservation.turnaround_minutes' => 30,
|
||||
'reservation.approval_deadline_hours' => 12,
|
||||
]), $administrator);
|
||||
$startsAt = CarbonImmutable::parse('2026-09-20 10:00:00');
|
||||
$endsAt = $startsAt->addHours(2);
|
||||
|
||||
$reservation = app(ReservationService::class)->createPending(User::factory()->create(), [
|
||||
'purpose' => 'Atividade para validar políticas configuráveis.',
|
||||
'usage_location' => 'Sala multimédia',
|
||||
'starts_at' => $startsAt->toDateTimeString(),
|
||||
'ends_at' => $endsAt->toDateTimeString(),
|
||||
'asset_ids' => [SnipeAsset::factory()->create()->id],
|
||||
]);
|
||||
$item = $reservation->items()->firstOrFail();
|
||||
|
||||
expect($item->buffer_starts_at->equalTo($startsAt->subMinutes(30)))->toBeTrue()
|
||||
->and($item->buffer_ends_at->equalTo($endsAt->addMinutes(30)))->toBeTrue()
|
||||
->and($reservation->created_at->diffInHours($reservation->approval_deadline))->toBe(12.0);
|
||||
});
|
||||
Reference in New Issue
Block a user