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

148 lines
4.9 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {
operationTreatments,
newSalesOperation,
evaluateSalesOperation,
recordSales,
saveSalesBook,
salesBook,
salesCurrent,
} from '../../resources/js/lib/iva-operations.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const ids = [
'industrial_feed',
'industrial_feed_inputs',
'veterinary_goods',
'agricultural_services',
];
function seed() {
return JSON.parse(
fs.readFileSync(
new URL('./fixtures/iva-publications.json', import.meta.url),
'utf8',
),
);
}
function fixture() {
const draft = seed();
draft.context_opportunity = 'opportunity:314';
draft.project_title = 'SYNTHETIC QA — G2E social';
let book = {
currency: 'MZN',
rows: ids.map((id, i) => ({
...newSalesOperation(`g2e-${i}`, '2026-06', 'MZN'),
description: `SYNTHETIC QA ${id}`,
establishment: 'SYNTHETIC QA equipamento Manica',
amount: '100',
basis: i % 2 ? 'included' : 'net',
treatment: id,
confirmed: operationTreatments
.find((t) => t.id === id)
.conditions.map((_, n) => n),
evidence:
'SYNTHETIC QA — natureza, entidade, reconhecimento e condições cumulativas pressupostos documentados; sem certificação',
})),
periods: [{ period: '2026-06', complete: true }],
};
book = recordSales(draft, book);
draft.modelo_a_snapshot = saveSalesBook(draft, book);
return { draft, book };
}
void test('G2E four branches require their own operation and eligibility conditions', () => {
const { book } = fixture();
for (const row of book.rows) {
const rule = operationTreatments.find((t) => t.id === row.treatment),
r = evaluateSalesOperation(row, 'MZN');
assert.equal(
r.field,
row.treatment === 'industrial_feed' ? '05' : '07',
);
assert.equal(r.net, '100.00');
assert.equal(r.vat, '0.00');
assert.equal(r.gross, '100.00');
assert.match(r.article, /9\((12|15)\)/);
assert.equal(rule.conditions.length, 3);
for (const missing of row.confirmed)
assert.equal(
evaluateSalesOperation(
{
...row,
confirmed: row.confirmed.filter((n) => n !== missing),
},
'MZN',
).vat,
null,
);
assert.equal(
evaluateSalesOperation({ ...row, evidence: '' }, 'MZN').vat,
null,
);
assert.equal(
evaluateSalesOperation({ ...row, period: '2025-06' }, 'MZN').vat,
null,
);
assert.equal(evaluateSalesOperation(row, 'USD').vat, null);
}
assert.equal(book.result.periods[0].fields['07'], '300.00');
assert.equal(book.result.periods[0].fields['05'], '100.00');
assert.match(book.result.rows[0].reason, /com direito/);
assert.ok(
book.result.rows
.slice(1)
.every((r) => r.reason.includes('sem direito')),
);
});
void test('new agro context round-trips and reports only its operations, preserving five accepted books without recalculation', () => {
const { draft, book } = fixture(),
original = seed();
const old = JSON.parse(original.modelo_a_snapshot).salesOperations;
const recovered = JSON.parse(JSON.stringify(draft)),
store = JSON.parse(recovered.modelo_a_snapshot).salesOperations;
for (const id of [
'opportunity:309',
'opportunity:310',
'opportunity:311',
'opportunity:312',
'opportunity:313',
]) {
assert.deepEqual(store[id], old[id]);
assert.equal(
salesCurrent({ ...recovered, context_opportunity: id }, store[id]),
true,
);
}
assert.equal(salesCurrent(recovered, salesBook(recovered)), true);
const model = JSON.stringify(
createProjectDossierReport(recovered, {
selectedSections: new Set(['finance']),
}),
);
for (const token of [
...ids,
'300.00',
'opportunity:314',
'Manica',
'2026-06',
'MZN',
])
assert.ok(model.includes(token), token);
for (const token of [
'financial_stamp',
'patient_transport',
'social_assistance_public',
'statutory_membership',
'author_rights',
])
assert.equal(model.includes(token), false);
assert.equal(book.result.rows.length, 4);
assert.equal(draft.currency, original.currency);
assert.deepEqual(draft.selection_labels, original.selection_labels);
});
if (process.env.IVA_G2E_OUT)
fs.writeFileSync(
process.env.IVA_G2E_OUT,
JSON.stringify(fixture().draft, null, 2),
);