150 lines
9.0 KiB
Markdown
150 lines
9.0 KiB
Markdown
# Позиция 4: Редактирование транзакций и правила категорий
|
||
|
||
## Цели
|
||
|
||
- Минимизировать ручной труд при категоризации транзакций.
|
||
- Обеспечить возможность "дообучения" системы за счёт действий пользователя.
|
||
- Отдельно обработать сложные случаи (маркетплейсы), где по описанию нельзя однозначно определить категорию.
|
||
|
||
## Редактирование транзакций (SPA)
|
||
|
||
При открытии истории операций пользователь может открыть карточку редактирования транзакции.
|
||
|
||
Доступные действия для одной транзакции:
|
||
|
||
- Изменить категорию (выбор из списка категорий `categories`).
|
||
- При необходимости добавить/изменить пользовательский комментарий (`comment`).
|
||
- Включить/отключить опцию "Создать правило для похожих транзакций в будущем".
|
||
|
||
Ограничения:
|
||
|
||
- Описание операции (`description`) **не редактируется** в SPA, чтобы сохранять оригинальные данные из банка.
|
||
|
||
Поле `comment` используется только для заметок пользователя и не влияет напрямую на
|
||
автоматические правила (на старте).
|
||
|
||
## Поля в таблице `transactions`
|
||
|
||
К ранее описанной структуре добавляются поля:
|
||
|
||
- `is_category_confirmed BOOLEAN NOT NULL DEFAULT FALSE` —
|
||
признак того, что текущая категория транзакции подтверждена пользователем
|
||
(явно или неявно).
|
||
- `comment TEXT` — пользовательский комментарий к транзакции.
|
||
|
||
Рекомендуемый DDL-дельта:
|
||
|
||
```sql
|
||
ALTER TABLE transactions
|
||
ADD COLUMN is_category_confirmed BOOLEAN NOT NULL DEFAULT FALSE;
|
||
|
||
ALTER TABLE transactions
|
||
ADD COLUMN comment TEXT;
|
||
```
|
||
|
||
## Поведение при редактировании транзакции
|
||
|
||
При сохранении изменений в SPA backend выполняет:
|
||
|
||
1. Обновление транзакции:
|
||
- устанавливается новое значение `category_id`;
|
||
- при изменении комментария сохраняется `comment`;
|
||
- поле `is_category_confirmed` устанавливается в `TRUE`.
|
||
|
||
2. Если опция "Создать правило для похожих транзакций в будущем" включена (по умолчанию включена):
|
||
- создаётся новая запись в `category_rules` или обновляется существующая.
|
||
|
||
## Создание правил из транзакций
|
||
|
||
В карточке редактирования транзакции отображается блок "Правило для будущих операций":
|
||
|
||
- Галочка (переключатель):
|
||
- по умолчанию **включена**;
|
||
- отвечает за то, будет ли на основе текущей транзакции создано/обновлено правило.
|
||
|
||
- Поле "ключевая строка/шаблон" (pattern):
|
||
- заполняется автоматически (например, ключевым словом из `description`),
|
||
но пользователь может его скорректировать;
|
||
- сохраняется в `category_rules.pattern`.
|
||
|
||
- Тип совпадения (match_type): на старте можно использовать только `"contains"`.
|
||
- В дальнейшем допускается расширение до `"starts_with"` и `"regex"`.
|
||
|
||
При сохранении:
|
||
|
||
- создаётся правило в `category_rules` с полями:
|
||
- `pattern` — строка из формы;
|
||
- `match_type` — тип (на старте `"contains"`);
|
||
- `category_id` — выбранная категория;
|
||
- `priority` — например, по умолчанию 100 для правил, созданных пользователем;
|
||
- `requires_confirmation` — если `TRUE`, транзакции, категоризированные этим правилом,
|
||
получают `is_category_confirmed = FALSE` и требуют ручного подтверждения.
|
||
По умолчанию `FALSE`. Используется для правил с неоднозначным соответствием (маркетплейсы и т.п.);
|
||
- `is_active = TRUE`.
|
||
|
||
Логика приоритета:
|
||
|
||
- Если для одной транзакции подходит несколько правил, выбирается правило
|
||
с максимальным значением `priority`.
|
||
|
||
## Правила с обязательным подтверждением (`requires_confirmation`)
|
||
|
||
Проблема: некоторые правила не могут однозначно определить категорию транзакции.
|
||
Например, по описанию "OZON", "WILDBERRIES" невозможно понять, что именно было куплено
|
||
(продукты, одежда, техника и т.п.).
|
||
|
||
Механизм:
|
||
|
||
- В таблице `category_rules` используется флаг `requires_confirmation BOOLEAN NOT NULL DEFAULT FALSE`.
|
||
- Если `requires_confirmation = TRUE`:
|
||
- правило присваивает категорию (например, "Дом" или любую другую, выбранную пользователем);
|
||
- но `is_category_confirmed` у транзакции устанавливается в `FALSE`.
|
||
- Если `requires_confirmation = FALSE` (по умолчанию):
|
||
- правило присваивает категорию и `is_category_confirmed = TRUE`.
|
||
|
||
Результат:
|
||
|
||
- Транзакции, категоризированные правилами с `requires_confirmation = TRUE`,
|
||
визуально подсвечиваются в истории как требующие внимания.
|
||
- Пользователь может:
|
||
- подтвердить категорию (`is_category_confirmed` становится `TRUE`);
|
||
- изменить категорию и при желании создать новое правило.
|
||
|
||
Дополнительно:
|
||
|
||
- Для таких транзакций (например, маркетплейсы) полезно поле `comment`, куда пользователь может
|
||
записать, что конкретно было куплено (например, "корм для Арчи", "мебель", "одежда").
|
||
|
||
## Применение правил к прошлым транзакциям
|
||
|
||
В интерфейсе управления правилами (отдельный раздел SPA) для каждого правила
|
||
может быть доступна опция:
|
||
|
||
- "Применить правило к прошлым транзакциям".
|
||
|
||
При активации этой опции backend:
|
||
|
||
- находит все транзакции, подходящие под данное правило,
|
||
у которых `category_id IS NULL` или `is_category_confirmed = FALSE`;
|
||
- проставляет им `category_id`;
|
||
- устанавливает `is_category_confirmed = FALSE` (категория считается предварительной).
|
||
|
||
Транзакции с `is_category_confirmed = TRUE` не затрагиваются — пользовательские подтверждения неприкосновенны.
|
||
|
||
Пользователь может затем:
|
||
|
||
- отфильтровать операции по `onlyUnconfirmed = true` через `/api/transactions`;
|
||
- просмотреть и при необходимости скорректировать категории;
|
||
- после ручного подтверждения транзакции становятся `is_category_confirmed = TRUE`.
|
||
|
||
## Связь с API `/api/transactions`
|
||
|
||
- Эндпоинт `/api/transactions` возвращает поля `isCategoryConfirmed` и `comment`,
|
||
что позволяет:
|
||
- отображать неподтверждённые категории отдельно (подсветка в UI);
|
||
- предоставлять фильтр "Только неподтверждённые" (`onlyUnconfirmed=true`).
|
||
|
||
- При редактировании транзакции через отдельный эндпоинт (например, `PUT /api/transactions/{id}`):
|
||
- передаются новые значения `categoryId` и/или `comment`;
|
||
- флаг `isCategoryConfirmed` устанавливается в `true`.
|