ДОМЕНЫ - ВОПРОСЫ - 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
@@ -380,6 +380,12 @@ function detectValueRankingFocus(userMessage) {
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";
}
@@ -1420,6 +1426,7 @@ function composeFactualReply(intent, rows, options = {}) {
const minOpsForAvgCheck = detectMinOpsForAvgCheck(options.userMessage);
const normalizedQuestion = normalizeQuestionText(options.userMessage);
const byCounterparty = new Map();
const byYear = new Map();
const deals = [];
for (const row of rows) {
const counterparty = extractCounterpartyName(row);
@@ -1453,9 +1460,30 @@ function composeFactualReply(intent, rows, options = {}) {
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([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));
const rankedByAvgCheck = [...profileRows]
@@ -1485,6 +1513,23 @@ function composeFactualReply(intent, rows, options = {}) {
text: lines.join("\n")
};
}
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