Files
compras/tests/Feature/SupplyTaskIntegrationTest.php
2026-11-03 11:51:44 +02:00

87 lines
6.7 KiB
PHP

<?php
use App\Models\SupplyRecord;
use App\Models\Tenant;
use App\Models\User;
use App\Services\SupplyPlanning;
use Illuminate\Support\Facades\DB;
use Inertia\Testing\AssertableInertia as Assert;
require_once __DIR__.'/../Support/SuggestionFixture.php';
beforeEach(function () {
$this->f = suggestionFixture();
$this->actingAs($this->f['receiver']);
app(SupplyPlanning::class)->save($this->f['receiver'], 'policy', supplyInput([], 'suspend', $this->f['policy']));
$this->data = [...supplyPolicy($this->f), 'purpose' => 'internal', 'agreement_key' => $this->f['agreement']->record_key];
$this->actingAs($this->f['issuer']);
$this->draft = app(SupplyPlanning::class)->save($this->f['issuer'], 'policy', supplyInput($this->data));
$this->path = '/compras/fornecimento?view=calendar&record_id='.$this->draft->id;
});
test('supply task policy reaches an independent reviewer and a stale link shows the new state without approving twice', function () {
supplyGrant($this->f['issuer'], ['supply_review']);
$this->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
$this->get($this->path)->assertInertia(fn (Assert $page) => $page->where('records.0.canApprove', false)->where('records.0.canReturn', false));
$this->actingAs($this->f['receiver'])->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1)
->where('tasks.data.0.href', $this->path.'#supply-record-'.$this->draft->id)->missing('tasks.data.0.data')->missing('tasks.data.0.snapshot'));
$before = [SupplyRecord::query()->count(), DB::table('audit_logs')->count(), DB::table('requisitions')->count()];
$this->get($this->path)->assertHeader('Cache-Control', 'max-age=0, no-store, private')->assertInertia(fn (Assert $page) => $page->has('records', 1)
->where('focusRecordId', $this->draft->id)->where('focusChanged', false)->where('records.0.canApprove', true)->where('records.0.canSuspend', false));
expect([SupplyRecord::query()->count(), DB::table('audit_logs')->count(), DB::table('requisitions')->count()])->toBe($before);
$approved = app(SupplyPlanning::class)->save($this->f['receiver'], 'policy', supplyInput([], 'approve', $this->draft));
$this->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
$this->get($this->path)->assertInertia(fn (Assert $page) => $page->where('focusChanged', true)->where('records.0.id', $approved->id)
->where('records.0.canApprove', false)->where('records.0.canSuspend', true));
});
test('supply task excludes every preparation contributor even after another person edits the current version', function () {
supplyGrant($this->f['issuer'], ['supply_review']);
supplyGrant($this->f['receiver'], ['supply_prepare']);
$this->actingAs($this->f['receiver']);
$updated = app(SupplyPlanning::class)->save($this->f['receiver'], 'policy', supplyInput([...$this->data, 'basis' => 'Revisão sintética conservando os intervenientes.'], 'save', $this->draft));
supplyGrant($this->f['otherReceiver'], ['supply_review']);
foreach ([$this->f['issuer'], $this->f['receiver']] as $contributor) {
$this->actingAs($contributor)->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
expect(app(SupplyPlanning::class)->canReview($contributor, $updated))->toBeFalse();
}
$this->actingAs($this->f['otherReceiver'])->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1)->where('tasks.data.0.id', 'supply:'.$updated->id.':review'));
});
test('supply task keeps a changed source available for return but cannot silently approve it', function () {
$this->f['stock']->update(['name' => 'Cadastro alterado depois da preparação']);
$this->actingAs($this->f['receiver'])->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1));
$this->postJson('/compras/fornecimento/policy', supplyInput([], 'approve', $this->draft))->assertUnprocessable();
$returned = app(SupplyPlanning::class)->save($this->f['receiver'], 'policy', supplyInput([], 'return', $this->draft));
expect($returned->state)->toBe('returned')->and($returned->snapshot['item'])->toBe($this->draft->snapshot['item']);
});
test('supply task retains older preparations across the former hundred row display limit', function () {
$first = $this->draft;
for ($index = 1; $index < 105; $index++) {
app(SupplyPlanning::class)->save($this->f['issuer'], 'policy', supplyInput($this->data));
}
$this->actingAs($this->f['receiver'])->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 105)->has('tasks.data', 25)->where('tasks.data.0.id', 'supply:'.$first->id.':review'));
$this->get('/requisicoes/tarefas?module=supply&page=5')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 105)->has('tasks.data', 5));
$this->get('/compras/fornecimento?view=calendar')->assertInertia(fn (Assert $page) => $page->has('records', 25)->where('recordPagination.total', 106));
$this->get($this->path)->assertInertia(fn (Assert $page) => $page->has('records', 1)->where('records.0.id', $first->id)->where('records.0.canApprove', true));
});
test('supply task and record focus preserve company isolation and the kind of the document', function () {
$tenant = Tenant::query()->create(['name' => 'Outra empresa sintética']);
$foreign = User::factory()->create(['tenant_id' => $tenant->id]);
supplyGrant($foreign, ['supply_review']);
$this->actingAs($foreign)->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
$this->getJson($this->path)->assertUnprocessable();
$this->actingAs($this->f['receiver'])->getJson('/compras/fornecimento?view=agreements&record_id='.$this->draft->id)->assertUnprocessable();
});
test('supply task does not inherit execution from maintenance and expires with the saved grant', function () {
DB::table('organization_memberships')->where('user_id', $this->f['receiver']->id)->update(['maintenance' => true, 'expires_at' => now()->addHour()]);
$this->actingAs($this->f['receiver'])->get('/requisicoes/tarefas?module=supply')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
$this->get($this->path)->assertForbidden();
expect(app(SupplyPlanning::class)->canReview($this->f['receiver'], $this->draft))->toBeFalse();
DB::table('organization_memberships')->where('user_id', $this->f['receiver']->id)->update(['expires_at' => now()->subMinute()]);
$this->get('/requisicoes/tarefas?module=supply')->assertForbidden();
});