import { afterEach, describe, expect, it, vi } from "vitest"; const { executeAddressMcpQueryMock } = vi.hoisted(() => ({ executeAddressMcpQueryMock: vi.fn() })); vi.mock("../src/services/addressMcpClient", async () => { const actual = await vi.importActual( "../src/services/addressMcpClient" ); return { ...actual, executeAddressMcpQuery: executeAddressMcpQueryMock }; }); import { AddressQueryService } from "../src/services/addressQueryService"; afterEach(() => { executeAddressMcpQueryMock.mockReset(); }); describe("inventory purchase-date selected-object follow-up", () => { it("routes short 'когда' follow-up to purchase provenance and reuses the active item", async () => { executeAddressMcpQueryMock.mockResolvedValueOnce({ fetched_rows: 1, matched_rows: 1, raw_rows: [ { Period: "2020-02-11T00:00:00Z", Registrator: "Поступление товаров и услуг 00000000077 от 11.02.2020 0:00:00", AccountDt: "41.01", AccountKt: "60.01", Amount: 165.83, SubcontoDt1: "Кромка с клеем 33 альмяндин 137 м", SubcontoDt3: "Основной склад", SubcontoKt1: "Торговый дом \\Союз МСК\\", SubcontoKt2: "Договор поставки № 12 от 01.02.2020", Organization: "ООО \\Альтернатива Плюс\\" } ], rows: [], error: null }); const service = new AddressQueryService(); const result = await service.tryHandle("когда", { followupContext: { previous_intent: "inventory_purchase_provenance_for_item", previous_filters: { item: "Кромка с клеем 33 альмяндин 137 м", warehouse: "Основной склад", as_of_date: "2020-03-31" }, previous_anchor_type: "unknown", previous_anchor_value: null } }); expect(result?.handled).toBe(true); expect(result?.response_type).toBe("FACTUAL_SUMMARY"); expect(result?.debug.detected_intent).toBe("inventory_purchase_provenance_for_item"); expect(result?.debug.extracted_filters?.item).toBe("Кромка с клеем 33 альмяндин 137 м"); expect(result?.debug.extracted_filters?.as_of_date).toBe("2020-03-31"); const replyLines = String(result?.reply_text ?? "").split("\n"); expect(replyLines[0]).toContain("11.02.2020"); expect(replyLines[0]).toContain("Кромка"); expect(String(result?.reply_text ?? "")).not.toContain("Блок 1"); expect(String(result?.reply_text ?? "")).toContain("Подтверждение"); expect(result?.debug.reasons).toContain("address_followup_context_applied"); }); it("routes bare 'когда' follow-up to purchase provenance with the carried active item", async () => { executeAddressMcpQueryMock.mockResolvedValueOnce({ fetched_rows: 1, matched_rows: 1, raw_rows: [ { Period: "2019-02-12T00:00:00Z", Registrator: "Поступление товаров и услуг 00000000003 от 12.02.2019 0:00:00", AccountDt: "41.01", AccountKt: "60.01", Amount: 3724.17, SubcontoDt1: "Столешница 600*3050*26 дуб ниагара", SubcontoDt3: "Основной склад", SubcontoKt1: "Торговый дом \\Союз МСК\\", SubcontoKt2: "Договор поставки № 12 от 01.02.2019", Organization: "ООО \\Альтернатива Плюс\\" } ], rows: [], error: null }); const service = new AddressQueryService(); const result = await service.tryHandle("когда", { followupContext: { previous_intent: "inventory_purchase_provenance_for_item", previous_filters: { item: "Столешница 600*3050*26 дуб ниагара", warehouse: "Основной склад", as_of_date: "2019-03-31" }, previous_anchor_type: "unknown", previous_anchor_value: null } }); expect(result?.handled).toBe(true); expect(result?.debug.detected_intent).toBe("inventory_purchase_provenance_for_item"); expect(result?.debug.extracted_filters?.item).toBe("Столешница 600*3050*26 дуб ниагара"); expect(result?.debug.extracted_filters?.as_of_date).toBe("2019-03-31"); expect(String(result?.reply_text ?? "").split("\n")[0]).toContain("12.02.2019"); expect(String(result?.reply_text ?? "")).not.toContain("Блок 1"); }); it("routes direct canonical purchase-date wording with an explicit item through the exact provenance lane", async () => { executeAddressMcpQueryMock.mockResolvedValueOnce({ fetched_rows: 1, matched_rows: 1, raw_rows: [ { Period: "2019-02-12T00:00:00Z", Registrator: "Поступление товаров и услуг 00000000003 от 12.02.2019 0:00:00", AccountDt: "41.01", AccountKt: "60.01", Amount: 3724.17, SubcontoDt1: "Столешница 600*3050*26 дуб ниагара", SubcontoDt3: "Основной склад", SubcontoKt1: "Торговый дом \\Союз МСК\\", SubcontoKt2: "Договор поставки № 12 от 01.02.2019", Organization: "ООО \\Альтернатива Плюс\\" } ], rows: [], error: null }); const service = new AddressQueryService(); const result = await service.tryHandle("Когда был куплен товар Столешница 600*3050*26 дуб ниагара", { followupContext: { previous_intent: "inventory_purchase_provenance_for_item", previous_filters: { item: "Столешница 600*3050*26 дуб ниагара", warehouse: "Основной склад", as_of_date: "2019-03-31" }, previous_anchor_type: "unknown", previous_anchor_value: null } }); expect(result?.handled).toBe(true); expect(result?.response_type).toBe("FACTUAL_SUMMARY"); expect(result?.debug.detected_intent).toBe("inventory_purchase_provenance_for_item"); expect(result?.debug.selected_recipe).toBe("address_inventory_purchase_provenance_for_item_v1"); expect(result?.debug.extracted_filters?.item).toBe("Столешница 600*3050*26 дуб ниагара"); expect(result?.debug.extracted_filters?.as_of_date).toBe("2019-03-31"); expect(String(result?.reply_text ?? "").split("\n")[0]).toContain("12.02.2019"); expect(String(result?.reply_text ?? "")).not.toContain("Блок 1"); }); it("routes 'когда примерно мы купили' follow-up to compact purchase-date answer with the carried item", async () => { executeAddressMcpQueryMock.mockResolvedValueOnce({ fetched_rows: 1, matched_rows: 1, raw_rows: [ { Period: "2020-02-11T00:00:00Z", Registrator: "Поступление товаров и услуг 00000000077 от 11.02.2020 0:00:00", AccountDt: "41.01", AccountKt: "60.01", Amount: 833.33, SubcontoDt1: "Четки Пост (84*117)", SubcontoDt3: "Основной склад", SubcontoKt1: "Торговый дом \\Союз МСК\\", SubcontoKt2: "Договор поставки № 12 от 01.02.2020", Organization: "ООО \\Альтернатива Плюс\\" } ], rows: [], error: null }); const service = new AddressQueryService(); const result = await service.tryHandle("когда примерно мы купили?", { followupContext: { previous_intent: "inventory_purchase_provenance_for_item", previous_filters: { item: "Четки Пост (84*117)", warehouse: "Основной склад", as_of_date: "2020-03-31" }, previous_anchor_type: "unknown", previous_anchor_value: null } }); expect(result?.handled).toBe(true); expect(result?.debug.detected_intent).toBe("inventory_purchase_provenance_for_item"); expect(result?.debug.extracted_filters?.item).toBe("Четки Пост (84*117)"); expect(result?.debug.extracted_filters?.as_of_date).toBe("2020-03-31"); expect(String(result?.reply_text ?? "").split("\n")[0]).toContain("11.02.2020"); expect(String(result?.reply_text ?? "")).toContain("Подтверждение"); expect(String(result?.reply_text ?? "")).not.toContain("Блок 1"); }); });