197 lines
5.5 KiB
Dart
197 lines
5.5 KiB
Dart
import 'package:seshat/data/services/api_client.dart';
|
|
import 'package:seshat/domain/models/accounting.dart';
|
|
import 'package:seshat/domain/models/bal.dart';
|
|
import 'package:seshat/domain/models/bal_stats.dart';
|
|
import 'package:seshat/domain/models/enums.dart';
|
|
import 'package:seshat/utils/result.dart';
|
|
|
|
/// Repository to manage [Bal]
|
|
class BalRepository {
|
|
BalRepository({required ApiClient apiClient}) : _apiClient = apiClient;
|
|
|
|
final ApiClient _apiClient;
|
|
|
|
/// [List<Bal>] of all the user's [Bal]
|
|
List<Bal>? _bals;
|
|
|
|
/// [Accounting] of [Bal], mapped by [Bal] id
|
|
final Map<int, Accounting?> _accountingMap = {};
|
|
|
|
/// Gets a list of all [Bal] from cache or remote
|
|
Future<Result<List<Bal>>> getBals() async {
|
|
if (_bals != null) {
|
|
return Result.ok(_bals!);
|
|
}
|
|
final result = await _apiClient.getBals();
|
|
switch (result) {
|
|
case Ok():
|
|
_bals = result.value;
|
|
return Result.ok(result.value);
|
|
case Error():
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// Gets a list of all [Bal] from remote only
|
|
Future<Result<List<Bal>>> _getBalsNoCache() async {
|
|
final result = await _apiClient.getBals();
|
|
switch (result) {
|
|
case Ok():
|
|
_bals = result.value;
|
|
return Result.ok(result.value);
|
|
case Error():
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// Gets a [Bal] by [balId], either from cache or remote
|
|
Future<Result<Bal>> balById(int balId) async {
|
|
if (_bals == null) {
|
|
await getBals();
|
|
}
|
|
Bal? bal = _bals!.where((bal) => bal.id == balId).firstOrNull;
|
|
if (bal != null) {
|
|
return Result.ok(bal);
|
|
}
|
|
final result = await _apiClient.getBalById(balId);
|
|
switch (result) {
|
|
case Ok():
|
|
return Result.ok(result.value);
|
|
case Error():
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// Return wether or not a [Bal] is currently [BalState.ongoing]
|
|
bool isABalOngoing() {
|
|
return _bals?.where((bal) => bal.state == BalState.ongoing).isNotEmpty ??
|
|
false;
|
|
}
|
|
|
|
/// Gets the [Bal] that is [BalState.ongoing]
|
|
Future<Bal?> ongoingBal() async {
|
|
if (_bals == null) {
|
|
await _getBalsNoCache();
|
|
}
|
|
return _bals!.where((bal) => bal.state == BalState.ongoing).firstOrNull;
|
|
}
|
|
|
|
/// Stops a [Bal] and refresh cache
|
|
Future<Result<Bal>> stopBal(int id) async {
|
|
final result = await _apiClient.stopBal(id);
|
|
_getBalsNoCache();
|
|
return result;
|
|
}
|
|
|
|
/// Starts a [Bal] and refresh cache
|
|
Future<Result<Bal>> startBal(int id) async {
|
|
if (isABalOngoing()) {
|
|
return Result.error(
|
|
Exception("Cannot have multiple BAL ongoing at the same time !"),
|
|
);
|
|
}
|
|
final result = await _apiClient.startBal(id);
|
|
_getBalsNoCache();
|
|
return result;
|
|
}
|
|
|
|
/// Changes a [Bal]'s [name], [startTime] or [endTime]
|
|
Future<Result<Bal>> editBal(
|
|
int id,
|
|
String name,
|
|
DateTime startTime,
|
|
DateTime endTime,
|
|
) async {
|
|
final result = await _apiClient.editBal(id, name, startTime, endTime);
|
|
await _getBalsNoCache();
|
|
return result;
|
|
}
|
|
|
|
/// Creates a [Bal] from its [name], [startTime] and [endTime]
|
|
Future<Result<void>> addBal(
|
|
String name,
|
|
DateTime startTime,
|
|
DateTime endTime,
|
|
) async {
|
|
final result = await _apiClient.addBal(name, startTime, endTime);
|
|
await _getBalsNoCache();
|
|
return result;
|
|
}
|
|
|
|
/// Gets a [BalStats] from its [balId]
|
|
Future<Result<BalStats>> getBalStats(int balId) async {
|
|
return _apiClient.getBalStats(balId);
|
|
}
|
|
|
|
/// Get [Accounting] of a [Bal] from remote only
|
|
Future<Result<Accounting>> getAccountingNoCache(int balId) async {
|
|
final result = await _apiClient.getAccounting(balId);
|
|
switch (result) {
|
|
case Ok():
|
|
_accountingMap[balId] = result.value;
|
|
break;
|
|
default:
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// Get [Accounting] of a [Bal] from cache or remote
|
|
Future<Result<Accounting>> getAccounting(int balId) async {
|
|
if (_accountingMap[balId] != null) {
|
|
return Result.ok(_accountingMap[balId]!);
|
|
}
|
|
final result = await _apiClient.getAccounting(balId);
|
|
switch (result) {
|
|
case Ok():
|
|
_accountingMap[balId] = result.value;
|
|
break;
|
|
default:
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// Manages what returning (of type [ReturnType]) does to cache and notifies remote
|
|
Future<Result<void>> returnToId(
|
|
int balId,
|
|
int ownerId,
|
|
ReturnType type,
|
|
) async {
|
|
final result = await _apiClient.returnToId(balId, ownerId, type.name);
|
|
switch (result) {
|
|
case Ok():
|
|
switch (type) {
|
|
case ReturnType.books:
|
|
final owner = _accountingMap[balId]?.owners
|
|
.where((el) => el.ownerId == ownerId)
|
|
.firstOrNull;
|
|
if (owner?.owedMoney == 0) {
|
|
_accountingMap[balId]?.owners.removeWhere(
|
|
(el) => el.ownerId == ownerId,
|
|
);
|
|
}
|
|
owner?.owed = [];
|
|
owner?.owedInstances = [];
|
|
break;
|
|
case ReturnType.money:
|
|
final owner = _accountingMap[balId]?.owners
|
|
.where((el) => el.ownerId == ownerId)
|
|
.firstOrNull;
|
|
if (owner?.owed == null || owner!.owed.isEmpty) {
|
|
_accountingMap[balId]?.owners.removeWhere(
|
|
(el) => el.ownerId == ownerId,
|
|
);
|
|
}
|
|
owner?.owedMoney = 0;
|
|
break;
|
|
case ReturnType.all:
|
|
_accountingMap[balId]?.owners.removeWhere(
|
|
(el) => el.ownerId == ownerId,
|
|
);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
}
|
|
return result;
|
|
}
|
|
}
|