146 lines
6.0 KiB
TypeScript
146 lines
6.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
|
||
import { composeCounterpartyAnalyticsReply } from "../src/services/address_runtime/counterpartyAnalyticsReplyBuilders";
|
||
import { composeInventoryReply } from "../src/services/address_runtime/inventoryReplyBuilders";
|
||
|
||
describe("address reply builders regressions", () => {
|
||
it("starts top customer aggregate reply with a direct business answer", () => {
|
||
const result = composeCounterpartyAnalyticsReply(
|
||
"customer_revenue_and_payments",
|
||
[
|
||
{
|
||
amount: 250000,
|
||
period: "2020-03-31",
|
||
registrator: "Поступление 1"
|
||
} as any
|
||
],
|
||
{
|
||
userMessage: "кто у нас самый доходный клиент за все время?"
|
||
},
|
||
{
|
||
formatPercent: () => null,
|
||
formatDateRu: (value: string) => value,
|
||
formatMoneyRub: (value: number) => `${value} ₽`,
|
||
extractYearFromIso: (value: string | null) => (value ? Number(value.slice(0, 4)) : null),
|
||
detectCounterpartyProfileFocus: () => "full_profile",
|
||
detectCounterpartyLifecycleFocus: () => "active_customers_all_time",
|
||
hasCounterpartyLifecycleLongevityQuestion: () => false,
|
||
hasCounterpartyActivityAgeQuestion: () => false,
|
||
detectRankingLimit: () => 5,
|
||
detectValueRankingFocus: () => "top_by_total",
|
||
detectContractValueFocus: () => "top_by_turnover",
|
||
detectMinOpsForAvgCheck: () => 1,
|
||
extractRequestedYearFromQuestion: () => null,
|
||
extractCounterpartyName: () => "Чапурнов",
|
||
extractContractName: () => null,
|
||
counterpartyLookupMatches: () => false,
|
||
toUtcDayTimestamp: () => null,
|
||
formatAgeYearsMonthsDays: () => "0 дней",
|
||
normalizeQuestionText: (value: string | null | undefined) => String(value ?? "")
|
||
}
|
||
);
|
||
|
||
expect(result?.text.split("\n")[0]).toContain("Самый доходный клиент");
|
||
expect(result?.text.split("\n")[0]).toContain("Чапурнов");
|
||
});
|
||
|
||
it("starts top year aggregate reply with a direct business answer", () => {
|
||
const result = composeCounterpartyAnalyticsReply(
|
||
"customer_revenue_and_payments",
|
||
[
|
||
{
|
||
amount: 320000,
|
||
period: "2021-05-12",
|
||
registrator: "Поступление 2"
|
||
} as any
|
||
],
|
||
{
|
||
userMessage: "какой у нас самый доходный год"
|
||
},
|
||
{
|
||
formatPercent: () => null,
|
||
formatDateRu: (value: string) => value,
|
||
formatMoneyRub: (value: number) => `${value} ₽`,
|
||
extractYearFromIso: (value: string | null) => (value ? Number(value.slice(0, 4)) : null),
|
||
detectCounterpartyProfileFocus: () => "full_profile",
|
||
detectCounterpartyLifecycleFocus: () => "active_customers_all_time",
|
||
hasCounterpartyLifecycleLongevityQuestion: () => false,
|
||
hasCounterpartyActivityAgeQuestion: () => false,
|
||
detectRankingLimit: () => 5,
|
||
detectValueRankingFocus: () => "top_years_by_total",
|
||
detectContractValueFocus: () => "top_by_turnover",
|
||
detectMinOpsForAvgCheck: () => 1,
|
||
extractRequestedYearFromQuestion: () => null,
|
||
extractCounterpartyName: () => "Чапурнов",
|
||
extractContractName: () => null,
|
||
counterpartyLookupMatches: () => false,
|
||
toUtcDayTimestamp: () => null,
|
||
formatAgeYearsMonthsDays: () => "0 дней",
|
||
normalizeQuestionText: (value: string | null | undefined) => String(value ?? "")
|
||
}
|
||
);
|
||
|
||
expect(result?.text.split("\n")[0]).toContain("Самый доходный год");
|
||
expect(result?.text.split("\n")[0]).toContain("2021");
|
||
});
|
||
|
||
it("keeps very old stock answer free of explicit as-of date in the first line", () => {
|
||
const result = composeInventoryReply(
|
||
"inventory_aging_by_purchase_date",
|
||
[
|
||
{
|
||
amount: 1000,
|
||
period: "2015-02-05",
|
||
registrator: "Поступление 3"
|
||
} as any
|
||
],
|
||
{
|
||
userMessage: "Есть ли остатки товара, которые закупались очень давно",
|
||
asOfDate: "2026-04-18"
|
||
},
|
||
{
|
||
resolvePayablesAsOfDate: () => "2026-04-18",
|
||
buildInventoryOnHandAggregate: () => [],
|
||
uniqueStrings: (values: string[]) => values,
|
||
formatDateRu: (value: string) => value,
|
||
formatNumberWithDots: (value: number) => String(value),
|
||
formatMoneyRub: (value: number) => `${value} ₽`,
|
||
isInventoryPurchaseMovement: () => true,
|
||
summarizeInventoryTraceRows: () => ({
|
||
item: "Рабочая станция",
|
||
warehouses: ["Основной склад"],
|
||
organizations: ["ООО Альтернатива Плюс"],
|
||
counterparties: ["Чапурнов"],
|
||
documents: ["Поступление 3"],
|
||
firstPeriod: "2015-02-05",
|
||
lastPeriod: "2015-02-05",
|
||
totalAmount: 1000
|
||
}),
|
||
formatInventoryTraceRows: () => [],
|
||
hasInventoryPurchaseDateActionFocus: () => false,
|
||
inventoryTraceDateLabel: (value: string | null) => value ?? "дата не указана",
|
||
extractInventoryCounterpartyCandidates: () => ["Чапурнов"],
|
||
buildInventoryAgingByItemAggregate: () => [
|
||
{
|
||
item: "Рабочая станция",
|
||
warehouse: "Основной склад",
|
||
organization: "ООО Альтернатива Плюс",
|
||
firstPurchasePeriod: "2015-02-05",
|
||
lastPurchasePeriod: "2015-02-05",
|
||
operations: 1,
|
||
documentCount: 1,
|
||
counterparties: ["Чапурнов"],
|
||
ageDays: 4089
|
||
}
|
||
],
|
||
formatInventoryAgingRows: () => ["1. Рабочая станция | первая закупка: 2015-02-05"],
|
||
isInventorySaleMovement: () => false
|
||
}
|
||
);
|
||
|
||
const firstLine = result?.text.split("\n")[0] ?? "";
|
||
expect(firstLine).toContain("К самым старым закупкам");
|
||
expect(firstLine).not.toContain("2026-04-18");
|
||
});
|
||
});
|