Feat: Fügt Benachrichtigungen für nicht überprüfte Transaktionen hinzu

This commit is contained in:
2026-01-05 01:07:23 +01:00
parent 40eaca3157
commit 6f3d987d19
14 changed files with 676 additions and 31 deletions

View File

@@ -5,8 +5,8 @@ import 'package:flutter/foundation.dart';
import 'package:isolate_manager/isolate_manager.dart'; import 'package:isolate_manager/isolate_manager.dart';
import 'package:workmanager/workmanager.dart'; import 'package:workmanager/workmanager.dart';
import '../Tasks/workers.dart'; import '../Tasks/BackgroundHandler/workers.dart';
import '../Tasks/workmanager_workers.dart'; import '../Tasks/BackgroundHandler/workmanager_workers.dart';
/// Erstellt Hintergrundtasks und führt diese aus /// Erstellt Hintergrundtasks und führt diese aus
class BackgroundTaskController { class BackgroundTaskController {
@@ -22,6 +22,14 @@ class BackgroundTaskController {
initialDelay: const Duration(minutes: 1), initialDelay: const Duration(minutes: 1),
), ),
); );
unawaited(
Workmanager().registerPeriodicTask(
'show-notifications',
'show_notifications',
frequency: const Duration(minutes: 120),
initialDelay: const Duration(minutes: 5),
),
);
} else { } else {
unawaited( unawaited(
IsolateManager.runFunction(runTask, { IsolateManager.runFunction(runTask, {
@@ -30,6 +38,16 @@ class BackgroundTaskController {
'frequencyMinutes': 30, 'frequencyMinutes': 30,
}), }),
); );
if (!kIsWeb) {
unawaited(
IsolateManager.runFunction(runTask, {
'taskName': 'show_notifications',
'initialDelayMinutes': 5,
'frequencyMinutes': 120,
}),
);
}
} }
} }
} }

View File

@@ -0,0 +1,204 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import '../Entities/drift_database.dart';
import '../Repositories/transaction_repository.dart';
import '../Services/date_service.dart';
import '../Services/initializer.dart';
import '../Services/transaction_service.dart';
import 'port_controller.dart';
import 'transaction_controller.dart';
/// Kümmert sich um die Verwendung von Benachrichtigungen auf verschiedenen
/// Plattformen
class LocalNotifications {
/// Gibt die aktuell gültige Instanz dieser Klasse zurück
factory LocalNotifications() => _instance;
LocalNotifications._internal() {
unawaited(_initialise());
}
static final _instance = LocalNotifications._internal();
final FlutterLocalNotificationsPlugin _localNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final Initializer _initializer = Initializer();
Future<void> _initialise() async {
if (_initializer.initialized) {
return;
}
await _localNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin
>()
?.requestNotificationsPermission();
const AndroidInitializationSettings androidInitializationSettings =
AndroidInitializationSettings('app_icon');
const LinuxInitializationSettings linuxInitializationSettings =
LinuxInitializationSettings(defaultActionName: 'Öffnen');
const InitializationSettings initializationSettings =
InitializationSettings(
android: androidInitializationSettings,
linux: linuxInitializationSettings,
);
await _localNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: _onDidReceiveNotificationResponse,
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
);
if (!kIsWeb && !Platform.isLinux) {
final NotificationAppLaunchDetails? notificationAppLaunchDetails =
await _localNotificationsPlugin.getNotificationAppLaunchDetails();
if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
_onDidReceiveNotificationResponse(
NotificationResponse(
notificationResponseType:
NotificationResponseType.selectedNotification,
payload:
notificationAppLaunchDetails!.notificationResponse?.payload,
),
);
}
}
_initializer.setInitialized();
}
/// Zeigt eine Benachrichtigung an, die einen dazu auffordert,
/// automatisch generierte Transaktionen zu überprüfen
Future<void> showTransactionsToCheckNotification(
final List<Transaction> transactions,
) async {
await _initializer.waitUntilInitialized();
const AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(
'transactions_to_check',
'Transaktionen zu prüfen',
channelDescription:
'Zeigt an, dass es zu prüfende Transaktionen gibt',
actions: <AndroidNotificationAction>[
AndroidNotificationAction('mark_checked', 'Als geprüft markieren'),
AndroidNotificationAction(
'show_transactions',
'Anzeigen',
showsUserInterface: true,
),
// TODO: Prüfen, ob die App geöffnet wird
],
);
const LinuxNotificationDetails linuxNotificationDetails =
LinuxNotificationDetails(
actions: [
LinuxNotificationAction(
key: 'mark_checked',
label: 'Als geprüft markieren',
),
LinuxNotificationAction(
key: 'show_transactions',
label: 'Anzeigen',
),
],
);
const NotificationDetails notificationDetails = NotificationDetails(
android: androidNotificationDetails,
linux: linuxNotificationDetails,
);
final String title;
final String body;
if (transactions.length == 1) {
title = 'Transaktion prüfen';
body =
'Es wurde eine neue Transaktion anhand einer '
'wiederkehrenden Transaktion erstellt:\n'
'${transactions[0].name} - '
'${DateService.dateFormat.format(transactions[0].date!)} - '
'${transactions[0].amount}\n\n'
'Diese muss überprüft werden!';
} else {
int counter = 0;
final List<String> transactionsToShow = [];
for (final Transaction transaction in transactions) {
if (counter >= 10) {
break;
}
transactionsToShow.add(
'${transaction.name} - '
'${DateService.dateFormat.format(transaction.date!)} - '
'${transaction.amount}',
);
counter++;
}
title = 'Transaktionen prüfen';
body =
'Es wurden neue Transaktionen anhand '
'wiederkehrender Transaktionen erstellt:\n'
'${transactionsToShow.join('\n')}\n\n'
'Diese müssen überprüft werden!';
}
await _localNotificationsPlugin.show(
0,
title,
body,
notificationDetails,
payload: TransactionService.transactionsToString(transactions),
);
}
void _onDidReceiveNotificationResponse(
final NotificationResponse notificationResponse,
) {
if (notificationResponse.actionId == 'mark_checked') {
TransactionRepository().markTransactionsAsChecked(
TransactionService.transactionsFromString(notificationResponse.payload),
);
if (kIsWeb) {
unawaited(TransactionController().updateTransactions());
} else {
PortController().getPort('update-transactions')?.send('ready');
}
} else {
if (kIsWeb) {
TransactionController().goToTransactions(
transactions: TransactionService.transactionsFromString(
notificationResponse.payload,
),
);
} else {
PortController()
.getPort('go-to-transactions')
?.send(notificationResponse.payload);
}
}
}
/// Wird von den LocalNotifications aufgerufen,
/// wenn eine Aktion im Hintergrund abgehandelt werden soll
@pragma('vm:entry-point')
static void notificationTapBackground(
final NotificationResponse notificationResponse,
) {
if (notificationResponse.actionId == 'mark_checked') {
TransactionRepository().markTransactionsAsChecked(
TransactionService.transactionsFromString(notificationResponse.payload),
);
}
}
}

View File

@@ -5,6 +5,7 @@ import 'package:drift/drift.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
import 'package:routemaster/routemaster.dart';
import '../Entities/drift_database.dart'; import '../Entities/drift_database.dart';
import '../Pages/Dialog/dialog_action.dart'; import '../Pages/Dialog/dialog_action.dart';
@@ -13,6 +14,8 @@ import '../Pages/Dialog/dialog_input_field_type_enum.dart';
import '../Pages/Dialog/dialog_type_enum.dart'; import '../Pages/Dialog/dialog_type_enum.dart';
import '../Pages/Dialog/dynamic_dialog.dart'; import '../Pages/Dialog/dynamic_dialog.dart';
import '../Repositories/transaction_repository.dart'; import '../Repositories/transaction_repository.dart';
import '../Services/navigation_service.dart';
import '../Services/transaction_service.dart';
import 'account_controller.dart'; import 'account_controller.dart';
import 'port_controller.dart'; import 'port_controller.dart';
@@ -72,13 +75,31 @@ class TransactionController {
}); });
if (!kIsWeb) { if (!kIsWeb) {
final ReceivePort receivePort = ReceivePort() final ReceivePort updateTransactionsReceivePort = ReceivePort()
..listen((_) { ..listen((_) {
Logger().i('Received update-transactions signal'); Logger().i('Received update-transactions signal');
unawaited(updateTransactions()); unawaited(updateTransactions());
}); });
PortController().addPort(receivePort.sendPort, 'update-transactions'); PortController().addPort(
updateTransactionsReceivePort.sendPort,
'update-transactions',
);
final ReceivePort gotToTransactionsReceivePort = ReceivePort()
..listen((final value) {
Logger().i('Received go-to-transactions signal');
final List<Transaction> transactions =
TransactionService.transactionsFromString(value);
goToTransactions(transactions: transactions);
});
PortController().addPort(
gotToTransactionsReceivePort.sendPort,
'go-to-transactions',
);
} }
unawaited(updateTransactions()); unawaited(updateTransactions());
@@ -121,6 +142,21 @@ class TransactionController {
} }
} }
/// Wechselt zur Übersicht über die Transaktionen
void goToTransactions({final List<Transaction>? transactions}) {
final BuildContext? context = NavigationService.getCurrentBuildContext();
if (context != null && transactions != null) {
if (transactions.length == 1) {
Routemaster.of(
context,
).push('/trend', queryParameters: {'name': transactions.first.name});
}
Routemaster.of(context).replace('/trend');
}
}
/// Startet den Prozess, um eine neue Transaktion anzulegen /// Startet den Prozess, um eine neue Transaktion anzulegen
void newTransactionHandler() { void newTransactionHandler() {
unawaited(_newTransactionDialog?.show()); unawaited(_newTransactionDialog?.show());

View File

@@ -14,6 +14,9 @@ class Accounts extends Table {
/// Name des Kontos /// Name des Kontos
TextColumn get name => text().withDefault(const Constant(''))(); TextColumn get name => text().withDefault(const Constant(''))();
/// Der externe Identifier, wenn woanders gespeichert
IntColumn get externalIdentifier => integer().nullable()();
/// Wann das Konto das letzte mal geupdated wurde /// Wann das Konto das letzte mal geupdated wurde
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
} }
@@ -43,6 +46,9 @@ class Transactions extends Table {
IntColumn get recurringTransactionId => IntColumn get recurringTransactionId =>
integer().nullable().references(RecurringTransactions, #id)(); integer().nullable().references(RecurringTransactions, #id)();
/// Der externe Identifier, wenn woanders gespeichert
IntColumn get externalIdentifier => integer().nullable()();
/// Wann die Transaktion das letzte mal geupdated wurde /// Wann die Transaktion das letzte mal geupdated wurde
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
} }
@@ -67,6 +73,9 @@ class RecurringTransactions extends Table {
/// Fremdschlüssel zum zugehörigen Konto /// Fremdschlüssel zum zugehörigen Konto
IntColumn get accountId => integer().references(Accounts, #id)(); IntColumn get accountId => integer().references(Accounts, #id)();
/// Der externe Identifier, wenn woanders gespeichert
IntColumn get externalIdentifier => integer().nullable()();
/// Wann die wiederkehrende Transaktion das letzte mal geupdated wurde /// Wann die wiederkehrende Transaktion das letzte mal geupdated wurde
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
} }

View File

@@ -31,6 +31,16 @@ class $AccountsTable extends Accounts with TableInfo<$AccountsTable, Account> {
requiredDuringInsert: false, requiredDuringInsert: false,
defaultValue: const Constant(''), defaultValue: const Constant(''),
); );
static const VerificationMeta _externalIdentifierMeta =
const VerificationMeta('externalIdentifier');
@override
late final GeneratedColumn<int> externalIdentifier = GeneratedColumn<int>(
'external_identifier',
aliasedName,
true,
type: DriftSqlType.int,
requiredDuringInsert: false,
);
static const VerificationMeta _updatedAtMeta = const VerificationMeta( static const VerificationMeta _updatedAtMeta = const VerificationMeta(
'updatedAt', 'updatedAt',
); );
@@ -44,7 +54,12 @@ class $AccountsTable extends Accounts with TableInfo<$AccountsTable, Account> {
defaultValue: currentDateAndTime, defaultValue: currentDateAndTime,
); );
@override @override
List<GeneratedColumn> get $columns => [id, name, updatedAt]; List<GeneratedColumn> get $columns => [
id,
name,
externalIdentifier,
updatedAt,
];
@override @override
String get aliasedName => _alias ?? actualTableName; String get aliasedName => _alias ?? actualTableName;
@override @override
@@ -66,6 +81,15 @@ class $AccountsTable extends Accounts with TableInfo<$AccountsTable, Account> {
name.isAcceptableOrUnknown(data['name']!, _nameMeta), name.isAcceptableOrUnknown(data['name']!, _nameMeta),
); );
} }
if (data.containsKey('external_identifier')) {
context.handle(
_externalIdentifierMeta,
externalIdentifier.isAcceptableOrUnknown(
data['external_identifier']!,
_externalIdentifierMeta,
),
);
}
if (data.containsKey('updated_at')) { if (data.containsKey('updated_at')) {
context.handle( context.handle(
_updatedAtMeta, _updatedAtMeta,
@@ -89,6 +113,10 @@ class $AccountsTable extends Accounts with TableInfo<$AccountsTable, Account> {
DriftSqlType.string, DriftSqlType.string,
data['${effectivePrefix}name'], data['${effectivePrefix}name'],
)!, )!,
externalIdentifier: attachedDatabase.typeMapping.read(
DriftSqlType.int,
data['${effectivePrefix}external_identifier'],
),
updatedAt: attachedDatabase.typeMapping.read( updatedAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, DriftSqlType.dateTime,
data['${effectivePrefix}updated_at'], data['${effectivePrefix}updated_at'],
@@ -109,11 +137,15 @@ class Account extends DataClass implements Insertable<Account> {
/// Name des Kontos /// Name des Kontos
final String name; final String name;
/// Der externe Identifier, wenn woanders gespeichert
final int? externalIdentifier;
/// Wann das Konto das letzte mal geupdated wurde /// Wann das Konto das letzte mal geupdated wurde
final DateTime updatedAt; final DateTime updatedAt;
const Account({ const Account({
required this.id, required this.id,
required this.name, required this.name,
this.externalIdentifier,
required this.updatedAt, required this.updatedAt,
}); });
@override @override
@@ -121,6 +153,9 @@ class Account extends DataClass implements Insertable<Account> {
final map = <String, Expression>{}; final map = <String, Expression>{};
map['id'] = Variable<int>(id); map['id'] = Variable<int>(id);
map['name'] = Variable<String>(name); map['name'] = Variable<String>(name);
if (!nullToAbsent || externalIdentifier != null) {
map['external_identifier'] = Variable<int>(externalIdentifier);
}
map['updated_at'] = Variable<DateTime>(updatedAt); map['updated_at'] = Variable<DateTime>(updatedAt);
return map; return map;
} }
@@ -129,6 +164,9 @@ class Account extends DataClass implements Insertable<Account> {
return AccountsCompanion( return AccountsCompanion(
id: Value(id), id: Value(id),
name: Value(name), name: Value(name),
externalIdentifier: externalIdentifier == null && nullToAbsent
? const Value.absent()
: Value(externalIdentifier),
updatedAt: Value(updatedAt), updatedAt: Value(updatedAt),
); );
} }
@@ -141,6 +179,7 @@ class Account extends DataClass implements Insertable<Account> {
return Account( return Account(
id: serializer.fromJson<int>(json['id']), id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']), name: serializer.fromJson<String>(json['name']),
externalIdentifier: serializer.fromJson<int?>(json['externalIdentifier']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']), updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
); );
} }
@@ -150,19 +189,31 @@ class Account extends DataClass implements Insertable<Account> {
return <String, dynamic>{ return <String, dynamic>{
'id': serializer.toJson<int>(id), 'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name), 'name': serializer.toJson<String>(name),
'externalIdentifier': serializer.toJson<int?>(externalIdentifier),
'updatedAt': serializer.toJson<DateTime>(updatedAt), 'updatedAt': serializer.toJson<DateTime>(updatedAt),
}; };
} }
Account copyWith({int? id, String? name, DateTime? updatedAt}) => Account( Account copyWith({
int? id,
String? name,
Value<int?> externalIdentifier = const Value.absent(),
DateTime? updatedAt,
}) => Account(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
externalIdentifier: externalIdentifier.present
? externalIdentifier.value
: this.externalIdentifier,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
); );
Account copyWithCompanion(AccountsCompanion data) { Account copyWithCompanion(AccountsCompanion data) {
return Account( return Account(
id: data.id.present ? data.id.value : this.id, id: data.id.present ? data.id.value : this.id,
name: data.name.present ? data.name.value : this.name, name: data.name.present ? data.name.value : this.name,
externalIdentifier: data.externalIdentifier.present
? data.externalIdentifier.value
: this.externalIdentifier,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
); );
} }
@@ -171,45 +222,52 @@ class Account extends DataClass implements Insertable<Account> {
String toString() { String toString() {
return (StringBuffer('Account(') return (StringBuffer('Account(')
..write('id: $id, ') ..write('id: $id, ')
..write('name: $name, ') ..write('name: $name, ')..write(
'externalIdentifier: $externalIdentifier, ')
..write('updatedAt: $updatedAt') ..write('updatedAt: $updatedAt')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@override @override
int get hashCode => Object.hash(id, name, updatedAt); int get hashCode => Object.hash(id, name, externalIdentifier, updatedAt);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
(other is Account && (other is Account &&
other.id == this.id && other.id == this.id &&
other.name == this.name && other.name == this.name &&
other.externalIdentifier == this.externalIdentifier &&
other.updatedAt == this.updatedAt); other.updatedAt == this.updatedAt);
} }
class AccountsCompanion extends UpdateCompanion<Account> { class AccountsCompanion extends UpdateCompanion<Account> {
final Value<int> id; final Value<int> id;
final Value<String> name; final Value<String> name;
final Value<int?> externalIdentifier;
final Value<DateTime> updatedAt; final Value<DateTime> updatedAt;
const AccountsCompanion({ const AccountsCompanion({
this.id = const Value.absent(), this.id = const Value.absent(),
this.name = const Value.absent(), this.name = const Value.absent(),
this.externalIdentifier = const Value.absent(),
this.updatedAt = const Value.absent(), this.updatedAt = const Value.absent(),
}); });
AccountsCompanion.insert({ AccountsCompanion.insert({
this.id = const Value.absent(), this.id = const Value.absent(),
this.name = const Value.absent(), this.name = const Value.absent(),
this.externalIdentifier = const Value.absent(),
this.updatedAt = const Value.absent(), this.updatedAt = const Value.absent(),
}); });
static Insertable<Account> custom({ static Insertable<Account> custom({
Expression<int>? id, Expression<int>? id,
Expression<String>? name, Expression<String>? name,
Expression<int>? externalIdentifier,
Expression<DateTime>? updatedAt, Expression<DateTime>? updatedAt,
}) { }) {
return RawValuesInsertable({ return RawValuesInsertable({
if (id != null) 'id': id, if (id != null) 'id': id,
if (name != null) 'name': name, if (name != null) 'name': name,
if (externalIdentifier != null) 'external_identifier': externalIdentifier,
if (updatedAt != null) 'updated_at': updatedAt, if (updatedAt != null) 'updated_at': updatedAt,
}); });
} }
@@ -217,11 +275,13 @@ class AccountsCompanion extends UpdateCompanion<Account> {
AccountsCompanion copyWith({ AccountsCompanion copyWith({
Value<int>? id, Value<int>? id,
Value<String>? name, Value<String>? name,
Value<int?>? externalIdentifier,
Value<DateTime>? updatedAt, Value<DateTime>? updatedAt,
}) { }) {
return AccountsCompanion( return AccountsCompanion(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
externalIdentifier: externalIdentifier ?? this.externalIdentifier,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
); );
} }
@@ -235,6 +295,9 @@ class AccountsCompanion extends UpdateCompanion<Account> {
if (name.present) { if (name.present) {
map['name'] = Variable<String>(name.value); map['name'] = Variable<String>(name.value);
} }
if (externalIdentifier.present) {
map['external_identifier'] = Variable<int>(externalIdentifier.value);
}
if (updatedAt.present) { if (updatedAt.present) {
map['updated_at'] = Variable<DateTime>(updatedAt.value); map['updated_at'] = Variable<DateTime>(updatedAt.value);
} }
@@ -245,7 +308,8 @@ class AccountsCompanion extends UpdateCompanion<Account> {
String toString() { String toString() {
return (StringBuffer('AccountsCompanion(') return (StringBuffer('AccountsCompanion(')
..write('id: $id, ') ..write('id: $id, ')
..write('name: $name, ') ..write('name: $name, ')..write(
'externalIdentifier: $externalIdentifier, ')
..write('updatedAt: $updatedAt') ..write('updatedAt: $updatedAt')
..write(')')) ..write(')'))
.toString(); .toString();
@@ -327,6 +391,16 @@ class $RecurringTransactionsTable extends RecurringTransactions
'REFERENCES accounts (id)', 'REFERENCES accounts (id)',
), ),
); );
static const VerificationMeta _externalIdentifierMeta =
const VerificationMeta('externalIdentifier');
@override
late final GeneratedColumn<int> externalIdentifier = GeneratedColumn<int>(
'external_identifier',
aliasedName,
true,
type: DriftSqlType.int,
requiredDuringInsert: false,
);
static const VerificationMeta _updatedAtMeta = const VerificationMeta( static const VerificationMeta _updatedAtMeta = const VerificationMeta(
'updatedAt', 'updatedAt',
); );
@@ -347,6 +421,7 @@ class $RecurringTransactionsTable extends RecurringTransactions
timeFrame, timeFrame,
amount, amount,
accountId, accountId,
externalIdentifier,
updatedAt, updatedAt,
]; ];
@override @override
@@ -390,6 +465,15 @@ class $RecurringTransactionsTable extends RecurringTransactions
} else if (isInserting) { } else if (isInserting) {
context.missing(_accountIdMeta); context.missing(_accountIdMeta);
} }
if (data.containsKey('external_identifier')) {
context.handle(
_externalIdentifierMeta,
externalIdentifier.isAcceptableOrUnknown(
data['external_identifier']!,
_externalIdentifierMeta,
),
);
}
if (data.containsKey('updated_at')) { if (data.containsKey('updated_at')) {
context.handle( context.handle(
_updatedAtMeta, _updatedAtMeta,
@@ -431,6 +515,10 @@ class $RecurringTransactionsTable extends RecurringTransactions
DriftSqlType.int, DriftSqlType.int,
data['${effectivePrefix}account_id'], data['${effectivePrefix}account_id'],
)!, )!,
externalIdentifier: attachedDatabase.typeMapping.read(
DriftSqlType.int,
data['${effectivePrefix}external_identifier'],
),
updatedAt: attachedDatabase.typeMapping.read( updatedAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, DriftSqlType.dateTime,
data['${effectivePrefix}updated_at'], data['${effectivePrefix}updated_at'],
@@ -467,6 +555,9 @@ class RecurringTransaction extends DataClass
/// Fremdschlüssel zum zugehörigen Konto /// Fremdschlüssel zum zugehörigen Konto
final int accountId; final int accountId;
/// Der externe Identifier, wenn woanders gespeichert
final int? externalIdentifier;
/// Wann die wiederkehrende Transaktion das letzte mal geupdated wurde /// Wann die wiederkehrende Transaktion das letzte mal geupdated wurde
final DateTime updatedAt; final DateTime updatedAt;
const RecurringTransaction({ const RecurringTransaction({
@@ -476,6 +567,7 @@ class RecurringTransaction extends DataClass
required this.timeFrame, required this.timeFrame,
required this.amount, required this.amount,
required this.accountId, required this.accountId,
this.externalIdentifier,
required this.updatedAt, required this.updatedAt,
}); });
@override @override
@@ -493,6 +585,9 @@ class RecurringTransaction extends DataClass
} }
map['amount'] = Variable<double>(amount); map['amount'] = Variable<double>(amount);
map['account_id'] = Variable<int>(accountId); map['account_id'] = Variable<int>(accountId);
if (!nullToAbsent || externalIdentifier != null) {
map['external_identifier'] = Variable<int>(externalIdentifier);
}
map['updated_at'] = Variable<DateTime>(updatedAt); map['updated_at'] = Variable<DateTime>(updatedAt);
return map; return map;
} }
@@ -507,6 +602,9 @@ class RecurringTransaction extends DataClass
timeFrame: Value(timeFrame), timeFrame: Value(timeFrame),
amount: Value(amount), amount: Value(amount),
accountId: Value(accountId), accountId: Value(accountId),
externalIdentifier: externalIdentifier == null && nullToAbsent
? const Value.absent()
: Value(externalIdentifier),
updatedAt: Value(updatedAt), updatedAt: Value(updatedAt),
); );
} }
@@ -525,6 +623,7 @@ class RecurringTransaction extends DataClass
), ),
amount: serializer.fromJson<double>(json['amount']), amount: serializer.fromJson<double>(json['amount']),
accountId: serializer.fromJson<int>(json['accountId']), accountId: serializer.fromJson<int>(json['accountId']),
externalIdentifier: serializer.fromJson<int?>(json['externalIdentifier']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']), updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
); );
} }
@@ -540,6 +639,7 @@ class RecurringTransaction extends DataClass
), ),
'amount': serializer.toJson<double>(amount), 'amount': serializer.toJson<double>(amount),
'accountId': serializer.toJson<int>(accountId), 'accountId': serializer.toJson<int>(accountId),
'externalIdentifier': serializer.toJson<int?>(externalIdentifier),
'updatedAt': serializer.toJson<DateTime>(updatedAt), 'updatedAt': serializer.toJson<DateTime>(updatedAt),
}; };
} }
@@ -551,6 +651,7 @@ class RecurringTransaction extends DataClass
TimeFrameEnum? timeFrame, TimeFrameEnum? timeFrame,
double? amount, double? amount,
int? accountId, int? accountId,
Value<int?> externalIdentifier = const Value.absent(),
DateTime? updatedAt, DateTime? updatedAt,
}) => RecurringTransaction( }) => RecurringTransaction(
id: id ?? this.id, id: id ?? this.id,
@@ -559,6 +660,9 @@ class RecurringTransaction extends DataClass
timeFrame: timeFrame ?? this.timeFrame, timeFrame: timeFrame ?? this.timeFrame,
amount: amount ?? this.amount, amount: amount ?? this.amount,
accountId: accountId ?? this.accountId, accountId: accountId ?? this.accountId,
externalIdentifier: externalIdentifier.present
? externalIdentifier.value
: this.externalIdentifier,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
); );
RecurringTransaction copyWithCompanion(RecurringTransactionsCompanion data) { RecurringTransaction copyWithCompanion(RecurringTransactionsCompanion data) {
@@ -569,6 +673,9 @@ class RecurringTransaction extends DataClass
timeFrame: data.timeFrame.present ? data.timeFrame.value : this.timeFrame, timeFrame: data.timeFrame.present ? data.timeFrame.value : this.timeFrame,
amount: data.amount.present ? data.amount.value : this.amount, amount: data.amount.present ? data.amount.value : this.amount,
accountId: data.accountId.present ? data.accountId.value : this.accountId, accountId: data.accountId.present ? data.accountId.value : this.accountId,
externalIdentifier: data.externalIdentifier.present
? data.externalIdentifier.value
: this.externalIdentifier,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
); );
} }
@@ -576,17 +683,29 @@ class RecurringTransaction extends DataClass
@override @override
String toString() { String toString() {
return (StringBuffer('RecurringTransaction(') return (StringBuffer('RecurringTransaction(')
..write('id: $id, ')..write('name: $name, ')..write( ..write('id: $id, ')
'startDate: $startDate, ')..write('timeFrame: $timeFrame, ')..write( ..write('name: $name, ')
'amount: $amount, ')..write('accountId: $accountId, ')..write( ..write('startDate: $startDate, ')
'updatedAt: $updatedAt') ..write('timeFrame: $timeFrame, ')
..write('amount: $amount, ')
..write('accountId: $accountId, ')
..write('externalIdentifier: $externalIdentifier, ')
..write('updatedAt: $updatedAt')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@override @override
int get hashCode => int get hashCode => Object.hash(
Object.hash(id, name, startDate, timeFrame, amount, accountId, updatedAt); id,
name,
startDate,
timeFrame,
amount,
accountId,
externalIdentifier,
updatedAt,
);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
@@ -597,6 +716,7 @@ class RecurringTransaction extends DataClass
other.timeFrame == this.timeFrame && other.timeFrame == this.timeFrame &&
other.amount == this.amount && other.amount == this.amount &&
other.accountId == this.accountId && other.accountId == this.accountId &&
other.externalIdentifier == this.externalIdentifier &&
other.updatedAt == this.updatedAt); other.updatedAt == this.updatedAt);
} }
@@ -608,6 +728,7 @@ class RecurringTransactionsCompanion
final Value<TimeFrameEnum> timeFrame; final Value<TimeFrameEnum> timeFrame;
final Value<double> amount; final Value<double> amount;
final Value<int> accountId; final Value<int> accountId;
final Value<int?> externalIdentifier;
final Value<DateTime> updatedAt; final Value<DateTime> updatedAt;
const RecurringTransactionsCompanion({ const RecurringTransactionsCompanion({
this.id = const Value.absent(), this.id = const Value.absent(),
@@ -616,6 +737,7 @@ class RecurringTransactionsCompanion
this.timeFrame = const Value.absent(), this.timeFrame = const Value.absent(),
this.amount = const Value.absent(), this.amount = const Value.absent(),
this.accountId = const Value.absent(), this.accountId = const Value.absent(),
this.externalIdentifier = const Value.absent(),
this.updatedAt = const Value.absent(), this.updatedAt = const Value.absent(),
}); });
RecurringTransactionsCompanion.insert({ RecurringTransactionsCompanion.insert({
@@ -625,6 +747,7 @@ class RecurringTransactionsCompanion
required TimeFrameEnum timeFrame, required TimeFrameEnum timeFrame,
this.amount = const Value.absent(), this.amount = const Value.absent(),
required int accountId, required int accountId,
this.externalIdentifier = const Value.absent(),
this.updatedAt = const Value.absent(), this.updatedAt = const Value.absent(),
}) : timeFrame = Value(timeFrame), }) : timeFrame = Value(timeFrame),
accountId = Value(accountId); accountId = Value(accountId);
@@ -635,6 +758,7 @@ class RecurringTransactionsCompanion
Expression<int>? timeFrame, Expression<int>? timeFrame,
Expression<double>? amount, Expression<double>? amount,
Expression<int>? accountId, Expression<int>? accountId,
Expression<int>? externalIdentifier,
Expression<DateTime>? updatedAt, Expression<DateTime>? updatedAt,
}) { }) {
return RawValuesInsertable({ return RawValuesInsertable({
@@ -644,6 +768,7 @@ class RecurringTransactionsCompanion
if (timeFrame != null) 'time_frame': timeFrame, if (timeFrame != null) 'time_frame': timeFrame,
if (amount != null) 'amount': amount, if (amount != null) 'amount': amount,
if (accountId != null) 'account_id': accountId, if (accountId != null) 'account_id': accountId,
if (externalIdentifier != null) 'external_identifier': externalIdentifier,
if (updatedAt != null) 'updated_at': updatedAt, if (updatedAt != null) 'updated_at': updatedAt,
}); });
} }
@@ -655,6 +780,7 @@ class RecurringTransactionsCompanion
Value<TimeFrameEnum>? timeFrame, Value<TimeFrameEnum>? timeFrame,
Value<double>? amount, Value<double>? amount,
Value<int>? accountId, Value<int>? accountId,
Value<int?>? externalIdentifier,
Value<DateTime>? updatedAt, Value<DateTime>? updatedAt,
}) { }) {
return RecurringTransactionsCompanion( return RecurringTransactionsCompanion(
@@ -664,6 +790,7 @@ class RecurringTransactionsCompanion
timeFrame: timeFrame ?? this.timeFrame, timeFrame: timeFrame ?? this.timeFrame,
amount: amount ?? this.amount, amount: amount ?? this.amount,
accountId: accountId ?? this.accountId, accountId: accountId ?? this.accountId,
externalIdentifier: externalIdentifier ?? this.externalIdentifier,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
); );
} }
@@ -691,6 +818,9 @@ class RecurringTransactionsCompanion
if (accountId.present) { if (accountId.present) {
map['account_id'] = Variable<int>(accountId.value); map['account_id'] = Variable<int>(accountId.value);
} }
if (externalIdentifier.present) {
map['external_identifier'] = Variable<int>(externalIdentifier.value);
}
if (updatedAt.present) { if (updatedAt.present) {
map['updated_at'] = Variable<DateTime>(updatedAt.value); map['updated_at'] = Variable<DateTime>(updatedAt.value);
} }
@@ -700,10 +830,14 @@ class RecurringTransactionsCompanion
@override @override
String toString() { String toString() {
return (StringBuffer('RecurringTransactionsCompanion(') return (StringBuffer('RecurringTransactionsCompanion(')
..write('id: $id, ')..write('name: $name, ')..write( ..write('id: $id, ')
'startDate: $startDate, ')..write('timeFrame: $timeFrame, ')..write( ..write('name: $name, ')
'amount: $amount, ')..write('accountId: $accountId, ')..write( ..write('startDate: $startDate, ')
'updatedAt: $updatedAt') ..write('timeFrame: $timeFrame, ')
..write('amount: $amount, ')
..write('accountId: $accountId, ')
..write('externalIdentifier: $externalIdentifier, ')
..write('updatedAt: $updatedAt')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@@ -799,6 +933,16 @@ class $TransactionsTable extends Transactions
'REFERENCES recurring_transactions (id)', 'REFERENCES recurring_transactions (id)',
), ),
); );
static const VerificationMeta _externalIdentifierMeta =
const VerificationMeta('externalIdentifier');
@override
late final GeneratedColumn<int> externalIdentifier = GeneratedColumn<int>(
'external_identifier',
aliasedName,
true,
type: DriftSqlType.int,
requiredDuringInsert: false,
);
static const VerificationMeta _updatedAtMeta = const VerificationMeta( static const VerificationMeta _updatedAtMeta = const VerificationMeta(
'updatedAt', 'updatedAt',
); );
@@ -820,6 +964,7 @@ class $TransactionsTable extends Transactions
checked, checked,
accountId, accountId,
recurringTransactionId, recurringTransactionId,
externalIdentifier,
updatedAt, updatedAt,
]; ];
@override @override
@@ -878,6 +1023,15 @@ class $TransactionsTable extends Transactions
), ),
); );
} }
if (data.containsKey('external_identifier')) {
context.handle(
_externalIdentifierMeta,
externalIdentifier.isAcceptableOrUnknown(
data['external_identifier']!,
_externalIdentifierMeta,
),
);
}
if (data.containsKey('updated_at')) { if (data.containsKey('updated_at')) {
context.handle( context.handle(
_updatedAtMeta, _updatedAtMeta,
@@ -921,6 +1075,10 @@ class $TransactionsTable extends Transactions
DriftSqlType.int, DriftSqlType.int,
data['${effectivePrefix}recurring_transaction_id'], data['${effectivePrefix}recurring_transaction_id'],
), ),
externalIdentifier: attachedDatabase.typeMapping.read(
DriftSqlType.int,
data['${effectivePrefix}external_identifier'],
),
updatedAt: attachedDatabase.typeMapping.read( updatedAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, DriftSqlType.dateTime,
data['${effectivePrefix}updated_at'], data['${effectivePrefix}updated_at'],
@@ -957,6 +1115,9 @@ class Transaction extends DataClass implements Insertable<Transaction> {
/// falls vorhanden /// falls vorhanden
final int? recurringTransactionId; final int? recurringTransactionId;
/// Der externe Identifier, wenn woanders gespeichert
final int? externalIdentifier;
/// Wann die Transaktion das letzte mal geupdated wurde /// Wann die Transaktion das letzte mal geupdated wurde
final DateTime updatedAt; final DateTime updatedAt;
const Transaction({ const Transaction({
@@ -967,6 +1128,7 @@ class Transaction extends DataClass implements Insertable<Transaction> {
required this.checked, required this.checked,
required this.accountId, required this.accountId,
this.recurringTransactionId, this.recurringTransactionId,
this.externalIdentifier,
required this.updatedAt, required this.updatedAt,
}); });
@override @override
@@ -983,6 +1145,9 @@ class Transaction extends DataClass implements Insertable<Transaction> {
if (!nullToAbsent || recurringTransactionId != null) { if (!nullToAbsent || recurringTransactionId != null) {
map['recurring_transaction_id'] = Variable<int>(recurringTransactionId); map['recurring_transaction_id'] = Variable<int>(recurringTransactionId);
} }
if (!nullToAbsent || externalIdentifier != null) {
map['external_identifier'] = Variable<int>(externalIdentifier);
}
map['updated_at'] = Variable<DateTime>(updatedAt); map['updated_at'] = Variable<DateTime>(updatedAt);
return map; return map;
} }
@@ -998,6 +1163,9 @@ class Transaction extends DataClass implements Insertable<Transaction> {
recurringTransactionId: recurringTransactionId == null && nullToAbsent recurringTransactionId: recurringTransactionId == null && nullToAbsent
? const Value.absent() ? const Value.absent()
: Value(recurringTransactionId), : Value(recurringTransactionId),
externalIdentifier: externalIdentifier == null && nullToAbsent
? const Value.absent()
: Value(externalIdentifier),
updatedAt: Value(updatedAt), updatedAt: Value(updatedAt),
); );
} }
@@ -1017,6 +1185,7 @@ class Transaction extends DataClass implements Insertable<Transaction> {
recurringTransactionId: serializer.fromJson<int?>( recurringTransactionId: serializer.fromJson<int?>(
json['recurringTransactionId'], json['recurringTransactionId'],
), ),
externalIdentifier: serializer.fromJson<int?>(json['externalIdentifier']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']), updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
); );
} }
@@ -1031,6 +1200,7 @@ class Transaction extends DataClass implements Insertable<Transaction> {
'checked': serializer.toJson<bool>(checked), 'checked': serializer.toJson<bool>(checked),
'accountId': serializer.toJson<int>(accountId), 'accountId': serializer.toJson<int>(accountId),
'recurringTransactionId': serializer.toJson<int?>(recurringTransactionId), 'recurringTransactionId': serializer.toJson<int?>(recurringTransactionId),
'externalIdentifier': serializer.toJson<int?>(externalIdentifier),
'updatedAt': serializer.toJson<DateTime>(updatedAt), 'updatedAt': serializer.toJson<DateTime>(updatedAt),
}; };
} }
@@ -1043,6 +1213,7 @@ class Transaction extends DataClass implements Insertable<Transaction> {
bool? checked, bool? checked,
int? accountId, int? accountId,
Value<int?> recurringTransactionId = const Value.absent(), Value<int?> recurringTransactionId = const Value.absent(),
Value<int?> externalIdentifier = const Value.absent(),
DateTime? updatedAt, DateTime? updatedAt,
}) => Transaction( }) => Transaction(
id: id ?? this.id, id: id ?? this.id,
@@ -1054,6 +1225,9 @@ class Transaction extends DataClass implements Insertable<Transaction> {
recurringTransactionId: recurringTransactionId.present recurringTransactionId: recurringTransactionId.present
? recurringTransactionId.value ? recurringTransactionId.value
: this.recurringTransactionId, : this.recurringTransactionId,
externalIdentifier: externalIdentifier.present
? externalIdentifier.value
: this.externalIdentifier,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
); );
Transaction copyWithCompanion(TransactionsCompanion data) { Transaction copyWithCompanion(TransactionsCompanion data) {
@@ -1067,6 +1241,9 @@ class Transaction extends DataClass implements Insertable<Transaction> {
recurringTransactionId: data.recurringTransactionId.present recurringTransactionId: data.recurringTransactionId.present
? data.recurringTransactionId.value ? data.recurringTransactionId.value
: this.recurringTransactionId, : this.recurringTransactionId,
externalIdentifier: data.externalIdentifier.present
? data.externalIdentifier.value
: this.externalIdentifier,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
); );
} }
@@ -1080,7 +1257,8 @@ class Transaction extends DataClass implements Insertable<Transaction> {
..write('amount: $amount, ') ..write('amount: $amount, ')
..write('checked: $checked, ') ..write('checked: $checked, ')
..write('accountId: $accountId, ') ..write('accountId: $accountId, ')
..write('recurringTransactionId: $recurringTransactionId, ') ..write('recurringTransactionId: $recurringTransactionId, ')..write(
'externalIdentifier: $externalIdentifier, ')
..write('updatedAt: $updatedAt') ..write('updatedAt: $updatedAt')
..write(')')) ..write(')'))
.toString(); .toString();
@@ -1095,6 +1273,7 @@ class Transaction extends DataClass implements Insertable<Transaction> {
checked, checked,
accountId, accountId,
recurringTransactionId, recurringTransactionId,
externalIdentifier,
updatedAt, updatedAt,
); );
@override @override
@@ -1108,6 +1287,7 @@ class Transaction extends DataClass implements Insertable<Transaction> {
other.checked == this.checked && other.checked == this.checked &&
other.accountId == this.accountId && other.accountId == this.accountId &&
other.recurringTransactionId == this.recurringTransactionId && other.recurringTransactionId == this.recurringTransactionId &&
other.externalIdentifier == this.externalIdentifier &&
other.updatedAt == this.updatedAt); other.updatedAt == this.updatedAt);
} }
@@ -1119,6 +1299,7 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
final Value<bool> checked; final Value<bool> checked;
final Value<int> accountId; final Value<int> accountId;
final Value<int?> recurringTransactionId; final Value<int?> recurringTransactionId;
final Value<int?> externalIdentifier;
final Value<DateTime> updatedAt; final Value<DateTime> updatedAt;
const TransactionsCompanion({ const TransactionsCompanion({
this.id = const Value.absent(), this.id = const Value.absent(),
@@ -1128,6 +1309,7 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
this.checked = const Value.absent(), this.checked = const Value.absent(),
this.accountId = const Value.absent(), this.accountId = const Value.absent(),
this.recurringTransactionId = const Value.absent(), this.recurringTransactionId = const Value.absent(),
this.externalIdentifier = const Value.absent(),
this.updatedAt = const Value.absent(), this.updatedAt = const Value.absent(),
}); });
TransactionsCompanion.insert({ TransactionsCompanion.insert({
@@ -1138,6 +1320,7 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
this.checked = const Value.absent(), this.checked = const Value.absent(),
required int accountId, required int accountId,
this.recurringTransactionId = const Value.absent(), this.recurringTransactionId = const Value.absent(),
this.externalIdentifier = const Value.absent(),
this.updatedAt = const Value.absent(), this.updatedAt = const Value.absent(),
}) : accountId = Value(accountId); }) : accountId = Value(accountId);
static Insertable<Transaction> custom({ static Insertable<Transaction> custom({
@@ -1148,6 +1331,7 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
Expression<bool>? checked, Expression<bool>? checked,
Expression<int>? accountId, Expression<int>? accountId,
Expression<int>? recurringTransactionId, Expression<int>? recurringTransactionId,
Expression<int>? externalIdentifier,
Expression<DateTime>? updatedAt, Expression<DateTime>? updatedAt,
}) { }) {
return RawValuesInsertable({ return RawValuesInsertable({
@@ -1159,6 +1343,7 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
if (accountId != null) 'account_id': accountId, if (accountId != null) 'account_id': accountId,
if (recurringTransactionId != null) if (recurringTransactionId != null)
'recurring_transaction_id': recurringTransactionId, 'recurring_transaction_id': recurringTransactionId,
if (externalIdentifier != null) 'external_identifier': externalIdentifier,
if (updatedAt != null) 'updated_at': updatedAt, if (updatedAt != null) 'updated_at': updatedAt,
}); });
} }
@@ -1171,6 +1356,7 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
Value<bool>? checked, Value<bool>? checked,
Value<int>? accountId, Value<int>? accountId,
Value<int?>? recurringTransactionId, Value<int?>? recurringTransactionId,
Value<int?>? externalIdentifier,
Value<DateTime>? updatedAt, Value<DateTime>? updatedAt,
}) { }) {
return TransactionsCompanion( return TransactionsCompanion(
@@ -1182,6 +1368,7 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
accountId: accountId ?? this.accountId, accountId: accountId ?? this.accountId,
recurringTransactionId: recurringTransactionId:
recurringTransactionId ?? this.recurringTransactionId, recurringTransactionId ?? this.recurringTransactionId,
externalIdentifier: externalIdentifier ?? this.externalIdentifier,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
); );
} }
@@ -1212,6 +1399,9 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
recurringTransactionId.value, recurringTransactionId.value,
); );
} }
if (externalIdentifier.present) {
map['external_identifier'] = Variable<int>(externalIdentifier.value);
}
if (updatedAt.present) { if (updatedAt.present) {
map['updated_at'] = Variable<DateTime>(updatedAt.value); map['updated_at'] = Variable<DateTime>(updatedAt.value);
} }
@@ -1227,7 +1417,8 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
..write('amount: $amount, ') ..write('amount: $amount, ')
..write('checked: $checked, ') ..write('checked: $checked, ')
..write('accountId: $accountId, ') ..write('accountId: $accountId, ')
..write('recurringTransactionId: $recurringTransactionId, ') ..write('recurringTransactionId: $recurringTransactionId, ')..write(
'externalIdentifier: $externalIdentifier, ')
..write('updatedAt: $updatedAt') ..write('updatedAt: $updatedAt')
..write(')')) ..write(')'))
.toString(); .toString();
@@ -1566,12 +1757,14 @@ typedef $$AccountsTableCreateCompanionBuilder =
AccountsCompanion Function({ AccountsCompanion Function({
Value<int> id, Value<int> id,
Value<String> name, Value<String> name,
Value<int?> externalIdentifier,
Value<DateTime> updatedAt, Value<DateTime> updatedAt,
}); });
typedef $$AccountsTableUpdateCompanionBuilder = typedef $$AccountsTableUpdateCompanionBuilder =
AccountsCompanion Function({ AccountsCompanion Function({
Value<int> id, Value<int> id,
Value<String> name, Value<String> name,
Value<int?> externalIdentifier,
Value<DateTime> updatedAt, Value<DateTime> updatedAt,
}); });
@@ -1645,6 +1838,11 @@ class $$AccountsTableFilterComposer
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
); );
ColumnFilters<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<DateTime> get updatedAt => $composableBuilder( ColumnFilters<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
@@ -1721,6 +1919,11 @@ class $$AccountsTableOrderingComposer
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
); );
ColumnOrderings<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<DateTime> get updatedAt => $composableBuilder( ColumnOrderings<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
@@ -1742,6 +1945,11 @@ class $$AccountsTableAnnotationComposer
GeneratedColumn<String> get name => GeneratedColumn<String> get name =>
$composableBuilder(column: $table.name, builder: (column) => column); $composableBuilder(column: $table.name, builder: (column) => column);
GeneratedColumn<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => column,
);
GeneratedColumn<DateTime> get updatedAt => GeneratedColumn<DateTime> get updatedAt =>
$composableBuilder(column: $table.updatedAt, builder: (column) => column); $composableBuilder(column: $table.updatedAt, builder: (column) => column);
@@ -1830,16 +2038,24 @@ class $$AccountsTableTableManager
({ ({
Value<int> id = const Value.absent(), Value<int> id = const Value.absent(),
Value<String> name = const Value.absent(), Value<String> name = const Value.absent(),
Value<int?> externalIdentifier = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(), Value<DateTime> updatedAt = const Value.absent(),
}) => AccountsCompanion(id: id, name: name, updatedAt: updatedAt), }) => AccountsCompanion(
id: id,
name: name,
externalIdentifier: externalIdentifier,
updatedAt: updatedAt,
),
createCompanionCallback: createCompanionCallback:
({ ({
Value<int> id = const Value.absent(), Value<int> id = const Value.absent(),
Value<String> name = const Value.absent(), Value<String> name = const Value.absent(),
Value<int?> externalIdentifier = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(), Value<DateTime> updatedAt = const Value.absent(),
}) => AccountsCompanion.insert( }) => AccountsCompanion.insert(
id: id, id: id,
name: name, name: name,
externalIdentifier: externalIdentifier,
updatedAt: updatedAt, updatedAt: updatedAt,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0
@@ -1936,6 +2152,7 @@ typedef $$RecurringTransactionsTableCreateCompanionBuilder =
required TimeFrameEnum timeFrame, required TimeFrameEnum timeFrame,
Value<double> amount, Value<double> amount,
required int accountId, required int accountId,
Value<int?> externalIdentifier,
Value<DateTime> updatedAt, Value<DateTime> updatedAt,
}); });
typedef $$RecurringTransactionsTableUpdateCompanionBuilder = typedef $$RecurringTransactionsTableUpdateCompanionBuilder =
@@ -1946,6 +2163,7 @@ typedef $$RecurringTransactionsTableUpdateCompanionBuilder =
Value<TimeFrameEnum> timeFrame, Value<TimeFrameEnum> timeFrame,
Value<double> amount, Value<double> amount,
Value<int> accountId, Value<int> accountId,
Value<int?> externalIdentifier,
Value<DateTime> updatedAt, Value<DateTime> updatedAt,
}); });
@@ -2042,6 +2260,11 @@ class $$RecurringTransactionsTableFilterComposer
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
); );
ColumnFilters<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<DateTime> get updatedAt => $composableBuilder( ColumnFilters<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
@@ -2130,6 +2353,11 @@ class $$RecurringTransactionsTableOrderingComposer
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
); );
ColumnOrderings<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<DateTime> get updatedAt => $composableBuilder( ColumnOrderings<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
@@ -2183,6 +2411,11 @@ class $$RecurringTransactionsTableAnnotationComposer
GeneratedColumn<double> get amount => GeneratedColumn<double> get amount =>
$composableBuilder(column: $table.amount, builder: (column) => column); $composableBuilder(column: $table.amount, builder: (column) => column);
GeneratedColumn<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => column,
);
GeneratedColumn<DateTime> get updatedAt => GeneratedColumn<DateTime> get updatedAt =>
$composableBuilder(column: $table.updatedAt, builder: (column) => column); $composableBuilder(column: $table.updatedAt, builder: (column) => column);
@@ -2280,6 +2513,7 @@ class $$RecurringTransactionsTableTableManager
Value<TimeFrameEnum> timeFrame = const Value.absent(), Value<TimeFrameEnum> timeFrame = const Value.absent(),
Value<double> amount = const Value.absent(), Value<double> amount = const Value.absent(),
Value<int> accountId = const Value.absent(), Value<int> accountId = const Value.absent(),
Value<int?> externalIdentifier = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(), Value<DateTime> updatedAt = const Value.absent(),
}) => RecurringTransactionsCompanion( }) => RecurringTransactionsCompanion(
id: id, id: id,
@@ -2288,6 +2522,7 @@ class $$RecurringTransactionsTableTableManager
timeFrame: timeFrame, timeFrame: timeFrame,
amount: amount, amount: amount,
accountId: accountId, accountId: accountId,
externalIdentifier: externalIdentifier,
updatedAt: updatedAt, updatedAt: updatedAt,
), ),
createCompanionCallback: createCompanionCallback:
@@ -2298,6 +2533,7 @@ class $$RecurringTransactionsTableTableManager
required TimeFrameEnum timeFrame, required TimeFrameEnum timeFrame,
Value<double> amount = const Value.absent(), Value<double> amount = const Value.absent(),
required int accountId, required int accountId,
Value<int?> externalIdentifier = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(), Value<DateTime> updatedAt = const Value.absent(),
}) => RecurringTransactionsCompanion.insert( }) => RecurringTransactionsCompanion.insert(
id: id, id: id,
@@ -2306,6 +2542,7 @@ class $$RecurringTransactionsTableTableManager
timeFrame: timeFrame, timeFrame: timeFrame,
amount: amount, amount: amount,
accountId: accountId, accountId: accountId,
externalIdentifier: externalIdentifier,
updatedAt: updatedAt, updatedAt: updatedAt,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0
@@ -2412,6 +2649,7 @@ typedef $$TransactionsTableCreateCompanionBuilder =
Value<bool> checked, Value<bool> checked,
required int accountId, required int accountId,
Value<int?> recurringTransactionId, Value<int?> recurringTransactionId,
Value<int?> externalIdentifier,
Value<DateTime> updatedAt, Value<DateTime> updatedAt,
}); });
typedef $$TransactionsTableUpdateCompanionBuilder = typedef $$TransactionsTableUpdateCompanionBuilder =
@@ -2423,6 +2661,7 @@ typedef $$TransactionsTableUpdateCompanionBuilder =
Value<bool> checked, Value<bool> checked,
Value<int> accountId, Value<int> accountId,
Value<int?> recurringTransactionId, Value<int?> recurringTransactionId,
Value<int?> externalIdentifier,
Value<DateTime> updatedAt, Value<DateTime> updatedAt,
}); });
@@ -2510,6 +2749,11 @@ class $$TransactionsTableFilterComposer
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
); );
ColumnFilters<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<DateTime> get updatedAt => $composableBuilder( ColumnFilters<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
@@ -2597,6 +2841,11 @@ class $$TransactionsTableOrderingComposer
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
); );
ColumnOrderings<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<DateTime> get updatedAt => $composableBuilder( ColumnOrderings<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
@@ -2674,6 +2923,11 @@ class $$TransactionsTableAnnotationComposer
GeneratedColumn<bool> get checked => GeneratedColumn<bool> get checked =>
$composableBuilder(column: $table.checked, builder: (column) => column); $composableBuilder(column: $table.checked, builder: (column) => column);
GeneratedColumn<int> get externalIdentifier => $composableBuilder(
column: $table.externalIdentifier,
builder: (column) => column,
);
GeneratedColumn<DateTime> get updatedAt => GeneratedColumn<DateTime> get updatedAt =>
$composableBuilder(column: $table.updatedAt, builder: (column) => column); $composableBuilder(column: $table.updatedAt, builder: (column) => column);
@@ -2760,6 +3014,7 @@ class $$TransactionsTableTableManager
Value<bool> checked = const Value.absent(), Value<bool> checked = const Value.absent(),
Value<int> accountId = const Value.absent(), Value<int> accountId = const Value.absent(),
Value<int?> recurringTransactionId = const Value.absent(), Value<int?> recurringTransactionId = const Value.absent(),
Value<int?> externalIdentifier = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(), Value<DateTime> updatedAt = const Value.absent(),
}) => TransactionsCompanion( }) => TransactionsCompanion(
id: id, id: id,
@@ -2769,6 +3024,7 @@ class $$TransactionsTableTableManager
checked: checked, checked: checked,
accountId: accountId, accountId: accountId,
recurringTransactionId: recurringTransactionId, recurringTransactionId: recurringTransactionId,
externalIdentifier: externalIdentifier,
updatedAt: updatedAt, updatedAt: updatedAt,
), ),
createCompanionCallback: createCompanionCallback:
@@ -2780,6 +3036,7 @@ class $$TransactionsTableTableManager
Value<bool> checked = const Value.absent(), Value<bool> checked = const Value.absent(),
required int accountId, required int accountId,
Value<int?> recurringTransactionId = const Value.absent(), Value<int?> recurringTransactionId = const Value.absent(),
Value<int?> externalIdentifier = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(), Value<DateTime> updatedAt = const Value.absent(),
}) => TransactionsCompanion.insert( }) => TransactionsCompanion.insert(
id: id, id: id,
@@ -2789,6 +3046,7 @@ class $$TransactionsTableTableManager
checked: checked, checked: checked,
accountId: accountId, accountId: accountId,
recurringTransactionId: recurringTransactionId, recurringTransactionId: recurringTransactionId,
externalIdentifier: externalIdentifier,
updatedAt: updatedAt, updatedAt: updatedAt,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0

View File

@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import '../Entities/drift_database.dart'; import '../Entities/drift_database.dart';
@@ -29,19 +31,29 @@ class TransactionRepository {
} }
/// Aktualisiert eine Transaktion in der Datenbank /// Aktualisiert eine Transaktion in der Datenbank
Future<bool> update(final TransactionsCompanion transaction) { Future<bool> update(final TransactionsCompanion transaction) async {
final Transaction? transactionInDb = await find(transaction.id.value);
final Transaction? transactionData = transactionInDb?.copyWithCompanion(
transaction,
);
final DateTime date = transaction.date.value!.add( final DateTime date = transaction.date.value!.add(
transaction.date.value!.timeZoneOffset, transaction.date.value!.timeZoneOffset,
); );
final TransactionsCompanion transactionToUpdate = TransactionsCompanion( final TransactionsCompanion transactionToUpdate = TransactionsCompanion(
id: transaction.id, id: Value(transactionData?.id ?? transaction.id.value),
name: transaction.name, name: Value(transactionData?.name ?? transaction.name.value),
date: Value(date), date: Value(date),
amount: transaction.amount, amount: Value(transactionData?.amount ?? transaction.amount.value),
checked: transaction.checked, checked: const Value(true),
accountId: transaction.accountId, accountId: Value(
recurringTransactionId: transaction.recurringTransactionId, transactionData?.accountId ?? transaction.accountId.value,
),
recurringTransactionId: Value(
transactionData?.recurringTransactionId ??
transaction.recurringTransactionId.value,
),
updatedAt: Value(DateTime.now()), updatedAt: Value(DateTime.now()),
); );
@@ -69,6 +81,7 @@ class TransactionRepository {
final double? amountMin, final double? amountMin,
final double? amountMax, final double? amountMax,
final Account? account, final Account? account,
final bool? checked,
final RecurringTransaction? recurringTransaction, final RecurringTransaction? recurringTransaction,
final int? limit, final int? limit,
final int? offset, final int? offset,
@@ -113,6 +126,10 @@ class TransactionRepository {
query.where((final t) => t.accountId.equals(account.id)); query.where((final t) => t.accountId.equals(account.id));
} }
if (checked != null) {
query.where((final t) => t.checked.equals(checked));
}
if (recurringTransaction != null) { if (recurringTransaction != null) {
query.where( query.where(
(final t) => t.recurringTransactionId.equals(recurringTransaction.id), (final t) => t.recurringTransactionId.equals(recurringTransaction.id),
@@ -262,4 +279,16 @@ class TransactionRepository {
return result; return result;
} }
/// Markiert die übergebenen Transaktionen als überprüft
void markTransactionsAsChecked(final List<Transaction> transactions) {
for (final value in transactions) {
final TransactionsCompanion transaction = TransactionsCompanion(
id: Value(value.id),
date: Value(value.date),
checked: const Value(true),
);
unawaited(update(transaction));
}
}
} }

View File

@@ -0,0 +1,25 @@
import 'dart:async';
/// Ein Service zur vereinfachung, um darauf zu warten,
/// dass etwas Initialisiert wurde
class Initializer {
bool _initialized = false;
final Completer<void> _initializedCompleter = Completer<void>();
/// Gibt zurück, ob bereits initialisiert wurde
bool get initialized => _initialized;
/// Auf diese Funktion kann gewartet werden,
/// bis [Initializer] initialisiert wurde
Future<void> waitUntilInitialized() => _initializedCompleter.future;
/// Setzt den [Initializer] auf initialisiert
void setInitialized() {
if (_initialized) {
return;
}
_initialized = true;
_initializedCompleter.complete();
}
}

View File

@@ -0,0 +1,29 @@
import 'dart:convert';
import '../Entities/drift_database.dart';
/// Ein Service um Transaktionen zu verarbeiten
class TransactionService {
/// Wandelt die übergebenen Transaktionen in einen String um
static String transactionsToString(final List<Transaction> transactions) {
final List<Map<String, dynamic>> jsonTransactions = transactions
.map((final value) => value.toJson())
.toList();
return jsonEncode(jsonTransactions);
}
/// Wandelt den String in eine Liste von Transaktionen um
static List<Transaction> transactionsFromString(final String? transactions) {
if (transactions == null) {
return [];
}
try {
final List<dynamic> decoded = jsonDecode(transactions);
return decoded.map((final item) => Transaction.fromJson(item)).toList();
} on Exception {
return [];
}
}
}

View File

@@ -1,7 +1,7 @@
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
import '../Controller/port_controller.dart'; import '../../Controller/port_controller.dart';
/// Initialisiert benötigte Services in Background-Isolates /// Initialisiert benötigte Services in Background-Isolates
Future<void> initBackground() async { Future<void> initBackground() async {

View File

@@ -2,8 +2,9 @@ import 'dart:async';
import 'package:isolate_manager/isolate_manager.dart'; import 'package:isolate_manager/isolate_manager.dart';
import '../generate_transactions_task.dart';
import '../show_notifications_task.dart';
import 'background_init_web.dart' if (dart.library.io) 'background_init.dart'; import 'background_init_web.dart' if (dart.library.io) 'background_init.dart';
import 'generate_transactions_task.dart';
@pragma('vm:entry-point') @pragma('vm:entry-point')
@isolateManagerWorker @isolateManagerWorker
@@ -32,6 +33,8 @@ Future<bool> executeTask(
switch (taskName) { switch (taskName) {
case 'generate_transactions': case 'generate_transactions':
return GenerateTransactionsTask().execute(); return GenerateTransactionsTask().execute();
case 'show_notifications':
return ShowNotificationsTask().execute();
} }
return Future.value(true); return Future.value(true);

View File

@@ -0,0 +1,28 @@
import 'package:logger/logger.dart';
import '../Controller/local_notifications.dart';
import '../Entities/drift_database.dart';
import '../Repositories/transaction_repository.dart';
import 'task.dart';
/// Zeigt Benachrichtigungen für nicht überprüfte Transaktionen an.
class ShowNotificationsTask extends Task {
final TransactionRepository _transactionRepository = TransactionRepository();
@override
Future<bool> execute() async {
final List<Transaction> transactions = await _transactionRepository.findBy(
checked: false,
dateTo: DateTime.now(),
);
if (transactions.isNotEmpty) {
Logger().i('Showing notification for unchecked transactions...');
await LocalNotifications().showTransactionsToCheckNotification(
transactions,
);
}
return Future.value(true);
}
}

View File

@@ -1,8 +1,10 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:routemaster/routemaster.dart'; import 'package:routemaster/routemaster.dart';
import 'Controller/background_task_controller.dart'; import 'Controller/background_task_controller.dart';
import 'Controller/local_notifications.dart';
import 'Controller/port_controller.dart'; import 'Controller/port_controller.dart';
import 'Services/navigation_service.dart'; import 'Services/navigation_service.dart';
import 'Services/router_service.dart'; import 'Services/router_service.dart';
@@ -14,6 +16,10 @@ void main() {
PortController(); PortController();
BackgroundTaskController(); BackgroundTaskController();
if (!kIsWeb) {
LocalNotifications();
}
runApp( runApp(
MaterialApp.router( MaterialApp.router(
routerDelegate: RoutemasterDelegate( routerDelegate: RoutemasterDelegate(