initial commit
This commit is contained in:
265
improvement.md
Normal file
265
improvement.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# Улучшения системы обработки банковских транзакций
|
||||
|
||||
## 1. Упрощение логики бесконечного редактирования
|
||||
|
||||
### 1.1 Текущая проблема
|
||||
|
||||
- Используется таблица `user_sessions` для хранения состояния редактирования
|
||||
- Множественные SELECT/UPDATE запросы при каждом действии пользователя
|
||||
- Сложная логика ветвления в n8n для управления сессиями
|
||||
|
||||
### 1.2 Решение: Stateful callback_data с editMessage
|
||||
|
||||
**Принцип работы:** Храним все состояние редактирования прямо в callback_data кнопок Telegram
|
||||
|
||||
#### Формат callback_data
|
||||
|
||||
```text
|
||||
edit_card_{transactionId}_{counterparty}_{category}
|
||||
set_category_{transactionId}_{counterparty}_{newCategory}
|
||||
edit_field_{transactionId}_{counterparty}_{category}_{field}
|
||||
confirm_{transactionId}_{counterparty}_{category}
|
||||
```
|
||||
|
||||
#### Примеры
|
||||
|
||||
```text
|
||||
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-клавиатура
|
||||
|
||||
#### Первый уровень — "умные" популярные категории
|
||||
|
||||
```javascript
|
||||
// Алгоритм выбора популярных категорий:
|
||||
// 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 = () => ["Продукты", "Авто", "Дом"];
|
||||
```
|
||||
|
||||
#### Второй уровень — все категории компактно
|
||||
|
||||
```javascript
|
||||
// Без эмодзи для экономии места
|
||||
const ALL_CATEGORIES = [
|
||||
["Продукты", "Авто", "Здоровье", "Арчи"],
|
||||
["ЖКХ", "Дом", "Проезд", "Одежда"],
|
||||
["Химия", "Косметика", "Инвестиции", "Развлечения"],
|
||||
["Общепит", "Штрафы", "Налоги", "Подписки"],
|
||||
["Перевод", "Наличные", "Подарки", "Спорт"],
|
||||
["Другое"]
|
||||
];
|
||||
|
||||
// Каждая кнопка: callback_data = "set_category_{id}_{counterparty}_{category}"
|
||||
```
|
||||
|
||||
#### Узлы n8n для изменения
|
||||
|
||||
1. 🔄 `category_edit` → `send_category_keyboard` (отправляет 4 кнопки)
|
||||
2. ✅ `show_all_categories` → новый узел для отправки полного списка
|
||||
3. ❌ Текстовый ввод категорий удаляется полностью
|
||||
|
||||
#### Кэширование популярных категорий
|
||||
|
||||
```javascript
|
||||
// В Redis или памяти n8n (Global Variables)
|
||||
// Ключ: user_top_cats_{chatId}
|
||||
// TTL: 1 час
|
||||
// Данные: ["Продукты", "Общепит", "Авто"]
|
||||
|
||||
// При запросе:
|
||||
// 1. Проверяем кэш
|
||||
// 2. Если нет → запрос к БД → сохранение в кэш
|
||||
// 3. Возвращаем данные
|
||||
```
|
||||
|
||||
### 2.3 Преимущества
|
||||
|
||||
- **В 3-5 раз быстрее** выбор категории
|
||||
- **Нет ошибок ввода** — только валидные категории
|
||||
- **Персонализация** — показываем часто используемые категории
|
||||
- **Экономия места** — без эмодзи больше категорий на экране
|
||||
|
||||
## 3. Техническая реализация
|
||||
|
||||
### Изменения в БД
|
||||
|
||||
```sql
|
||||
-- Удаляем таблицу 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
|
||||
|
||||
#### Ветка редактирования (новая)
|
||||
|
||||
```text
|
||||
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)
|
||||
```
|
||||
|
||||
#### Ветка выбора категории
|
||||
|
||||
```text
|
||||
set_category (callback) →
|
||||
update_category_stats (DB) → -- инкрементируем счетчик
|
||||
update_card (editMessage) → -- обновляем карточку
|
||||
(возврат в режим редактирования)
|
||||
```
|
||||
|
||||
#### Ветка "все категории"
|
||||
|
||||
```text
|
||||
show_all_cats (callback) →
|
||||
send_all_categories (Telegram Message) → -- компактная клавиатура 5x4
|
||||
(пользователь выбирает) →
|
||||
set_category (существующая ветка)
|
||||
```
|
||||
|
||||
### Лимиты и ограничения
|
||||
|
||||
1. **Callback_data length** ≤ 64 байт
|
||||
|
||||
```javascript
|
||||
// Решение: кодирование/декодирование длинных строк
|
||||
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:
|
||||
|
||||
```javascript
|
||||
// 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 и производительности.
|
||||
Reference in New Issue
Block a user