253 lines
9.0 KiB
JavaScript
253 lines
9.0 KiB
JavaScript
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/);
|
|
});
|