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=['public_security','official_military_supplies','sisa_subject_operation','exempt_activity_asset_sale','no_deduction_right_asset_sale','excluded_deduction_asset_sale']; function seed(){return JSON.parse(fs.readFileSync(new URL('./fixtures/iva-services-nature.json',import.meta.url),'utf8'));} function fixture(){const draft=seed();draft.context_opportunity='opportunity:316';draft.project_title='SYNTHETIC QA — G2G social'; let book={currency:'MZN',rows:ids.map((id,i)=>({...newSalesOperation(`g2g-${i}`,'2026-08','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-08',complete:true}]};book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};} test('G2G four branches with six conditional treatments 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,'07');assert.equal(r.net,'100.00');assert.equal(r.vat,'0.00');assert.equal(r.gross,'100.00');assert.match(r.article,/9\((2|11|12)\)/); assert.ok(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-08'},'MZN').vat,null); assert.equal(evaluateSalesOperation(row,'USD').vat,null); } assert.equal(book.result.periods[0].fields['07'],'600.00');assert.equal(book.result.periods[0].fields['05'],'0.00');assert.ok(book.result.rows.every(r=>r.reason.includes('sem direito'))); }); test('new conditional context round-trips and reports only its operations, preserving seven 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','opportunity:314','opportunity:315']){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,'600.00','opportunity:316','Manica','2026-08','MZN'])assert.ok(model.includes(token),token); for(const token of ['financial_stamp','patient_transport','social_assistance_public','statutory_membership','author_rights','industrial_feed','special_tax_games'])assert.equal(model.includes(token),false); assert.equal(book.result.rows.length,6);assert.equal(draft.currency,original.currency);assert.deepEqual(draft.selection_labels,original.selection_labels); }); if(process.env.IVA_G2G_OUT)fs.writeFileSync(process.env.IVA_G2G_OUT,JSON.stringify(fixture().draft,null,2));