Files
dragon_ledger/lib/Repositories/transaction_repository.dart

247 lines
7.2 KiB
Dart

import 'package:drift/drift.dart';
import '../Entities/drift_database.dart';
import '../Services/database_service.dart';
/// Funktionen zum interagieren mit der Datenbank für die Transaktionen
class TransactionRepository {
final AppDatabase _db = DatabaseService().database;
/// Fügt eine neue Transaktion zur Datenbank hinzu
Future<Transaction?> add(final TransactionsCompanion transaction) async {
final int id = await _db.into(_db.transactions).insert(transaction);
return find(id);
}
/// Aktualisiert eine Transaktion in der Datenbank
Future<bool> update(final TransactionsCompanion transaction) {
final TransactionsCompanion transactionToUpdate = TransactionsCompanion(
id: transaction.id,
name: transaction.name,
date: transaction.date,
amount: transaction.amount,
checked: transaction.checked,
accountId: transaction.accountId,
recurringTransactionId: transaction.recurringTransactionId,
updatedAt: Value(DateTime.now()),
);
return _db.update(_db.transactions).replace(transactionToUpdate);
}
/// Entfernt eine Transaktion aus der Datenbank
Future<int> remove(final Transaction transaction) => (_db.delete(
_db.transactions,
)..where((final t) => t.id.equals(transaction.id))).go();
/// Sucht eine Transaktion anhand seiner Id aus der Datenbank
Future<Transaction?> find(final int id) => (_db.select(
_db.transactions,
)..where((final t) => t.id.equals(id))).getSingleOrNull();
/// Sucht Transaktionen anhand der gegebenen Parameter aus der Datenbank
Future<List<Transaction>> findBy({
final int? id,
final String? name,
final DateTime? date,
final DateTime? dateFrom,
final DateTime? dateTo,
final double? amount,
final double? amountMin,
final double? amountMax,
final Account? account,
final RecurringTransaction? recurringTransaction,
final int? limit,
final int? offset,
final String? orderBy,
}) {
final SimpleSelectStatement<$TransactionsTable, Transaction> query = _db
.select(_db.transactions);
if (id != null) {
query.where((final t) => t.id.equals(id));
}
if (name != null && name.isNotEmpty) {
query.where((final t) => t.name.like('%$name%'));
}
if (date != null) {
query.where((final t) => t.date.equals(date));
}
if (dateFrom != null) {
query.where((final t) => t.date.isBiggerThanValue(dateFrom));
}
if (dateTo != null) {
query.where((final t) => t.date.isSmallerThanValue(dateTo));
}
if (amount != null) {
query.where((final t) => t.amount.equals(amount));
}
if (amountMin != null) {
query.where((final t) => t.amount.isBiggerThanValue(amountMin));
}
if (amountMax != null) {
query.where((final t) => t.amount.isSmallerThanValue(amountMax));
}
if (account != null) {
query.where((final t) => t.accountId.equals(account.id));
}
if (recurringTransaction != null) {
query.where(
(final t) => t.recurringTransactionId.equals(recurringTransaction.id),
);
}
if (limit != null) {
query.limit(limit, offset: offset);
}
if (orderBy != null) {
switch (orderBy) {
case 'nameAsc':
query.orderBy([(final t) => OrderingTerm.asc(t.name)]);
case 'nameDesc':
query.orderBy([(final t) => OrderingTerm.desc(t.name)]);
case 'dateAsc':
query.orderBy([(final t) => OrderingTerm.asc(t.date)]);
case 'dateDesc':
query.orderBy([(final t) => OrderingTerm.desc(t.date)]);
case 'amountAsc':
query.orderBy([(final t) => OrderingTerm.asc(t.amount)]);
case 'amountDesc':
query.orderBy([(final t) => OrderingTerm.desc(t.amount)]);
}
}
return query.get();
}
/// Gibt den Kontostand zurück
Future<double> balance({
final Account? account,
final DateTime? until,
}) async {
final JoinedSelectStatement<$TransactionsTable, Transaction> query =
_db.selectOnly(_db.transactions)
..addColumns([_db.transactions.amount.sum()]);
if (account != null) {
query.where(_db.transactions.accountId.equals(account.id));
}
if (until != null) {
query.where(_db.transactions.date.isSmallerOrEqualValue(until));
}
return (await query
.map((final row) => row.read(_db.transactions.amount.sum()) ?? 0)
.getSingle()) *
-1;
}
/// Gibt den Kontostand der letzten 12 Monate zurück
Future<List<Map<String, dynamic>>> monthlyBalances({
final Account? account,
final String? name,
final double? amountMin,
final double? amountMax,
DateTime? dateFrom,
DateTime? dateTo,
}) async {
final now = DateTime.now();
final monthStart = DateTime(now.year, now.month - 12);
final monthEnd = DateTime(now.year, now.month + 1, 0);
if (dateFrom == null || dateFrom.compareTo(monthStart) < 0) {
dateFrom = monthStart;
}
if (dateTo == null || dateTo.compareTo(monthEnd) > 0) {
dateTo = monthEnd;
}
final Expression<int> yearExpr = _db.transactions.date.year;
final Expression<int> monthExpr = _db.transactions.date.month;
final Expression<double> sumExpr = _db.transactions.amount.sum();
final JoinedSelectStatement<$TransactionsTable, Transaction> query =
_db.selectOnly(_db.transactions)
..addColumns([yearExpr, monthExpr, sumExpr])
..groupBy([yearExpr, monthExpr])
..orderBy([OrderingTerm.asc(yearExpr), OrderingTerm.asc(monthExpr)])
..where(_db.transactions.date.isBiggerOrEqualValue(dateFrom))
..where(_db.transactions.date.isSmallerOrEqualValue(dateTo));
if (account != null) {
query.where(_db.transactions.accountId.equals(account.id));
}
if (name != null && name.isNotEmpty) {
query.where(_db.transactions.name.like('%$name%'));
}
if (amountMin != null) {
query.where(_db.transactions.amount.isBiggerOrEqualValue(amountMin));
}
if (amountMax != null) {
query.where(_db.transactions.amount.isSmallerOrEqualValue(amountMax));
}
final List<Map<String, Object>> rows = (await query.get()).map((final row) {
final int year = row.read(yearExpr)!;
final int month = row.read(monthExpr)!;
return {
'date': DateTime(year, month),
'balance': (row.read(sumExpr) ?? 0) * -1,
};
}).toList();
double amount = await balance(account: account, until: dateFrom);
DateTime dateTimeLoop = dateFrom;
int loop = 0;
final List<Map<String, Object>> result = [];
while (dateTimeLoop.compareTo(monthEnd) < 0) {
Map<String, Object>? row;
for (final value in rows) {
final Object? rowDate = value['date'];
if (rowDate is DateTime) {
if (dateTimeLoop.compareTo(rowDate) == 0) {
row = value;
}
}
}
if (row == null) {
result.add({'date': dateTimeLoop, 'balance': 0.0});
} else {
result.add(row);
}
final double balance = double.parse(result[loop]['balance'].toString());
amount = balance + amount;
result[loop]['balance'] = amount;
loop = loop + 1;
dateTimeLoop = DateTime(dateTimeLoop.year, dateTimeLoop.month + 1);
}
return result;
}
}