Files
Krezus/lib/domains/account/account_bloc.dart

212 lines
6.5 KiB
Dart

import 'dart:async';
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/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';
part 'account_state.dart';
final colors = [
'FF74feff',
'FF64c0ff',
'FF5873fe',
'FF4b4cff',
'FFc0fcfd',
'FFa7caff',
'FF8d7efd',
'FF7f65fe',
'FFe7ffff',
'FFd7dafd',
'FFd8a6ff',
'FFc065fe',
'FFffffff',
'FFffe6fe',
'FFffbdff',
'FFff80fe',
];
class AccountBloc extends Bloc<AccountEvent, AccountState> {
final TransactionsRepository _transactionsRepository;
final MetadataRepository _metadataRepository;
AccountBloc({
required MetadataRepository metadataRepository,
required TransactionsRepository transactionsRepository,
})
: _metadataRepository = metadataRepository,
_transactionsRepository = transactionsRepository,
super(const AccountState()
) {
on<AccountImportCSV>(_onAccountImportCSV);
on<AccountLoad>(_onAccountLoad);
// on<AccountExportJSON>(_onAccountImportJSON);
// on<AccountExportCSV>(_onAccountImportJSON);
on<AccountAdd>(_onAccountAdd);
on<AccountRemove>(_onAcountRemove);
on<AccountEditLabel>(_onAccountEditLabel);
on<AccountEditSaving>(_onAccountEditSaving);
on<AccountEditColor>(_onAccountEditColor);
_metadataRepository
.getAccountsStream()
.listen((subAccounts) => add(AccountLoad(subAccounts)));
}
double _universalConvertToDouble(dynamic value) {
if (value is String) {
return double.parse(value);
} else if (value is int) {
return value.toDouble();
} else if (value is double) {
return value;
} else {
throw Error();
}
}
_onAccountImportCSV(AccountImportCSV event, Emitter<AccountState> emit) async {
int colorIndex = 0;
FilePickerResult? result = await FilePicker.platform.pickFiles();
final csvPath = result?.files.first.path;
if (csvPath != null) {
final File csv = File(csvPath);
final String csvFileContent = await csv.readAsString();
final List<List<dynamic>> csvList = const CsvToListConverter(fieldDelimiter: '|', eol: '\n').convert(csvFileContent);
final Map<String, Category> categoriesMap = {};
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 );
// }
categoriesMap[categoryLabel] = Category(label: categoryLabel, color: value > 0 ? 'FF21E297' : 'FFFFB4AB' );
}
String accountLabel = line[3];
if (accounts[accountLabel] == null) {
accounts[accountLabel] = Account(label: accountLabel, color: 'FF74feff');
}
return Transaction(
uuid: const Uuid().v8(),
date: DateTime.parse(line[0]),
category: categoryLabel,
description: line[2],
account: line[3],
value: value
);
})
.toList();
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);
}
}
_onAccountLoad(
AccountLoad event, Emitter<AccountState> emit
) {
emit(
state.copyWith(event.subAccounts)
);
}
_onAccountAdd(AccountAdd event, Emitter<AccountState> emit) async {
String uuid = const Uuid().v8();
Account account = Account(
label: 'Account $uuid',
color: 'FF74feff',
saving: false
);
emit(
state.copyWith(await _saveAccount(account))
);
}
_onAcountRemove(AccountRemove event, Emitter<AccountState> emit) async {
Account accountToRemove = event.account;
List<Account> accounts = state.accounts;
List<Transaction> transactions = _transactionsRepository.getTransactions();
if (transactions.any((transaction) => transaction.account == accountToRemove.label)) {
emit(AccountRemoveFail());
emit(AccountState(accounts: accounts));
} else {
accounts.removeWhere((account) => account.label == accountToRemove.label);
emit(AccountRemoveSucess());
emit(
state.copyWith(await _metadataRepository.saveAccounts(accounts))
);
}
}
_onAccountEditLabel(AccountEditLabel event, Emitter<AccountState> emit) async {
Account account = event.account;
account.label = event.label;
emit(
state.copyWith(await _saveAccount(account))
);
}
_onAccountEditSaving(AccountEditSaving event, Emitter<AccountState> emit) async {
Account account = event.account;
account.saving = event.saving;
emit(
state.copyWith(await _saveAccount(account))
);
}
_onAccountEditColor(AccountEditColor event, Emitter<AccountState> emit) async {
Account account = event.account;
account.color = event.color;
emit(
state.copyWith(await _saveAccount(account))
);
}
Future<List<Account>> _saveAccount(Account accountToSave) async {
List<Account> accounts = _metadataRepository.getAccounts();
try {
Account accountFound = accounts.firstWhere((account) => account.label == accountToSave.label);
accountFound.color = accountToSave.color;
accountFound.saving = accountToSave.saving;
} catch (e) {
accounts.add(accountToSave);
}
await _metadataRepository.saveAccounts(accounts);
return accounts;
}
}