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), );