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('