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'; import 'package:pweb/models/report/operation/document.dart'; import 'package:pweb/utils/report/operations/document_rule.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, ]) ?? ''; final operationDocument = _resolveOperationDocument(payment); return OperationItem( status: statusFromPayment(payment), fileName: _extractFileName(payment.metadata), amount: amount, currency: currency, toAmount: toAmount, toCurrency: toCurrency, payId: payId, paymentRef: payment.paymentRef, operationRef: operationDocument?.operationRef, gatewayService: operationDocument?.gatewayService, cardNumber: null, name: name, date: resolvePaymentDate(payment), comment: comment, ); } OperationDocumentInfo? _resolveOperationDocument(Payment payment) { for (final operation in payment.operations) { final operationRef = operation.operationRef; final gatewayService = operation.gateway; if (operationRef == null || operationRef.isEmpty) continue; if (gatewayService == null || gatewayService.isEmpty) continue; if (!isOperationDocumentEligible(operation.code)) continue; return OperationDocumentInfo( operationRef: operationRef, gatewayService: gatewayService, ); } return null; } 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? metadata) { if (metadata == null || metadata.isEmpty) return null; return _firstNonEmpty([ metadata['upload_filename'], metadata['upload_file_name'], metadata['filename'], ]); } String? _firstNonEmpty(List values) { for (final value in values) { final trimmed = value?.trim(); if (trimmed != null && trimmed.isNotEmpty) return trimmed; } return null; }