Files
OnBudget/lib/src/features/notification_parsing/application/rules_controller.dart
T
2026-05-30 00:18:06 +03:00

91 lines
2.8 KiB
Dart

import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../data/parser/rule_lookup.dart';
import '../domain/entities/parse_rule.dart';
import '../domain/entities/raw_message.dart';
import '../domain/enums.dart';
import 'notification_parsing_providers.dart';
part 'rules_controller.g.dart';
/// Все правила пользователя — для экрана «Правила парсинга».
@riverpod
Stream<List<ParseRule>> parseRulesList(Ref ref, String userId) =>
ref.watch(parseRulesRepositoryProvider).watchByUser(userId);
/// Одно правило по id — для редактора.
@riverpod
Future<ParseRule?> parseRuleById(Ref ref, String id) =>
ref.watch(parseRulesRepositoryProvider).findById(id);
/// Live-превью (§9.3): сообщения за 30 дней, совпадающие с паттерном.
@riverpod
Future<List<RawMessage>> ruleMatchPreview(
Ref ref,
String userId,
String pattern,
MatchMode mode,
) async {
if (pattern.trim().isEmpty) return const [];
final since = DateTime.now().subtract(const Duration(days: 30));
final messages =
await ref.watch(rawMessagesRepositoryProvider).recentByUser(userId, since);
return messages
.where((m) => patternMatches(pattern, mode, body: m.body))
.toList();
}
/// CRUD над правилами парсинга.
@Riverpod(keepAlive: true)
class RulesController extends _$RulesController {
@override
AsyncValue<void> build() => const AsyncData(null);
Future<ParseRule> create({
required String userId,
required ParseRuleKind kind,
required MatchMode matchMode,
required String pattern,
int priority = 0,
String? merchantCanonical,
String? categoryId,
String? accountId,
}) async {
state = const AsyncLoading();
try {
final rule = await ref.read(parseRulesRepositoryProvider).create(
userId: userId,
kind: kind,
matchMode: matchMode,
pattern: pattern,
priority: priority,
merchantCanonical: merchantCanonical,
categoryId: categoryId,
accountId: accountId,
);
state = const AsyncData(null);
return rule;
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> update(ParseRule rule) async {
state = const AsyncLoading();
try {
await ref.read(parseRulesRepositoryProvider).update(rule);
state = const AsyncData(null);
} catch (e, st) {
state = AsyncError(e, st);
rethrow;
}
}
Future<void> setEnabled(String id, {required bool enabled}) =>
ref.read(parseRulesRepositoryProvider).setEnabled(id, enabled: enabled);
Future<void> delete(String id) =>
ref.read(parseRulesRepositoryProvider).deleteById(id);
}