ДОМЕНЫ - ВОПРОСЫ - fix: переведен exact-маршрут кому должны на дату на Хозрасчетный.Остатки (без Движения.СубконтоДт1/Кт1)

This commit is contained in:
2026-04-12 16:59:18 +03:00
parent 278eb4abeb
commit 143cf6efe1
13 changed files with 646 additions and 127 deletions
@@ -51,6 +51,7 @@ type CounterpartyProfileFocus =
type CounterpartyLifecycleFocus = "active_customers_period" | "active_customers_all_time";
type ValueRankingFocus =
| "top_by_total"
| "top_years_by_total"
| "top_by_ops"
| "top_by_max_single"
| "top_by_avg_check_min_ops"
@@ -524,6 +525,13 @@ function detectValueRankingFocus(userMessage: string | null | undefined): ValueR
if (!text) {
return "top_by_total";
}
const asksYearlyRevenueRanking =
/(?:доходн|выручк|оборот|прибыл|деньг|денег|revenue|turnover|income)/iu.test(text) &&
/(?:год|года|годы|year|years|по\s+годам)/iu.test(text) &&
/(?:сам(?:ый|ая|ое|ые)|топ|луч|best|max|наибольш|больше)/iu.test(text);
if (asksYearlyRevenueRanking) {
return "top_years_by_total";
}
if (/(?:сам(?:ый|ая|ое|ые)\s+высок[а-яё]*|highest|largest)\s+чек|(?:max\s+check|чек\s+макс)/iu.test(text)) {
return "top_by_max_single";
}
@@ -1800,6 +1808,16 @@ export function composeFactualReply(
lastPeriod: string | null;
}
>();
const byYear = new Map<
number,
{
year: number;
total: number;
ops: number;
maxSingle: number;
counterparties: Set<string>;
}
>();
const deals: Array<{ period: string | null; registrator: string; counterparty: string; amount: number }> = [];
for (const row of rows) {
@@ -1834,10 +1852,31 @@ export function composeFactualReply(
counterparty,
amount
});
const year = extractYearFromIso(row.period);
if (year !== null) {
const yearBucket = byYear.get(year);
if (!yearBucket) {
byYear.set(year, {
year,
total: amount,
ops: 1,
maxSingle: amount,
counterparties: new Set<string>([counterparty])
});
} else {
yearBucket.total += amount;
yearBucket.ops += 1;
yearBucket.maxSingle = Math.max(yearBucket.maxSingle, amount);
yearBucket.counterparties.add(counterparty);
}
}
}
const profileRows = Array.from(byCounterparty.values());
const yearRows = Array.from(byYear.values());
const rankedByTotal = [...profileRows].sort((a, b) => b.total - a.total || b.ops - a.ops || a.name.localeCompare(b.name));
const rankedByYearTotal = [...yearRows].sort((a, b) => b.total - a.total || b.ops - a.ops || a.year - b.year);
const rankedByOps = [...profileRows].sort((a, b) => b.ops - a.ops || b.total - a.total || a.name.localeCompare(b.name));
const rankedByMaxSingle = [...profileRows].sort(
(a, b) => b.maxSingle - a.maxSingle || b.total - a.total || a.name.localeCompare(b.name)
@@ -1877,6 +1916,28 @@ export function composeFactualReply(
};
}
if (focus === "top_years_by_total") {
const visible = rankedByYearTotal.slice(0, limit);
const heading = isSupplier
? `Топ-${visible.length} лет по сумме выплат:`
: `Топ-${visible.length} лет по сумме поступлений:`;
lines.unshift(heading);
if (visible.length === 0) {
lines.push("По доступному окну не удалось собрать годовые агрегаты по суммам.");
} else {
lines.push(
...visible.map(
(item, index) =>
`${index + 1}. ${item.year} | сумма: ${item.total} | операций: ${item.ops} | контрагентов: ${item.counterparties.size} | макс: ${item.maxSingle}`
)
);
}
return {
responseType: "FACTUAL_LIST",
text: lines.join("\n")
};
}
if (focus === "top_by_ops") {
const visible = rankedByOps.slice(0, limit);
const heading = isSupplier