112 lines
3.2 KiB
Dart
112 lines
3.2 KiB
Dart
import 'package:pshared/models/payment/operation.dart';
|
|
import 'package:pshared/models/payment/payment.dart';
|
|
import 'package:pshared/models/payment/state.dart';
|
|
import 'package:pshared/models/payment/status.dart';
|
|
import 'package:pshared/utils/money.dart';
|
|
|
|
|
|
OperationItem mapPaymentToOperation(Payment payment) {
|
|
final debit = payment.lastQuote?.amounts?.sourceDebitTotal;
|
|
final settlement = payment.lastQuote?.amounts?.destinationSettlement;
|
|
final amountMoney = debit ?? settlement;
|
|
|
|
final amount = parseMoneyAmount(amountMoney?.amount);
|
|
final currency = amountMoney?.currency ?? '';
|
|
final toAmount = settlement == null
|
|
? amount
|
|
: parseMoneyAmount(settlement.amount);
|
|
final toCurrency = settlement?.currency ?? currency;
|
|
|
|
final payId =
|
|
_firstNonEmpty([payment.paymentRef, payment.idempotencyKey]) ?? '-';
|
|
final name =
|
|
_firstNonEmpty([
|
|
payment.lastQuote?.quoteRef,
|
|
payment.paymentRef,
|
|
payment.idempotencyKey,
|
|
]) ??
|
|
'-';
|
|
final comment =
|
|
_firstNonEmpty([
|
|
payment.failureReason,
|
|
payment.failureCode,
|
|
payment.state,
|
|
]) ??
|
|
'';
|
|
|
|
return OperationItem(
|
|
status: statusFromPayment(payment),
|
|
fileName: _extractFileName(payment.metadata),
|
|
amount: amount,
|
|
currency: currency,
|
|
toAmount: toAmount,
|
|
toCurrency: toCurrency,
|
|
payId: payId,
|
|
paymentRef: payment.paymentRef,
|
|
cardNumber: null,
|
|
name: name,
|
|
date: resolvePaymentDate(payment),
|
|
comment: comment,
|
|
);
|
|
}
|
|
|
|
OperationStatus statusFromPayment(Payment payment) {
|
|
switch (payment.orchestrationState) {
|
|
case PaymentOrchestrationState.failed:
|
|
return OperationStatus.error;
|
|
case PaymentOrchestrationState.settled:
|
|
return OperationStatus.success;
|
|
case PaymentOrchestrationState.needsAttention:
|
|
return OperationStatus.needsAttention;
|
|
case PaymentOrchestrationState.created:
|
|
return OperationStatus.pending;
|
|
case PaymentOrchestrationState.executing:
|
|
return OperationStatus.processing;
|
|
case PaymentOrchestrationState.unspecified:
|
|
return OperationStatus.pending;
|
|
}
|
|
}
|
|
|
|
DateTime resolvePaymentDate(Payment payment) {
|
|
final createdAt = payment.createdAt;
|
|
if (createdAt != null) return createdAt.toLocal();
|
|
|
|
final expiresAt = payment.lastQuote?.fxQuote?.expiresAtUnixMs;
|
|
if (expiresAt != null && expiresAt > 0) {
|
|
return DateTime.fromMillisecondsSinceEpoch(
|
|
expiresAt,
|
|
isUtc: true,
|
|
).toLocal();
|
|
}
|
|
|
|
return DateTime.fromMillisecondsSinceEpoch(0);
|
|
}
|
|
|
|
String? paymentIdFromOperation(OperationItem operation) {
|
|
final candidates = [operation.paymentRef, operation.payId];
|
|
for (final candidate in candidates) {
|
|
final trimmed = candidate?.trim();
|
|
if (trimmed != null && trimmed.isNotEmpty && trimmed != '-') {
|
|
return trimmed;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
String? _extractFileName(Map<String, String>? metadata) {
|
|
if (metadata == null || metadata.isEmpty) return null;
|
|
return _firstNonEmpty([
|
|
metadata['upload_filename'],
|
|
metadata['upload_file_name'],
|
|
metadata['filename'],
|
|
]);
|
|
}
|
|
|
|
String? _firstNonEmpty(List<String?> values) {
|
|
for (final value in values) {
|
|
final trimmed = value?.trim();
|
|
if (trimmed != null && trimmed.isNotEmpty) return trimmed;
|
|
}
|
|
return null;
|
|
}
|