159 lines
5.3 KiB
JavaScript
159 lines
5.3 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 seed = () =>
|
|
JSON.parse(
|
|
fs.readFileSync(
|
|
new URL('./fixtures/iva-production.json', import.meta.url),
|
|
'utf8',
|
|
),
|
|
);
|
|
function fixture() {
|
|
const draft = seed();
|
|
draft.context_opportunity = 'opportunity:319';
|
|
draft.project_title = 'SYNTHETIC QA G2J fundraising';
|
|
let book = {
|
|
currency: 'MZN',
|
|
rows: ['fundraising_public', 'fundraising_nonprofit'].map((id, i) => ({
|
|
...newSalesOperation(`g2j-${i}`, '2026-11', 'MZN'),
|
|
description: `SYNTHETIC QA ${id}`,
|
|
establishment: 'SYNTHETIC QA Manica',
|
|
amount: '100',
|
|
basis: i ? 'included' : 'net',
|
|
treatment: id,
|
|
confirmed: operationTreatments
|
|
.find((t) => t.id === id)
|
|
.conditions.map((_, n) => n),
|
|
evidence:
|
|
'SYNTHETIC QA: entidade, actividade habitual isenta, proveito exclusivo e total anual expressamente pressupostos',
|
|
fundraiser: {
|
|
entityReference: `SYNTHETIC-ENTITY-${i}`,
|
|
annualEvents: i ? '8' : '1',
|
|
eventNumber: i ? '8' : '1',
|
|
activity: 'social_assistance',
|
|
},
|
|
})),
|
|
periods: [{ period: '2026-11', complete: true }],
|
|
};
|
|
book = recordSales(draft, book);
|
|
draft.modelo_a_snapshot = saveSalesBook(draft, book);
|
|
return { draft, book };
|
|
}
|
|
void test('one fundraising branch: public/nonprofit, eighth admitted, ninth/unknown/activity mismatch indeterminate', () => {
|
|
const { draft, book } = fixture();
|
|
assert.equal(book.result.periods[0].fields['07'], '200.00');
|
|
for (const row of book.rows) {
|
|
assert.equal(evaluateSalesOperation(row, 'MZN').vat, '0.00');
|
|
for (const n of row.confirmed)
|
|
assert.equal(
|
|
evaluateSalesOperation(
|
|
{ ...row, confirmed: row.confirmed.filter((i) => i !== n) },
|
|
'MZN',
|
|
).vat,
|
|
null,
|
|
);
|
|
for (const patch of [
|
|
{ annualEvents: '9' },
|
|
{ annualEvents: '' },
|
|
{ annualEvents: '0' },
|
|
{ eventNumber: '9' },
|
|
{ eventNumber: '2', annualEvents: '1' },
|
|
{ entityReference: '' },
|
|
{ activity: 'religious_personnel' },
|
|
{ activity: '' },
|
|
])
|
|
assert.equal(
|
|
evaluateSalesOperation(
|
|
{ ...row, fundraiser: { ...row.fundraiser, ...patch } },
|
|
'MZN',
|
|
).vat,
|
|
null,
|
|
);
|
|
assert.equal(
|
|
evaluateSalesOperation({ ...row, evidence: '' }, 'MZN').vat,
|
|
null,
|
|
);
|
|
}
|
|
const nonprofit = book.rows[1];
|
|
assert.equal(
|
|
evaluateSalesOperation(
|
|
{
|
|
...nonprofit,
|
|
fundraiser: {
|
|
...nonprofit.fundraiser,
|
|
activity: 'health_public',
|
|
},
|
|
},
|
|
'MZN',
|
|
).vat,
|
|
null,
|
|
);
|
|
const conflicting = {
|
|
...book,
|
|
rows: book.rows.map((r) => ({
|
|
...r,
|
|
fundraiser: { ...r.fundraiser, entityReference: 'SAME' },
|
|
})),
|
|
};
|
|
assert.ok(
|
|
recordSales(draft, conflicting).result.rows.every(
|
|
(r) => r.vat === null,
|
|
),
|
|
);
|
|
const sameEvent = {
|
|
...book,
|
|
rows: [book.rows[0], { ...book.rows[0], id: 'second-sale' }],
|
|
};
|
|
assert.equal(
|
|
recordSales(draft, sameEvent).result.periods[0].fields['07'],
|
|
'200.00',
|
|
);
|
|
});
|
|
void test('fundraising context reports annual data preserving ten books; only changed G2I calendar version becomes historical', () => {
|
|
const { draft, book } = fixture(),
|
|
old = JSON.parse(seed().modelo_a_snapshot).salesOperations,
|
|
store = JSON.parse(draft.modelo_a_snapshot).salesOperations;
|
|
for (const [id, value] of Object.entries(old)) {
|
|
assert.deepEqual(store[id], value);
|
|
assert.equal(
|
|
salesCurrent({ ...draft, context_opportunity: id }, value),
|
|
id !== 'opportunity:318',
|
|
);
|
|
}
|
|
assert.equal(Object.keys(old).length, 10);
|
|
assert.equal(salesCurrent(draft, salesBook(draft)), true);
|
|
const model = JSON.stringify(
|
|
createProjectDossierReport(draft, {
|
|
selectedSections: new Set(['finance']),
|
|
}),
|
|
);
|
|
for (const token of [
|
|
'fundraising_public',
|
|
'fundraising_nonprofit',
|
|
'200.00',
|
|
'SYNTHETIC-ENTITY-1',
|
|
'2026-11',
|
|
'opportunity:319',
|
|
'Manica',
|
|
'total anual declarado 8',
|
|
])
|
|
assert.ok(model.includes(token), token);
|
|
assert.equal(model.includes('production_forestry_opted'), false);
|
|
assert.equal(book.result.rows.length, 2);
|
|
});
|
|
if (process.env.IVA_G2J_OUT)
|
|
fs.writeFileSync(
|
|
process.env.IVA_G2J_OUT,
|
|
JSON.stringify(fixture().draft, null, 2),
|
|
);
|