134 lines
4.6 KiB
JavaScript
134 lines
4.6 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 } 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",
|
|
);
|
|
});
|