ledger top up functionality and few small fixes for project architechture and design
This commit is contained in:
115
frontend/pweb/lib/utils/payment/page_handlers.dart
Normal file
115
frontend/pweb/lib/utils/payment/page_handlers.dart
Normal file
@@ -0,0 +1,115 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/methods/ledger.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/provider/payment/flow.dart';
|
||||
import 'package:pshared/provider/payment/provider.dart';
|
||||
import 'package:pshared/provider/payment/quotation/quotation.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
|
||||
import 'package:pweb/app/router/payout_routes.dart';
|
||||
import 'package:pweb/widgets/sidebar/destinations.dart';
|
||||
import 'package:pweb/widgets/dialogs/payment_status_dialog.dart';
|
||||
import 'package:pweb/controllers/payments/page.dart';
|
||||
import 'package:pweb/controllers/payments/page_ui.dart';
|
||||
import 'package:pweb/controllers/payouts/payout_verification.dart';
|
||||
import 'package:pweb/utils/payment/verification_flow.dart';
|
||||
|
||||
|
||||
void initializePaymentPage(
|
||||
BuildContext context,
|
||||
PaymentType? initialPaymentType, {
|
||||
String? destinationLedgerAccountRef,
|
||||
}) {
|
||||
final flowProvider = context.read<PaymentFlowProvider>();
|
||||
final recipientsProvider = context.read<RecipientsProvider>();
|
||||
|
||||
flowProvider.setPreferredType(initialPaymentType);
|
||||
|
||||
final destinationRef = destinationLedgerAccountRef?.trim();
|
||||
if (destinationRef != null && destinationRef.isNotEmpty) {
|
||||
recipientsProvider.setCurrentObject(null);
|
||||
flowProvider.setPreferredType(PaymentType.ledger);
|
||||
flowProvider.setManualPaymentData(
|
||||
LedgerPaymentMethod(ledgerAccountRef: destinationRef),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
flowProvider.setManualPaymentData(null);
|
||||
}
|
||||
|
||||
void handleSearchChanged(PaymentPageUiController uiController, String query) {
|
||||
uiController.setQuery(query);
|
||||
}
|
||||
|
||||
void handleRecipientSelected(
|
||||
BuildContext context,
|
||||
PaymentPageUiController uiController,
|
||||
Recipient recipient,
|
||||
) {
|
||||
final recipientProvider = context.read<RecipientsProvider>();
|
||||
recipientProvider.setCurrentObject(recipient.id);
|
||||
uiController.clearSearch();
|
||||
}
|
||||
|
||||
void handleRecipientCleared(
|
||||
BuildContext context,
|
||||
PaymentPageUiController uiController,
|
||||
) {
|
||||
final recipientProvider = context.read<RecipientsProvider>();
|
||||
recipientProvider.setCurrentObject(null);
|
||||
uiController.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> handleSendPayment({
|
||||
required State state,
|
||||
required PayoutDestination fallbackDestination,
|
||||
}) async {
|
||||
final context = state.context;
|
||||
final paymentProvider = context.read<PaymentProvider>();
|
||||
final quotationProvider = context.read<QuotationProvider>();
|
||||
final controller = context.read<PaymentPageController>();
|
||||
final verificationController = context.read<PayoutVerificationController>();
|
||||
if (paymentProvider.isLoading) return;
|
||||
final verificationContextKey =
|
||||
quotationProvider.quotation?.quoteRef ??
|
||||
quotationProvider.quotation?.idempotencyKey;
|
||||
|
||||
final verified = await runPayoutVerification(
|
||||
context: context,
|
||||
controller: verificationController,
|
||||
contextKey: verificationContextKey,
|
||||
);
|
||||
if (!verified || !state.mounted) return;
|
||||
|
||||
final isSuccess = await controller.sendPayment();
|
||||
if (!state.mounted) return;
|
||||
|
||||
await showPaymentStatusDialog(context, isSuccess: isSuccess);
|
||||
if (!state.mounted) return;
|
||||
|
||||
if (isSuccess) {
|
||||
controller.handleSuccess();
|
||||
context.goToPayout(fallbackDestination);
|
||||
}
|
||||
}
|
||||
|
||||
void handleAddRecipient(BuildContext context) {
|
||||
final recipients = context.read<RecipientsProvider>();
|
||||
recipients.setCurrentObject(null);
|
||||
context.pushToPayout(PayoutDestination.addrecipient);
|
||||
}
|
||||
|
||||
void handleAddPaymentMethod(BuildContext context) {
|
||||
final recipients = context.read<RecipientsProvider>();
|
||||
final recipient = recipients.currentObject;
|
||||
if (recipient == null) return;
|
||||
recipients.setCurrentObject(recipient.id);
|
||||
context.pushNamed(PayoutRoutes.editRecipient);
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
import 'package:pshared/models/payment/operation_document.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';
|
||||
|
||||
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;
|
||||
@@ -55,7 +56,7 @@ OperationItem mapPaymentToOperation(Payment payment) {
|
||||
);
|
||||
}
|
||||
|
||||
OperationDocumentInfo? _resolveOperationDocument(Payment payment) {
|
||||
OperationDocumentRef? _resolveOperationDocument(Payment payment) {
|
||||
for (final operation in payment.operations) {
|
||||
final operationRef = operation.operationRef;
|
||||
final gatewayService = operation.gateway;
|
||||
@@ -64,7 +65,7 @@ OperationDocumentInfo? _resolveOperationDocument(Payment payment) {
|
||||
|
||||
if (!isOperationDocumentEligible(operation.code)) continue;
|
||||
|
||||
return OperationDocumentInfo(
|
||||
return OperationDocumentRef(
|
||||
operationRef: operationRef,
|
||||
gatewayService: gatewayService,
|
||||
);
|
||||
|
||||
112
frontend/pweb/lib/utils/report/source_filter.dart
Normal file
112
frontend/pweb/lib/utils/report/source_filter.dart
Normal file
@@ -0,0 +1,112 @@
|
||||
import 'package:pshared/models/payment/intent.dart';
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/methods/ledger.dart';
|
||||
import 'package:pshared/models/payment/methods/managed_wallet.dart';
|
||||
import 'package:pshared/models/payment/methods/wallet.dart';
|
||||
import 'package:pshared/models/payment/payment.dart';
|
||||
import 'package:pshared/models/payment/source_type.dart';
|
||||
|
||||
|
||||
bool paymentMatchesSource(
|
||||
Payment payment, {
|
||||
required PaymentSourceType sourceType,
|
||||
required String sourceRef,
|
||||
}) {
|
||||
final normalizedSourceRef = _normalize(sourceRef);
|
||||
if (normalizedSourceRef == null) return false;
|
||||
|
||||
final paymentSourceRef = _paymentSourceRef(payment, sourceType);
|
||||
return paymentSourceRef != null && paymentSourceRef == normalizedSourceRef;
|
||||
}
|
||||
|
||||
String? _paymentSourceRef(Payment payment, PaymentSourceType sourceType) {
|
||||
final fromIntent = _sourceRefFromIntent(payment.intent, sourceType);
|
||||
if (fromIntent != null) return fromIntent;
|
||||
return _sourceRefFromMetadata(payment.metadata, sourceType);
|
||||
}
|
||||
|
||||
String? _sourceRefFromIntent(
|
||||
PaymentIntent? intent,
|
||||
PaymentSourceType sourceType,
|
||||
) {
|
||||
final source = intent?.source;
|
||||
if (source == null) return null;
|
||||
|
||||
final fromIntentAttributes = _sourceRefFromMetadata(
|
||||
intent?.attributes,
|
||||
sourceType,
|
||||
);
|
||||
if (fromIntentAttributes != null) return fromIntentAttributes;
|
||||
|
||||
switch (sourceType) {
|
||||
case PaymentSourceType.wallet:
|
||||
return _walletSourceRef(source);
|
||||
case PaymentSourceType.ledger:
|
||||
return _ledgerSourceRef(source);
|
||||
}
|
||||
}
|
||||
|
||||
String? _walletSourceRef(PaymentMethodData source) {
|
||||
if (source is ManagedWalletPaymentMethod) {
|
||||
return _normalize(source.managedWalletRef) ??
|
||||
_sourceRefFromMetadata(source.metadata, PaymentSourceType.wallet);
|
||||
}
|
||||
if (source is WalletPaymentMethod) {
|
||||
return _normalize(source.walletId) ??
|
||||
_sourceRefFromMetadata(source.metadata, PaymentSourceType.wallet);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _ledgerSourceRef(PaymentMethodData source) {
|
||||
if (source is LedgerPaymentMethod) {
|
||||
return _normalize(source.ledgerAccountRef) ??
|
||||
_sourceRefFromMetadata(source.metadata, PaymentSourceType.ledger);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _sourceRefFromMetadata(
|
||||
Map<String, String>? metadata,
|
||||
PaymentSourceType sourceType,
|
||||
) {
|
||||
if (metadata == null || metadata.isEmpty) return null;
|
||||
|
||||
final keys = switch (sourceType) {
|
||||
PaymentSourceType.wallet => const <String>[
|
||||
'source_wallet_ref',
|
||||
'managed_wallet_ref',
|
||||
'wallet_ref',
|
||||
'wallet_id',
|
||||
'source_wallet_id',
|
||||
'source_wallet_user_id',
|
||||
'wallet_user_id',
|
||||
'wallet_user_ref',
|
||||
'wallet_number',
|
||||
'source_wallet_number',
|
||||
'source_managed_wallet_ref',
|
||||
'source_ref',
|
||||
],
|
||||
PaymentSourceType.ledger => const <String>[
|
||||
'source_ledger_account_ref',
|
||||
'ledger_account_ref',
|
||||
'source_account_code',
|
||||
'ledger_account_code',
|
||||
'account_code',
|
||||
'source_ref',
|
||||
],
|
||||
};
|
||||
|
||||
for (final key in keys) {
|
||||
final value = _normalize(metadata[key]);
|
||||
if (value != null) return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _normalize(String? value) {
|
||||
final normalized = value?.trim();
|
||||
if (normalized == null || normalized.isEmpty) return null;
|
||||
return normalized;
|
||||
}
|
||||
Reference in New Issue
Block a user