Implementa qualificacao documental com requisitos e analises por versao

This commit is contained in:
2026-10-28 19:28:05 +02:00
parent b7a52e9e00
commit 9138379432
21 changed files with 1677 additions and 11 deletions
+14
View File
@@ -15,6 +15,7 @@ use App\Models\PurchaseAward;
use App\Models\PurchaseControlPolicy;
use App\Models\PurchaseOrder;
use App\Models\PurchaseRevision;
use App\Models\QualificationSet;
use App\Models\Quotation;
use App\Models\Requisition;
use App\Models\SparePart;
@@ -27,6 +28,8 @@ use App\Models\Warehouse;
use App\Services\BudgetWorkflow;
use App\Services\ConflictGuard;
use App\Services\EquipmentWorkflow;
use App\Services\ProposalComparison;
use App\Services\ProposalOpeningWorkflow;
use App\Services\PurchaseControlPolicyWorkflow;
use App\Services\PurchaseRevisionWorkflow;
use App\Services\RequisitionWorkflow;
@@ -613,3 +616,14 @@ test('cancellation and reservation release roll back together if audit fails', f
->and(BudgetEntry::query()->where('kind', 'release')->count())->toBe(0)
->and((int) BudgetEntry::query()->sum('reserved_minor'))->toBeGreaterThan(0);
});
test('documentary noncompliance does not silently exclude an otherwise eligible award', function () {
$opening = app(ProposalOpeningWorkflow::class);
$comparison = app(ProposalComparison::class)->inspect($this->r);
$this->actingAs($this->buyer)->post('/requisicoes/'.$this->r->id.'/qualificacao', ['previous_id' => 0, 'basis_hash' => $opening->basis($opening->proposals($this->r)), 'reason' => 'Requisito documental fictício do processo', 'criteria' => [['label' => 'Requisito documental para conferência', 'category' => 'administrative', 'required' => true]]])->assertSessionHasNoErrors();
$set = QualificationSet::query()->sole();
$this->actingAs($this->finance)->post('/qualificacoes/'.$set->id.'/analises', ['previous_id' => 0, 'quotation_id' => $this->quotes[0]->id, 'reason' => 'Registo documental sem decisão formal', 'answers' => [['criterion_id' => 1, 'result' => 'not_met', 'evidence' => 'Referência de teste fictícia', 'reason' => 'Não conformidade registada para apreciação']]])->assertSessionHasNoErrors();
expect(app(ProposalComparison::class)->inspect($this->r))->toBe($comparison);
$order = issuePurchaseOrder($this, selectPurchaseAward($this));
expect($order->total_minor)->toBe(10000)->and(PurchaseOrder::query()->count())->toBe(1);
});