f = receiptFixture(); supplyGrant($this->f['issuer'], ['warehouse_request_prepare']); $this->actingAs($this->f['issuer']); $this->data = ['operation_key' => (string) Str::uuid(), 'warehouse_id' => $this->f['warehouse']->id, 'cost_center_id' => $this->f['r']->cost_center_id, 'destination' => 'Oficina da unidade', 'reason' => 'Material para manutenção da unidade.', 'priority' => 'normal', 'lines' => [['stock_item_id' => $this->f['stock']->id, 'quantity' => '2.500', 'use' => 'internal', 'equipment_id' => null]]]; }); test('warehouse draft freezes catalogue and destination once without stock budget or purchase effects', function () { $moves = DB::table('stock_movements')->count(); $purchases = DB::table('requisitions')->count(); $this->postJson('/stock/requisicoes', $this->data)->assertRedirect(); $this->postJson('/stock/requisicoes', $this->data)->assertRedirect(); $record = WarehouseRequest::query()->sole(); expect($record->snapshot['lines'][0]['quantity_milli'])->toBe(2500)->and($record->snapshot['lines'][0]['item']['unit'])->toBe($this->f['stock']->unit) ->and($record->snapshot['destination'])->toBe($this->data['destination']) ->and(DB::table('stock_movements')->count())->toBe($moves)->and(DB::table('requisitions')->count())->toBe($purchases) ->and(DB::table('budget_entries')->count())->toBe(0); $this->f['stock']->update(['name' => 'Nome futuro do artigo']); expect($record->fresh()->snapshot['lines'][0]['item']['name'])->not->toBe('Nome futuro do artigo'); $this->postJson('/stock/requisicoes', [...$this->data, 'destination' => 'Outro local'])->assertUnprocessable(); $this->get('/stock/requisicoes')->assertOk()->assertInertia(fn (Assert $p) => $p->component('stock/requests')->where('records.total', 1)->missing('records.data.0.input_hash')); }); test('equipment destination is conditional and selected from the permitted catalogue', function () { $this->data['lines'][0]['use'] = 'equipment'; $this->postJson('/stock/requisicoes', $this->data)->assertUnprocessable(); $level = CriticalityLevel::query()->create(['tenant_id' => $this->f['tenant']->id, 'created_by' => $this->f['issuer']->id, 'code' => 'NORMAL', 'name' => 'Normal', 'criteria' => 'Critério de teste.', 'is_critical' => false, 'created_at' => now()]); $equipment = Equipment::query()->create(['tenant_id' => $this->f['tenant']->id, 'created_by' => $this->f['issuer']->id, 'department_id' => $this->f['issuer']->department_id, 'criticality_level_id' => $level->id, 'code' => 'EQ-1', 'description' => 'Máquina da oficina', 'area' => 'Oficina', 'status' => 'active']); $this->data['lines'][0]['equipment_id'] = $equipment->id; $this->postJson('/stock/requisicoes', $this->data)->assertRedirect(); expect(WarehouseRequest::query()->sole()->snapshot['lines'][0]['equipment']['code'])->toBe('EQ-1'); $this->data['operation_key'] = (string) Str::uuid(); $this->data['lines'][0]['use'] = 'internal'; $this->postJson('/stock/requisicoes', $this->data)->assertUnprocessable(); $this->data['lines'][0]['use'] = 'sale'; $this->postJson('/stock/requisicoes', $this->data)->assertUnprocessable(); }); test('warehouse draft rejects another company sources and revoked access', function () { $foreign = receiptFixture(); $this->actingAs($this->f['issuer'])->postJson('/stock/requisicoes', [...$this->data, 'warehouse_id' => $foreign['warehouse']->id])->assertNotFound(); DB::table('organization_memberships')->where('user_id', $this->f['issuer']->id)->update(['expires_at' => now()->subMinute()]); $this->postJson('/stock/requisicoes', $this->data)->assertForbidden(); expect(DB::table('warehouse_requests')->count())->toBe(0); }); test('warehouse draft audit failure leaves no partial document', function () { $this->mock(RequisitionWorkflow::class)->shouldReceive('audit')->once()->andThrow(new RuntimeException('Injected draft audit failure')); $this->withoutExceptionHandling(); expect(fn () => $this->postJson('/stock/requisicoes', $this->data))->toThrow(RuntimeException::class); expect(DB::table('warehouse_requests')->count())->toBe(0); });