okane/lib/database/database.dart

278 lines
7.0 KiB
Dart

import 'dart:async';
import 'package:isar/isar.dart';
import 'package:get_it/get_it.dart';
import 'package:okane/database/collections/account.dart';
import 'package:okane/database/collections/beneficiary.dart';
import 'package:okane/database/collections/expense_category.dart';
import 'package:okane/database/collections/recurrent.dart';
import 'package:okane/database/collections/template.dart';
import 'package:okane/database/collections/transaction.dart';
import 'package:okane/ui/state/core.dart';
import 'package:okane/ui/utils.dart';
import 'package:path_provider/path_provider.dart';
import 'collections/budget.dart';
Future<Isar> openDatabase() async {
final dir = await getApplicationDocumentsDirectory();
return Isar.open([
AccountSchema,
BeneficiarySchema,
TransactionSchema,
TransactionTemplateSchema,
RecurringTransactionSchema,
ExpenseCategorySchema,
BudgetSchema,
BudgetItemSchema,
], directory: dir.path);
}
Future<List<Account>> getAccounts() {
return GetIt.I.get<Isar>().accounts.where().findAll();
}
Future<double> getTotalBalance(Account account) async {
return GetIt.I
.get<Isar>()
.transactions
.filter()
.account((q) => q.idEqualTo(account.id))
.amountProperty()
.sum();
}
Future<List<Transaction>> getLastTransactions(
Account account,
DateTime today,
int days,
) async {
return GetIt.I
.get<Isar>()
.transactions
.filter()
.account((q) => q.idEqualTo(account.id))
.dateGreaterThan(toMidnight(today.subtract(Duration(days: days))))
.findAll();
}
Future<List<RecurringTransaction>> getRecurringTransactions(Account? account) {
if (account == null) {
return Future.value([]);
}
return GetIt.I
.get<Isar>()
.recurringTransactions
.filter()
.account((q) => q.idEqualTo(account.id))
.findAll();
}
Stream<void> watchRecurringTransactions(Account account) {
final account = GetIt.I.get<CoreCubit>().activeAccount!;
return GetIt.I
.get<Isar>()
.recurringTransactions
.filter()
.account((q) => q.idEqualTo(account.id))
.build()
.watchLazy(fireImmediately: true);
}
Future<void> upsertAccount(Account account) async {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() async {
print("Before account insert");
final id = await db.accounts.put(account);
print("After account insert: $id");
});
}
Future<void> upsertBeneficiary(Beneficiary beneficiary) async {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() async {
await db.beneficiarys.put(beneficiary);
await beneficiary.account.save();
});
}
Future<Beneficiary?> getAccountBeneficiary(Account account) {
return GetIt.I
.get<Isar>()
.beneficiarys
.filter()
.account((q) => q.idEqualTo(account.id))
.findFirst();
}
Future<void> upsertTransactionTemplate(TransactionTemplate template) async {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() async {
await db.transactionTemplates.put(template);
await template.beneficiary.save();
await template.account.save();
await template.expenseCategory.save();
});
}
Future<void> upsertRecurringTransaction(RecurringTransaction template) async {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() async {
await db.recurringTransactions.put(template);
await template.template.save();
await template.account.save();
});
}
Future<void> upsertTransaction(Transaction transaction) async {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() async {
await db.transactions.put(transaction);
await transaction.beneficiary.save();
await transaction.account.save();
await transaction.expenseCategory.save();
});
}
Stream<void> watchAccounts() {
return GetIt.I.get<Isar>().accounts.watchLazy();
}
Stream<void> watchTransactionTemplates(Account account) {
return GetIt.I
.get<Isar>()
.transactionTemplates
.filter()
.account((q) => q.idEqualTo(account.id))
.recurringEqualTo(false)
.watchLazy(fireImmediately: true);
}
Future<List<TransactionTemplate>> getTransactionTemplates(Account? account) {
if (account == null) {
return Future.value([]);
}
return GetIt.I
.get<Isar>()
.transactionTemplates
.filter()
.account((q) => q.idEqualTo(account.id))
.recurringEqualTo(false)
.findAll();
}
Stream<void> watchTransactions(Account account) {
return GetIt.I
.get<Isar>()
.transactions
.filter()
.account((q) => q.idEqualTo(account.id))
.watchLazy(fireImmediately: true);
}
Future<List<Transaction>> getTransactions(Account? account) {
if (account == null) {
return Future.value([]);
}
return GetIt.I
.get<Isar>()
.transactions
.filter()
.account((q) => q.idEqualTo(account.id))
.findAll();
}
Stream<void> watchBeneficiaries() {
return GetIt.I.get<Isar>().beneficiarys.watchLazy(fireImmediately: true);
}
Future<List<Beneficiary>> getBeneficiaries() {
return GetIt.I.get<Isar>().beneficiarys.where().findAll();
}
Stream<Beneficiary?> watchBeneficiaryObject(Id id) {
return GetIt.I.get<Isar>().beneficiarys.watchObject(id);
}
Future<void> upsertExpenseCategory(ExpenseCategory category) {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() => db.expenseCategorys.put(category));
}
Future<List<ExpenseCategory>> getExpenseCategories() {
return GetIt.I.get<Isar>().expenseCategorys.where().findAll();
}
Stream<void> watchExpenseCategory() {
return GetIt.I.get<Isar>().expenseCategorys.watchLazy(fireImmediately: true);
}
Stream<void> watchBudgets(Account account) {
return GetIt.I
.get<Isar>()
.budgets
.filter()
.account((q) => q.idEqualTo(account.id))
.watchLazy(fireImmediately: true);
}
Future<List<Budget>> getBudgets(Account? account) {
if (account == null) {
return Future.value([]);
}
return GetIt.I
.get<Isar>()
.budgets
.filter()
.account((q) => q.idEqualTo(account.id))
.findAll();
}
Future<void> upsertBudget(Budget budget) {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() async {
await db.budgets.put(budget);
await budget.items.save();
await budget.account.save();
});
}
Future<void> upsertBudgetItem(BudgetItem item) {
final db = GetIt.I.get<Isar>();
return db.writeTxn(() async {
await db.budgetItems.put(item);
await item.expenseCategory.save();
});
}
enum TransactionQueryDateOption { thisMonth }
Future<List<Transaction>> getTransactionsInTimeframe(
Account account,
DateTime today,
TransactionQueryDateOption option,
) async {
final lower = switch (option) {
TransactionQueryDateOption.thisMonth => DateTime(
today.year,
today.month,
0,
),
};
final upper = switch (option) {
TransactionQueryDateOption.thisMonth => monthEnding(today),
};
return GetIt.I
.get<Isar>()
.transactions
.filter()
.account((q) => q.idEqualTo(account.id))
.dateBetween(lower, upper)
.findAll();
}