Files
NODEDC_1C/llm_normalizer/backend/tests/assistantWave11DataLayerRecovery.test.ts
T

142 lines
4.9 KiB
TypeScript

import fs from "fs";
import os from "os";
import path from "path";
import { afterEach, describe, expect, it, vi } from "vitest";
const TEMP_DIRS: string[] = [];
const FLAG_KEYS = [
"FEATURE_ASSISTANT_BROAD_GUARD_V1",
"FEATURE_ASSISTANT_MIN_EVIDENCE_GATE_V1"
] as const;
const ORIGINAL_FLAGS: Record<string, string | undefined> = Object.fromEntries(FLAG_KEYS.map((key) => [key, process.env[key]]));
function restoreFlags(): void {
for (const key of FLAG_KEYS) {
const original = ORIGINAL_FLAGS[key];
if (original === undefined) {
delete process.env[key];
} else {
process.env[key] = original;
}
}
}
function cleanupTempDirs(): void {
for (const dir of TEMP_DIRS.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
}
function createSnapshotRoot(keyFields: Array<Record<string, unknown>>): string {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "assistant-wave11-recovery-"));
TEMP_DIRS.push(root);
const write = (fileName: string, records: Array<Record<string, unknown>>) => {
fs.writeFileSync(path.resolve(root, fileName), JSON.stringify({ records }, null, 2), "utf-8");
};
write("09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json", keyFields);
write("03_snapshot_fragment_problem_cases.json", []);
write("07_samples_DocumentJournals.json", []);
write("08_samples_NDS_registers.json", []);
write("04_samples_SpisanieSRaschetnogoScheta.json", []);
write("05_samples_RealizaciyaTovarovUslug.json", []);
write("06_samples_PostuplenieTovarovUslug.json", []);
return root;
}
function buildDrilldownAnchorRecord(): Record<string, unknown> {
return {
source_entity: "Document",
source_id: "DOC-SETTLE-4",
display_name: "Оплата по счету 4",
unknown_link_count: 0,
attributes: {
Number: "4",
Date: "2020-07-07T00:00:00",
Amount: 276873.6,
Description: "Оплата по счету 4 от 07.07.20",
Account: "62.02"
},
links: [
{
relation: "document_has_counterparty",
target_entity: "Counterparty",
target_id: "CP-4",
source_field: "Counterparty"
}
]
};
}
function buildSettlementRecoveryRecord(): Record<string, unknown> {
return {
source_entity: "Document",
source_id: "DOC-SETTLE-RECOVERY-1",
display_name: "Payment settlement tail",
unknown_link_count: 1,
attributes: {
Period: "2020-07-15T00:00:00",
Description: "payment linked to contract and buyer with unresolved closure"
},
links: [
{
relation: "document_has_counterparty",
target_entity: "Counterparty",
target_id: "CP-RECOVERY",
source_field: "Counterparty"
},
{
relation: "document_refers_to_document",
target_entity: "Document",
target_id: "DOC-CHAIN-1",
source_field: "Recorder"
}
]
};
}
describe.sequential("wave11 data-layer recovery", () => {
afterEach(() => {
cleanupTempDirs();
restoreFlags();
vi.resetModules();
});
it("settlement_object_trace_with_number_date_amount_must_not_require_guid_by_default", async () => {
const { AssistantDataLayer } = await import("../src/services/assistantDataLayer");
const dataLayer = new AssistantDataLayer(createSnapshotRoot([buildDrilldownAnchorRecord()]));
const result = dataLayer.executeRoute(
"live_mcp_drilldown",
"Оплата по счету № 4 от 07.07.20 на 276 873,60 пришла 13 июля по счету 62.02."
);
expect(result.status).toBe("ok");
const summary = result.summary as Record<string, unknown>;
expect(summary.reason).toBe("business_anchor_trace");
expect(summary.reason).not.toBe("guid_not_provided");
expect(Array.isArray(result.items)).toBe(true);
expect(result.items.length).toBeGreaterThan(0);
});
it("broad_settlement_query_must_not_drop_all_retrieval_due_to_strict_purity_if_in_scope", async () => {
process.env.FEATURE_ASSISTANT_BROAD_GUARD_V1 = "0";
process.env.FEATURE_ASSISTANT_MIN_EVIDENCE_GATE_V1 = "0";
vi.resetModules();
const { AssistantDataLayer } = await import("../src/services/assistantDataLayer");
const dataLayer = new AssistantDataLayer(createSnapshotRoot([buildSettlementRecoveryRecord()]));
const result = dataLayer.executeRoute(
"hybrid_store_plus_live",
"Почему по поставщику деньги ушли, а долг остался по счетам 60.01/62.02 в июле?"
);
expect(result.status).toBe("ok");
expect(result.items.length).toBeGreaterThan(0);
const summary = result.summary as Record<string, unknown>;
const guard = (summary.domain_purity_guard ?? {}) as Record<string, unknown>;
expect(Number(guard.source_selection_allowed ?? 0)).toBeGreaterThan(0);
expect(Boolean(guard.settlement_source_recovery) || Boolean(guard.settlement_narrowing_recovery)).toBe(true);
});
});