payment recipient data

This commit is contained in:
Stephan D
2025-12-26 15:14:31 +01:00
parent 3836ff5ef3
commit 8adfab94b5
20 changed files with 442 additions and 68 deletions

View File

@@ -0,0 +1,41 @@
import 'package:json_annotation/json_annotation.dart';
part 'customer.g.dart';
@JsonSerializable()
class CustomerDTO {
final String id;
@JsonKey(name: 'first_name')
final String? firstName;
@JsonKey(name: 'middle_name')
final String? middleName;
@JsonKey(name: 'last_name')
final String? lastName;
final String? ip;
final String? zip;
final String? country;
final String? state;
final String? city;
final String? address;
const CustomerDTO({
required this.id,
this.firstName,
this.middleName,
this.lastName,
this.ip,
this.zip,
this.country,
this.state,
this.city,
this.address,
});
factory CustomerDTO.fromJson(Map<String, dynamic> json) => _$CustomerDTOFromJson(json);
Map<String, dynamic> toJson() => _$CustomerDTOToJson(this);
}

View File

@@ -1,6 +1,7 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:pshared/data/dto/payment/endpoint.dart';
import 'package:pshared/data/dto/payment/intent/customer.dart';
import 'package:pshared/data/dto/payment/intent/fx.dart';
import 'package:pshared/data/dto/payment/money.dart';
@@ -20,6 +21,7 @@ class PaymentIntentDTO {
final String? settlementMode;
final Map<String, String>? attributes;
final CustomerDTO? customer;
const PaymentIntentDTO({
this.kind,
@@ -29,6 +31,7 @@ class PaymentIntentDTO {
this.fx,
this.settlementMode,
this.attributes,
this.customer,
});
factory PaymentIntentDTO.fromJson(Map<String, dynamic> json) => _$PaymentIntentDTOFromJson(json);

View File

@@ -0,0 +1,33 @@
import 'package:pshared/data/dto/payment/intent/customer.dart';
import 'package:pshared/models/payment/customer.dart';
extension CustomerMapper on Customer {
CustomerDTO toDTO() => CustomerDTO(
id: id,
firstName: firstName,
middleName: middleName,
lastName: lastName,
ip: ip,
zip: zip,
country: country,
state: state,
city: city,
address: address,
);
}
extension CustomerDTOMapper on CustomerDTO {
Customer toDomain() => Customer(
id: id,
firstName: firstName,
middleName: middleName,
lastName: lastName,
ip: ip,
zip: zip,
country: country,
state: state,
city: city,
address: address,
);
}

View File

@@ -1,30 +1,34 @@
import 'package:pshared/data/dto/payment/intent/payment.dart';
import 'package:pshared/data/mapper/payment/payment.dart';
import 'package:pshared/data/mapper/payment/enums.dart';
import 'package:pshared/data/mapper/payment/intent/customer.dart';
import 'package:pshared/data/mapper/payment/intent/fx.dart';
import 'package:pshared/data/mapper/payment/money.dart';
import 'package:pshared/models/payment/intent.dart';
extension PaymentIntentMapper on PaymentIntent {
PaymentIntentDTO toDTO() => PaymentIntentDTO(
kind: paymentKindToValue(kind),
source: source?.toDTO(),
destination: destination?.toDTO(),
amount: amount?.toDTO(),
fx: fx?.toDTO(),
settlementMode: settlementModeToValue(settlementMode),
attributes: attributes,
);
kind: paymentKindToValue(kind),
source: source?.toDTO(),
destination: destination?.toDTO(),
amount: amount?.toDTO(),
fx: fx?.toDTO(),
settlementMode: settlementModeToValue(settlementMode),
attributes: attributes,
customer: customer?.toDTO(),
);
}
extension PaymentIntentDTOMapper on PaymentIntentDTO {
PaymentIntent toDomain() => PaymentIntent(
kind: paymentKindFromValue(kind),
source: source?.toDomain(),
destination: destination?.toDomain(),
amount: amount?.toDomain(),
fx: fx?.toDomain(),
settlementMode: settlementModeFromValue(settlementMode),
attributes: attributes,
);
kind: paymentKindFromValue(kind),
source: source?.toDomain(),
destination: destination?.toDomain(),
amount: amount?.toDomain(),
fx: fx?.toDomain(),
settlementMode: settlementModeFromValue(settlementMode),
attributes: attributes,
customer: customer?.toDomain(),
);
}

View File

@@ -0,0 +1,25 @@
class Customer {
final String id;
final String? firstName;
final String? middleName;
final String? lastName;
final String? ip;
final String? zip;
final String? country;
final String? state;
final String? city;
final String? address;
const Customer({
required this.id,
this.firstName,
this.middleName,
this.lastName,
this.ip,
this.zip,
this.country,
this.state,
this.city,
this.address,
});
}

View File

@@ -1,5 +1,6 @@
import 'package:pshared/models/payment/fx/intent.dart';
import 'package:pshared/models/payment/kind.dart';
import 'package:pshared/models/payment/customer.dart';
import 'package:pshared/models/payment/methods/data.dart';
import 'package:pshared/models/payment/money.dart';
import 'package:pshared/models/payment/settlement_mode.dart';
@@ -13,6 +14,7 @@ class PaymentIntent {
final FxIntent? fx;
final SettlementMode settlementMode;
final Map<String, String>? attributes;
final Customer? customer;
const PaymentIntent({
this.kind = PaymentKind.unspecified,
@@ -22,5 +24,6 @@ class PaymentIntent {
this.fx,
this.settlementMode = SettlementMode.unspecified,
this.attributes,
this.customer,
});
}

View File

@@ -8,18 +8,22 @@ import 'package:pshared/api/requests/payment/quote.dart';
import 'package:pshared/data/mapper/payment/intent/payment.dart';
import 'package:pshared/models/asset.dart';
import 'package:pshared/models/payment/currency_pair.dart';
import 'package:pshared/models/payment/customer.dart';
import 'package:pshared/models/payment/fx/intent.dart';
import 'package:pshared/models/payment/fx/side.dart';
import 'package:pshared/models/payment/kind.dart';
import 'package:pshared/models/payment/methods/managed_wallet.dart';
import 'package:pshared/models/payment/methods/type.dart';
import 'package:pshared/models/payment/money.dart';
import 'package:pshared/models/payment/settlement_mode.dart';
import 'package:pshared/models/payment/intent.dart';
import 'package:pshared/models/payment/quote.dart';
import 'package:pshared/models/recipient/recipient.dart';
import 'package:pshared/provider/organizations.dart';
import 'package:pshared/provider/payment/amount.dart';
import 'package:pshared/provider/payment/flow.dart';
import 'package:pshared/provider/payment/wallets.dart';
import 'package:pshared/provider/recipient/provider.dart';
import 'package:pshared/provider/recipient/pmethods.dart';
import 'package:pshared/provider/resource.dart';
import 'package:pshared/service/payment/quotation.dart';
@@ -36,12 +40,17 @@ class QuotationProvider extends ChangeNotifier {
PaymentAmountProvider payment,
WalletsProvider wallets,
PaymentFlowProvider flow,
RecipientsProvider recipients,
PaymentMethodsProvider methods,
) {
_organizations = venue;
final t = flow.selectedType;
final method = methods.methods.firstWhereOrNull((m) => m.type == t);
if ((wallets.selectedWallet != null) && (method != null)) {
final customer = _buildCustomer(
recipient: recipients.currentObject,
method: method,
);
getQuotation(PaymentIntent(
kind: PaymentKind.payout,
amount: Money(
@@ -61,6 +70,7 @@ class QuotationProvider extends ChangeNotifier {
side: FxSide.sellBaseBuyQuote,
),
settlementMode: payment.payerCoversFee ? SettlementMode.fixReceived : SettlementMode.fixSource,
customer: customer,
));
}
}
@@ -108,3 +118,42 @@ class QuotationProvider extends ChangeNotifier {
notifyListeners();
}
}
Customer? _buildCustomer({
required Recipient? recipient,
required PaymentMethod method,
}) {
final recipientId = (recipient?.id ?? method.recipientRef).trim();
if (recipientId.isEmpty) {
return null;
}
var firstName = '';
var lastName = '';
final cardData = method.cardData;
if (cardData != null) {
firstName = cardData.firstName.trim();
lastName = cardData.lastName.trim();
}
if ((firstName.isEmpty || lastName.isEmpty) && recipient != null) {
final parts = recipient.name.trim().split(RegExp(r'\s+'));
if (parts.isNotEmpty && firstName.isEmpty) {
firstName = parts.first;
}
if (parts.length > 1 && lastName.isEmpty) {
lastName = parts.sublist(1).join(' ');
}
}
if (lastName.isEmpty) {
lastName = firstName;
}
return Customer(
id: recipientId,
firstName: firstName.isEmpty ? null : firstName,
lastName: lastName.isEmpty ? null : lastName,
country: cardData?.country,
);
}

View File

@@ -128,9 +128,10 @@ class _PaymentPageState extends State<PaymentPage> {
ChangeNotifierProvider(
create: (_) => PaymentAmountProvider(),
),
ChangeNotifierProxyProvider5<OrganizationsProvider, PaymentAmountProvider, WalletsProvider, PaymentFlowProvider, PaymentMethodsProvider, QuotationProvider>(
ChangeNotifierProxyProvider6<OrganizationsProvider, PaymentAmountProvider, WalletsProvider, PaymentFlowProvider, RecipientsProvider, PaymentMethodsProvider, QuotationProvider>(
create: (_) => QuotationProvider(),
update: (_, organization, payment, wallet, flow, methods, provider) => provider!..update(organization, payment, wallet, flow, methods),
update: (_, organization, payment, wallet, flow, recipients, methods, provider) =>
provider!..update(organization, payment, wallet, flow, recipients, methods),
),
ChangeNotifierProxyProvider2<OrganizationsProvider, QuotationProvider, PaymentProvider>(
create: (_) => PaymentProvider(),