169 lines
5.7 KiB
JavaScript
169 lines
5.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import fs from 'node:fs';
|
|
import { l1DeltaFixture } from './fixtures/iva-l1-delta-fixture.mjs';
|
|
import {
|
|
calculateSales,
|
|
evaluateSalesOperation,
|
|
modeloA06Correspondence,
|
|
salesBook,
|
|
salesCurrent,
|
|
saveSalesBook,
|
|
} from '../../resources/js/lib/iva-operations.ts';
|
|
import {
|
|
calculateAcquisitions,
|
|
saveAcquisitionBook,
|
|
} from '../../resources/js/lib/iva-acquisitions.ts';
|
|
import {
|
|
addFractions,
|
|
decimalFraction,
|
|
fraction,
|
|
fractionLabel,
|
|
fractionPresentation,
|
|
} from '../../resources/js/lib/fiscal-rational.ts';
|
|
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
|
|
void test('periodic included5% retains exact rational amounts; only presentation is rounded', () => {
|
|
const { book } = l1DeltaFixture(),
|
|
r = book.result.rows[0];
|
|
assert.deepEqual(r.exact.net, { numerator: '20', denominator: '21' });
|
|
assert.deepEqual(r.exact.vat, { numerator: '1', denominator: '21' });
|
|
assert.equal(r.net, '0.952381');
|
|
assert.equal(r.vat, '0.047619');
|
|
assert.equal(r.status, 'calculated');
|
|
assert.match(r.reason, /apresentação técnica/);
|
|
assert.deepEqual(addFractions([r.exact.net, r.exact.vat]), r.exact.gross);
|
|
assert.deepEqual(book.result.rows[1].exact.vat, {
|
|
numerator: '100',
|
|
denominator: '21',
|
|
});
|
|
});
|
|
void test('aggregation uses exact fractions, not21 rounded values', () => {
|
|
const { draft, book } = l1DeltaFixture();
|
|
book.rows = Array.from({ length: 21 }, (_, i) => ({
|
|
...book.rows[0],
|
|
id: `q${i}`,
|
|
}));
|
|
const r = calculateSales(draft, book);
|
|
assert.equal(
|
|
r.rows.every((row) => row.vat === '0.047619'),
|
|
true,
|
|
);
|
|
assert.equal(r.periods[0].fields['04'], '1.00');
|
|
assert.deepEqual(r.periods[0].exactFields['04'], {
|
|
numerator: '1',
|
|
denominator: '1',
|
|
});
|
|
assert.equal(r.periods[0].fields['03'], '20.00');
|
|
});
|
|
void test('new version round trips by opportunity, keeping accepted first snapshot untouched', () => {
|
|
const accepted = JSON.parse(
|
|
fs.readFileSync(
|
|
new URL('./fixtures/iva-operations.json', import.meta.url),
|
|
'utf8',
|
|
),
|
|
);
|
|
const original = JSON.parse(accepted.modelo_a_snapshot).salesOperations[
|
|
'opportunity:309'
|
|
];
|
|
const { draft, book } = l1DeltaFixture();
|
|
const saved = JSON.parse(
|
|
JSON.stringify({
|
|
...draft,
|
|
modelo_a_snapshot: saveSalesBook(draft, book),
|
|
}),
|
|
);
|
|
assert.deepEqual(
|
|
JSON.parse(saved.modelo_a_snapshot).salesOperations['opportunity:309'],
|
|
original,
|
|
);
|
|
assert.equal(salesCurrent(saved, salesBook(saved)), true);
|
|
assert.deepEqual(
|
|
salesBook(saved).result.rows[2].exact,
|
|
book.result.rows[2].exact,
|
|
);
|
|
});
|
|
void test('conditional14-18 and report carry exact precision rather than rounded line amounts', () => {
|
|
const { draft, book } = l1DeltaFixture();
|
|
const a = {
|
|
currency: 'MZN',
|
|
rows: [],
|
|
periods: ['2026-01', '2026-02', '2026-03', '2026-04'].map((period) => ({
|
|
period,
|
|
complete: true,
|
|
absent: ['03', '04', '05', '06', '07', '11', '12', '13'],
|
|
})),
|
|
};
|
|
const result = calculateAcquisitions(draft, a);
|
|
assert.equal(
|
|
fractionLabel(result.periods[0].exactFields['17']),
|
|
'5051/1050',
|
|
);
|
|
assert.equal(result.periods[0].fields['17'], '4.810476');
|
|
a.result = result;
|
|
draft.modelo_a_snapshot = saveAcquisitionBook(draft, a);
|
|
const report = JSON.stringify(
|
|
createProjectDossierReport(draft, {
|
|
selectedSections: new Set(['finance']),
|
|
}),
|
|
);
|
|
assert.match(report, /5051\/1050/);
|
|
assert.match(report, /20\/21/);
|
|
assert.match(report, /opportunity:310/);
|
|
assert.match(report, /apresentação técnica/);
|
|
assert.equal(book.result.rows.length, 3);
|
|
});
|
|
void test('missing inputs still block only the affected result; invalid fractions do not become zero', () => {
|
|
const { book } = l1DeltaFixture();
|
|
assert.equal(
|
|
evaluateSalesOperation({ ...book.rows[0], amount: '' }, 'MZN').vat,
|
|
null,
|
|
);
|
|
assert.equal(
|
|
evaluateSalesOperation({ ...book.rows[0], basis: '' }, 'MZN').vat,
|
|
null,
|
|
);
|
|
assert.equal(
|
|
evaluateSalesOperation({ ...book.rows[0], amount: '0' }, 'MZN').vat,
|
|
'0.00',
|
|
);
|
|
const { draft } = l1DeltaFixture();
|
|
book.rows[0].sourceAmount = '1';
|
|
const stale = calculateSales(draft, book).rows[0];
|
|
assert.equal(stale.vat, null);
|
|
assert.equal(stale.exact, undefined);
|
|
assert.throws(() =>
|
|
fractionPresentation({ numerator: '1', denominator: '0' }),
|
|
);
|
|
assert.equal(fractionPresentation(fraction(1n, 21n)).approximate, true);
|
|
assert.equal(
|
|
fractionPresentation(decimalFraction('105')).approximate,
|
|
false,
|
|
);
|
|
});
|
|
void test('confirmed form06 correspondence preserves unknown foreign treatment', () => {
|
|
const { book } = l1DeltaFixture();
|
|
const r = evaluateSalesOperation(
|
|
{ ...book.rows[0], treatment: 'foreign_operation' },
|
|
'MZN',
|
|
);
|
|
assert.equal(r.field, null);
|
|
assert.equal(r.vat, null);
|
|
assert.match(
|
|
modeloA06Correspondence,
|
|
/Correspond\u00eancia confirmada pela Tempo/,
|
|
);
|
|
assert.match(
|
|
modeloA06Correspondence,
|
|
/Opera\u00e7\u00e3o no estrangeiro n\u00e3o significa06/,
|
|
);
|
|
assert.match(
|
|
modeloA06Correspondence,
|
|
/Originais e resultados hist\u00f3ricos preservados/,
|
|
);
|
|
});
|
|
if (process.env.IVA_L1_DELTA_OUT)
|
|
fs.writeFileSync(
|
|
process.env.IVA_L1_DELTA_OUT,
|
|
JSON.stringify(l1DeltaFixture().draft, null, 2),
|
|
);
|