94 lines
5.2 KiB
PHP
94 lines
5.2 KiB
PHP
<?php
|
|
|
|
use App\Enums\PurchasingRole;
|
|
use App\Models\AuditLog;
|
|
use App\Models\Department;
|
|
use App\Models\QualificationAssessment;
|
|
use App\Models\QualificationSet;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use App\Services\DocumentaryQualificationWorkflow;
|
|
use App\Services\ProcurementReviewReport;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Inertia\Testing\AssertableInertia as Assert;
|
|
|
|
require_once __DIR__.'/../Support/QualificationFixture.php';
|
|
|
|
beforeEach(function () {
|
|
$this->f = qualificationFixture();
|
|
$this->url = '/requisicoes/'.$this->f['r']->id.'/relatorio';
|
|
$this->actingAs($this->f['issuer']);
|
|
});
|
|
|
|
function documentaryReportRecords(object $test): QualificationSet
|
|
{
|
|
$workflow = app(DocumentaryQualificationWorkflow::class);
|
|
$test->actingAs($test->f['issuer']);
|
|
$set = $workflow->define($test->f['issuer'], $test->f['r'], $test->f['definition']);
|
|
$test->actingAs($test->f['analyst']);
|
|
$workflow->assess($test->f['analyst'], $set, $test->f['assessment']);
|
|
|
|
return $set;
|
|
}
|
|
|
|
test('review report returns a private read-only consultation without inventing missing decisions', function () {
|
|
$before = AuditLog::query()->count();
|
|
$this->get($this->url)->assertOk()->assertHeader('Cache-Control', 'max-age=0, no-store, private')
|
|
->assertInertia(fn (Assert $page) => $page->component('purchases/review-report')
|
|
->where('report.requisition.number', $this->f['r']->number)
|
|
->where('report.comparison.ready', false)->where('report.comparison.top_count', 0)
|
|
->where('report.comparison.rows.0.score_minor', null)->where('report.comparison.rows.0.is_top', false)
|
|
->where('report.qualification', null)->where('report.award', null)->where('report.order', null)
|
|
->missing('report.recommended_supplier_id')->missing('report.bank_snapshot'));
|
|
expect(AuditLog::query()->count())->toBe($before);
|
|
});
|
|
|
|
test('review report separates current comparison from outdated documentary identities and results', function () {
|
|
$set = documentaryReportRecords($this);
|
|
$this->f['quote']->update(['reference' => 'REFERENCIA-POSTERIOR']);
|
|
$this->get($this->url)->assertInertia(fn (Assert $page) => $page->where('report.comparison.rows.0.reference', 'REFERENCIA-POSTERIOR')
|
|
->where('report.qualification.is_current', false)->where('report.qualification.revision', $set->revision)
|
|
->where('report.qualification.proposals.0.reference', 'PROP-TEST')
|
|
->where('report.qualification.proposals.0.analyses.0.answers.1.result', 'pending'));
|
|
});
|
|
|
|
test('review report retains the latest record of each analyst without majority or silent replacement', function () {
|
|
$set = documentaryReportRecords($this);
|
|
$first = QualificationAssessment::query()->sole();
|
|
$workflow = app(DocumentaryQualificationWorkflow::class);
|
|
$workflow->assess($this->f['analyst'], $set, [...$this->f['assessment'], 'previous_id' => $first->id, 'reason' => 'Correcção fictícia para conferência']);
|
|
$this->actingAs($this->f['other_analyst']);
|
|
$workflow->assess($this->f['other_analyst'], $set, $this->f['assessment']);
|
|
$before = AuditLog::query()->count();
|
|
$this->get($this->url)->assertInertia(fn (Assert $page) => $page->where('report.qualification.is_current', true)
|
|
->has('report.qualification.proposals.0.analyses', 2)
|
|
->where('report.qualification.proposals.0.analyses.0.revision', 2)
|
|
->where('report.qualification.proposals.0.analyses.1.revision', 1));
|
|
expect(QualificationAssessment::query()->count())->toBe(3)->and(AuditLog::query()->count())->toBe($before);
|
|
});
|
|
|
|
test('review report enforces financial-reader roles companies departments and guest protection', function () {
|
|
$this->actingAs($this->f['receiver'])->get($this->url)->assertForbidden();
|
|
$department = Department::query()->create(['tenant_id' => $this->f['tenant']->id, 'name' => 'Outro departamento']);
|
|
$head = User::factory()->create(['tenant_id' => $this->f['tenant']->id, 'department_id' => $department->id, 'purchasing_role' => PurchasingRole::DepartmentHead]);
|
|
$this->actingAs($head)->get($this->url)->assertNotFound();
|
|
$head->forceFill(['department_id' => $this->f['r']->department_id])->save();
|
|
$this->actingAs($head)->get($this->url)->assertOk();
|
|
$other = Tenant::query()->create(['name' => 'Outra empresa fictícia']);
|
|
$this->actingAs(User::factory()->create(['tenant_id' => $other->id, 'purchasing_role' => PurchasingRole::Admin]))->get($this->url)->assertNotFound();
|
|
auth()->logout();
|
|
$this->get($this->url)->assertRedirect('/login');
|
|
});
|
|
|
|
test('review report reloads cached actor access before reading business records', function () {
|
|
$this->actingAs($this->f['analyst']);
|
|
DB::table('users')->where('id', $this->f['analyst']->id)->update(['purchasing_role' => 'requester']);
|
|
$this->get($this->url)->assertForbidden();
|
|
});
|
|
|
|
test('review report omits unneeded supplier and evaluator details', function () {
|
|
$report = app(ProcurementReviewReport::class)->build($this->f['issuer'], $this->f['r']->id);
|
|
expect($report['comparison']['rows'][0]['supplier'])->toBeString()
|
|
->and($report['comparison']['rows'][0])->not->toHaveKeys(['evaluations', 'qualified_evaluations', 'items', 'beneficiaries', 'document_references', 'bank_snapshot']);
|
|
});
|