Files
Investidor-V2/tests/frontend/fiscal-qa-preview.test.mjs
T
2026-10-21 11:59:50 +02:00

177 lines
7.0 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { fiscalQaRows } from "../../resources/js/lib/fiscal-qa-preview.ts";
import { exportCompletedArithmeticCsv, readArithmeticSnapshot } from "../../resources/js/lib/simulation-form.ts";
import { createProjectDossierReport } from "../../resources/js/lib/project-dossier-report.ts";
function fixture() {
const snapshot = {
contract_version: 1,
scenario_kind: "fiscal_rule_qa_preview",
base: "0.03",
currency: "MZN",
indicative_total: "0.0048",
legal_interpretation: false,
formula_version: "investmoz.tax.v1",
context: {
reference_date: "2026-10-21",
currency: "MZN",
currency_fraction_digits: 2,
scenario_id: "61000100-0000-4000-8000-000000000099",
scenario_version: 1,
engine_version: "fiscal-draft-preview-v1",
ruleset_version: "IVA-GERAL-BASE-LIQUIDA:1",
},
result: {
status: "calculated",
value: "0.0048",
unit: "MZN",
explanation:
"Cálculo exacto QA; enquadramento declarado; não é saldo a pagar.",
missing_inputs: [],
source_ids: ["source-fixture"],
},
intermediate: { result: "48/10000" },
fiscal_provenance: {
rule: {
rule_code: "IVA-GERAL-BASE-LIQUIDA",
rule_version: 1,
valid_from: "2023-01-01",
valid_until: null,
source_sha256: "a".repeat(64),
source: { diploma: "Lei 22/2022", article: "Artigo 17(1)" },
},
},
};
return {
id: "61000100-0000-4000-8000-000000000088",
status: "completed",
version_no: 2,
result_snapshot: snapshot,
reports: [
{
id: "61000100-0000-4000-8000-000000000077",
version_no: 1,
status: "ready",
report_snapshot: structuredClone(snapshot),
report_sha256: "b".repeat(64),
},
],
};
}
test("screen rows preserve sub-cent IVA as a string and distinguish calculation from payment", () => {
const simulation = fixture();
const before = JSON.stringify(simulation);
const rows = fiscalQaRows(simulation.result_snapshot);
assert.equal(
rows.find(([label]) => label.startsWith("IVA calculado"))[1],
"0.0048",
);
assert.match(
rows.find(([label]) => label === "Arredondamento")[1],
/Não aplicado/,
);
assert.match(
rows.find(([label]) => label === "Enquadramento")[1],
/não validado juridicamente/,
);
assert.equal(JSON.stringify(simulation), before);
});
test("CSV preserves the exact amount and refuses a mismatched immutable report", () => {
const simulation = fixture();
const csv = exportCompletedArithmeticCsv(
simulation,
"2026-10-21T09:00:00Z",
);
assert.match(csv, /0\.0048/);
assert.doesNotMatch(csv, /Resultado fiscal final,Indeterminado/);
simulation.reports[0].report_snapshot.result.value = "0.00";
assert.throws(
() => exportCompletedArithmeticCsv(simulation),
/relatório preservado/,
);
});
test("dossier report uses the same exact snapshot and preserves genuine indetermination", () => {
const simulation = fixture();
function report() {
return createProjectDossierReport(
{ project_title: "QA fiscal", currency: "MZN" },
{
selectedSections: new Set(["finance"]),
currentCalculation: {
status: "completed",
version: 2,
snapshot: simulation.result_snapshot,
},
},
);
}
const rows = report().sections.find(
(section) => section.id === "finance",
).rows;
assert.equal(
rows.find((row) => row.field.startsWith("IVA calculado")).value,
"0.0048",
);
assert.equal(
rows.find((row) => row.field === "Fonte da taxa").value,
"Lei 22/2022 — Artigo 17(1)",
);
simulation.result_snapshot.result.status = "indeterminate";
simulation.result_snapshot.result.value = null;
simulation.result_snapshot.indicative_total = null;
simulation.result_snapshot.result.missing_inputs = ["eligible_parameter"];
assert.equal(
report()
.sections.find((section) => section.id === "finance")
.rows.find((row) => row.field.startsWith("IVA calculado")).value,
"Indeterminado",
);
});
test("published consumer routes the frozen snapshot through screen CSV and dossier without QA labels", () => {
const simulation = fixture();
const snapshot = simulation.result_snapshot;
snapshot.scenario_kind = "fiscal_rule_published";
snapshot.context.engine_version = "fiscal-published-v1";
snapshot.presentation = { value: snapshot.result.value, rounding_applied: false };
snapshot.result.explanation = "IVA pela versão publicada; enquadramento declarado.";
snapshot.fiscal_provenance.rule.status = "published";
snapshot.fiscal_provenance.scope_status = "user_declared";
snapshot.fiscal_provenance.mode = "published_version";
simulation.reports[0].report_snapshot = structuredClone(snapshot);
const before = JSON.stringify(simulation);
const rows = fiscalQaRows(snapshot);
assert.equal(readArithmeticSnapshot(snapshot).integrity, "versioned");
assert.match(rows[0][1], /publicada/);
assert.doesNotMatch(JSON.stringify(rows), /rascunho|não publicada|QA/);
const csv = exportCompletedArithmeticCsv(simulation, "2026-10-21T12:00:00Z");
for (const [label, value] of rows) {
assert.ok(csv.includes(label));
assert.ok(csv.includes(value.replaceAll('"', '""')));
}
const report = createProjectDossierReport({ project_title: "Published IVA QA", currency: "MZN" }, {
selectedSections: new Set(["finance"]), currentCalculation: { status: "completed", version: 2, snapshot },
});
const finance = report.sections.find((section) => section.id === "finance");
for (const [field, value] of rows) assert.ok(finance.rows.some((row) => row.field === field && row.value === value));
assert.doesNotMatch(JSON.stringify(finance), /rascunho|proveniência QA/);
assert.equal(JSON.stringify(simulation), before);
});
test("published consumer indeterminate snapshot is valid and a mismatched presentation is refused", () => {
const snapshot = fixture().result_snapshot;
snapshot.scenario_kind = "fiscal_rule_published";
snapshot.result.status = "indeterminate";
snapshot.result.value = null;
snapshot.result.missing_inputs = ["operation_scope"];
snapshot.indicative_total = null;
snapshot.presentation = { value: null, rounding_applied: false };
assert.equal(readArithmeticSnapshot(snapshot).integrity, "versioned");
snapshot.presentation.value = "0";
assert.equal(readArithmeticSnapshot(snapshot).integrity, "invalid");
});