import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts'; import assert from 'node:assert/strict'; test('legacy draft without a compatible source keeps its shape and identity',()=>{ const legacy={activity_id:'legacy-activity',infrastructure_needs:['energia']}; assert.equal(inheritSimulatorFields(legacy),legacy); assert.equal(Object.hasOwn(inheritSimulatorFields(legacy),'compatible_fields_snapshot'),false); }); import test from 'node:test'; import { inheritCompatibleFields, inheritSimulatorFields, reusedInvestmentValue } from '../../resources/js/lib/context-inheritance.ts'; import { serializeBusinessPlanSnapshot } from '../../resources/js/lib/business-financial-plan.ts'; import { monthlySalesFromDraft } from '../../resources/js/lib/monthly-iva.ts'; import { restoreSimulationDraft, partitionSimulationDraft } from '../../resources/js/lib/simulation-form.ts'; test('known investment questions become editable summaries after save/recovery, while missing and deliberate edits remain questions', () => { const scope='dossier:A:simulator'; const source={project_title:'Florestas — Beira',project_summary:'Preparar investimento florestal',province_id:'p1',province_id_label:'Sofala',sector_id:'3',sector_id_label:'Agronegócio'}; const reused=inheritCompatibleFields(scope,{},source,null); const draft={...reused.patch,context_reuse:reused.metadata,purpose:'simulate_only',journey_type:'investor'}; const saved=partitionSimulationDraft(draft); const recovered=restoreSimulationDraft(saved.personal_snapshot,saved.economic_snapshot); assert.equal(reusedInvestmentValue(scope,'project_title',recovered),source.project_title); assert.equal(reusedInvestmentValue(scope,'province_id',recovered),'Sofala'); assert.equal(reusedInvestmentValue(scope,'sector_id',recovered),'Agronegócio'); assert.equal(reusedInvestmentValue(scope,'district_id',recovered),null); assert.equal(reusedInvestmentValue('dossier:B:simulator','project_title',recovered),null); assert.equal(reusedInvestmentValue(scope,'project_title',{...recovered,project_title:'Edição deliberada'}),null); assert.equal(reusedInvestmentValue(scope,'project_title',{...recovered,project_title:''}),null); assert.equal(reusedInvestmentValue(scope,'province_id',{...recovered,province_id_label:''}),null); assert.equal(reusedInvestmentValue(scope,'currency',{...recovered,currency:'MZN'}),null); assert.equal(reusedInvestmentValue(scope,'project_title',{...recovered,context_reuse:'invalid'}),null); }); test('local geography and sector keep their labels when the dossier proposes different identifiers', () => { const scope='dossier:A:simulator'; const source={province_id:'p1',province_id_label:'Sofala',district_id:'d1',district_id_label:'Dondo',sector_id:'3',sector_id_label:'Agronegócio'}; const local={province_id:'p2',province_id_label:'Gaza',district_id:'d2',district_id_label:'Outro distrito',sector_id:'4',sector_id_label:'Turismo'}; const reconciliation=inheritCompatibleFields(scope,local,source,null); assert.deepEqual(reconciliation.patch,{}); assert.ok(reconciliation.conflicts.includes('province_id')); const first=inheritCompatibleFields(scope,{},source,null); const changed=inheritCompatibleFields(scope,{...first.patch,context_reuse:first.metadata},{...source,province_id:'p3',province_id_label:'Manica',district_id:'',district_id_label:''},first.metadata); assert.equal(changed.patch.province_id,'p3');assert.equal(changed.patch.province_id_label,'Manica'); assert.equal(changed.patch.district_id,'');assert.equal(changed.patch.district_id_label,''); const stale=inheritCompatibleFields(scope,{province_id_label:'Nome antigo'},source,null); assert.equal(stale.patch.province_id,'p1');assert.equal(stale.patch.province_id_label,'Sofala'); }); test('investment entry selects the existing simulation route without replacing an earlier deliberate purpose', () => { const scope='dossier:A:simulator'; const source={journey_type:'investor',journey_type_label:'Avaliar o meu investimento',purpose:'simulate_only',purpose_label:'Apenas simular'}; const first=inheritCompatibleFields(scope,{},source,null); const values={...first.patch,context_reuse:first.metadata}; assert.equal(reusedInvestmentValue(scope,'journey_type',values),'Avaliar o meu investimento'); assert.equal(reusedInvestmentValue(scope,'purpose',values),'Apenas simular'); const old=inheritCompatibleFields(scope,{journey_type:'small_business',purpose:'seek_partner'},source,null); assert.deepEqual(old.patch,{}); assert.equal(reusedInvestmentValue(scope,'purpose',{purpose:'seek_partner',context_reuse:old.metadata}),null); }); test('inherited source updates follow through recovery while local edits and deliberate clears survive',()=>{ const first=inheritCompatibleFields('dossier:A:simulator',{}, {currency:'MZN',project_title:'A'}, null); const saved={...first.patch,context_reuse:first.metadata}; const changed=inheritCompatibleFields('dossier:A:simulator',saved,{currency:'USD',project_title:'A2'},saved.context_reuse); assert.deepEqual(changed.patch,{currency:'USD',project_title:'A2'}); const edited=inheritCompatibleFields('dossier:A:simulator',{...saved,currency:'EUR',project_title:''},{currency:'USD',project_title:'A2'},saved.context_reuse); assert.deepEqual(edited.patch,{});assert.deepEqual(edited.conflicts,['currency','project_title']); const recovered=JSON.parse(JSON.stringify({...saved,currency:'EUR',project_title:''})); assert.deepEqual(inheritCompatibleFields('dossier:A:simulator',recovered,{currency:'USD',project_title:'A2'},recovered.context_reuse).patch,{}); assert.ok(!first.metadata.includes('MZN'));assert.ok(!first.metadata.includes('project_title":"A')); }); test('a different dossier cannot take ownership of existing values using another dossier metadata',()=>{ const first=inheritCompatibleFields('dossier:A:simulator',{}, {currency:'MZN'}, null); const second=inheritCompatibleFields('dossier:B:simulator',first.patch,{currency:'USD'},first.metadata); assert.deepEqual(second.patch,{});assert.deepEqual(second.conflicts,['currency']); }); test('a local geographic override protects the entire hierarchy',()=>{ const first=inheritCompatibleFields('A',{}, {province_id:'p1',district_id:'d1'},null); const update=inheritCompatibleFields('A',{...first.patch,province_id:'p-local'},{province_id:'p2',district_id:'d2'},first.metadata); assert.deepEqual(update.patch,{}); }); test('compatible currency and date reuse survives backend partition and new session recovery without invented tax scope',()=>{ const initial=inheritSimulatorFields({currency:'USD',expected_start_date:'2026-03-01',purpose:'simulate_only'}); assert.equal(initial.fiscal_currency,'USD');assert.equal(initial.published_iva_currency,'USD');assert.equal(initial.opportunity_currency,'USD'); assert.equal(JSON.parse(initial.monthly_iva_settings).start,'2026-03');assert.equal(JSON.parse(initial.monthly_iva_settings).declared,false); assert.equal(initial.published_iva_date,undefined); assert.equal(inheritSimulatorFields({expected_start_date:'2026-01-01',monthly_iva_settings:'[invalid stored input'}).monthly_iva_settings,'[invalid stored input'); const saved=partitionSimulationDraft(initial,true);const recovered=restoreSimulationDraft(saved.economic_snapshot,saved.personal_snapshot); assert.equal(recovered.published_iva_currency,'USD');assert.strictEqual(inheritSimulatorFields(recovered),recovered); const changed=inheritSimulatorFields({...recovered,currency:'EUR'});assert.equal(changed.fiscal_currency,'EUR'); const override=inheritSimulatorFields({...changed,fiscal_currency:'MZN',published_iva_currency:''});assert.equal(override.fiscal_currency,'MZN');assert.equal(override.published_iva_currency,''); }); test('land consumer reuses geography inside an empty parcel and preserves all other parcel data',()=>{ const first=inheritCompatibleFields('land', {parcels:[{area:'12',province_id:''},{area:'20',province_id:'other'}]}, {parcels:[{province_id:'P',district_id:'D'}]},null); assert.equal(first.patch.parcels[0].area,'12');assert.equal(first.patch.parcels[0].district_id,'D');assert.equal(first.patch.parcels[1].province_id,'other'); const changed=inheritCompatibleFields('land',{parcels:[{...first.patch.parcels[0],area:'13'},first.patch.parcels[1]]},{parcels:[{province_id:'P2'}]},first.metadata); assert.equal(changed.patch.parcels[0].area,'13');assert.equal(changed.patch.parcels[0].district_id,''); }); test('clearing an inherited zone reference clears only the inherited value, preserving a deliberate override',()=>{ const first=inheritCompatibleFields('A',{}, {special_zone_id:'zone'},null); assert.equal(inheritCompatibleFields('A',first.patch,{special_zone_id:''},first.metadata).patch.special_zone_id,''); assert.deepEqual(inheritCompatibleFields('A',{special_zone_id:'local'},{special_zone_id:''},first.metadata).patch,{}); }); test('conflicting saved sales currency is explained instead of relabelled or converted',()=>{ const fields=['openingCash','monthlyCollections','monthlyVariableCostPayments','monthlyInventoryPurchases','monthlyOperatingExpenses','monthlyOperatingPayments','monthlyPayrollExpense','monthlyPayrollPayments','assetInvestment','inventory','receivables','payables','equity','shareholderLoans','bankLoanProceeds','grants','assetDepreciation','monthlyInterestExpense','monthlyInterestPayment','monthlyPrincipalRepayment']; const plan={...Object.fromEntries(fields.map(key=>[key,'0'])),currency:'MZN',periods:4,depreciationLifeMonths:60,products:[{label:'QA',monthlyUnits:'1',unitPrice:'100',unitVariableCost:'0'}]}; assert.throws(()=>monthlySalesFromDraft({currency:'USD',business_plan_snapshot:serializeBusinessPlanSnapshot(plan)}),/projecção de vendas está em MZN.*projecto está em USD/); }); test('report preserves consulted zone version and makes unsupported benefit explicit without inventing a fiscal result',()=>{ const context={version:1,context_revision:3,zone:{title:'Referência QA',version:7,href:'/zonas/qa'},fields:{currency:'USD'}}; const draft={project_title:'QA',currency:'USD',context_applicability_snapshot:JSON.stringify(context)}; const saved=JSON.stringify(draft);const report=createProjectDossierReport(draft,{selectedSections:new Set(['sources'])}); assert.match(JSON.stringify(report),/Referência QA, versão 7/);assert.match(JSON.stringify(report),/Benefício fiscal da zona indeterminado/);assert.equal(JSON.stringify(draft),saved); });