Files
Investidor-V2/tests/frontend/iva-acquisition-continuity.test.mjs
T

212 lines
7.3 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
acquisitionTreatmentIssue,
continueWithoutFormerExploration,
formerExplorationSource,
} from '../../resources/js/lib/iva-acquisition-continuity.ts';
import {
newAcquisition,
evaluateAcquisition,
recordAcquisitions,
acquisitionBook,
acquisitionCurrent,
saveAcquisitionBook,
acquisitionReportRows,
} from '../../resources/js/lib/iva-acquisitions.ts';
import { salesCurrent } from '../../resources/js/lib/iva-operations.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const frozen = JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-g5a-inputs.json', import.meta.url),
'utf8',
),
);
const row = () => ({
...newAcquisition('g5b-0', '2026-12', 'MZN'),
field: '10',
net: '100',
vat: '16',
gross: '116',
documentType: 'invoice',
documentRef: 'SYNTHETIC QA G5B 001',
documentDate: '2026-12-10',
supplier: 'SYNTHETIC QA fornecedor',
supplierRegistered: 'yes',
legalDocument: 'yes',
held: 'yes',
domestic: 'yes',
allocation: 'taxable_only',
exclusion: 'none',
integrity: 'yes',
description:
'SYNTHETIC QA — serviço de pesquisa; antiga referência14(2)(c)',
acquisitionTreatment: 'former_exploration_exemption',
});
function fixture() {
const draft = {
...structuredClone(frozen),
context_opportunity: 'opportunity:329',
project_title: 'SYNTHETIC QA — G5B / Continuidade da aquisição',
};
const prior = recordAcquisitions(draft, {
currency: 'MZN',
taxpayerRegistered: 'yes',
rows: [row()],
periods: [{ period: '2026-12', complete: true, absent: [] }],
});
draft.modelo_a_snapshot = saveAcquisitionBook(draft, prior);
return { draft, prior };
}
void test('2017 rectification prevents former14(2)(c) exemption in2026,including explicit zero;unknown is not a normal treatment', () => {
assert.match(formerExplorationSource, /BR89/);
assert.match(
acquisitionTreatmentIssue('former_exploration_exemption'),
/eliminada/,
);
for (const vat of ['16', '0', '']) {
const input = { ...row(), vat, gross: vat === '0' ? '100' : '116' },
result = evaluateAcquisition(input, 'MZN', 'yes');
assert.equal(result.deductible, null);
assert.match(result.reason, /Não se aplica nesta cobertura2026/);
assert.equal(input.net, '100');
}
assert.equal(
evaluateAcquisition(
{ ...row(), acquisitionTreatment: 'unknown' },
'MZN',
'yes',
).deductible,
null,
);
assert.match(
evaluateAcquisition({ ...row(), period: '2016-12' }, 'MZN', 'yes')
.reason,
/fora do âmbito/,
);
});
void test('explicit continuation keeps values,document,answers and source;normal deduction requires existing conditions', () => {
const input = row(),
next = continueWithoutFormerExploration(input);
for (const key of Object.keys(input).filter(
(k) => k !== 'acquisitionTreatment',
))
assert.deepEqual(next[key], input[key], key);
assert.equal(input.acquisitionTreatment, 'former_exploration_exemption');
assert.equal(next.acquisitionTreatment, 'normal');
assert.equal(
next.acquisitionTreatmentOrigin.id,
'former_exploration_exemption',
);
assert.equal(evaluateAcquisition(next, 'MZN', 'yes').deductible, '16.00');
for (const patch of [
{ held: '' },
{ allocation: 'mixed' },
{ legalDocument: '' },
{ sourceCurrency: 'USD' },
{ vat: '', gross: '' },
{ domestic: 'no' },
{ documentDate: '2026-11-10' },
])
assert.equal(
evaluateAcquisition({ ...next, ...patch }, 'MZN', 'yes').deductible,
null,
);
assert.throws(
() =>
continueWithoutFormerExploration({
...input,
acquisitionTreatment: 'normal',
}),
/antiga referência/,
);
});
void test('manual purchase month does not require sales;previous classification remains in history and incomplete totals remain unknown', () => {
const { draft, prior } = fixture();
assert.equal(draft.monthly_iva_settings, undefined);
assert.equal(prior.result.rows[0].deductible, null);
assert.equal(prior.result.periods[0].fields['10'], null);
const next = recordAcquisitions(draft, {
...prior,
rows: [continueWithoutFormerExploration(prior.rows[0])],
});
assert.deepEqual(next.history, [prior.result]);
assert.equal(next.result.rows[0].deductible, '16.00');
assert.equal(next.result.periods[0].fields['10'], '16.00');
for (const f of ['01', '02', '11', '14', '15', '16', '17', '18'])
assert.equal(next.result.periods[0].fields[f], null, f);
assert.throws(
() => recordAcquisitions(draft, { ...next, periods: [] }),
/meses aplicáveis/,
);
assert.throws(
() =>
recordAcquisitions(draft, {
...next,
periods: [...next.periods, ...next.periods],
}),
/meses aplicáveis/,
);
assert.throws(
() =>
recordAcquisitions(draft, {
...next,
rows: [
{
...next.rows[0],
sourceMonth: 1,
sourceAmount: '100',
sourceBasis: 'net',
},
],
}),
/orçamentos do plano mudaram/,
);
});
void test('save/recovery/report retain rectification,continuation and history;all20 prior sales books stay identical/current', () => {
const { draft, prior } = fixture();
const book = recordAcquisitions(draft, {
...prior,
rows: [continueWithoutFormerExploration(prior.rows[0])],
});
draft.modelo_a_snapshot = saveAcquisitionBook(draft, book);
assert.ok(acquisitionCurrent(draft, book));
assert.deepEqual(
acquisitionBook(JSON.parse(JSON.stringify(draft))),
JSON.parse(JSON.stringify(book)),
);
const before = JSON.parse(frozen.modelo_a_snapshot),
after = JSON.parse(draft.modelo_a_snapshot);
assert.equal(Object.keys(before.salesOperations).length, 20);
assert.deepEqual(after.salesOperations, before.salesOperations);
assert.deepEqual(Object.keys(after.books), ['opportunity:329']);
for (const [context, original] of Object.entries(before.salesOperations))
assert.ok(
salesCurrent({ ...draft, context_opportunity: context }, original),
);
const report = JSON.stringify(
createProjectDossierReport(draft, {
selectedSections: new Set(['finance']),
version: 'QA G5B',
}),
);
for (const token of [
'opportunity:329',
'Manica',
'2026-12',
'16.00',
'BR89',
'Continuidade14(2)(c)',
'eliminado',
'expressamente escolhida',
])
assert.ok(report.includes(token), token);
assert.match(
JSON.stringify(acquisitionReportRows(draft)),
/antiga isenção/,
);
if (process.env.IVA_G5B_CALCULATED)
fs.writeFileSync(process.env.IVA_G5B_CALCULATED, JSON.stringify(draft));
});