91 lines
2.8 KiB
Dart
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);
|
|
}
|