Refactored json storage

This commit is contained in:
2024-02-17 14:16:07 +01:00
parent 1a7f28703a
commit b2da8436e4
29 changed files with 389 additions and 235 deletions

View File

@@ -1,14 +1,14 @@
import 'dart:convert';
import 'dart:io';
import 'package:csv/csv.dart';
import 'package:equatable/equatable.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tunas/repositories/account/account_repository.dart';
import 'package:tunas/repositories/account/models/account.dart';
import 'package:tunas/repositories/account/models/category.dart';
import 'package:tunas/repositories/account/models/transaction.dart';
import 'package:tunas/repositories/metadata/models/category.dart';
import 'package:tunas/repositories/metadata/metadata_repository.dart';
import 'package:tunas/repositories/metadata/models/account.dart';
import 'package:tunas/repositories/transactions/models/transaction.dart';
import 'package:tunas/repositories/transactions/transactions_repository.dart';
import 'package:uuid/uuid.dart';
part 'account_event.dart';
@@ -34,20 +34,25 @@ final colors = [
];
class AccountBloc extends Bloc<AccountEvent, AccountState> {
final AccountRepository _accountRepository;
final TransactionsRepository _transactionsRepository;
final MetadataRepository _metadataRepository;
AccountBloc({required AccountRepository accountRepository})
: _accountRepository = accountRepository,
super(const AccountState()) {
on<AccountImportJSON>(_onAccountImportJSON);
AccountBloc({
required MetadataRepository metadataRepository,
required TransactionsRepository transactionsRepository,
})
: _metadataRepository = metadataRepository,
_transactionsRepository = transactionsRepository,
super(const AccountState()
) {
on<AccountImportCSV>(_onAccountImportCSV);
on<SubAccountLoad>(_onSubAccountLoad);
on<AccountLoad>(_onAccountLoad);
// on<AccountExportJSON>(_onAccountImportJSON);
// on<AccountExportCSV>(_onAccountImportJSON);
_accountRepository
.getSubAccountsStream()
.listen((subAccounts) => add(SubAccountLoad(subAccounts)));
_metadataRepository
.getAccountsStream()
.listen((subAccounts) => add(AccountLoad(subAccounts)));
}
double _universalConvertToDouble(dynamic value) {
@@ -62,8 +67,7 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
}
}
_onAccountImportCSV(
AccountImportCSV event, Emitter<AccountState> emit) async {
_onAccountImportCSV(AccountImportCSV event, Emitter<AccountState> emit) async {
int colorIndex = 0;
FilePickerResult? result = await FilePicker.platform.pickFiles();
@@ -74,27 +78,33 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
final List<List<dynamic>> csvList = const CsvToListConverter(fieldDelimiter: '|', eol: '\n').convert(csvFileContent);
final Map<String, Category> categoriesMap = {};
final Set<String> subAccounts = {};
final Map<String, Account> accounts = {};
final transactions = csvList
.map((line) {
double value = _universalConvertToDouble(line[4]);
String? categoryLabel = line[1];
if (categoryLabel == null || categoryLabel == '') {
categoryLabel = 'N/A';
}
if (categoriesMap[categoryLabel] == null) {
if (categoryLabel == 'N/A') {
categoriesMap[categoryLabel] = Category(label: 'N/A', color: 'FFFF0000' );
} else {
String color = colorIndex >= colors.length ? 'FF0000FF' : colors[colorIndex];
colorIndex++;
categoriesMap[categoryLabel] = Category(label: categoryLabel, color: color );
}
// if (categoryLabel == 'N/A') {
// categoriesMap[categoryLabel] = Category(label: 'N/A', color: 'FFFF0000' );
// } else {
// String color = colorIndex >= colors.length ? 'FF0000FF' : colors[colorIndex];
// colorIndex++;
// categoriesMap[categoryLabel] = Category(label: categoryLabel, color: color );
// }
categoriesMap[categoryLabel] = Category(label: categoryLabel, color: value > 0 ? 'FF21E297' : 'FFFFB4AB' );
}
subAccounts.add(line[3]);
String accountLabel = line[3];
if (accounts[accountLabel] == null) {
accounts[accountLabel] = Account(label: accountLabel);
}
return Transaction(
uuid: const Uuid().v8(),
@@ -102,34 +112,23 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
category: categoryLabel,
description: line[2],
account: line[3],
value: _universalConvertToDouble(line[4]));
})
value: value
);
})
.toList();
await _accountRepository.deleteAccount();
final account = Account(transactions: transactions, categories: categoriesMap.values.toList(), subAccounts: subAccounts);
await _accountRepository.saveAccount(account);
await _metadataRepository.deleteMetadata();
await _transactionsRepository.deleteTransactions();
await _metadataRepository.saveAccounts(accounts.values.toList());
await _metadataRepository.saveBudgets([]);
await _metadataRepository.saveCategories(categoriesMap.values.toList());
await _transactionsRepository.saveTransactions(transactions);
}
}
_onAccountImportJSON(
AccountImportJSON event, Emitter<AccountState> emit) async {
FilePickerResult? result = await FilePicker.platform.pickFiles();
final jsonPath = result?.files.first.path;
if (jsonPath != null) {
final File json = File(jsonPath);
final String jsonString = await json.readAsString();
final List<dynamic> jsonList = jsonDecode(jsonString);
final List<Transaction> transactions = jsonList.map((transaction) => Transaction.fromJson(transaction)).toList();
await _accountRepository.deleteAccount();
await _accountRepository.saveTransactions(transactions);
}
}
_onSubAccountLoad(
SubAccountLoad event, Emitter<AccountState> emit
_onAccountLoad(
AccountLoad event, Emitter<AccountState> emit
) {
emit(
state.copyWith(event.subAccounts)

View File

@@ -23,9 +23,9 @@ final class AccountExportCSV extends AccountEvent {
const AccountExportCSV();
}
final class SubAccountLoad extends AccountEvent {
final Set<String> subAccounts;
const SubAccountLoad(this.subAccounts);
final class AccountLoad extends AccountEvent {
final List<Account> subAccounts;
const AccountLoad(this.subAccounts);
@override
List<Object> get props => [subAccounts];

View File

@@ -1,18 +1,18 @@
part of 'account_bloc.dart';
final class AccountState extends Equatable {
final Set<String> subAccounts;
final List<Account> accounts;
const AccountState({
this.subAccounts = const {},
this.accounts = const [],
});
AccountState copyWith(Set<String>? subAccounts) {
AccountState copyWith(List<Account>? accounts) {
return AccountState(
subAccounts: subAccounts ?? this.subAccounts,
accounts: accounts ?? this.accounts,
);
}
@override
List<Object?> get props => [subAccounts];
List<Object?> get props => [accounts];
}

View File

@@ -1,18 +1,18 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tunas/repositories/account/account_repository.dart';
import 'package:tunas/repositories/account/models/budget.dart';
import 'package:tunas/repositories/metadata/models/budget.dart';
import 'package:tunas/repositories/metadata/metadata_repository.dart';
part 'budget_event.dart';
part 'budget_state.dart';
class BudgetBloc extends Bloc<BudgetEvent, BudgetState> {
final AccountRepository _accountRepository;
final MetadataRepository _metadataRepository;
BudgetBloc({required AccountRepository accountRepository}) : _accountRepository = accountRepository, super(const BudgetState()) {
BudgetBloc({required MetadataRepository metadataRepository}) : _metadataRepository = metadataRepository, super(const BudgetState()) {
on<BudgetsLoad>(_onBudgetsLoad);
_accountRepository
_metadataRepository
.getBudgetsStream()
.listen((budgets) => add(BudgetsLoad(budgets)));
}

View File

@@ -2,19 +2,19 @@ import 'dart:ui';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tunas/repositories/account/account_repository.dart';
import 'package:tunas/repositories/account/models/category.dart';
import 'package:tunas/repositories/metadata/metadata_repository.dart';
import 'package:tunas/repositories/metadata/models/category.dart';
part 'category_event.dart';
part 'category_state.dart';
class CategoryBloc extends Bloc<CategoryEvent, CategoryState> {
final AccountRepository _accountRepository;
final MetadataRepository _metadataRepository;
CategoryBloc({required AccountRepository accountRepository}) : _accountRepository = accountRepository, super(const CategoryState()) {
CategoryBloc({required MetadataRepository metadataRepository}) : _metadataRepository = metadataRepository, super(const CategoryState()) {
on<CategoriesLoad>(_onCategoriesLoad);
_accountRepository
_metadataRepository
.getCategoriesStream()
.listen((categories) => add(CategoriesLoad(categories)));
}

View File

@@ -4,29 +4,32 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tunas/domains/charts/models/month_totals.dart';
import 'package:tunas/domains/transaction/models/transaction_line.dart';
import 'package:tunas/domains/charts/models/chart_item.dart';
import 'package:tunas/repositories/account/account_repository.dart';
import 'package:tunas/repositories/account/models/category.dart';
import 'package:tunas/repositories/account/models/transaction.dart';
import 'package:tunas/repositories/metadata/metadata_repository.dart';
import 'package:tunas/repositories/metadata/models/category.dart';
import 'package:tunas/repositories/transactions/models/transaction.dart';
import 'package:tunas/repositories/transactions/models/transactions.dart';
import 'package:tunas/repositories/transactions/transactions_repository.dart';
part 'chart_event.dart';
part 'chart_state.dart';
class ChartBloc extends Bloc<ChartEvent, ChartState> {
final AccountRepository _accountRepository;
final MetadataRepository _metadataRepository;
final TransactionsRepository _transactionsRepository;
ChartBloc({required AccountRepository accountRepository}) :
_accountRepository = accountRepository, super(const ChartState()) {
ChartBloc({required MetadataRepository metadataRepository, required TransactionsRepository transactionsRepository}) :
_metadataRepository = metadataRepository, _transactionsRepository = transactionsRepository, super(const ChartState()) {
on<ChartTransactionsLoad>(_onChartTransactionsLoad);
on<ChartCategoriesLoad>(_onChartCategoriesLoad);
on<ChartNextYear>(_onNextYear);
on<ChartPreviousYear>(_onPreviousYear);
_accountRepository
_transactionsRepository
.getTransactionsStream()
.listen((transactions) => add(ChartTransactionsLoad(transactions)));
_accountRepository
_metadataRepository
.getCategoriesStream()
.listen((categories) => add(ChartCategoriesLoad(categories)));
}

View File

@@ -1,4 +1,4 @@
import 'package:tunas/repositories/account/models/transaction.dart';
import 'package:tunas/repositories/transactions/models/transaction.dart';
class TransactionLine {
Transaction transaction;

View File

@@ -8,18 +8,18 @@ import 'package:tunas/domains/transaction/models/transaction_date.dart';
import 'package:tunas/domains/transaction/models/transaction_description.dart';
import 'package:tunas/domains/transaction/models/transaction_line.dart';
import 'package:tunas/domains/transaction/models/transaction_value.dart';
import 'package:tunas/repositories/account/account_repository.dart';
import 'package:tunas/repositories/account/models/transaction.dart';
import 'package:tunas/repositories/transactions/models/transaction.dart';
import 'package:tunas/repositories/transactions/transactions_repository.dart';
import 'package:uuid/uuid.dart';
part 'transaction_event.dart';
part 'transaction_state.dart';
class TransactionBloc extends Bloc<TransactionEvent, TransactionState> {
final AccountRepository _accountRepository;
final TransactionsRepository _transactionsRepository;
TransactionBloc({required AccountRepository accountRepository})
: _accountRepository = accountRepository,
TransactionBloc({required TransactionsRepository transactionsRepository})
: _transactionsRepository = transactionsRepository,
super(const TransactionState()) {
on<TransactionsLoad>(_onAccountLoad);
on<TransactionDateChange>(_onTransactionDateChange);
@@ -33,7 +33,7 @@ class TransactionBloc extends Bloc<TransactionEvent, TransactionState> {
on<TransactionSetCurrent>(_onTransactionSetCurrent);
on<TransactionDeleteCurrent>(_onTransactionDeleteCurrent);
_accountRepository
_transactionsRepository
.getTransactionsStream()
.listen((transactions) => add(TransactionsLoad(transactions)));
}
@@ -161,7 +161,7 @@ class TransactionBloc extends Bloc<TransactionEvent, TransactionState> {
));
final computeResult = _computeTransactionLine(transactions);
await _accountRepository.saveTransactions(transactions);
await _transactionsRepository.saveTransactions(transactions);
emit(state.copyWith(
currentTransaction: null,
@@ -211,7 +211,7 @@ class TransactionBloc extends Bloc<TransactionEvent, TransactionState> {
List<Transaction> transactions = state.transactions;
transactions.removeWhere((transaction) => transaction.uuid == currentTransaction.uuid);
final computeResult = _computeTransactionLine(transactions);
await _accountRepository.saveTransactions(transactions);
await _transactionsRepository.saveTransactions(transactions);
emit(state.copyWith(
currentTransaction: null,
transactionDate: const TransactionDate.pure(),