Add per-app rules, transfer pairing, self-merchant flag, two-step onboarding

Notification parsing:
- Per-app parse rules (parse_rules.packageName; getEnabledForApp, NULL = legacy global)
- Transfer pairing: transfer_pair_matcher + transfer_pairing_blocklist table/dao/repo
- source_apps.selfMerchant flag (Ozon inbox rework: default account picker, suppress
  AI category prefill + rule suggestion)
- raw_messages.diagnostics dump captured under diagnostic-mode toggle
- Inbox card / settings / log UI reworks

Onboarding:
- Two-step flow (name -> first account); UserSeeder seeds categories only, no accounts

Schema bumped to v11; drop obsolete migration + mixed-merchant tests, add new coverage.
Add ios/ platform folder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 22:49:04 +03:00
co-authored by Claude Opus 4.8
parent 1ac68c0eb1
commit da65bf6f8e
123 changed files with 5943 additions and 1246 deletions
+5 -4
View File
@@ -277,10 +277,11 @@ await verifier.migrateAndValidate(db, 8);
Сейчас сидер всюду фейкается; реальный код не исполняется ни одним тестом, при этом
от него зависит первый запуск приложения.
1. `seedForNewUser(userId)` → созданы дефолтные счета и категории (количества > 0;
точные наборы не пиннить — они будут меняться), все с правильным `userId`.
2. Один счёт помечен `isDefault` (если это контракт сидера — проверить по коду).
3. Демо-транзакции созданы и ссылаются на посеянные счета/категории (FK-цепочка цела).
1. `seedForNewUser(userId)` → созданы дефолтные **категории** (количество > 0; точные
наборы не пиннить), все с правильным `userId`. Счета НЕ создаются и `isDefault` не
выставляется — первый счёт создаёт пользователь на втором шаге онбординга.
2. `seedDemoTransactionsForUser(userId)` (ручной путь из профиля) — создаёт недостающие
счета/категории и демо-транзакции, ссылающиеся на них (FK-цепочка цела).
Тест оформить так, чтобы при удалении демо-сида (пункт 2 бэклога CLAUDE.md)
достаточно было удалить один блок ассертов.
4. Повторный вызов для того же пользователя: пиннить фактическое поведение
+2 -1
View File
@@ -147,7 +147,8 @@ unique `(userId, packageName)`. Присутствие строки = прило
`accountTrusted=false` (multi-binding) → `inbox`; нет счёта → `inbox`.
4. **Allowlist-тест** (`parsing_worker`): сообщение от пакета НЕ из включённых → `ignored`, AI не вызывается;
от включённого банка без карты, но с глобальным дефолтом + правилом категории → авто-применение на дефолт.
(Помнить про `container.listen(pendingMessagesProvider(userId), …)` — см. CLAUDE.md.)
(Устарело: `pendingMessagesProvider` удалён — воркер подписан на Drift-стримы репозитория
напрямую, в тестах достаточно `container.read(parsingWorkerProvider(userId))`.)
5. Существующий пакет `test/features/notification_parsing/` — зелёный.
6. Ручная проверка (`flutter run`): добавить приложение из каталога → включить → задать привязку к счёту
и дефолт; убедиться, что уведомление от не-включённого пакета игнорируется; создать `senderToAccount`-правило.