import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { newServiceLocation, switchServiceTreatment, serviceLocationConditions, ownServiceConditions, serviceLocationTreatments, evaluateServiceLocation, recordServiceLocations, saveServiceLocationBook, serviceLocationBook, serviceLocationCurrent, serviceLocationReportRows, } from '../../resources/js/lib/iva-service-location.ts'; const frozen = JSON.parse( fs.readFileSync( 'tests/frontend/fixtures/iva-g8-services-preserved.json', 'utf8', ), ); const draft = { ...frozen, context_opportunity: 'opportunity:349', project_title: 'SYNTHETIC QA — G8 services / Manica', }; function row(t, country = 'MZ') { return { ...newServiceLocation(t + '-' + country), treatment: t, description: 'SYNTHETIC QA serviço', period: '2026-12', origin: 'projected', operationDate: '2026-12-12', operationRef: 'SYNTHETIC QA operação', documentRef: 'SYNTHETIC QA documento/pressuposto', documentDate: '2026-12-12', scope: 'SYNTHETIC QA operação/serviço/dezembro2026', evidence: 'SYNTHETIC QA pressupostos expressos', servicePlace: 'SYNTHETIC QA local material', placeCountry: country, placeRef: 'SYNTHETIC QA referência local', providerPlace: 'SYNTHETIC QA estabelecimento prestador', providerCountry: country, providerRef: 'SYNTHETIC QA referência estabelecimento', subjectRef: 'SYNTHETIC QA imóvel/bens/actividade', totalDistance: '100.50', nationalDistance: country === 'MZ' ? '80.25' : '0', departure: country, arrival: country, routeRef: 'SYNTHETIC QA trajecto individual', conditions: Object.fromEntries( [...serviceLocationConditions, ...ownServiceConditions(t)].map( ([key]) => [key, 'yes'], ), ), }; } for (const treatment of serviceLocationTreatments) void test( treatment.branch + ' facts,own guards and territorial direction', () => { for (const country of ['MZ', 'foreign']) { const r = row(treatment.id, country); const expected = country === 'MZ' ? 'national' : 'outside'; assert.equal(evaluateServiceLocation(r).territory, expected); assert.deepEqual( ['baseAmount', 'vat', 'rate'].map( (k) => evaluateServiceLocation(r)[k], ), [null, null, null], ); if (treatment.id !== 'general_service') { r.providerCountry = country === 'MZ' ? 'foreign' : 'MZ'; assert.equal( evaluateServiceLocation(r).territory, expected, ); } for (const [key] of [ ...serviceLocationConditions, ...ownServiceConditions(treatment.id), ]) { const missing = structuredClone(r); delete missing.conditions[key]; assert.equal( evaluateServiceLocation(missing).status, 'indeterminate', ); missing.conditions[key] = 'no'; assert.equal( evaluateServiceLocation(missing).status, 'not_applicable', ); assert.equal( evaluateServiceLocation(missing).territory, null, ); } for (const field of [ 'operationRef', 'documentRef', 'scope', 'evidence', ...(treatment.id === 'general_service' ? ['providerPlace', 'providerCountry', 'providerRef'] : treatment.id === 'transport_service' ? [ 'routeRef', 'totalDistance', 'nationalDistance', 'departure', 'arrival', ] : [ 'servicePlace', 'placeCountry', 'placeRef', 'subjectRef', ]), ]) assert.equal( evaluateServiceLocation({ ...r, [field]: '' }).status, 'indeterminate', field, ); assert.equal( evaluateServiceLocation({ ...r, operationDate: '2026-11-12', }).status, 'indeterminate', ); assert.equal( evaluateServiceLocation({ ...r, documentDate: '2026-02-30', }).status, 'indeterminate', ); assert.equal( evaluateServiceLocation({ ...r, period: '2025-12' }).status, 'indeterminate', ); } }, ); void test('Four branches persist together,history,scope,hidden retention and previous books', () => { const rows = serviceLocationTreatments.flatMap((t) => ['MZ', 'foreign'].map((c) => row(t.id, c)), ); let book = recordServiceLocations(draft, { rows }); book = recordServiceLocations(draft, book); assert.equal(book.history.length, 1); const next = { ...draft, modelo_a_snapshot: saveServiceLocationBook(draft, book), }; assert.deepEqual(serviceLocationBook(next), book); assert.ok(serviceLocationCurrent(next, book)); assert.equal( serviceLocationCurrent({ ...next, context_opportunity: 'other' }, book), false, ); assert.equal( serviceLocationCurrent( { ...next, currency: 'USD', customer_country: 'foreign' }, book, ), true, ); assert.equal(serviceLocationReportRows(next).length, 10); for (const t of serviceLocationTreatments) assert.ok( serviceLocationReportRows(next).some((r) => r[1].includes(t.branch), ), ); const store = JSON.parse(next.modelo_a_snapshot); delete store.serviceLocations; assert.deepEqual(store, JSON.parse(frozen.modelo_a_snapshot)); const switched = switchServiceTreatment(rows[0], 'immovable_service'); assert.equal(switched.providerRef, rows[0].providerRef); assert.equal(switched.servicePlace, rows[0].servicePlace); assert.equal(switched.conditions.propertyRelation, undefined); assert.equal(evaluateServiceLocation(switched).status, 'indeterminate'); const corrupt = { ...next, modelo_a_snapshot: JSON.stringify({ ...JSON.parse(next.modelo_a_snapshot), serviceLocations: [], }), }; assert.throws(() => serviceLocationBook(corrupt)); assert.throws(() => recordServiceLocations(next, { rows: [rows[0], rows[0]] }), ); if (process.env.IVA_G8_SERVICES_FIXTURE) fs.writeFileSync( process.env.IVA_G8_SERVICES_FIXTURE, JSON.stringify(next, null, 2) + '\n', ); }); void test('P110 domestic deemed distance,mixed route,zero,invalid and exact distances', () => { const r = row('transport_service'); assert.equal(evaluateServiceLocation(r).territory, 'national'); assert.equal( evaluateServiceLocation({ ...r, arrival: 'foreign' }).territory, 'partial', ); assert.equal( evaluateServiceLocation({ ...r, arrival: 'foreign', nationalDistance: '0', }).territory, 'outside', ); assert.equal( evaluateServiceLocation({ ...r, arrival: 'foreign', nationalDistance: r.totalDistance, }).territory, 'national', ); for (const patch of [ { totalDistance: '0' }, { nationalDistance: '101' }, { nationalDistance: '-1' }, { totalDistance: '1e3' }, { totalDistance: '1,5' }, { departure: '' }, { arrival: '' }, ]) assert.equal( evaluateServiceLocation({ ...r, ...patch }).status, 'indeterminate', ); assert.equal( evaluateServiceLocation({ ...r, arrival: 'foreign', nationalDistance: '0.000001', totalDistance: '999999999999999999.123456', }).territory, 'partial', ); assert.match(evaluateServiceLocation(r).reason, /08\/06\/2017/); assert.match(evaluateServiceLocation(r).reason, /Ida e volta/); });