Files
Investidor-V2/tests/frontend/iva-offer-workflow.test.mjs
T

242 lines
8.7 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
newOfferPreparation,
emptyOfferRequest,
saveOfferPreparationBook,
offerPreparationBook,
offerScenarios,
offerPathReport,
} from '../../resources/js/lib/iva-offer-preparations.ts';
import {
emptyOfferWorkflow,
recordOfferWorkflow,
offerWorkflowApplied,
offerWrittenRequest,
} from '../../resources/js/lib/iva-offer-workflow.ts';
const frozen = JSON.parse(
fs.readFileSync('tests/frontend/fixtures/iva-returnees.json', 'utf8'),
),
draft = {
...frozen,
context_opportunity: 'opportunity:364',
project_title: 'SYNTHETIC QA — Pedidos ofertas / Manica',
},
prior = JSON.parse(frozen.modelo_a_snapshot);
const attachment = {
id: '00000000-0000-4000-8000-000000000001',
draftId: '00000000-0000-4000-8000-000000000002',
name: 'SYNTHETIC-QA-despacho.txt',
sha256: 'a'.repeat(64),
scan: 'pending',
url: '/api/v1/simulation-drafts/00000000-0000-4000-8000-000000000002/offer-documents/00000000-0000-4000-8000-000000000001',
};
function initial(branch) {
return {
...newOfferPreparation(branch, branch, 'MZN'),
operation: 'acquisition',
description: 'SYNTHETIC QA bensA',
period: '2026-10',
amount: '1000',
beneficiary: 'SYNTHETIC QA entidade',
purpose:
branch === 'P084'
? 'SYNTHETIC QA interesse público/fins sociais'
: 'SYNTHETIC QA atenuar cheias',
evidence: 'SYNTHETIC QA justificação',
nationalInstitution: 'yes',
publicSocialInstitution: 'yes',
goodsSuitable: 'yes',
publicInterestUse: 'yes',
mitigation: 'yes',
disaster: 'SYNTHETIC QA cheias',
humanitarianPurpose: 'SYNTHETIC QA assistência humanitária',
normalVat: '160',
normalVatSource: 'SYNTHETIC QA hipótese',
conditionalAssumption: 'yes',
request: emptyOfferRequest(),
workflow: emptyOfferWorkflow(),
};
}
const completed = [];
for (const branch of ['P084', 'P085'])
void test(
branch +
' pedido → apresentação externa → decisão anexa → formulário com despacho',
() => {
let row = recordOfferWorkflow(initial(branch), 'request');
assert.equal(offerWorkflowApplied(row).applied, false);
assert.match(
offerWrittenRequest(row, row.workflow),
/apresentação ocorre fora/,
);
row = {
...row,
request: {
...row.request,
state: 'presented',
reference: 'SYNTHETIC QA pedido1',
presentedOn: '2026-10-01',
},
};
row = recordOfferWorkflow(row, 'presented');
assert.equal(offerScenarios(row).applied, false);
assert.equal(offerScenarios(row).conditionalVat, '0.00');
row = {
...row,
request: {
...row.request,
state: 'granted',
decisionRef: 'SYNTHETIC QA despacho1',
decisionOn: '2026-10-03',
goods: 'SYNTHETIC QA apenas bensA',
operation: 'acquisition',
periodFrom: '2026-10',
periodTo: '2026-10',
conditions: 'SYNTHETIC QA só operaçãoA',
},
workflow: {
...row.workflow,
decisionIssuer: 'SYNTHETIC QA MF/AT',
decisionAttachment: attachment,
scopeConfirmed: 'yes',
},
};
row = recordOfferWorkflow(row, 'decision');
assert.equal(offerScenarios(row).applied, true);
assert.throws(
() =>
recordOfferWorkflow(
{ ...row, description: 'outros bens' },
'form',
),
/explicitamente/,
);
const outside = recordOfferWorkflow(
{
...row,
request: {
...row.request,
periodFrom: '2027-01',
periodTo: '2027-01',
},
},
'decision',
);
assert.equal(offerWorkflowApplied(outside).applied, false);
assert.equal(offerScenarios(row).appliedVat, '0.00');
assert.equal(
offerWorkflowApplied({ ...row, description: 'outros bens' })
.applied,
false,
);
assert.equal(
offerWorkflowApplied({ ...row, period: '2026-11' }).applied,
false,
);
assert.equal(
offerWorkflowApplied({ ...row, beneficiary: 'outra entidade' })
.applied,
false,
);
assert.equal(
offerWorkflowApplied({
...row,
request: { ...row.request, state: 'denied' },
}).applied,
false,
);
row = {
...row,
workflow: {
...row.workflow,
formName: 'SYNTHETIC QA formulário aplicável',
formSource:
'SYNTHETIC QA correspondência documentada apenas operaçãoA',
formContent: offerWrittenRequest(row, row.workflow),
},
};
row = recordOfferWorkflow(row, 'form');
assert.equal(row.workflow.formDecisionId, attachment.id);
assert.equal(row.workflow.formDecisionHash, attachment.sha256);
assert.deepEqual(
row.workflow.records.map((r) => r.stage),
['request', 'presented', 'decision', 'form'],
);
assert.match(
offerPathReport(row),
/Procedimento operacional fornecido pela Tempo/,
);
assert.match(offerPathReport(row), /submissão fora/);
assert.match(offerPathReport(row), /SYNTHETIC QA pedido1/);
assert.match(offerPathReport(row), /2026-10-01/);
completed.push(row);
},
);
void test('decisão e formulário incompletos não bloqueiam guardar rascunho nem inventam concessão', () => {
const row = initial('P085');
assert.throws(
() =>
recordOfferWorkflow(
{ ...row, request: { ...row.request, state: 'presented' } },
'presented',
),
/referência/,
);
assert.throws(
() =>
recordOfferWorkflow(
{ ...row, request: { ...row.request, state: 'granted' } },
'decision',
),
/número/,
);
const denied = {
...completed[0],
request: { ...completed[0].request, state: 'denied' },
};
assert.throws(() => recordOfferWorkflow(denied, 'form'), /indeferimento/);
for (const patch of [
{ decisionIssuer: '' },
{ decisionAttachment: undefined },
{ scopeConfirmed: 'no' },
])
assert.equal(
offerWorkflowApplied({
...completed[0],
workflow: { ...completed[0].workflow, ...patch },
}).applied,
false,
);
const value = saveOfferPreparationBook(draft, { rows: [row] });
assert.equal(
offerPreparationBook({ ...draft, modelo_a_snapshot: value }).rows[0]
.workflow.records.length,
0,
);
});
void test('127 fechos e P058 parcial conservados;histórico e ambos percursos recuperáveis', () => {
const old = prior.offerPreparations ?? {};
const value = saveOfferPreparationBook(draft, { rows: completed });
draft.modelo_a_snapshot = value;
const next = JSON.parse(value);
assert.deepEqual(
Object.fromEntries(
Object.entries(next).filter(([k]) => k !== 'offerPreparations'),
),
Object.fromEntries(
Object.entries(prior).filter(([k]) => k !== 'offerPreparations'),
),
);
for (const [k, v] of Object.entries(old))
assert.deepEqual(next.offerPreparations[k], v);
assert.equal(offerPreparationBook(draft).rows.length, 2);
assert.deepEqual(next.returneeImports, prior.returneeImports);
if (process.env.IVA_OFFER_WORKFLOW_FIXTURE)
fs.writeFileSync(
'tests/frontend/fixtures/iva-offer-workflow.json',
JSON.stringify(draft),
);
});