r = app(WarehouseRequests::class)->draft($this->f['issuer'], [...$this->draftData, 'operation_key' => (string) Str::uuid(), 'reason' => '=SUM(100;200)']);
warehouseCommand($this, $this->f['issuer'], 'submit', ['partial_allowed' => true]);
warehouseCommand($this, $this->reviewer, 'authorize', ['partial_allowed' => true]);
warehouseCommand($this, $this->f['receiver'], 'deliver', ['lines' => [['index' => 0, 'quantity' => '1.500']]]);
$before = [];
foreach (['warehouse_requests', 'warehouse_request_events', 'warehouse_reservations', 'stock_operations', 'stock_movements', 'audit_logs'] as $table) {
$before[$table] = DB::table($table)->orderBy('id')->get()->toArray();
}
$this->actingAs($this->reviewer);
$url = '/stock/requisicoes.csv?view=reserve&state=partial&search=RA-'.$this->r->id.'&warehouse_id='.$this->f['warehouse']->id.'&page=2';
$csv = $this->get($url)->assertOk()->assertHeader('Cache-Control', 'max-age=0, no-store, private')->streamedContent();
$rows = array_map(fn ($line) => str_getcsv($line, ';', '"', ''), explode("\n", trim($csv)));
expect($rows)->toHaveCount(4)->and($rows[2])->toHaveCount(21)->and($rows[3][0])->toBe('RA-'.$this->r->id)
->and($rows[3][7])->toBe("'=SUM(100;200)")->and(array_slice($rows[3], 14, 5))->toBe(['4.000', '2.500', '1.500', '2.500', '0.000']);
expect($this->get('/stock/requisicoes.csv?state=draft')->streamedContent())->not->toContain('RA-'.$this->r->id);
foreach ($before as $table => $rows) {
expect(DB::table($table)->orderBy('id')->get()->toArray())->toEqual($rows);
}
});
test('warehouse request export includes old pending requests beyond pagination', function () {
foreach (range(1, 16) as $index) {
app(WarehouseRequests::class)->draft($this->f['issuer'], [...$this->draftData, 'operation_key' => (string) Str::uuid(), 'reason' => 'Pendência antiga '.$index]);
}
$csv = $this->get('/stock/requisicoes.csv?state=draft&page=2')->assertOk()->streamedContent();
expect(explode("\n", trim($csv)))->toHaveCount(20);
expect($csv)->toContain('RA-'.$this->r->id, 'Pendência antiga 16');
});
test('warehouse request export enforces roles tenant scope and validates filters', function () {
$this->getJson('/stock/requisicoes.csv?state=invalid')->assertUnprocessable();
$other = User::factory()->create(['tenant_id' => $this->f['tenant']->id, 'department_id' => $this->f['department']->id]);
$this->actingAs($other)->get('/stock/requisicoes.csv')->assertForbidden();
supplyGrant($other, ['warehouse_request_prepare']);
expect($this->actingAs($other)->get('/stock/requisicoes.csv')->assertOk()->streamedContent())->not->toContain('RA-'.$this->r->id);
$foreign = receiptFixture();
supplyGrant($foreign['receiver'], ['warehouse_request_read']);
expect($this->actingAs($foreign['receiver'])->get('/stock/requisicoes.csv')->assertOk()->streamedContent())->not->toContain('RA-'.$this->r->id);
$this->getJson('/stock/requisicoes.csv?warehouse_id='.$this->f['warehouse']->id)->assertUnprocessable();
});
test('warehouse request print reproduces reservations partial deliveries and confirmations without writes', function () {
warehouseCommand($this, $this->f['issuer'], 'submit', ['partial_allowed' => true]);
warehouseCommand($this, $this->reviewer, 'authorize', ['partial_allowed' => true]);
warehouseCommand($this, $this->f['receiver'], 'deliver', ['lines' => [['index' => 0, 'quantity' => '1.500']], 'reason' => '']);
$delivery = WarehouseRequestEvent::query()->where('action', 'deliver')->sole();
$url = '/stock/requisicoes/'.$this->r->id.'/imprimir';
$tables = ['warehouse_requests', 'warehouse_request_events', 'warehouse_reservations', 'stock_movements', 'stock_operations', 'audit_logs', 'budget_entries'];
$before = [];
foreach ($tables as $table) {
$before[$table] = DB::table($table)->orderBy('id')->get()->toArray();
}
$this->get($url)->assertOk()->assertHeader('Cache-Control', 'max-age=0, no-store, private')
->assertSee('Entrega parcial')->assertSee('4,000')->assertSee('1,500')->assertSee('2,500')->assertSee('Sem factura')
->assertSee($this->reviewer->name)->assertSee('Oficina interna')->assertSee('Recepção por confirmar')
->assertSee('/entregas/'.$delivery->id.'/imprimir', false)->assertDontSee('']);
$first = WarehouseRequestEvent::query()->where('action', 'deliver')->sole();
warehouseCommand($this, $this->f['receiver'], 'deliver', ['lines' => [['index' => 0, 'quantity' => '2.500']]]);
$url = '/stock/requisicoes/'.$this->r->id.'/entregas/'.$first->id.'/imprimir';
$tables = ['warehouse_requests', 'warehouse_request_events', 'stock_movements', 'stock_operations', 'warehouse_reservations', 'audit_logs', 'invoices', 'budget_entries'];
$before = [];
foreach ($tables as $table) {
$before[$table] = DB::table($table)->orderBy('id')->get()->toArray();
}
$this->get($url)->assertOk()->assertHeader('Cache-Control', 'max-age=0, no-store, private')
->assertSee('RA-'.$this->r->id)->assertSee('Sem factura')->assertSee('1,500')->assertDontSee('2,500')
->assertSee('Oficina interna')->assertSee($this->reviewer->name)->assertSee('Recepção por confirmar')->assertDontSee('