324 lines
10 KiB
JavaScript
324 lines
10 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import {
|
|
newFuelBase,
|
|
switchFuelTaxTreatment,
|
|
fuelBaseTreatments,
|
|
fuelBaseConditions,
|
|
evaluateFuelBase,
|
|
recordFuelBases,
|
|
saveFuelBaseBook,
|
|
fuelBaseBook,
|
|
fuelBaseCurrent,
|
|
fuelBaseReportRows,
|
|
} from '../../resources/js/lib/iva-fuel-base.ts';
|
|
import { actSaleCurrent } from '../../resources/js/lib/iva-act-sale-base.ts';
|
|
import { commissionBaseCurrent } from '../../resources/js/lib/iva-commission-base.ts';
|
|
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
|
|
const frozen = JSON.parse(
|
|
fs.readFileSync(
|
|
new URL('./fixtures/iva-g7d-preserved-inputs.json', import.meta.url),
|
|
'utf8',
|
|
),
|
|
);
|
|
const row = (treatment = fuelBaseTreatments[0].id) => ({
|
|
...newFuelBase('g7d-' + treatment, 'MZN'),
|
|
treatment,
|
|
description: 'SYNTHETIC QA revenda de combustível A',
|
|
period: '2026-12',
|
|
operationDate: '2026-12-12',
|
|
priceRef: 'SYNTHETIC QA referência preço A / Autoridade Pública',
|
|
priceScope:
|
|
'SYNTHETIC QA combustível A, revenda A, Manica, dezembro2026, pressupostos',
|
|
priceFrom: '2026-12-01',
|
|
priceTo: '2026-12-31',
|
|
documentRef: 'SYNTHETIC QA G7D ' + treatment,
|
|
documentDate: '2026-12-12',
|
|
consideration: '1500.25',
|
|
fuelTax: '100.10',
|
|
fuelTaxRef: 'SYNTHETIC QA TC desta operação sem estimar taxa',
|
|
compositionRef: 'SYNTHETIC QA composição15(1)/(5)/(6),líquida de IVA',
|
|
evidence: 'SYNTHETIC QA pressupostos expressos,não documento real',
|
|
conditions: Object.fromEntries(
|
|
fuelBaseConditions.map(([key]) => [key, 'yes']),
|
|
),
|
|
});
|
|
const draft = () => ({
|
|
...structuredClone(frozen),
|
|
context_opportunity: 'opportunity:342',
|
|
project_title: 'SYNTHETIC QA — G7D / Bases de combustíveis',
|
|
});
|
|
|
|
void test('P095 own resale/price/scope/composition conditions; missing references and wrong date never become zero', () => {
|
|
for (const rule of fuelBaseTreatments) {
|
|
const input = row(rule.id),
|
|
ok = evaluateFuelBase(input, 'MZN');
|
|
assert.equal(ok.status, 'determined');
|
|
assert.equal(
|
|
ok.baseAmount,
|
|
rule.id === 'fuel_tax_included' ? '1400.15' : '1500.25',
|
|
);
|
|
assert.equal(ok.vat, null);
|
|
assert.equal(ok.rate, null);
|
|
for (const [key] of fuelBaseConditions)
|
|
for (const value of ['', 'unknown', 'no']) {
|
|
const r = evaluateFuelBase(
|
|
{
|
|
...input,
|
|
conditions: { ...input.conditions, [key]: value },
|
|
},
|
|
'MZN',
|
|
);
|
|
assert.equal(
|
|
r.status,
|
|
value === 'no' ? 'not_applicable' : 'indeterminate',
|
|
);
|
|
assert.equal(r.baseAmount, null);
|
|
assert.equal(r.vat, null);
|
|
}
|
|
for (const patch of [
|
|
{ description: '' },
|
|
{ priceRef: '' },
|
|
{ priceScope: '' },
|
|
{ documentRef: '' },
|
|
{ documentDate: '2026-02-30' },
|
|
{ compositionRef: '' },
|
|
{ evidence: '' },
|
|
{ period: '2025-12' },
|
|
{ currency: 'USD' },
|
|
{ treatment: 'unknown' },
|
|
{ operationDate: '2026-11-12' },
|
|
{ operationDate: '2026-02-30' },
|
|
{ priceFrom: '' },
|
|
{ priceTo: 'invalid' },
|
|
{ priceFrom: '2026-12-20' },
|
|
{ priceTo: '2026-12-11' },
|
|
{ priceFrom: '2026-12-31', priceTo: '2026-12-01' },
|
|
])
|
|
assert.equal(
|
|
evaluateFuelBase({ ...input, ...patch }, 'MZN').baseAmount,
|
|
null,
|
|
);
|
|
assert.equal(
|
|
evaluateFuelBase({ ...input, priceTo: '' }, 'MZN').status,
|
|
'determined',
|
|
);
|
|
for (const operationDate of ['2026-12-01', '2026-12-31'])
|
|
assert.equal(
|
|
evaluateFuelBase({ ...input, operationDate }, 'MZN').status,
|
|
'determined',
|
|
);
|
|
}
|
|
});
|
|
|
|
void test('TC subtracted exactly once only when included; zero,precision,excess and treatment changes preserve inputs', () => {
|
|
const input = row();
|
|
for (const [patch, expected] of [
|
|
[{ consideration: '0', fuelTax: '0' }, '0.00'],
|
|
[{ consideration: '1.000002', fuelTax: '0.000001' }, '1.000001'],
|
|
[
|
|
{ consideration: '999999999999999.999999', fuelTax: '0.000001' },
|
|
'999999999999999.999998',
|
|
],
|
|
[
|
|
{
|
|
treatment: 'fuel_tax_excluded',
|
|
fuelTax: 'invalid',
|
|
fuelTaxRef: '',
|
|
},
|
|
'1500.25',
|
|
],
|
|
])
|
|
assert.equal(
|
|
evaluateFuelBase({ ...input, ...patch }, 'MZN').baseAmount,
|
|
expected,
|
|
);
|
|
for (const patch of [
|
|
{ consideration: '' },
|
|
{ fuelTax: '' },
|
|
{ fuelTaxRef: '' },
|
|
{ consideration: '-1' },
|
|
{ fuelTax: 'NaN' },
|
|
{ fuelTax: '0.0000001' },
|
|
{ fuelTax: '1500.26' },
|
|
])
|
|
assert.equal(
|
|
evaluateFuelBase({ ...input, ...patch }, 'MZN').baseAmount,
|
|
null,
|
|
);
|
|
const switched = switchFuelTaxTreatment(input, 'fuel_tax_excluded');
|
|
assert.equal(switched.conditions.fuelTaxTreatment, '');
|
|
for (const field of [
|
|
'consideration',
|
|
'fuelTax',
|
|
'fuelTaxRef',
|
|
'priceRef',
|
|
'priceScope',
|
|
'priceFrom',
|
|
'priceTo',
|
|
'documentRef',
|
|
])
|
|
assert.equal(switched[field], input[field]);
|
|
assert.equal(evaluateFuelBase(switched, 'MZN').baseAmount, null);
|
|
assert.equal(
|
|
evaluateFuelBase(
|
|
{
|
|
...switched,
|
|
conditions: { ...switched.conditions, fuelTaxTreatment: 'yes' },
|
|
},
|
|
'MZN',
|
|
).baseAmount,
|
|
'1500.25',
|
|
);
|
|
});
|
|
|
|
void test('save/recovery/history/report preserve all81 delivered books including P094/P091 and currentkeys', () => {
|
|
const d = draft(),
|
|
prior = JSON.parse(d.modelo_a_snapshot);
|
|
assert.deepEqual(fuelBaseBook(d), { rows: [] });
|
|
assert.deepEqual(fuelBaseReportRows(d), []);
|
|
let book = recordFuelBases(d, {
|
|
rows: fuelBaseTreatments.map((rule) => ({
|
|
...row(rule.id),
|
|
conditions: {},
|
|
})),
|
|
});
|
|
book = recordFuelBases(d, {
|
|
...book,
|
|
rows: fuelBaseTreatments.map((rule) => ({
|
|
...row(rule.id),
|
|
conditions: { ...row(rule.id).conditions, publicFixedPrice: 'no' },
|
|
})),
|
|
});
|
|
book = recordFuelBases(d, {
|
|
...book,
|
|
rows: fuelBaseTreatments.map((rule) => row(rule.id)),
|
|
});
|
|
assert.equal(book.history.length, 2);
|
|
assert.ok(
|
|
book.history.every((h) =>
|
|
h.rows.every((r) => r.baseAmount === null && r.vat === null),
|
|
),
|
|
);
|
|
assert.ok(fuelBaseCurrent(d, book));
|
|
for (const field of [
|
|
'treatment',
|
|
'consideration',
|
|
'fuelTax',
|
|
'fuelTaxRef',
|
|
'priceRef',
|
|
'priceScope',
|
|
'priceFrom',
|
|
'priceTo',
|
|
'operationDate',
|
|
])
|
|
assert.ok(
|
|
!fuelBaseCurrent(d, {
|
|
...book,
|
|
rows: book.rows.map((r) => ({ ...r, [field]: 'changed' })),
|
|
}),
|
|
);
|
|
for (const patch of [
|
|
{ context_opportunity: 'opportunity:343' },
|
|
{ currency: 'USD' },
|
|
{ selection_labels: { province_id: 'Maputo' } },
|
|
])
|
|
assert.ok(!fuelBaseCurrent({ ...d, ...patch }, book));
|
|
d.modelo_a_snapshot = saveFuelBaseBook(d, book);
|
|
assert.deepEqual(fuelBaseBook(JSON.parse(JSON.stringify(d))), book);
|
|
const next = JSON.parse(d.modelo_a_snapshot);
|
|
const { regulatedFuelBases: _regulatedFuelBases, ...untouched } = next;
|
|
assert.deepEqual(untouched, prior);
|
|
for (const [scope, previous] of Object.entries(prior.actSaleBases))
|
|
assert.ok(
|
|
actSaleCurrent({ ...d, context_opportunity: scope }, previous),
|
|
);
|
|
for (const [scope, previous] of Object.entries(prior.commissionBases))
|
|
assert.ok(
|
|
commissionBaseCurrent(
|
|
{ ...d, context_opportunity: scope },
|
|
previous,
|
|
),
|
|
);
|
|
assert.equal(
|
|
next.actSaleBases['opportunity:341'].result.rows[1].baseAmount,
|
|
'2200.50',
|
|
);
|
|
assert.equal(
|
|
next.commissionBases['opportunity:340'].result.rows[0].baseAmount,
|
|
'900.15',
|
|
);
|
|
assert.equal(
|
|
next.publicAuthorityBases['opportunity:339'].result.rows[0].vat,
|
|
null,
|
|
);
|
|
assert.equal(
|
|
next.importExemptions['opportunity:338'].result.rows[1].importVat,
|
|
'400.00',
|
|
);
|
|
assert.equal(
|
|
next.books['opportunity:329'].result.periods[0].fields['11'],
|
|
null,
|
|
);
|
|
const report = JSON.stringify(
|
|
createProjectDossierReport(d, {
|
|
selectedSections: new Set(['finance']),
|
|
version: 'QA G7D',
|
|
}),
|
|
);
|
|
for (const token of [
|
|
'Base P095',
|
|
'1400.15',
|
|
'1500.25',
|
|
'IVA: Indeterminado',
|
|
'opportunity:342',
|
|
'Manica',
|
|
'2026-12-12',
|
|
'preço A',
|
|
'15(2)(i)',
|
|
'100.10',
|
|
'2026-12-01',
|
|
'2026-12-31',
|
|
'campo11',
|
|
])
|
|
assert.ok(report.includes(token), token);
|
|
assert.deepEqual(
|
|
fuelBaseReportRows({ ...d, context_opportunity: 'opportunity:343' }),
|
|
[],
|
|
);
|
|
if (process.env.IVA_G7D_CALCULATED)
|
|
fs.writeFileSync(process.env.IVA_G7D_CALCULATED, JSON.stringify(d));
|
|
});
|
|
|
|
void test('corrupt fuel rows/store cannot overwrite originals; duplicate operation identifiers cannot be recorded', () => {
|
|
const d = draft(),
|
|
original = d.modelo_a_snapshot;
|
|
for (const patch of [
|
|
{ fuelTax: 4 },
|
|
{ conditions: [] },
|
|
{ priceRef: null },
|
|
])
|
|
assert.throws(
|
|
() => saveFuelBaseBook(d, { rows: [{ ...row(), ...patch }] }),
|
|
/originais preservados/,
|
|
);
|
|
assert.equal(d.modelo_a_snapshot, original);
|
|
assert.throws(
|
|
() => recordFuelBases(d, { rows: [row(), row()] }),
|
|
/distintos/,
|
|
);
|
|
assert.throws(() => recordFuelBases(d, { rows: [] }), /distintos/);
|
|
assert.throws(
|
|
() =>
|
|
fuelBaseBook({
|
|
...d,
|
|
modelo_a_snapshot: JSON.stringify({
|
|
...JSON.parse(original),
|
|
regulatedFuelBases: [],
|
|
}),
|
|
}),
|
|
/originais preservados/,
|
|
);
|
|
});
|