Files
test/improvement.md
2026-01-16 18:37:32 +03:00

10 KiB
Raw Permalink Blame History

Улучшения системы обработки банковских транзакций

1. Упрощение логики бесконечного редактирования

1.1 Текущая проблема

  • Используется таблица user_sessions для хранения состояния редактирования
  • Множественные SELECT/UPDATE запросы при каждом действии пользователя
  • Сложная логика ветвления в n8n для управления сессиями

1.2 Решение: Stateful callback_data с editMessage

Принцип работы: Храним все состояние редактирования прямо в callback_data кнопок Telegram

Формат callback_data

edit_card_{transactionId}_{counterparty}_{category}
set_category_{transactionId}_{counterparty}_{newCategory}
edit_field_{transactionId}_{counterparty}_{category}_{field}
confirm_{transactionId}_{counterparty}_{category}

Примеры

edit_card_123_Пятёрочкародукты
set_category_123_Пятёрочка_Авто
edit_field_123_Пятёрочкародукты_category
confirm_123_Пятёрочкародукты

Узлы n8n для удаления

  1. user_sessions таблица
  2. get_session (SELECT)
  3. add_session_category (INSERT)
  4. add_session_counterparty (INSERT)
  5. merge_user_and_session
  6. parse_text_input (частично)
  7. merge_changes

Новые узлы

  1. create_edit_card — генерирует карточку редактирования с inline-клавиатурой
  2. update_card_on_action — обрабатывает callback и обновляет сообщение через editMessage

1.3 Преимущества

  • Уменьшение нагрузки на БД на 80% — убираем 5-7 запросов на одно действие
  • Упрощение workflow — вместо ветвления по сессиям — линейная обработка
  • Мгновенная обратная связь — editMessage вместо новых сообщений
  • Stateless архитектура — нет зависимостей между запросами

2. Улучшение UX для выбора категорий

2.1 Текущая проблема

  • Текстовый ввод категорий требует запоминания всех 20 вариантов
  • Ошибки при ручном вводе (опечатки, синонимы)
  • Медленный процесс категоризации

2.2 Решение: Многоуровневая inline-клавиатура

Первый уровень — "умные" популярные категории

// Алгоритм выбора популярных категорий:
// 1. Берем топ-3 категории пользователя из истории (если есть)
// 2. Добавляем глобально популярные категории
// 3. Всего 4 кнопки

const getUserTopCategories = async (chatId) => {
  // Запрос к БД за последние 30 дней
  const topCats = await db.query(`
    SELECT category, COUNT(*) as count 
    FROM transactions 
    WHERE chat_id = $1 
      AND category IS NOT NULL
      AND received_at > NOW() - INTERVAL '30 days'
    GROUP BY category 
    ORDER BY count DESC 
    LIMIT 3
  `, [chatId]);
  
  return topCats.map(row => row.category);
};

const getDefaultCategories = () => ["Продукты", "Авто", "Дом"];

Второй уровень — все категории компактно

// Без эмодзи для экономии места
const ALL_CATEGORIES = [
  ["Продукты", "Авто", "Здоровье", "Арчи"],
  ["ЖКХ", "Дом", "Проезд", "Одежда"],
  ["Химия", "Косметика", "Инвестиции", "Развлечения"],
  ["Общепит", "Штрафы", "Налоги", "Подписки"],
  ["Перевод", "Наличные", "Подарки", "Спорт"],
  ["Другое"]
];

// Каждая кнопка: callback_data = "set_category_{id}_{counterparty}_{category}"

Узлы n8n для изменения

  1. 🔄 category_editsend_category_keyboard (отправляет 4 кнопки)
  2. show_all_categories → новый узел для отправки полного списка
  3. Текстовый ввод категорий удаляется полностью

Кэширование популярных категорий

// В Redis или памяти n8n (Global Variables)
// Ключ: user_top_cats_{chatId}
// TTL: 1 час
// Данные: ["Продукты", "Общепит", "Авто"]

// При запросе:
// 1. Проверяем кэш
// 2. Если нет → запрос к БД → сохранение в кэш
// 3. Возвращаем данные

2.3 Преимущества

  • В 3-5 раз быстрее выбор категории
  • Нет ошибок ввода — только валидные категории
  • Персонализация — показываем часто используемые категории
  • Экономия места — без эмодзи больше категорий на экране

3. Техническая реализация

Изменения в БД

-- Удаляем таблицу user_sessions
DROP TABLE IF EXISTS user_sessions;

-- Добавляем кэш популярных категорий (опционально)
CREATE TABLE IF NOT EXISTS user_category_stats (
  chat_id BIGINT,
  category VARCHAR(100),
  count INTEGER DEFAULT 1,
  last_used TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (chat_id, category)
);

-- Индекс для быстрого получения топ категорий
CREATE INDEX idx_user_cats ON user_category_stats(chat_id, count DESC);

Изменения в workflow n8n

Ветка редактирования (новая)

edit_field (callback) → 
  IF field = 'category' → 
    get_top_categories (Code + возможно DB) → 
    send_category_keyboard (Telegram Message)
    
  IF field = 'counterparty' → 
    request_counterparty_input (Telegram Message) → 
    (текстовый ответ) → 
    update_card_with_new_counterparty (editMessage)

Ветка выбора категории

set_category (callback) → 
  update_category_stats (DB) →  -- инкрементируем счетчик
  update_card (editMessage) →   -- обновляем карточку
  (возврат в режим редактирования)

Ветка "все категории"

show_all_cats (callback) → 
  send_all_categories (Telegram Message) →  -- компактная клавиатура 5x4
  (пользователь выбирает) → 
  set_category (существующая ветка)

Лимиты и ограничения

  1. Callback_data length ≤ 64 байт

    // Решение: кодирование/декодирование длинных строк
    const encodeData = (str) => encodeURIComponent(str.substring(0, 20));
    const decodeData = (str) => decodeURIComponent(str);
    
  2. Inline keyboard rows ≤ 8-10 для удобства

  3. Кэш TTL = 1 час для актуальности

4. Ожидаемые результаты

Метрики улучшений

Показатель Было Стало Улучшение
Запросов к БД на действие 5-7 1-2 ~70% ↓
Время категоризации 10-30 сек 2-5 сек 5x ↑
Ошибок категоризации 15-20% <2% 10x ↓
Пользовательских кликов 3-5 1-2 2x ↓

Безопасность

  1. Все данные в callback_data URL-encoded
  2. Валидация transactionId при каждом запросе
  3. Проверка прав доступа к чату

Резервное решение

Если callback_data превышает лимит Telegram:

// Fallback: короткий хэш + временное хранилище
const hash = md5(transactionId + counterparty + category).substring(0, 8);
cache.set(`card_${hash}`, {transactionId, counterparty, category}, 300); // 5 мин
callback_data = `short_${hash}`;

5. План внедрения

Фаза 1: Подготовка (1-2 дня)

  1. Создать новую таблицу user_category_stats
  2. Написать миграцию данных из истории транзакций
  3. Обновить узлы обработки callback_data

Фаза 2: Внедрение (1 день)

  1. Добавить новые узлы n8n параллельно существующим
  2. Протестировать на отдельном Telegram-боте
  3. Проверить лимиты callback_data

Фаза 3: Переключение (1 день)

  1. Направить 10% трафика на новую систему
  2. Сравнить метрики
  3. Полное переключение при успехе

Фаза 4: Оптимизация (непрерывно)

  1. Мониторинг нагрузки БД
  2. Настройка кэширования
  3. A/B тестирование разных наборов популярных категорий

Заключение

Предложенные изменения устраняют основные боли пользователей:

  • Упрощают редактирование через мгновенное обновление карточек
  • Ускоряют категоризацию через умные inline-клавиатуры
  • Уменьшают нагрузку на инфраструктуру через stateless дизайн

Общее количество узлов n8n сократится с 36 до ~25 при улучшении UX и производительности.