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

448 lines
15 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import {
recordSales,
saveSalesBook,
} from '../../resources/js/lib/iva-operations.ts';
import {
recordAcquisitions,
evaluateAcquisition,
saveAcquisitionBook,
acquisitionBook,
acquisitionCurrent,
acquisitionReportRows,
readAcquisitionStore,
} from '../../resources/js/lib/iva-acquisitions.ts';
import { saveImportExemptionBook } from '../../resources/js/lib/iva-import-exemptions.ts';
import {
newAcquisitionAllocation,
adoptAllocationReduced,
} from '../../resources/js/lib/iva-acquisition-allocation.ts';
import {
newReducedBase,
reducedBaseConditions,
ownReducedConditions,
recordReducedBases,
saveReducedBaseBook,
reducedBaseBook,
} from '../../resources/js/lib/iva-reduced-bases.ts';
const frozen = JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-l2d-preserved.json', import.meta.url),
'utf8',
),
);
export function allocationFixture() {
const draft = {
...structuredClone(frozen),
context_opportunity: 'opportunity:370',
project_title: 'SYNTHETIC QA — L2-D afectação e proporções',
};
const store = JSON.parse(frozen.modelo_a_snapshot);
draft.modelo_a_snapshot = saveSalesBook(
draft,
recordSales(
draft,
structuredClone(store.salesOperations['opportunity:369']),
),
);
draft.modelo_a_snapshot = saveImportExemptionBook(
draft,
structuredClone(store.importExemptions['opportunity:369']),
);
const base = store.books['opportunity:369'];
const d = (method, patch = {}) => ({
...newAcquisitionAllocation('2026-12'),
method,
numerator: '1',
denominator: '3',
unit: 'm2 utilizados',
scopeRef: 'SYNTHETIC QA entidade/actividades/ano2026',
source: 'SYNTHETIC QA contabilidade/critério',
communicationRef: 'SYNTHETIC QA comunicação prévia22(2)',
noExcludedPayments: 'yes',
basis: 'prior_year',
facts: {
scopeConfirmed: 'yes',
rightBasis: 'yes',
actualScope: 'yes',
communication: 'yes',
conditionsMet: 'yes',
annualScope: 'yes',
netExclusions: 'yes',
},
...patch,
});
const row = (id, method = 'actual', patch = {}, dpatch = {}) => ({
...structuredClone(base.rows[3]),
id,
description: 'SYNTHETIC QA ' + id,
documentRef: 'SYNTHETIC QA ' + id,
deductionLink: undefined,
allocation: 'mixed',
d: d(method, dpatch),
...patch,
});
const imported = {
...structuredClone(base.rows[0]),
id: 'imported',
deductionLink: undefined,
allocation: 'mixed',
d: d('pro_rata', { numerator: '2', denominator: '3' }),
};
const book = {
currency: 'MZN',
rightVersion: 'acquisition-operation-right/1',
taxpayerRegistered: 'yes',
rows: [
row('actual'),
row('pro-rata', 'pro_rata'),
row('diesel', 'actual', { bc: { ...base.rows[1].bc } }),
imported,
],
periods: structuredClone(base.periods),
};
return { draft, book, row, d };
}
void test('actual allocation uses exact fraction and prior communication,without inventing approval or bypassing C', () => {
const { draft, row } = allocationFixture();
const r = row('actual');
let value = evaluateAcquisition(r, 'MZN', 'yes', draft);
assert.deepEqual(value.deductibleExact, {
numerator: '16',
denominator: '3',
});
assert.deepEqual(value.nonDeductibleExact, {
numerator: '32',
denominator: '3',
});
assert.equal(value.eligibility.status, 'eligible');
for (const patch of [
{ numerator: '' },
{ denominator: '0' },
{ denominator: '0.1' },
{ unit: '' },
{ communicationRef: '' },
{ scopeRef: '' },
{ source: '' },
{ facts: { ...r.d.facts, communication: '' } },
{ facts: { ...r.d.facts, conditionsMet: '' } },
{ facts: { ...r.d.facts, rightBasis: '' } },
])
assert.equal(
evaluateAcquisition(
{ ...r, d: { ...r.d, ...patch } },
'MZN',
'yes',
draft,
).deductible,
null,
JSON.stringify(patch),
);
for (const patch of [
{ held: '' },
{ documentRef: '' },
{ legalDocument: '' },
{ documentDate: '2026-11-10' },
])
assert.equal(
evaluateAcquisition({ ...r, ...patch }, 'MZN', 'yes', draft)
.deductible,
null,
);
assert.equal(
evaluateAcquisition(
{ ...r, bc: { ...r.bc, expense: 'travel' } },
'MZN',
'yes',
draft,
).deductible,
'0.00',
);
assert.equal(
evaluateAcquisition(
{ ...r, bc: { ...r.bc, reducedSupply: 'yes' } },
'MZN',
'yes',
draft,
).deductible,
'0.00',
);
});
void test('pro rata uses annual prior year or declared initial estimate;ceil hundredth is preserved separately from money', () => {
const { draft, row } = allocationFixture();
const r = row('pro', 'pro_rata');
const calc = (patch) =>
evaluateAcquisition(
{ ...r, d: { ...r.d, ...patch } },
'MZN',
'yes',
draft,
);
const v = calc({});
assert.deepEqual(v.allocationCalculation.rawRatio, {
numerator: '1',
denominator: '3',
});
assert.deepEqual(v.allocationCalculation.ratio, {
numerator: '17',
denominator: '50',
});
assert.equal(v.deductible, '5.44');
assert.match(v.reason, /34%/);
assert.equal(calc({ numerator: '0' }).deductible, '0.00');
assert.equal(calc({ numerator: '3' }).deductible, '16.00');
assert.equal(calc({ numerator: '1', denominator: '2' }).deductible, '8.00');
for (const patch of [
{ referenceYear: '2026' },
{ actualRequired: 'yes' },
{ basis: '' },
{ facts: { ...r.d.facts, annualScope: '' } },
{ facts: { ...r.d.facts, netExclusions: '' } },
])
assert.equal(calc(patch).deductible, null, JSON.stringify(patch));
const initial = {
basis: 'initial_changed',
referenceYear: '2026',
declarationRef: 'SYNTHETIC QA início/alteração',
facts: { ...r.d.facts, initialChanged: 'yes' },
};
assert.equal(calc(initial).deductible, '5.44');
assert.equal(calc({ ...initial, declarationRef: '' }).deductible, null);
});
void test('F composes C diesel only once with D and import11,keeps exact fractions and unknown dependencies', () => {
const { draft, book } = allocationFixture();
const result = recordAcquisitions(draft, book).result;
assert.deepEqual(result.rows[2].allocationCalculation.before, {
numerator: '8',
denominator: '1',
});
assert.deepEqual(result.rows[2].deductibleExact, {
numerator: '8',
denominator: '3',
});
assert.deepEqual(
['09', '11', '14', '15', '16', '17', '18'].map(
(k) => result.periods[0].fields[k],
),
['13.44', '10.72', '1000.00', '24.16', '160.00', '135.84', '0.00'],
);
const incomplete = structuredClone(book);
incomplete.rows[0].d.denominator = '0';
assert.equal(
recordAcquisitions(draft, incomplete).result.periods[0].fields['15'],
null,
);
const coverage = structuredClone(book);
coverage.periods[0].importsComplete = false;
assert.equal(
recordAcquisitions(draft, coverage).result.periods[0].fields['17'],
null,
);
const duplicate = structuredClone(book);
duplicate.rows.push({ ...book.rows[0], id: 'duplicate' });
assert.throws(() => recordAcquisitions(draft, duplicate), /repetido/);
const saved = recordAcquisitions(draft, book);
draft.modelo_a_snapshot = saveAcquisitionBook(draft, saved);
addReduced(draft);
assert.equal(acquisitionCurrent(draft, saved), false);
const outputGap = recordAcquisitions(draft, saved).result;
assert.equal(outputGap.periods[0].fields['15'], '24.16');
assert.equal(outputGap.periods[0].fields['16'], null);
});
function addReduced(draft) {
const rows = [
'regulated_energy',
'aeronautical_fees',
'public_works',
'public_water',
].map((t) => ({
...newReducedBase(t, 'MZN'),
treatment: t,
description: 'SYNTHETIC QA ' + t,
period: '2026-12',
operationDate: '2026-12-10',
documentDate: '2026-12-10',
documentRef: 'SYNTHETIC QA ' + t,
priceRef: 'SYNTHETIC QA preço/taxa',
priceFrom: '2026-01-01',
priceScope: 'SYNTHETIC QA âmbito',
consideration: '100',
projectRef: 'SYNTHETIC QA contrato público',
workCategory: 'roads',
compositionRef: 'SYNTHETIC QA composição semIVA',
evidence: 'SYNTHETIC QA condições',
conditions: Object.fromEntries(
[...reducedBaseConditions, ...ownReducedConditions(t)].map(
([key]) => [key, 'yes'],
),
),
}));
draft.modelo_a_snapshot = saveReducedBaseBook(
draft,
recordReducedBases(draft, { rows }),
);
}
void test('18(6) reuses all four demonstrated reduced bases;no double base reduction or invented output tax', () => {
const { draft, row } = allocationFixture();
addReduced(draft);
const expected = {
regulated_energy: '9.92',
aeronautical_fees: '13.60',
public_works: '6.40',
public_water: '12.00',
};
for (const [id, value] of Object.entries(expected)) {
const r = row('purchase-' + id, 'reduced', {
allocation: 'taxable_only',
});
r.d = adoptAllocationReduced(draft, r.d, id);
r.d.facts.scopeConfirmed = 'yes';
const result = evaluateAcquisition(r, 'MZN', 'yes', draft);
assert.equal(result.deductible, value, id);
assert.equal(r.net, '100');
assert.equal(r.vat, '16');
const book = recordAcquisitions(draft, {
currency: 'MZN',
taxpayerRegistered: 'yes',
rows: [r],
periods: [
{
period: '2026-12',
complete: true,
importsComplete: true,
absent: ['12', '13'],
},
],
});
assert.equal(book.result.periods[0].fields['15'], value);
for (const f of ['14', '16', '17', '18'])
assert.equal(book.result.periods[0].fields[f], null, f);
const saved = {
...draft,
modelo_a_snapshot: saveAcquisitionBook(draft, book),
};
assert.ok(acquisitionCurrent(saved, book));
const removed = {
...saved,
modelo_a_snapshot: saveReducedBaseBook(saved, {
rows: reducedBaseBook(saved).rows,
}),
};
assert.equal(acquisitionCurrent(removed, book), false);
assert.equal(
evaluateAcquisition(
{ ...r, allocation: 'mixed' },
'MZN',
'yes',
draft,
).deductible,
null,
);
const changed = reducedBaseBook(draft);
changed.rows.find((x) => x.id === id).description += ' alteração';
const other = {
...draft,
modelo_a_snapshot: saveReducedBaseBook(
draft,
recordReducedBases(draft, changed),
),
};
assert.equal(
evaluateAcquisition(r, 'MZN', 'yes', other).deductible,
null,
);
}
});
void test('save recovery/report preserves every prior ABC/L1 book and frozen D histories;no automatic recalculation', () => {
let { draft, book } = allocationFixture();
const prior = JSON.parse(frozen.modelo_a_snapshot);
book = recordAcquisitions(draft, book);
draft.modelo_a_snapshot = saveAcquisitionBook(draft, book);
const first = structuredClone(book.result);
book = recordAcquisitions(draft, book);
draft.modelo_a_snapshot = saveAcquisitionBook(draft, book);
const recovered = JSON.parse(JSON.stringify(draft));
assert.ok(acquisitionCurrent(recovered, acquisitionBook(recovered)));
assert.deepEqual(book.history, [first]);
const current = JSON.parse(draft.modelo_a_snapshot);
for (const k of Object.keys(prior).filter((k) => k !== 'version'))
for (const [id, v] of Object.entries(prior[k]))
assert.deepEqual(current[k][id], v, k + id);
for (const scope of ['opportunity:368', 'opportunity:369'])
assert.ok(
acquisitionCurrent(
{ ...recovered, context_opportunity: scope },
prior.books[scope],
),
);
const report = JSON.stringify(acquisitionReportRows(recovered));
for (const token of [
'AfectaçãoD',
'16/3',
'1/3',
'34%',
'24.16',
'135.84',
'22(2)',
])
assert.ok(report.includes(token), token);
book.rows[0].d.numerator = '2';
draft.modelo_a_snapshot = saveAcquisitionBook(draft, book);
assert.equal(acquisitionCurrent(draft, book), false);
assert.deepEqual(book.history, [first]);
assert.match(
JSON.stringify(acquisitionReportRows(draft)),
/Histórico desactualizado/,
);
const broken = JSON.parse(recovered.modelo_a_snapshot);
broken.books['opportunity:370'].rows[0].d.facts.scopeConfirmed = 'maybe';
assert.throws(
() => readAcquisitionStore(JSON.stringify(broken)),
/AfectaçãoD/,
);
if (process.env.IVA_L2D_CALCULATED) {
const special = {
...recovered,
context_opportunity: 'opportunity:371',
};
special.modelo_a_snapshot = saveSalesBook(
special,
recordSales(
special,
structuredClone(current.salesOperations['opportunity:370']),
),
);
addReduced(special);
const reduced = allocationFixture().row(
'reduced-public-works',
'reduced',
{ allocation: 'taxable_only' },
);
reduced.d = adoptAllocationReduced(special, reduced.d, 'public_works');
reduced.d.facts.scopeConfirmed = 'yes';
const reducedBook = recordAcquisitions(special, {
currency: 'MZN',
taxpayerRegistered: 'yes',
rows: [reduced],
periods: [
{
period: '2026-12',
complete: true,
importsComplete: true,
absent: ['12', '13'],
},
],
});
special.modelo_a_snapshot = saveAcquisitionBook(special, reducedBook);
fs.writeFileSync(
process.env.IVA_L2D_CALCULATED,
JSON.stringify({
...special,
context_opportunity: 'opportunity:370',
}),
);
}
});