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(); }