commit21
This commit is contained in:
@@ -13,8 +13,10 @@ use App\Services\ReceiptWorkflow;
|
||||
use App\Services\RequisitionWorkflow;
|
||||
use App\Services\StockWorkflow;
|
||||
use App\Services\SupplyPlanning;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Inertia\Testing\AssertableInertia as Assert;
|
||||
|
||||
require_once __DIR__.'/../Support/ReceiptFixture.php';
|
||||
require_once __DIR__.'/../Support/SupplyFixture.php';
|
||||
@@ -189,3 +191,83 @@ test('HTTP menu and commands use the same functional permissions without automat
|
||||
$this->postJson('/stock/ocorrencias', supplyInput(dispositionData($this)))->assertForbidden();
|
||||
expect(app(SupplyPlanning::class)->latest('stock_event')->sole()->state)->toBe('executed');
|
||||
});
|
||||
test('disposition task connects independent review and physical execution once without financial documents', function () {
|
||||
$draft = app(InventoryDispositions::class)->save($this->f['receiver'], supplyInput(dispositionData($this)));
|
||||
$path = '/stock/ocorrencias?record_id='.$draft->id;
|
||||
supplyGrant($this->f['receiver'], ['inventory_disposition_review']);
|
||||
supplyGrant($this->f['issuer'], ['warehouse']);
|
||||
$this->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
|
||||
$this->get($path)->assertInertia(fn (Assert $page) => $page->where('records.0.canApprove', false));
|
||||
$this->actingAs($this->f['issuer'])->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1)
|
||||
->where('tasks.data.0.task', 'disposition_approve')->where('tasks.data.0.href', $path.'#disposition-'.$draft->id)->missing('tasks.data.0.snapshot'));
|
||||
$before = [SupplyRecord::query()->count(), StockMovement::query()->count(), DB::table('audit_logs')->count(), Invoice::query()->count()];
|
||||
$this->get($path)->assertHeader('Cache-Control', 'max-age=0, no-store, private')->assertInertia(fn (Assert $page) => $page->has('records', 1)->where('focusChanged', false)->where('records.0.canApprove', true));
|
||||
expect([SupplyRecord::query()->count(), StockMovement::query()->count(), DB::table('audit_logs')->count(), Invoice::query()->count()])->toBe($before);
|
||||
$approved = app(InventoryDispositions::class)->save($this->f['issuer'], supplyInput([], 'approve', $draft));
|
||||
expect(app(StockWorkflow::class)->balance($this->f['stock']->id, $this->f['warehouse']->id)['quantity'])->toBe(10000);
|
||||
$this->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
|
||||
$this->get($path)->assertInertia(fn (Assert $page) => $page->where('focusChanged', true)->where('records.0.id', $approved->id)->where('records.0.canExecute', false)->where('records.0.canReturn', true));
|
||||
$this->actingAs($this->f['receiver'])->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1)->where('tasks.data.0.task', 'disposition_execute'));
|
||||
$command = supplyInput(['event_on' => today()->toDateString(), 'evidence' => 'Saída física confirmada no ensaio descartável.'], 'execute', $approved);
|
||||
$this->postJson('/stock/ocorrencias', $command)->assertRedirect();
|
||||
$this->postJson('/stock/ocorrencias', $command)->assertRedirect();
|
||||
expect(app(StockWorkflow::class)->balance($this->f['stock']->id, $this->f['warehouse']->id)['quantity'])->toBe(7000)
|
||||
->and(Invoice::query()->count())->toBe($before[3])->and(StockMovement::query()->count())->toBe($before[1] + 1);
|
||||
$this->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
|
||||
});
|
||||
|
||||
test('disposition task keeps changed stock sources pending for return without permitting silent execution', function () {
|
||||
$approved = approvedDisposition($this, ['kind' => 'write_off']);
|
||||
$this->f['stock']->update(['name' => 'Identificação revista depois da autorização']);
|
||||
$this->actingAs($this->f['receiver'])->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1)->where('tasks.data.0.blocked', true));
|
||||
$this->postJson('/stock/ocorrencias', supplyInput(['event_on' => today()->toDateString(), 'evidence' => 'A saída não pode ignorar alteração da origem.'], 'execute', $approved))->assertUnprocessable();
|
||||
expect(app(StockWorkflow::class)->balance($this->f['stock']->id, $this->f['warehouse']->id)['quantity'])->toBe(10000);
|
||||
$this->actingAs($this->f['issuer']);
|
||||
$this->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1)->where('tasks.data.0.task', 'disposition_return')->where('tasks.data.0.blocked', true));
|
||||
$returned = app(InventoryDispositions::class)->save($this->f['issuer'], supplyInput([], 'return', $approved));
|
||||
expect($returned->state)->toBe('returned')->and($returned->snapshot['source'])->toBe($approved->snapshot['source']);
|
||||
$this->actingAs($this->f['receiver'])->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
|
||||
});
|
||||
|
||||
test('disposition task excludes every preparer while retaining the separately authorised physical executor', function () {
|
||||
$draft = app(InventoryDispositions::class)->save($this->f['receiver'], supplyInput(dispositionData($this)));
|
||||
supplyGrant($this->f['issuer'], ['inventory_disposition_prepare']);
|
||||
$this->actingAs($this->f['issuer']);
|
||||
$updated = app(InventoryDispositions::class)->save($this->f['issuer'], supplyInput(dispositionData($this), 'save', $draft));
|
||||
supplyGrant($this->f['receiver'], ['inventory_disposition_review']);
|
||||
foreach ([$this->f['issuer'], $this->f['receiver']] as $person) {
|
||||
expect(app(InventoryDispositions::class)->canAct($person, $updated, 'approve'))->toBeFalse();
|
||||
}
|
||||
supplyGrant($this->f['otherReceiver'], ['inventory_disposition_review']);
|
||||
$this->actingAs($this->f['otherReceiver'])->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 1));
|
||||
$approved = app(InventoryDispositions::class)->save($this->f['otherReceiver'], supplyInput([], 'approve', $updated));
|
||||
expect(app(InventoryDispositions::class)->canAct($this->f['otherReceiver'], $approved, 'execute'))->toBeFalse()
|
||||
->and(app(InventoryDispositions::class)->canAct($this->f['receiver'], $approved, 'execute'))->toBeTrue();
|
||||
});
|
||||
|
||||
test('disposition task preserves oldest pending events beyond the initial display cap', function () {
|
||||
$first = app(InventoryDispositions::class)->save($this->f['receiver'], supplyInput(dispositionData($this)));
|
||||
for ($index = 1; $index < 105; $index++) {
|
||||
app(InventoryDispositions::class)->save($this->f['receiver'], supplyInput(dispositionData($this)));
|
||||
}
|
||||
$this->actingAs($this->f['issuer'])->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 105)->has('tasks.data', 25)
|
||||
->where('tasks.data.0.id', 'disposition:'.$first->id.':approve'));
|
||||
$this->get('/requisicoes/tarefas?module=warehouse&page=5')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 105)->has('tasks.data', 5));
|
||||
$this->get('/stock/ocorrencias')->assertInertia(fn (Assert $page) => $page->has('records', 25)->where('recordPagination.total', 105));
|
||||
$this->get('/stock/ocorrencias?record_id='.$first->id)->assertInertia(fn (Assert $page) => $page->has('records', 1)->where('records.0.id', $first->id)->where('records.0.canApprove', true));
|
||||
});
|
||||
|
||||
test('disposition task preserves company isolation maintenance and expired assignments', function () {
|
||||
$draft = app(InventoryDispositions::class)->save($this->f['receiver'], supplyInput(dispositionData($this)));
|
||||
$path = '/stock/ocorrencias?record_id='.$draft->id;
|
||||
$foreign = receiptFixture();
|
||||
supplyGrant($foreign['receiver'], ['warehouse']);
|
||||
$this->actingAs($foreign['receiver'])->getJson($path)->assertUnprocessable();
|
||||
$this->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
|
||||
DB::table('organization_memberships')->where('user_id', $this->f['issuer']->id)->update(['maintenance' => true, 'expires_at' => now()->addHour()]);
|
||||
$this->actingAs($this->f['issuer'])->get('/requisicoes/tarefas?module=warehouse')->assertInertia(fn (Assert $page) => $page->where('tasks.total', 0));
|
||||
$this->get($path)->assertForbidden();
|
||||
expect(app(InventoryDispositions::class)->canAct($this->f['issuer'], $draft, 'approve'))->toBeFalse();
|
||||
DB::table('organization_memberships')->where('user_id', $this->f['issuer']->id)->update(['expires_at' => now()->subMinute()]);
|
||||
$this->get('/requisicoes/tarefas?module=warehouse')->assertForbidden();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user