Files
sendico/frontend/pshared/lib/utils/payment/quote_helpers.dart

131 lines
3.5 KiB
Dart

import 'package:money2/money2.dart';
import 'package:pshared/models/payment/fees/line.dart';
import 'package:pshared/models/payment/quote/quote.dart';
import 'package:pshared/utils/currency.dart';
Money? quoteFeeTotal(PaymentQuote? quote) {
return quoteFeeTotalFromLines(
quote?.fees?.lines,
preferredCurrency:
quote?.amounts?.sourcePrincipal?.currency.isoCode ??
quote?.amounts?.sourceDebitTotal?.currency.isoCode,
);
}
Money? quoteSourceDebitTotal(
PaymentQuote? quote, {
String? preferredSourceCurrency,
}) {
final sourceDebitTotal = quote?.amounts?.sourceDebitTotal;
final preferredCurrency = _normalizeCurrency(
preferredSourceCurrency ??
quote?.amounts?.sourcePrincipal?.currency.isoCode,
);
if (sourceDebitTotal == null) {
return _rebuildSourceDebitTotal(
quote,
preferredSourceCurrency: preferredCurrency,
);
}
if (preferredCurrency == null ||
_normalizeCurrency(sourceDebitTotal.currency.isoCode) ==
preferredCurrency) {
return sourceDebitTotal;
}
final rebuilt = _rebuildSourceDebitTotal(
quote,
preferredSourceCurrency: preferredCurrency,
);
return rebuilt ?? sourceDebitTotal;
}
Money? quoteFeeTotalFromLines(
List<FeeLine>? lines, {
String? preferredCurrency,
}) {
if (lines == null || lines.isEmpty) return null;
final normalizedPreferred = _normalizeCurrency(preferredCurrency);
final totalsByCurrency = <String, Money>{};
for (final line in lines) {
final parsedAmount = line.amount;
if (parsedAmount == null) continue;
final currencyCode = parsedAmount.currency.isoCode;
final signedAmount = _isCreditLine(line.side) ? -parsedAmount : parsedAmount;
final current = totalsByCurrency[currencyCode];
totalsByCurrency[currencyCode] = current == null
? signedAmount
: current + signedAmount;
}
if (totalsByCurrency.isEmpty) return null;
final selectedCurrency =
normalizedPreferred != null &&
totalsByCurrency.containsKey(normalizedPreferred)
? normalizedPreferred
: totalsByCurrency.keys.first;
return totalsByCurrency[selectedCurrency];
}
List<Money> aggregateMoneyByCurrency(Iterable<Money?> values) {
final totals = <String, Money>{};
for (final value in values) {
if (value == null) continue;
final currency = value.currency.isoCode;
final current = totals[currency];
totals[currency] = current == null ? value : current + value;
}
return totals.values.toList();
}
Money? _rebuildSourceDebitTotal(
PaymentQuote? quote, {
String? preferredSourceCurrency,
}) {
final principal = quote?.amounts?.sourcePrincipal;
if (principal == null) return null;
final principalCurrency = principal.currency.isoCode;
if (preferredSourceCurrency != null &&
principalCurrency != preferredSourceCurrency) {
return null;
}
var totalAmount = principal;
final fee = quoteFeeTotalFromLines(
quote?.fees?.lines,
preferredCurrency: principalCurrency,
);
if (fee != null && fee.currency.isoCode == principalCurrency) {
totalAmount += fee;
}
return totalAmount;
}
bool _isCreditLine(String? side) {
final normalized = side?.trim().toLowerCase() ?? '';
switch (normalized) {
case 'entry_side_credit':
case 'credit':
return true;
default:
return false;
}
}
String? _normalizeCurrency(String? currency) {
final normalized = currency?.trim();
if (normalized == null || normalized.isEmpty) return null;
return money2CurrencyFromCode(normalized)?.isoCode ?? normalized.toUpperCase();
}