NODEDC_1C/llm_normalizer/backend/tests/addressFollowupTemporalRegr...

295 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it } from "vitest";
import { runAddressDecomposeStage } from "../src/services/address_runtime/decomposeStage";
describe("address follow-up temporal regressions", () => {
it("replaces VAT month-only follow-up with the previous follow-up year", () => {
const result = runAddressDecomposeStage("а на март", {
previous_intent: "vat_payable_confirmed_as_of_date",
previous_filters: {
period_from: "2019-05-01",
period_to: "2019-05-31",
as_of_date: "2019-05-31"
},
previous_anchor_type: "unknown",
previous_anchor_value: null
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("vat_payable_confirmed_as_of_date");
expect(result?.filters.extracted_filters.period_from).toBe("2019-03-01");
expect(result?.filters.extracted_filters.period_to).toBe("2019-03-31");
expect(result?.filters.extracted_filters.as_of_date).toBe("2019-03-31");
expect(result?.baseReasons).toContain("period_derived_from_followup_context_year");
});
it("replaces VAT month-only follow-up with a later month from the same inherited year", () => {
const result = runAddressDecomposeStage("на сентябрь", {
previous_intent: "vat_payable_confirmed_as_of_date",
previous_filters: {
period_from: "2019-05-01",
period_to: "2019-05-31",
as_of_date: "2019-05-31"
},
previous_anchor_type: "unknown",
previous_anchor_value: null
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("vat_payable_confirmed_as_of_date");
expect(result?.filters.extracted_filters.period_from).toBe("2019-09-01");
expect(result?.filters.extracted_filters.period_to).toBe("2019-09-30");
expect(result?.filters.extracted_filters.as_of_date).toBe("2019-09-30");
expect(result?.baseReasons).toContain("period_derived_from_followup_context_year");
});
it("inherits the previous VAT period for 'за этот период' follow-up", () => {
const result = runAddressDecomposeStage("какой НДС мы должны примерно заплатить за этот период", {
previous_intent: "vat_payable_confirmed_as_of_date",
previous_filters: {
period_from: "2017-05-01",
period_to: "2017-05-31",
as_of_date: "2017-05-31"
},
previous_anchor_type: "unknown",
previous_anchor_value: null
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("vat_liability_confirmed_for_tax_period");
expect(result?.filters.extracted_filters.period_from).toBe("2017-05-01");
expect(result?.filters.extracted_filters.period_to).toBe("2017-05-31");
expect(result?.filters.extracted_filters.as_of_date).toBe("2017-05-31");
expect(result?.baseReasons).toContain("period_from_from_followup_context");
});
it("keeps inherited period when a follow-up retargets from receivables into VAT for the same period", () => {
const result = runAddressDecomposeStage("а какой НДС мы должны примерно заплатить за этот период", {
previous_intent: "receivables_confirmed_as_of_date",
target_intent: "vat_payable_confirmed_as_of_date",
previous_filters: {
period_from: "2017-05-01",
period_to: "2017-05-31",
as_of_date: "2017-05-31"
},
previous_anchor_type: "organization",
previous_anchor_value: 'ООО "Альтернатива Плюс"'
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("vat_liability_confirmed_for_tax_period");
expect(result?.filters.extracted_filters.period_from).toBe("2017-05-01");
expect(result?.filters.extracted_filters.period_to).toBe("2017-05-31");
expect(result?.filters.extracted_filters.as_of_date).toBe("2017-05-31");
});
it("uses follow-up target intent for short debt mirror like 'а нам?'", () => {
const result = runAddressDecomposeStage("а нам?", {
previous_intent: "payables_confirmed_as_of_date",
target_intent: "receivables_confirmed_as_of_date",
previous_filters: {
as_of_date: "2026-04-16"
},
previous_anchor_type: "organization",
previous_anchor_value: 'ООО "Альтернатива Плюс"'
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("receivables_confirmed_as_of_date");
expect(result?.filters.extracted_filters.as_of_date).toBe("2026-04-16");
});
it("keeps same-date inventory pivot anchored to the previous VAT date", () => {
const result = runAddressDecomposeStage("какие остатки по складу на эту же дату", {
previous_intent: "vat_payable_confirmed_as_of_date",
previous_filters: {
period_from: "2019-09-01",
period_to: "2019-09-30",
as_of_date: "2019-09-30"
},
previous_anchor_type: "unknown",
previous_anchor_value: null
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("inventory_on_hand_as_of_date");
expect(result?.filters.extracted_filters.as_of_date).toBe("2019-09-30");
expect(result?.filters.extracted_filters.warehouse).toBeUndefined();
expect(result?.baseReasons).toContain("as_of_date_from_followup_context");
});
it("keeps period window on inventory same-date follow-up phrased as 'по этой же дате'", () => {
const result = runAddressDecomposeStage(
"\u043f\u043e\u043a\u0430\u0436\u0438 \u043e\u0441\u0442\u0430\u0442\u043a\u0438 \u043d\u0430 \u0441\u043a\u043b\u0430\u0434\u0435 \u043f\u043e \u044d\u0442\u043e\u0439 \u0436\u0435 \u0434\u0430\u0442\u0435",
{
previous_intent: "receivables_confirmed_as_of_date",
previous_filters: {
organization: "\u0420\u0410\u0419\u041c",
period_from: "2020-03-01",
period_to: "2020-03-31",
as_of_date: "2020-03-31"
},
previous_anchor_type: "organization",
previous_anchor_value: "\u0420\u0410\u0419\u041c"
}
);
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("inventory_on_hand_as_of_date");
expect(result?.filters.extracted_filters.organization).toBe("\u0420\u0410\u0419\u041c");
expect(result?.filters.extracted_filters.as_of_date).toBe("2020-03-31");
expect(result?.filters.extracted_filters.period_from).toBe("2020-03-01");
expect(result?.filters.extracted_filters.period_to).toBe("2020-03-31");
expect(result?.filters.extracted_filters.warehouse).toBeUndefined();
expect(result?.baseReasons).toContain("period_from_from_followup_context");
expect(result?.baseReasons).toContain("period_to_from_followup_context");
});
it("does not inherit stale inventory as-of date over an explicit fresh snapshot date", () => {
const result = runAddressDecomposeStage(
"Покажи складской срез Альтернативы Плюс на 2026-04-16: что есть в остатках, какие самые заметные позиции, и что это говорит о бизнесе.",
{
previous_intent: "inventory_on_hand_as_of_date",
target_intent: "inventory_on_hand_as_of_date",
previous_filters: {
organization: "ООО Альтернатива Плюс",
period_from: "2020-01-01",
period_to: "2020-12-31",
as_of_date: "2020-12-31"
},
previous_anchor_type: "organization",
previous_anchor_value: "ООО Альтернатива Плюс"
}
);
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("inventory_on_hand_as_of_date");
expect(result?.filters.extracted_filters.as_of_date).toBe("2026-04-16");
expect(result?.filters.extracted_filters.period_from).toBe("2026-04-01");
expect(result?.filters.extracted_filters.period_to).toBe("2026-04-30");
expect(result?.baseReasons).not.toContain("as_of_date_from_open_items_followup_context");
});
it("retargets inventory purchase-date VAT bridge into confirmed VAT period with inherited purchase month", () => {
const result = runAddressDecomposeStage("ндс можешь прикинуть на дату покупки рабочей станции?", {
previous_intent: "inventory_purchase_provenance_for_item",
target_intent: "vat_liability_confirmed_for_tax_period",
previous_filters: {
item: "Рабочая станция универсального специалиста",
organization: 'ООО "Альтернатива Плюс"',
period_from: "2015-02-01",
period_to: "2015-02-28",
as_of_date: "2016-03-31"
},
previous_anchor_type: "item",
previous_anchor_value: "Рабочая станция универсального специалиста"
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("vat_liability_confirmed_for_tax_period");
expect(result?.filters.extracted_filters.period_from).toBe("2015-02-01");
expect(result?.filters.extracted_filters.period_to).toBe("2015-02-28");
expect(result?.baseReasons).toContain("period_from_followup_context");
});
it("clears counterparty noise from bare organization clarification selections that resume inventory", () => {
const result = runAddressDecomposeStage("АЛЬТЕРНАТИВА", {
previous_intent: "inventory_on_hand_as_of_date",
target_intent: "inventory_on_hand_as_of_date",
previous_filters: {
organization: "ООО Альтернатива Плюс",
as_of_date: "2026-04-19"
},
previous_anchor_type: "organization",
previous_anchor_value: "ООО Альтернатива Плюс"
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("inventory_on_hand_as_of_date");
expect(result?.filters.extracted_filters.organization).toBe("ООО Альтернатива Плюс");
expect(result?.filters.extracted_filters.as_of_date).toBe("2026-04-19");
expect(result?.filters.extracted_filters.counterparty).toBeUndefined();
});
it("does not re-inherit organization alias as counterparty into historical inventory follow-up", () => {
const result = runAddressDecomposeStage("давай на июль 2017", {
previous_intent: "inventory_on_hand_as_of_date",
target_intent: "inventory_on_hand_as_of_date",
previous_filters: {
organization: "ООО Альтернатива Плюс",
counterparty: "АЛЬТЕРНАТИВА",
as_of_date: "2026-04-19"
},
previous_anchor_type: "counterparty",
previous_anchor_value: "АЛЬТЕРНАТИВА",
root_intent: "inventory_on_hand_as_of_date",
root_filters: {
organization: "ООО Альтернатива Плюс",
as_of_date: "2026-04-19"
},
root_anchor_type: "organization",
root_anchor_value: "ООО Альтернатива Плюс",
current_frame_kind: "inventory_root"
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("inventory_on_hand_as_of_date");
expect(result?.filters.extracted_filters.organization).toBe("ООО Альтернатива Плюс");
expect(result?.filters.extracted_filters.period_from).toBe("2017-07-01");
expect(result?.filters.extracted_filters.period_to).toBe("2017-07-31");
expect(result?.filters.extracted_filters.counterparty).toBeUndefined();
expect(result?.baseReasons).toContain("counterparty_cleared_as_organization_scope_alias");
});
it("does not inherit stale historical period into a fresh counterparty document root", () => {
const result = runAddressDecomposeStage("по чепурнову покажи все доки", {
previous_intent: "inventory_on_hand_as_of_date",
target_intent: "list_documents_by_counterparty",
previous_filters: {
organization: "ООО Альтернатива Плюс",
period_from: "2016-03-01",
period_to: "2016-03-31",
as_of_date: "2016-03-31"
},
previous_anchor_type: "organization",
previous_anchor_value: "ООО Альтернатива Плюс"
}, {
scope_target_kind: "counterparty",
scope_target_text: "Чепурнов",
date_scope_kind: "missing",
self_scope_detected: false,
selected_object_scope_detected: false
});
expect(result).not.toBeNull();
expect(result?.intent.intent).toBe("list_documents_by_counterparty");
expect(result?.filters.extracted_filters.counterparty).toBeTruthy();
expect(result?.filters.extracted_filters.period_from).toBeUndefined();
expect(result?.filters.extracted_filters.period_to).toBeUndefined();
});
it("replaces document and movement service-word anchors from counterparty follow-up context", () => {
const followupContext = {
previous_intent: "customer_revenue_and_payments" as const,
target_intent: "list_documents_by_counterparty" as const,
previous_filters: {
organization: "ООО Альтернатива Плюс",
counterparty: "Группа СВК",
period_from: "2020-01-01",
period_to: "2020-12-31"
},
previous_anchor_type: "counterparty" as const,
previous_anchor_value: "Группа СВК",
resolved_counterparty_from_display: true
};
const documents = runAddressDecomposeStage("документы по контрагенту документам", followupContext);
const movements = runAddressDecomposeStage("Проверить движение по счетам или документам", followupContext);
expect(documents?.intent.intent).toBe("list_documents_by_counterparty");
expect(documents?.filters.extracted_filters.counterparty).toBe("Группа СВК");
expect(documents?.baseReasons).toContain("counterparty_from_followup_context");
expect(movements?.intent.intent).toBe("list_documents_by_counterparty");
expect(movements?.filters.extracted_filters.counterparty).toBe("Группа СВК");
expect(movements?.baseReasons).toContain("counterparty_from_followup_context");
});
});