93 lines
2.6 KiB
Dart
93 lines
2.6 KiB
Dart
import 'package:pshared/models/money.dart';
|
|
import 'package:pshared/models/payment/fees/line.dart';
|
|
import 'package:pshared/models/payment/quote/quote.dart';
|
|
import 'package:pshared/utils/currency.dart';
|
|
import 'package:pshared/utils/money.dart';
|
|
|
|
Money? quoteFeeTotal(PaymentQuote? quote) {
|
|
final preferredCurrency =
|
|
quote?.amounts?.sourcePrincipal?.currency ??
|
|
quote?.amounts?.sourceDebitTotal?.currency;
|
|
return quoteFeeTotalFromLines(
|
|
quote?.fees?.lines,
|
|
preferredCurrency: preferredCurrency,
|
|
);
|
|
}
|
|
|
|
Money? quoteFeeTotalFromLines(
|
|
List<FeeLine>? lines, {
|
|
String? preferredCurrency,
|
|
}) {
|
|
if (lines == null || lines.isEmpty) return null;
|
|
|
|
final normalizedPreferred = _normalizeCurrency(preferredCurrency);
|
|
final totalsByCurrency = <String, double>{};
|
|
|
|
for (final line in lines) {
|
|
final money = line.amount;
|
|
if (money == null) continue;
|
|
|
|
final currency = _normalizeCurrency(money.currency);
|
|
if (currency == null) continue;
|
|
|
|
final amount = parseMoneyAmount(money.amount, fallback: double.nan);
|
|
if (amount.isNaN) continue;
|
|
|
|
final sign = _lineSign(line.side);
|
|
final signedAmount = sign * amount.abs();
|
|
totalsByCurrency[currency] =
|
|
(totalsByCurrency[currency] ?? 0) + signedAmount;
|
|
}
|
|
|
|
if (totalsByCurrency.isEmpty) return null;
|
|
|
|
final selectedCurrency =
|
|
normalizedPreferred != null &&
|
|
totalsByCurrency.containsKey(normalizedPreferred)
|
|
? normalizedPreferred
|
|
: totalsByCurrency.keys.first;
|
|
final total = totalsByCurrency[selectedCurrency];
|
|
if (total == null) return null;
|
|
|
|
return Money(amount: amountToString(total), currency: selectedCurrency);
|
|
}
|
|
|
|
List<Money> aggregateMoneyByCurrency(Iterable<Money?> values) {
|
|
final totals = <String, double>{};
|
|
for (final value in values) {
|
|
if (value == null) continue;
|
|
|
|
final currency = _normalizeCurrency(value.currency);
|
|
if (currency == null) continue;
|
|
|
|
final amount = parseMoneyAmount(value.amount, fallback: double.nan);
|
|
if (amount.isNaN) continue;
|
|
|
|
totals[currency] = (totals[currency] ?? 0) + amount;
|
|
}
|
|
|
|
return totals.entries
|
|
.map(
|
|
(entry) =>
|
|
Money(amount: amountToString(entry.value), currency: entry.key),
|
|
)
|
|
.toList();
|
|
}
|
|
|
|
double _lineSign(String? side) {
|
|
final normalized = side?.trim().toLowerCase() ?? '';
|
|
switch (normalized) {
|
|
case 'entry_side_credit':
|
|
case 'credit':
|
|
return -1;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
String? _normalizeCurrency(String? currency) {
|
|
final normalized = currency?.trim().toUpperCase();
|
|
if (normalized == null || normalized.isEmpty) return null;
|
|
return normalized;
|
|
}
|