[infra][rebuild]Merge pull request 'Orchestration / payments v2' (#554) from pqpov2-547 into main
All checks were successful
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/billing_documents Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/discovery Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/gateway_mntx Pipeline was successful
ci/woodpecker/push/gateway_chain Pipeline was successful
ci/woodpecker/push/gateway_tgsettle Pipeline was successful
ci/woodpecker/push/gateway_tron Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_methods Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/payments_quotation Pipeline was successful
All checks were successful
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/billing_documents Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/discovery Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/gateway_mntx Pipeline was successful
ci/woodpecker/push/gateway_chain Pipeline was successful
ci/woodpecker/push/gateway_tgsettle Pipeline was successful
ci/woodpecker/push/gateway_tron Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_methods Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/payments_quotation Pipeline was successful
[infra][rebuild]Reviewed-on: #554
This commit was merged in pull request #554.
This commit is contained in:
@@ -7,7 +7,7 @@ import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/asset_type_field.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/description.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/employees_loading_indicator.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/ledger_fields.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/ledger/fields.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/managed_wallet_fields.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/name.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/owner.dart';
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/currency.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
|
||||
|
||||
DropdownMenuItem<Currency> currencyItem(Currency currency) => DropdownMenuItem(
|
||||
value: currency,
|
||||
child: Text(currencyCodeToString(currency)),
|
||||
);
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/currency.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/constants.dart';
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/add/ledger/currency_item.dart';
|
||||
import 'package:pweb/utils/text_field_styles.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
@@ -24,10 +24,8 @@ class LedgerFields extends StatelessWidget {
|
||||
initialValue: currency,
|
||||
decoration: getInputDecoration(context, AppLocalizations.of(context)!.currency, true),
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: ledgerCurrencyDefault,
|
||||
child: Text(currencyCodeToString(ledgerCurrencyDefault)),
|
||||
),
|
||||
currencyItem(ledgerCurrencyDefault),
|
||||
currencyItem(managedCurrencyDefault),
|
||||
],
|
||||
onChanged: onCurrencyChanged,
|
||||
);
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/payment.dart';
|
||||
import 'package:pshared/utils/payment/quote_helpers.dart';
|
||||
|
||||
import 'package:pweb/pages/report/details/summary_card/amount_headline.dart';
|
||||
import 'package:pweb/pages/report/details/summary_card/copy_id.dart';
|
||||
@@ -13,7 +14,6 @@ import 'package:pweb/utils/clipboard.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class PaymentSummaryCard extends StatelessWidget {
|
||||
final Payment payment;
|
||||
final VoidCallback? onDownloadAct;
|
||||
@@ -31,11 +31,11 @@ class PaymentSummaryCard extends StatelessWidget {
|
||||
final status = statusFromPayment(payment);
|
||||
final dateLabel = formatDateLabel(context, resolvePaymentDate(payment));
|
||||
|
||||
final primaryAmount = payment.lastQuote?.debitAmount ??
|
||||
payment.lastQuote?.expectedSettlementAmount;
|
||||
final toAmount = payment.lastQuote?.expectedSettlementAmount;
|
||||
final fee = payment.lastQuote?.expectedFeeTotal ??
|
||||
payment.lastQuote?.networkFee?.networkFee;
|
||||
final primaryAmount =
|
||||
payment.lastQuote?.amounts?.sourceDebitTotal ??
|
||||
payment.lastQuote?.amounts?.destinationSettlement;
|
||||
final toAmount = payment.lastQuote?.amounts?.destinationSettlement;
|
||||
final fee = quoteFeeTotal(payment.lastQuote);
|
||||
|
||||
final amountLabel = formatMoney(primaryAmount);
|
||||
final toAmountLabel = formatMoney(toAmount);
|
||||
@@ -108,11 +108,8 @@ class PaymentSummaryCard extends StatelessWidget {
|
||||
child: CopyableId(
|
||||
label: loc.paymentIdLabel,
|
||||
value: paymentRef,
|
||||
onCopy: () => copyToClipboard(
|
||||
context,
|
||||
paymentRef,
|
||||
loc.paymentIdCopied,
|
||||
),
|
||||
onCopy: () =>
|
||||
copyToClipboard(context, paymentRef, loc.paymentIdCopied),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -2,19 +2,20 @@ import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:pshared/models/money.dart';
|
||||
import 'package:pshared/models/payment/payment.dart';
|
||||
import 'package:pshared/models/payment/quote/quote.dart';
|
||||
import 'package:pshared/models/payment/quote/status_type.dart';
|
||||
import 'package:pshared/models/payment/wallet.dart';
|
||||
import 'package:pshared/provider/payment/multiple/provider.dart';
|
||||
import 'package:pshared/provider/payment/multiple/quotation.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
import 'package:pshared/utils/money.dart';
|
||||
import 'package:pshared/utils/payment/quote_helpers.dart';
|
||||
|
||||
import 'package:pweb/models/payment/multiple_payouts/csv_row.dart';
|
||||
import 'package:pweb/models/payment/multiple_payouts/state.dart';
|
||||
import 'package:pweb/utils/payment/multiple_csv_parser.dart';
|
||||
import 'package:pweb/utils/payment/multiple_intent_builder.dart';
|
||||
|
||||
|
||||
class MultiplePayoutsProvider extends ChangeNotifier {
|
||||
final MultipleCsvParser _csvParser;
|
||||
final MultipleIntentBuilder _intentBuilder;
|
||||
@@ -34,10 +35,7 @@ class MultiplePayoutsProvider extends ChangeNotifier {
|
||||
}) : _csvParser = csvParser ?? MultipleCsvParser(),
|
||||
_intentBuilder = intentBuilder ?? MultipleIntentBuilder();
|
||||
|
||||
void update(
|
||||
MultiQuotationProvider quotation,
|
||||
MultiPaymentProvider payment,
|
||||
) {
|
||||
void update(MultiQuotationProvider quotation, MultiPaymentProvider payment) {
|
||||
_bindQuotation(quotation);
|
||||
_payment = payment;
|
||||
}
|
||||
@@ -60,7 +58,9 @@ class MultiplePayoutsProvider extends ChangeNotifier {
|
||||
if (quotation.isLoading) return QuoteStatusType.loading;
|
||||
if (quotation.error != null) return QuoteStatusType.error;
|
||||
if (quotation.quotation == null) return QuoteStatusType.missing;
|
||||
if (_isQuoteExpired(quotation.quoteExpiresAt)) return QuoteStatusType.expired;
|
||||
if (_isQuoteExpired(quotation.quoteExpiresAt)) {
|
||||
return QuoteStatusType.expired;
|
||||
}
|
||||
return QuoteStatusType.active;
|
||||
}
|
||||
|
||||
@@ -78,10 +78,10 @@ class MultiplePayoutsProvider extends ChangeNotifier {
|
||||
|
||||
Money? aggregateDebitAmountFor(Wallet? sourceWallet) {
|
||||
if (_rows.isEmpty) return null;
|
||||
return _moneyForSourceCurrency(
|
||||
_quotation?.quotation?.aggregate?.debitAmounts,
|
||||
sourceWallet,
|
||||
final totals = aggregateMoneyByCurrency(
|
||||
_quoteItems().map((quote) => quote.amounts?.sourceDebitTotal),
|
||||
);
|
||||
return _moneyForSourceCurrency(totals, sourceWallet);
|
||||
}
|
||||
|
||||
Money? get requestedSentAmount {
|
||||
@@ -99,18 +99,16 @@ class MultiplePayoutsProvider extends ChangeNotifier {
|
||||
|
||||
Money? aggregateSettlementAmountFor(Wallet? sourceWallet) {
|
||||
if (_rows.isEmpty) return null;
|
||||
return _moneyForSourceCurrency(
|
||||
_quotation?.quotation?.aggregate?.expectedSettlementAmounts,
|
||||
sourceWallet,
|
||||
final totals = aggregateMoneyByCurrency(
|
||||
_quoteItems().map((quote) => quote.amounts?.destinationSettlement),
|
||||
);
|
||||
return _moneyForSourceCurrency(totals, sourceWallet);
|
||||
}
|
||||
|
||||
Money? aggregateFeeAmountFor(Wallet? sourceWallet) {
|
||||
if (_rows.isEmpty) return null;
|
||||
return _moneyForSourceCurrency(
|
||||
_quotation?.quotation?.aggregate?.expectedFeeTotals,
|
||||
sourceWallet,
|
||||
);
|
||||
final totals = aggregateMoneyByCurrency(_quoteItems().map(quoteFeeTotal));
|
||||
return _moneyForSourceCurrency(totals, sourceWallet);
|
||||
}
|
||||
|
||||
double? aggregateFeePercentFor(Wallet? sourceWallet) {
|
||||
@@ -256,10 +254,7 @@ class MultiplePayoutsProvider extends ChangeNotifier {
|
||||
};
|
||||
}
|
||||
|
||||
Money? _moneyForSourceCurrency(
|
||||
List<Money>? values,
|
||||
Wallet? sourceWallet,
|
||||
) {
|
||||
Money? _moneyForSourceCurrency(List<Money>? values, Wallet? sourceWallet) {
|
||||
if (values == null || values.isEmpty) return null;
|
||||
|
||||
if (sourceWallet != null) {
|
||||
@@ -274,6 +269,9 @@ class MultiplePayoutsProvider extends ChangeNotifier {
|
||||
return values.first;
|
||||
}
|
||||
|
||||
List<PaymentQuote> _quoteItems() =>
|
||||
_quotation?.quotation?.items ?? const <PaymentQuote>[];
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_quotation?.removeListener(_onQuotationChanged);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:pshared/models/money.dart';
|
||||
import 'package:pshared/models/payment/asset.dart';
|
||||
import 'package:pshared/models/payment/chain_network.dart';
|
||||
import 'package:pshared/models/payment/fees/treatment.dart';
|
||||
import 'package:pshared/models/payment/intent.dart';
|
||||
import 'package:pshared/models/payment/kind.dart';
|
||||
import 'package:pshared/models/payment/methods/card.dart';
|
||||
@@ -12,7 +13,6 @@ import 'package:pshared/utils/payment/fx_helpers.dart';
|
||||
|
||||
import 'package:pweb/models/payment/multiple_payouts/csv_row.dart';
|
||||
|
||||
|
||||
class MultipleIntentBuilder {
|
||||
static const String _currency = 'RUB';
|
||||
|
||||
@@ -35,32 +35,27 @@ class MultipleIntentBuilder {
|
||||
);
|
||||
|
||||
return rows
|
||||
.map(
|
||||
(row) {
|
||||
final amount = Money(amount: row.amount, currency: _currency);
|
||||
return PaymentIntent(
|
||||
kind: PaymentKind.payout,
|
||||
source: ManagedWalletPaymentMethod(
|
||||
managedWalletRef: sourceWallet.id,
|
||||
asset: sourceAsset,
|
||||
),
|
||||
destination: CardPaymentMethod(
|
||||
pan: row.pan,
|
||||
firstName: row.firstName,
|
||||
lastName: row.lastName,
|
||||
expMonth: row.expMonth,
|
||||
expYear: row.expYear,
|
||||
),
|
||||
amount: amount,
|
||||
settlementMode: SettlementMode.fixReceived,
|
||||
settlementCurrency: FxIntentHelper.resolveSettlementCurrency(
|
||||
amount: amount,
|
||||
fx: fxIntent,
|
||||
),
|
||||
fx: fxIntent,
|
||||
);
|
||||
},
|
||||
)
|
||||
.map((row) {
|
||||
final amount = Money(amount: row.amount, currency: _currency);
|
||||
return PaymentIntent(
|
||||
kind: PaymentKind.payout,
|
||||
source: ManagedWalletPaymentMethod(
|
||||
managedWalletRef: sourceWallet.id,
|
||||
asset: sourceAsset,
|
||||
),
|
||||
destination: CardPaymentMethod(
|
||||
pan: row.pan,
|
||||
firstName: row.firstName,
|
||||
lastName: row.lastName,
|
||||
expMonth: row.expMonth,
|
||||
expYear: row.expYear,
|
||||
),
|
||||
amount: amount,
|
||||
feeTreatment: FeeTreatment.addToSource,
|
||||
settlementMode: SettlementMode.fixReceived,
|
||||
fx: fxIntent,
|
||||
);
|
||||
})
|
||||
.toList(growable: false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import 'package:pshared/utils/money.dart';
|
||||
|
||||
import 'package:pweb/models/payment/payment_state.dart';
|
||||
|
||||
|
||||
OperationItem mapPaymentToOperation(Payment payment) {
|
||||
final debit = payment.lastQuote?.debitAmount;
|
||||
final settlement = payment.lastQuote?.expectedSettlementAmount;
|
||||
final debit = payment.lastQuote?.amounts?.sourceDebitTotal;
|
||||
final settlement = payment.lastQuote?.amounts?.destinationSettlement;
|
||||
final amountMoney = debit ?? settlement;
|
||||
|
||||
final amount = parseMoneyAmount(amountMoney?.amount);
|
||||
@@ -18,18 +17,17 @@ OperationItem mapPaymentToOperation(Payment payment) {
|
||||
: parseMoneyAmount(settlement.amount);
|
||||
final toCurrency = settlement?.currency ?? currency;
|
||||
|
||||
final payId = _firstNonEmpty([
|
||||
payment.paymentRef,
|
||||
payment.idempotencyKey,
|
||||
]) ??
|
||||
'-';
|
||||
final name = _firstNonEmpty([
|
||||
final payId =
|
||||
_firstNonEmpty([payment.paymentRef, payment.idempotencyKey]) ?? '-';
|
||||
final name =
|
||||
_firstNonEmpty([
|
||||
payment.lastQuote?.quoteRef,
|
||||
payment.paymentRef,
|
||||
payment.idempotencyKey,
|
||||
]) ??
|
||||
'-';
|
||||
final comment = _firstNonEmpty([
|
||||
final comment =
|
||||
_firstNonEmpty([
|
||||
payment.failureReason,
|
||||
payment.failureCode,
|
||||
payment.state,
|
||||
@@ -72,17 +70,17 @@ DateTime resolvePaymentDate(Payment payment) {
|
||||
|
||||
final expiresAt = payment.lastQuote?.fxQuote?.expiresAtUnixMs;
|
||||
if (expiresAt != null && expiresAt > 0) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(expiresAt, isUtc: true).toLocal();
|
||||
return DateTime.fromMillisecondsSinceEpoch(
|
||||
expiresAt,
|
||||
isUtc: true,
|
||||
).toLocal();
|
||||
}
|
||||
|
||||
return DateTime.fromMillisecondsSinceEpoch(0);
|
||||
}
|
||||
|
||||
String? paymentIdFromOperation(OperationItem operation) {
|
||||
final candidates = [
|
||||
operation.paymentRef,
|
||||
operation.payId,
|
||||
];
|
||||
final candidates = [operation.paymentRef, operation.payId];
|
||||
for (final candidate in candidates) {
|
||||
final trimmed = candidate?.trim();
|
||||
if (trimmed != null && trimmed.isNotEmpty && trimmed != '-') {
|
||||
|
||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 2.6.0+507
|
||||
version: 3.0.0+605
|
||||
|
||||
environment:
|
||||
sdk: ^3.8.1
|
||||
@@ -52,7 +52,7 @@ dependencies:
|
||||
share_plus: ^12.0.1
|
||||
collection: ^1.18.0
|
||||
flutter_timezone: ^5.0.1
|
||||
json_annotation: ^4.10.0
|
||||
json_annotation: ^4.11.0
|
||||
go_router: ^17.0.0
|
||||
jovial_svg: ^1.1.23
|
||||
cached_network_image: ^3.4.1
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pweb/app/app.dart';
|
||||
import 'package:pweb/providers/account.dart';
|
||||
import 'package:pweb/providers/locale.dart';
|
||||
import 'package:pshared/provider/account.dart';
|
||||
import 'package:pshared/provider/locale.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const PayApp());
|
||||
testWidgets('PayApp builds with required providers', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<LocaleProvider>(
|
||||
create: (_) => PwebLocaleProvider(null),
|
||||
),
|
||||
ChangeNotifierProxyProvider<LocaleProvider, AccountProvider>(
|
||||
create: (_) => PwebAccountProvider(),
|
||||
update: (context, localeProvider, provider) =>
|
||||
provider!..updateProvider(localeProvider),
|
||||
),
|
||||
],
|
||||
child: const PayApp(),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(PayApp), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user