From 49b6961fd123f3156115dbbbdff51f6307d5c2db Mon Sep 17 00:00:00 2001 From: Eric Jinks <3147296+Jinksi@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:10:32 +1000 Subject: [PATCH 01/33] Add TS type assertion for disputes CSV export API response to fix type safety (#10008) Co-authored-by: Shendy <73803630+shendy-a8c@users.noreply.github.com> --- ...isputes-csv-export-response-type-assertion | 4 +++ client/disputes/index.tsx | 35 ++++++++++--------- 2 files changed, 23 insertions(+), 16 deletions(-) create mode 100644 changelog/fix-10007-disputes-csv-export-response-type-assertion diff --git a/changelog/fix-10007-disputes-csv-export-response-type-assertion b/changelog/fix-10007-disputes-csv-export-response-type-assertion new file mode 100644 index 00000000000..b578456ece2 --- /dev/null +++ b/changelog/fix-10007-disputes-csv-export-response-type-assertion @@ -0,0 +1,4 @@ +Significance: patch +Type: dev + +Add type assertion for disputes CSV export response to ensure type safety and fix TypeScript error diff --git a/client/disputes/index.tsx b/client/disputes/index.tsx index 6e8c4d2d61b..ad5e8258d7f 100644 --- a/client/disputes/index.tsx +++ b/client/disputes/index.tsx @@ -397,22 +397,25 @@ export const DisputesList = (): JSX.Element => { window.confirm( confirmMessage ) ) { try { - const { exported_disputes: exportedDisputes } = await apiFetch( - { - path: getDisputesCSV( { - userEmail, - locale, - dateAfter, - dateBefore, - dateBetween, - match, - filter, - statusIs, - statusIsNot, - } ), - method: 'POST', - } - ); + const { + exported_disputes: exportedDisputes, + } = await apiFetch< { + /** The total number of disputes that will be exported in the CSV. */ + exported_disputes: number; + } >( { + path: getDisputesCSV( { + userEmail, + locale, + dateAfter, + dateBefore, + dateBetween, + match, + filter, + statusIs, + statusIsNot, + } ), + method: 'POST', + } ); createNotice( 'success', From 96372477c893eeb6892c268b3893e944ec0aac9e Mon Sep 17 00:00:00 2001 From: Eric Jinks <3147296+Jinksi@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:15:00 +1000 Subject: [PATCH 02/33] =?UTF-8?q?Upgrade=20`@woocommerce/csv-export`=20to?= =?UTF-8?q?=20v1.10.0=20=E2=80=93=20fixes=20unnecessary=20escaping=20of=20?= =?UTF-8?q?negative=20values=20in=20CSV=20exports=20(#10028)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...303-upgrade-woocommerce-csv-export-package | 4 + package-lock.json | 83 ++++++++++--------- package.json | 4 +- 3 files changed, 49 insertions(+), 42 deletions(-) create mode 100644 changelog/fix-9303-upgrade-woocommerce-csv-export-package diff --git a/changelog/fix-9303-upgrade-woocommerce-csv-export-package b/changelog/fix-9303-upgrade-woocommerce-csv-export-package new file mode 100644 index 00000000000..db23bab80b2 --- /dev/null +++ b/changelog/fix-9303-upgrade-woocommerce-csv-export-package @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Upgrade `@woocommerce/csv-export` package to v1.10.0 – fixes unnecessary escaping of negative values in CSV exports that was preventing numerical analysis in spreadsheet applications diff --git a/package-lock.json b/package-lock.json index 083ed1adf12..1ddaf7a4ded 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "@typescript-eslint/parser": "4.15.2", "@woocommerce/api": "0.2.0", "@woocommerce/components": "12.3.0", - "@woocommerce/csv-export": "1.9.0", + "@woocommerce/csv-export": "1.10.0", "@woocommerce/currency": "4.3.0", "@woocommerce/date": "4.2.0", "@woocommerce/dependency-extraction-webpack-plugin": "2.2.0", @@ -10969,6 +10969,11 @@ "react-dom": ">=16.8.0" } }, + "node_modules/@woocommerce/components/node_modules/@types/node": { + "version": "16.18.122", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.122.tgz", + "integrity": "sha512-rF6rUBS80n4oK16EW8nE75U+9fw0SSUgoPtWSvHhPXdT7itbvmS7UjB/jyM8i3AkvI6yeSM5qCwo+xN0npGDHg==" + }, "node_modules/@woocommerce/components/node_modules/@types/react": { "version": "17.0.80", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.80.tgz", @@ -10989,6 +10994,19 @@ "@types/wordpress__rich-text": "*" } }, + "node_modules/@woocommerce/components/node_modules/@woocommerce/csv-export": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@woocommerce/csv-export/-/csv-export-1.9.0.tgz", + "integrity": "sha512-fo1byPYTljic8ml5HxvxafdhrYc8pMYXqjlGZtZ9xNxWL2yffXJvskbcb7Kj6JSQhHT3BCh/5PlczJci9vQuDQ==", + "dependencies": { + "@types/node": "^16.18.68", + "browser-filesaver": "^1.1.1" + }, + "engines": { + "node": "^20.11.1", + "pnpm": "^9.1.0" + } + }, "node_modules/@woocommerce/components/node_modules/@wordpress/api-fetch": { "version": "6.55.0", "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-6.55.0.tgz", @@ -11652,23 +11670,19 @@ } }, "node_modules/@woocommerce/csv-export": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@woocommerce/csv-export/-/csv-export-1.9.0.tgz", - "integrity": "sha512-fo1byPYTljic8ml5HxvxafdhrYc8pMYXqjlGZtZ9xNxWL2yffXJvskbcb7Kj6JSQhHT3BCh/5PlczJci9vQuDQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@woocommerce/csv-export/-/csv-export-1.10.0.tgz", + "integrity": "sha512-OckWCp52fGFcyK2lwBJyiheBbvUFl0dO3Ai6tSfX+jApJa8SUlx9txhwKVSz4Xnpo+nH0B0SPHjoPtQeQeXa2w==", + "dev": true, "dependencies": { - "@types/node": "^16.18.68", + "@types/node": "20.x.x", "browser-filesaver": "^1.1.1" }, "engines": { "node": "^20.11.1", - "pnpm": "^9.1.0" + "pnpm": "9.1.3" } }, - "node_modules/@woocommerce/csv-export/node_modules/@types/node": { - "version": "16.18.102", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.102.tgz", - "integrity": "sha512-eSe2YwGCcRjqPidxfm20IAq02krERWcIIJW4FNPkU0zQLbc4L9pvhsmB0p6UJecjEf0j/E2ERHsKq7madvthKw==" - }, "node_modules/@woocommerce/currency": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@woocommerce/currency/-/currency-4.3.0.tgz", @@ -13775,6 +13789,24 @@ "pnpm": "^8.12.1" } }, + "node_modules/@woocommerce/onboarding/node_modules/@types/node": { + "version": "16.18.122", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.122.tgz", + "integrity": "sha512-rF6rUBS80n4oK16EW8nE75U+9fw0SSUgoPtWSvHhPXdT7itbvmS7UjB/jyM8i3AkvI6yeSM5qCwo+xN0npGDHg==" + }, + "node_modules/@woocommerce/onboarding/node_modules/@woocommerce/csv-export": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@woocommerce/csv-export/-/csv-export-1.9.0.tgz", + "integrity": "sha512-fo1byPYTljic8ml5HxvxafdhrYc8pMYXqjlGZtZ9xNxWL2yffXJvskbcb7Kj6JSQhHT3BCh/5PlczJci9vQuDQ==", + "dependencies": { + "@types/node": "^16.18.68", + "browser-filesaver": "^1.1.1" + }, + "engines": { + "node": "^20.11.1", + "pnpm": "^9.1.0" + } + }, "node_modules/@woocommerce/onboarding/node_modules/@woocommerce/experimental": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@woocommerce/experimental/-/experimental-3.2.0.tgz", @@ -20443,23 +20475,6 @@ "node": ">= 10.13.0" } }, - "node_modules/@wordpress/scripts/node_modules/rechoir/node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/@wordpress/scripts/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -20655,18 +20670,6 @@ "node": ">=8" } }, - "node_modules/@wordpress/scripts/node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@wordpress/scripts/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", diff --git a/package.json b/package.json index f634378e064..cf6c7f7b843 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "@typescript-eslint/parser": "4.15.2", "@woocommerce/api": "0.2.0", "@woocommerce/components": "12.3.0", - "@woocommerce/csv-export": "1.9.0", + "@woocommerce/csv-export": "1.10.0", "@woocommerce/currency": "4.3.0", "@woocommerce/date": "4.2.0", "@woocommerce/dependency-extraction-webpack-plugin": "2.2.0", @@ -215,7 +215,7 @@ "overrides": { "@automattic/puppeteer-utils": "github:Automattic/puppeteer-utils#update/babel-deps", "@woocommerce/components": { - "@woocommerce/csv-export": "1.9.0", + "@woocommerce/csv-export": "1.10.0", "@woocommerce/currency": "4.3.0" }, "@wordpress/scripts": { From 952e4314cee6c902931af89e6c7408ce1174fb50 Mon Sep 17 00:00:00 2001 From: Leonardo Lopes de Albuquerque Date: Mon, 23 Dec 2024 17:48:24 -0300 Subject: [PATCH 03/33] Prevent WooPay opt-in checks from running when WooPayments is not available (#9943) --- changelog/fix-9942-no-cost-subscription | 4 ++++ client/checkout/blocks/index.js | 3 ++- .../save-user/checkout-page-save-user.js | 20 ++++++++++++------- 3 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 changelog/fix-9942-no-cost-subscription diff --git a/changelog/fix-9942-no-cost-subscription b/changelog/fix-9942-no-cost-subscription new file mode 100644 index 00000000000..dc40262f302 --- /dev/null +++ b/changelog/fix-9942-no-cost-subscription @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Zero dollar subscriptions with zero dollar renewals checkout error diff --git a/client/checkout/blocks/index.js b/client/checkout/blocks/index.js index 3f98863d707..da139e3a27c 100644 --- a/client/checkout/blocks/index.js +++ b/client/checkout/blocks/index.js @@ -98,12 +98,13 @@ Object.entries( enabledPaymentMethodsConfig ) savedTokenComponent: , canMakePayment: ( cartData ) => { const billingCountry = cartData.billingAddress.country; + const needsPayment = cartData.cart.cartNeedsPayment; const isRestrictedInAnyCountry = !! upeConfig.countries.length; const isAvailableInTheCountry = ! isRestrictedInAnyCountry || upeConfig.countries.includes( billingCountry ); // We used to check if stripe was loaded with `getStripeForUPE`, but we can't guarantee it will be loaded synchronously. - return isAvailableInTheCountry; + return needsPayment && isAvailableInTheCountry; }, paymentMethodId: upeMethods[ upeName ], // see .wc-block-checkout__payment-method styles in blocks/style.scss diff --git a/client/components/woopay/save-user/checkout-page-save-user.js b/client/components/woopay/save-user/checkout-page-save-user.js index 45295c5c170..89c753cae7a 100644 --- a/client/components/woopay/save-user/checkout-page-save-user.js +++ b/client/components/woopay/save-user/checkout-page-save-user.js @@ -54,6 +54,13 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => { const { isWCPayChosen, isNewPaymentTokenChosen } = useSelectedPaymentMethod( isBlocksCheckout ); + + // In classic checkout the saved tokens are under WCPay, so we need to check if new token is selected or not, + // under WCPay. For blocks checkout considering isWCPayChosen is enough. + const isWCPayWithNewTokenChosen = isBlocksCheckout + ? isWCPayChosen + : isWCPayChosen && isNewPaymentTokenChosen; + const viewportWidth = window.document.documentElement.clientWidth; const viewportHeight = window.document.documentElement.clientHeight; @@ -193,7 +200,11 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => { return; } - if ( isSaveDetailsChecked && ! isPhoneValid ) { + if ( + isSaveDetailsChecked && + ! isPhoneValid && + isWCPayWithNewTokenChosen + ) { setValidationErrors( { [ errorId ]: { message: __( @@ -212,14 +223,9 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => { isSaveDetailsChecked, sendExtensionData, setValidationErrors, + isWCPayWithNewTokenChosen, ] ); - // In classic checkout the saved tokens are under WCPay, so we need to check if new token is selected or not, - // under WCPay. For blocks checkout considering isWCPayChosen is enough. - const isWCPayWithNewTokenChosen = isBlocksCheckout - ? isWCPayChosen - : isWCPayChosen && isNewPaymentTokenChosen; - const updatePhoneNumber = useCallback( () => { if ( isPhoneNumberTouched.current ) { return; From 504a42cc9b69b0d4207e04feee4c7652dc8c0bec Mon Sep 17 00:00:00 2001 From: Eric Jinks <3147296+Jinksi@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:27:51 +1000 Subject: [PATCH 04/33] Remove unused useEffect import to fix GH linter warning (#10035) --- changelog/dev-10034-linter-warning-useeffect-unused-import | 5 +++++ .../modal/progressive-onboarding-eligibility/index.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelog/dev-10034-linter-warning-useeffect-unused-import diff --git a/changelog/dev-10034-linter-warning-useeffect-unused-import b/changelog/dev-10034-linter-warning-useeffect-unused-import new file mode 100644 index 00000000000..4d2131a41b7 --- /dev/null +++ b/changelog/dev-10034-linter-warning-useeffect-unused-import @@ -0,0 +1,5 @@ +Significance: patch +Type: dev +Comment: Not user-facing: removed an unused `useEffect` import causing linter warnings + + diff --git a/client/overview/modal/progressive-onboarding-eligibility/index.tsx b/client/overview/modal/progressive-onboarding-eligibility/index.tsx index 6f6be89a707..21a6e5a22fa 100644 --- a/client/overview/modal/progressive-onboarding-eligibility/index.tsx +++ b/client/overview/modal/progressive-onboarding-eligibility/index.tsx @@ -1,7 +1,7 @@ /** * External dependencies */ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { __, sprintf } from '@wordpress/i18n'; import { addQueryArgs } from '@wordpress/url'; import { Button, Modal } from '@wordpress/components'; From 21d5cf8341a6545f59b2d0fc7079c333855a776e Mon Sep 17 00:00:00 2001 From: Nagesh Pai <4162931+nagpai@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:06:26 +0530 Subject: [PATCH 05/33] Add TS type assertion for payout CSV export code for type safety and prevent TypeScript errors (#10030) Co-authored-by: Nagesh Pai --- .../dev-10029-export-deposit-type-assert | 5 +++ client/deposits/list/index.tsx | 35 ++++++++++--------- 2 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 changelog/dev-10029-export-deposit-type-assert diff --git a/changelog/dev-10029-export-deposit-type-assert b/changelog/dev-10029-export-deposit-type-assert new file mode 100644 index 00000000000..684727000a7 --- /dev/null +++ b/changelog/dev-10029-export-deposit-type-assert @@ -0,0 +1,5 @@ +Significance: patch +Type: dev +Comment: Add type assertion for payouts CSV export response to ensure type safety and fix TypeScript linting error + + diff --git a/client/deposits/list/index.tsx b/client/deposits/list/index.tsx index dc3e20ac02a..52194cb184f 100644 --- a/client/deposits/list/index.tsx +++ b/client/deposits/list/index.tsx @@ -260,22 +260,25 @@ export const DepositsList = (): JSX.Element => { window.confirm( confirmMessage ) ) { try { - const { exported_deposits: exportedDeposits } = await apiFetch( - { - path: getDepositsCSV( { - userEmail, - locale, - dateAfter, - dateBefore, - dateBetween, - match, - statusIs, - statusIsNot, - storeCurrencyIs, - } ), - method: 'POST', - } - ); + const { + exported_deposits: exportedDeposits, + } = await apiFetch< { + /** The total number of payouts that will be exported in the CSV */ + exported_deposits: number; + } >( { + path: getDepositsCSV( { + userEmail, + locale, + dateAfter, + dateBefore, + dateBetween, + match, + statusIs, + statusIsNot, + storeCurrencyIs, + } ), + method: 'POST', + } ); createNotice( 'success', From 889ae36d6dd44e9db31ef4bfe2cde2de4b0835c5 Mon Sep 17 00:00:00 2001 From: deepakpathania <68396823+deepakpathania@users.noreply.github.com> Date: Tue, 24 Dec 2024 17:41:13 +0530 Subject: [PATCH 06/33] Consistently format the order notes for refunds and charges (#10036) --- changelog/feature-consistent-note-formatting | 4 +++ includes/class-wc-payments-order-service.php | 12 +++++---- includes/multi-currency/MultiCurrency.php | 27 +++++++++++++++++++ ...c-payment-gateway-wcpay-process-refund.php | 12 ++++----- ...wc-payments-webhook-processing-service.php | 24 +++++++++++++++++ 5 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 changelog/feature-consistent-note-formatting diff --git a/changelog/feature-consistent-note-formatting b/changelog/feature-consistent-note-formatting new file mode 100644 index 00000000000..bb18d73c7ee --- /dev/null +++ b/changelog/feature-consistent-note-formatting @@ -0,0 +1,4 @@ +Significance: minor +Type: fix + +Ensure consistent formatting of refund notes with MC. diff --git a/includes/class-wc-payments-order-service.php b/includes/class-wc-payments-order-service.php index f685b50debf..eb74cde866f 100644 --- a/includes/class-wc-payments-order-service.php +++ b/includes/class-wc-payments-order-service.php @@ -1752,10 +1752,8 @@ private function generate_dispute_closed_note( $charge_id, $status, $is_inquiry * @return string HTML note. */ private function generate_payment_refunded_note( float $refunded_amount, string $refunded_currency, string $wcpay_refund_id, string $refund_reason, WC_Order $order ): string { - $formatted_price = WC_Payments_Explicit_Price_Formatter::get_explicit_price( - wc_price( $refunded_amount, [ 'currency' => strtoupper( $refunded_currency ) ] ), - $order - ); + $multi_currency_instance = WC_Payments_Multi_Currency(); + $formatted_price = WC_Payments_Explicit_Price_Formatter::get_explicit_price( $multi_currency_instance->get_backend_formatted_wc_price( $refunded_amount, [ 'currency' => strtoupper( $refunded_currency ) ] ), $order ); if ( empty( $refund_reason ) ) { $note = sprintf( @@ -1930,7 +1928,11 @@ private function complete_order_processing( $order, $intent_status = null ) { * @return string The formatted order total. */ private function get_order_amount( $order ) { - return WC_Payments_Explicit_Price_Formatter::get_explicit_price( wc_price( $order->get_total(), [ 'currency' => $order->get_currency() ] ), $order ); + $multi_currency_instance = WC_Payments_Multi_Currency(); + $order_price = $order->get_total(); + + $formatted_price = $multi_currency_instance->get_backend_formatted_wc_price( $order_price, [ 'currency' => $order->get_currency() ] ); + return WC_Payments_Explicit_Price_Formatter::get_explicit_price( $formatted_price, $order ); } /** diff --git a/includes/multi-currency/MultiCurrency.php b/includes/multi-currency/MultiCurrency.php index 9ab1ac0f19a..c177d253978 100644 --- a/includes/multi-currency/MultiCurrency.php +++ b/includes/multi-currency/MultiCurrency.php @@ -17,6 +17,7 @@ use WCPay\MultiCurrency\Logger; use WCPay\MultiCurrency\Notes\NoteMultiCurrencyAvailable; use WCPay\MultiCurrency\Utils; +use WC_Payments_Features; defined( 'ABSPATH' ) || exit; @@ -1326,6 +1327,32 @@ public function is_initialized(): bool { return static::$is_initialized; } + /** + * Returns the amount with the backend format. + * + * @param float $amount The amount to format. + * @param array $args The arguments to pass to wc_price. + * + * @return string The formatted amount. + */ + public function get_backend_formatted_wc_price( float $amount, array $args = [] ): string { + // Return early if MC isn't enabled or merchant has a single currency. + if ( ! self::has_additional_currencies_enabled() || ! WC_Payments_Features::is_customer_multi_currency_enabled() ) { + return wc_price( $amount, $args ); + } + + $has_filter = has_filter( 'wc_price_args', [ $this->backend_currencies, 'build_wc_price_args' ] ); + if ( false !== $has_filter ) { + return wc_price( $amount, $args ); + } + + add_filter( 'wc_price_args', [ $this->backend_currencies, 'build_wc_price_args' ], 50 ); + $price = wc_price( $amount, $args ); + remove_filter( 'wc_price_args', [ $this->backend_currencies, 'build_wc_price_args' ], 50 ); + + return $price; + } + /** * Gets the price after adjusting it with the rounding and charm settings. * diff --git a/tests/unit/test-class-wc-payment-gateway-wcpay-process-refund.php b/tests/unit/test-class-wc-payment-gateway-wcpay-process-refund.php index b75d1721c16..f3a0aefa442 100644 --- a/tests/unit/test-class-wc-payment-gateway-wcpay-process-refund.php +++ b/tests/unit/test-class-wc-payment-gateway-wcpay-process-refund.php @@ -278,7 +278,7 @@ public function test_process_refund_save_wcpay_refund_id_to_refund_meta_and_orde $this->assertTrue( $result ); $this->assertStringContainsString( 'successfully processed', $latest_wcpay_note->content ); - $this->assertStringContainsString( wc_price( 19.99, [ 'currency' => 'USD' ] ), $latest_wcpay_note->content ); + $this->assertStringContainsString( WC_Payments_Multi_Currency()->get_backend_formatted_wc_price( 19.99, [ 'currency' => 'USD' ] ), $latest_wcpay_note->content ); $this->assertStringContainsString( 're_123456789', $latest_wcpay_note->content ); } @@ -349,7 +349,7 @@ public function test_process_refund_non_usd() { $this->assertTrue( $result ); $this->assertStringContainsString( 'successfully processed', $latest_wcpay_note->content ); - $this->assertStringContainsString( wc_price( 19.99, [ 'currency' => strtoupper( $currency ) ] ), $latest_wcpay_note->content ); + $this->assertStringContainsString( WC_Payments_Multi_Currency()->get_backend_formatted_wc_price( 19.99, [ 'currency' => strtoupper( $currency ) ] ), $latest_wcpay_note->content ); } public function test_process_refund_with_reason_non_usd() { @@ -419,7 +419,7 @@ public function test_process_refund_with_reason_non_usd() { $this->assertStringContainsString( 'successfully processed', $latest_wcpay_note->content ); $this->assertStringContainsString( 'some reason', $latest_wcpay_note->content ); - $this->assertStringContainsString( wc_price( 19.99, [ 'currency' => strtoupper( $currency ) ] ), $latest_wcpay_note->content ); + $this->assertStringContainsString( WC_Payments_Multi_Currency()->get_backend_formatted_wc_price( 19.99, [ 'currency' => strtoupper( $currency ) ] ), $latest_wcpay_note->content ); $this->assertTrue( $result ); } @@ -511,7 +511,7 @@ public function test_process_refund_interac_present() { $this->assertTrue( $result ); $this->assertStringContainsString( 'successfully processed', $latest_wcpay_note->content ); - $this->assertStringContainsString( wc_price( $amount, [ 'currency' => $currency ] ), $latest_wcpay_note->content ); + $this->assertStringContainsString( WC_Payments_Multi_Currency()->get_backend_formatted_wc_price( $amount, [ 'currency' => $currency ] ), $latest_wcpay_note->content ); } public function test_process_refund_interac_present_without_payment_method_id_meta() { @@ -591,7 +591,7 @@ public function test_process_refund_interac_present_without_payment_method_id_me $this->assertTrue( $result ); $this->assertStringContainsString( 'successfully processed', $latest_wcpay_note->content ); - $this->assertStringContainsString( wc_price( $amount, [ 'currency' => 'USD' ] ), $latest_wcpay_note->content ); + $this->assertStringContainsString( WC_Payments_Multi_Currency()->get_backend_formatted_wc_price( $amount, [ 'currency' => 'USD' ] ), $latest_wcpay_note->content ); } public function test_process_refund_interac_present_without_app_refund() { @@ -809,7 +809,7 @@ public function test_process_refund_card_present() { $this->assertTrue( $result ); $this->assertStringContainsString( 'successfully processed', $latest_wcpay_note->content ); - $this->assertStringContainsString( wc_price( $amount, [ 'currency' => strtoupper( $currency ) ] ), $latest_wcpay_note->content ); + $this->assertStringContainsString( WC_Payments_Multi_Currency()->get_backend_formatted_wc_price( $amount, [ 'currency' => strtoupper( $currency ) ] ), $latest_wcpay_note->content ); } public function test_process_refund_on_uncaptured_payment() { diff --git a/tests/unit/test-class-wc-payments-webhook-processing-service.php b/tests/unit/test-class-wc-payments-webhook-processing-service.php index 2acb5c318ad..e628c533848 100644 --- a/tests/unit/test-class-wc-payments-webhook-processing-service.php +++ b/tests/unit/test-class-wc-payments-webhook-processing-service.php @@ -652,6 +652,10 @@ public function test_payment_intent_successful_and_completes_order() { ->expects( $this->exactly( 2 ) ) ->method( 'save' ); + $this->mock_order + ->method( 'get_total' ) + ->willReturn( 15.00 ); + $this->mock_order ->expects( $this->exactly( 2 ) ) ->method( 'has_status' ) @@ -747,6 +751,10 @@ public function test_payment_intent_successful_and_completes_order_without_inten ->expects( $this->exactly( 2 ) ) ->method( 'save' ); + $this->mock_order + ->method( 'get_total' ) + ->willReturn( 15.00 ); + $this->mock_order ->expects( $this->exactly( 2 ) ) ->method( 'has_status' ) @@ -939,6 +947,10 @@ public function test_payment_intent_successful_and_send_card_reader_receipt() { ) ->willReturn( false ); + $this->mock_order + ->method( 'get_total' ) + ->willReturn( 15.00 ); + $this->mock_order ->expects( $this->once() ) ->method( 'payment_complete' ); @@ -1040,6 +1052,10 @@ public function test_payment_intent_successful_and_save_mandate() { [ '_intention_status', $intent_status ] ); + $this->mock_order + ->method( 'get_total' ) + ->willReturn( 15.00 ); + $this->mock_order ->expects( $this->exactly( 2 ) ) ->method( 'save' ); @@ -1123,6 +1139,10 @@ public function test_payment_intent_fails_and_fails_order() { ->with( '_payment_method_id' ) ->willReturn( 'pm_123123123123123' ); + $this->mock_order + ->method( 'get_total' ) + ->willReturn( 15.00 ); + $this->mock_order ->expects( $this->exactly( 3 ) ) ->method( 'has_status' ) @@ -1190,6 +1210,10 @@ public function test_payment_intent_without_charges_fails_and_fails_order() { ->with( '_payment_method_id' ) ->willReturn( 'pm_123123123123123' ); + $this->mock_order + ->method( 'get_total' ) + ->willReturn( 15.00 ); + $this->mock_order ->expects( $this->exactly( 3 ) ) ->method( 'has_status' ) From 442ba90742cbfb5f9b7df672675b48a3f40b91ed Mon Sep 17 00:00:00 2001 From: Rafael Zaleski Date: Thu, 26 Dec 2024 22:47:58 -0300 Subject: [PATCH 07/33] Update currency conversion method for booking products (#10042) --- changelog/fix-472-mccy-wc-bookings | 4 ++ .../Compatibility/WooCommerceBookings.php | 62 ++++++++++++------ includes/multi-currency/MultiCurrency.php | 26 ++++++-- .../test-class-woocommerce-bookings.php | 63 ++++++++----------- 4 files changed, 94 insertions(+), 61 deletions(-) create mode 100644 changelog/fix-472-mccy-wc-bookings diff --git a/changelog/fix-472-mccy-wc-bookings b/changelog/fix-472-mccy-wc-bookings new file mode 100644 index 00000000000..aaffc2d5921 --- /dev/null +++ b/changelog/fix-472-mccy-wc-bookings @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Update currency conversion method for booking products. diff --git a/includes/multi-currency/Compatibility/WooCommerceBookings.php b/includes/multi-currency/Compatibility/WooCommerceBookings.php index 756e4eef355..bb6bc4bb667 100644 --- a/includes/multi-currency/Compatibility/WooCommerceBookings.php +++ b/includes/multi-currency/Compatibility/WooCommerceBookings.php @@ -10,6 +10,7 @@ use WCPay\MultiCurrency\FrontendCurrencies; use WCPay\MultiCurrency\MultiCurrency; use WCPay\MultiCurrency\Utils; +use WC_Product; /** * Class that controls Multi Currency Compatibility with WooCommerce Bookings Plugin. @@ -43,6 +44,7 @@ public function init() { // Add needed actions and filters if Bookings is active. if ( class_exists( 'WC_Bookings' ) ) { if ( ! is_admin() || wp_doing_ajax() ) { + add_filter( 'woocommerce_bookings_calculated_booking_cost', [ $this, 'adjust_amount_for_calculated_booking_cost' ], 50, 1 ); add_filter( 'woocommerce_product_get_block_cost', [ $this, 'get_price' ], 50, 1 ); add_filter( 'woocommerce_product_get_cost', [ $this, 'get_price' ], 50, 1 ); add_filter( 'woocommerce_product_get_display_cost', [ $this, 'get_price' ], 50, 1 ); @@ -50,7 +52,7 @@ public function init() { add_filter( 'woocommerce_product_booking_person_type_get_cost', [ $this, 'get_price' ], 50, 1 ); add_filter( 'woocommerce_product_get_resource_base_costs', [ $this, 'get_resource_prices' ], 50, 1 ); add_filter( 'woocommerce_product_get_resource_block_costs', [ $this, 'get_resource_prices' ], 50, 1 ); - add_filter( MultiCurrency::FILTER_PREFIX . 'should_convert_product_price', [ $this, 'should_convert_product_price' ] ); + add_filter( MultiCurrency::FILTER_PREFIX . 'should_convert_product_price', [ $this, 'should_convert_product_price' ], 50, 2 ); add_action( 'wp_ajax_wc_bookings_calculate_costs', [ $this, 'add_wc_price_args_filter_for_ajax' ], 9 ); add_action( 'wp_ajax_nopriv_wc_bookings_calculate_costs', [ $this, 'add_wc_price_args_filter_for_ajax' ], 9 ); } @@ -58,7 +60,28 @@ public function init() { } /** - * Returns the price for an item. + * Adjusts the calculated booking cost for the selected currency, applying rounding and charm pricing as necessary. + * + * @param mixed $costs The original calculated booking costs. + * @return mixed The booking cost adjusted for the selected currency. + */ + public function adjust_amount_for_calculated_booking_cost( $costs ) { + /** + * Prevents adjustment of the calculated booking cost during cart addition. + * + * When a booking is added to the cart, the Booking plugin calculates the booking cost and + * overrides the cart item price with this calculated amount. To avoid interfering with this process, + * this function skips any additional adjustments at this stage. + */ + if ( $this->utils->is_call_in_backtrace( [ 'WC_Cart->add_to_cart' ] ) ) { + return $costs; + } + + return $this->multi_currency->adjust_amount_for_selected_currency( $costs ); + } + + /** + * Retrieves the price for an item, converting it based on the selected currency and context. * * @param mixed $price The item's price. * @@ -68,7 +91,19 @@ public function get_price( $price ) { if ( ! $price ) { return $price; } - return $this->multi_currency->get_price( $price, 'product' ); + + // Skip conversion during specific booking cost calculations to avoid double conversion. + if ( $this->utils->is_call_in_backtrace( [ 'WC_Cart->add_to_cart' ] ) && $this->utils->is_call_in_backtrace( [ 'WC_Bookings_Cost_Calculation::calculate_booking_cost' ] ) ) { + return $price; + } + + /** + * When showing the price in HTML, the function applies currency conversion, charm pricing, + * and rounding. For internal calculations, it uses the raw exchange rate, with charm pricing + * and rounding adjustments applied only to the final calculated amount (handled in + * adjust_amount_for_calculated_booking_cost). + */ + return $this->multi_currency->get_price( $price, $this->utils->is_call_in_backtrace( [ 'WC_Product_Booking->get_price_html' ] ) ? 'product' : 'exchange_rate' ); } /** @@ -90,28 +125,17 @@ public function get_resource_prices( $prices ) { /** * Checks to see if the product's price should be converted. * - * @param bool $return Whether to convert the product's price or not. Default is true. + * @param bool $return Whether to convert the product's price or not. Default is true. + * @param WC_Product $product The product instance being checked. * * @return bool True if it should be converted. */ - public function should_convert_product_price( bool $return ): bool { - // If it's already false, return it. - if ( ! $return ) { + public function should_convert_product_price( bool $return, WC_Product $product ): bool { + // If it's already false, or the product is not a booking, ignore it. + if ( ! $return || $product->get_type() !== 'booking' ) { return $return; } - // This prevents a double conversion of the price in the cart. - if ( $this->utils->is_call_in_backtrace( [ 'WC_Product_Booking->get_price' ] ) ) { - $calls = [ - 'WC_Cart_Totals->calculate_item_totals', - 'WC_Cart->get_product_price', - 'WC_Cart->get_product_subtotal', - ]; - if ( $this->utils->is_call_in_backtrace( $calls ) ) { - return false; - } - } - // Fixes price display on product page and in shop. if ( $this->utils->is_call_in_backtrace( [ 'WC_Product_Booking->get_price_html' ] ) ) { return false; diff --git a/includes/multi-currency/MultiCurrency.php b/includes/multi-currency/MultiCurrency.php index c177d253978..2070b8b8c56 100644 --- a/includes/multi-currency/MultiCurrency.php +++ b/includes/multi-currency/MultiCurrency.php @@ -1108,7 +1108,7 @@ public function set_client_format_and_rounding_precision() { woocommerce_admin_meta_boxes.rounding_precision = ; base + is_admin() + && $current_tab && $current_screen + && 'wcpay_multi_currency' === $current_tab + && 'woocommerce_page_wc-settings' === $current_screen->base ); } @@ -1277,7 +1277,7 @@ public function get_all_customer_currencies(): array { $query_union = []; if ( class_exists( 'Automattic\WooCommerce\Utilities\OrderUtil' ) && - \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) { + \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) { foreach ( $currencies as $currency ) { $query_union[] = $wpdb->prepare( "SELECT %s AS currency_code, EXISTS(SELECT currency FROM {$wpdb->prefix}wc_orders WHERE currency=%s LIMIT 1) AS exists_in_orders", @@ -1327,6 +1327,20 @@ public function is_initialized(): bool { return static::$is_initialized; } + /** + * Adjusts the given amount for the currently selected currency. + * + * Applies charm pricing if specified, and adjusts the amount according to + * the selected currency's conversion rate. + * + * @param float $amount The original amount to adjust. + * @param bool $apply_charm_pricing Optional. Whether to apply charm pricing to the adjusted amount. Default true. + * @return float The amount adjusted for the selected currency. + */ + public function adjust_amount_for_selected_currency( $amount, $apply_charm_pricing = true ) { + return $this->get_adjusted_price( $amount, $apply_charm_pricing, $this->get_selected_currency() ); + } + /** * Returns the amount with the backend format. * diff --git a/tests/unit/multi-currency/compatibility/test-class-woocommerce-bookings.php b/tests/unit/multi-currency/compatibility/test-class-woocommerce-bookings.php index 82409afeb38..cda1202ac80 100644 --- a/tests/unit/multi-currency/compatibility/test-class-woocommerce-bookings.php +++ b/tests/unit/multi-currency/compatibility/test-class-woocommerce-bookings.php @@ -51,6 +51,13 @@ class WCPay_Multi_Currency_WooCommerceBookings_Tests extends WCPAY_UnitTestCase */ private $localization_service; + /** + * Mock product. + * + * @var \WC_Product|PHPUnit_Framework_MockObject_MockObject + */ + private $mock_product; + /** * Pre-test setup */ @@ -62,6 +69,14 @@ public function set_up() { $this->mock_frontend_currencies = $this->createMock( FrontendCurrencies::class ); $this->woocommerce_bookings = new WooCommerceBookings( $this->mock_multi_currency, $this->mock_utils, $this->mock_frontend_currencies ); $this->localization_service = new WC_Payments_Localization_Service(); + + $this->mock_product = $this->createMock( \WC_Product::class ); + $this->mock_product + ->method( 'get_id' ) + ->willReturn( 42 ); + $this->mock_product + ->method( 'get_type' ) + ->willReturn( 'booking' ); } public function test_get_price_returns_empty_string() { @@ -95,53 +110,29 @@ public function test_get_resource_prices_returns_converted_prices() { // If false is passed, it should automatically return false. public function test_should_convert_product_price_returns_false_if_false_passed() { $this->mock_utils->expects( $this->exactly( 0 ) )->method( 'is_call_in_backtrace' ); - $this->assertFalse( $this->woocommerce_bookings->should_convert_product_price( false ) ); + $this->assertFalse( $this->woocommerce_bookings->should_convert_product_price( false, $this->mock_product ) ); } - // If the first two sets of calls are found, it should return false. - public function test_should_convert_product_price_returns_false_if_cart_calls_found() { - $first_calls = [ 'WC_Product_Booking->get_price' ]; - $second_calls = [ - 'WC_Cart_Totals->calculate_item_totals', - 'WC_Cart->get_product_price', - 'WC_Cart->get_product_subtotal', - ]; - $this->mock_utils - ->expects( $this->exactly( 2 ) ) - ->method( 'is_call_in_backtrace' ) - ->withConsecutive( [ $first_calls ], [ $second_calls ] ) - ->willReturn( true, true ); - $this->assertFalse( $this->woocommerce_bookings->should_convert_product_price( true ) ); - } - - // If the last set of calls are found, it should return false. - // This also tests to make sure if the first set of calls is found, but not the second, it continues. + // If the get_price_html call is found, it should return false. public function test_should_convert_product_price_returns_false_if_display_calls_found() { - $first_calls = [ 'WC_Product_Booking->get_price' ]; - $second_calls = [ - 'WC_Cart_Totals->calculate_item_totals', - 'WC_Cart->get_product_price', - 'WC_Cart->get_product_subtotal', - ]; - $third_calls = [ 'WC_Product_Booking->get_price_html' ]; + $expected_calls = [ 'WC_Product_Booking->get_price_html' ]; $this->mock_utils - ->expects( $this->exactly( 3 ) ) + ->expects( $this->exactly( 1 ) ) ->method( 'is_call_in_backtrace' ) - ->withConsecutive( [ $first_calls ], [ $second_calls ], [ $third_calls ] ) - ->willReturn( true, false, true ); - $this->assertFalse( $this->woocommerce_bookings->should_convert_product_price( true ) ); + ->with( $expected_calls ) + ->willReturn( true ); + $this->assertFalse( $this->woocommerce_bookings->should_convert_product_price( true, $this->mock_product ) ); } // If no calls are found, it should return true. public function test_should_convert_product_price_returns_true_if_no_calls_found() { - $first_calls = [ 'WC_Product_Booking->get_price' ]; - $third_calls = [ 'WC_Product_Booking->get_price_html' ]; + $expected_calls = [ 'WC_Product_Booking->get_price_html' ]; $this->mock_utils - ->expects( $this->exactly( 2 ) ) + ->expects( $this->exactly( 1 ) ) ->method( 'is_call_in_backtrace' ) - ->withConsecutive( [ $first_calls ], [ $third_calls ] ) - ->willReturn( false, false ); - $this->assertTrue( $this->woocommerce_bookings->should_convert_product_price( true ) ); + ->with( $expected_calls ) + ->willReturn( false ); + $this->assertTrue( $this->woocommerce_bookings->should_convert_product_price( true, $this->mock_product ) ); } public function test_filter_wc_price_args_returns_expected_results() { From cd3e288bf8d357f8c2ada5fc754608156c4e154e Mon Sep 17 00:00:00 2001 From: Nagesh Pai <4162931+nagpai@users.noreply.github.com> Date: Mon, 30 Dec 2024 13:05:55 +0530 Subject: [PATCH 08/33] Reporting: Fix transaction list sort by payout currency (#10041) Co-authored-by: Nagesh Pai Co-authored-by: Jessy Pappachan <32092402+jessy-p@users.noreply.github.com> --- changelog/fix-10038-payout-currency-sort | 4 ++++ client/transactions/list/index.tsx | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 changelog/fix-10038-payout-currency-sort diff --git a/changelog/fix-10038-payout-currency-sort b/changelog/fix-10038-payout-currency-sort new file mode 100644 index 00000000000..54a89873c71 --- /dev/null +++ b/changelog/fix-10038-payout-currency-sort @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Fix transaction list sorting by payout currency diff --git a/client/transactions/list/index.tsx b/client/transactions/list/index.tsx index a4d9abc852a..6f2c68a590d 100644 --- a/client/transactions/list/index.tsx +++ b/client/transactions/list/index.tsx @@ -202,7 +202,7 @@ const getColumns = ( visible: false, }, { - key: 'deposit_currency', + key: 'currency', label: __( 'Payout Currency', 'woocommerce-payments' ), screenReaderLabel: __( 'Payout Currency', 'woocommerce-payments' ), isSortable: true, @@ -537,7 +537,7 @@ export const TransactionsList = ( display: clickable( txn.customer_currency.toUpperCase() ), }, customer_amount: formatCustomerAmount(), - deposit_currency: { + currency: { value: txn.currency.toUpperCase(), display: clickable( txn.currency.toUpperCase() ), }, From bacc8ed7b4177c28bee88d266bd386b2693341ff Mon Sep 17 00:00:00 2001 From: Nagesh Pai <4162931+nagpai@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:36:38 +0530 Subject: [PATCH 09/33] Reporting: Overview - improve mobile view of Balances card (#10040) Co-authored-by: Nagesh Pai --- changelog/fix-8599-balances-card-layout | 4 + client/components/account-balances/index.tsx | 82 ++++---- client/components/account-balances/style.scss | 34 ++- .../test/__snapshots__/index.test.tsx.snap | 193 ++++++++++-------- 4 files changed, 189 insertions(+), 124 deletions(-) create mode 100644 changelog/fix-8599-balances-card-layout diff --git a/changelog/fix-8599-balances-card-layout b/changelog/fix-8599-balances-card-layout new file mode 100644 index 00000000000..42fb99563db --- /dev/null +++ b/changelog/fix-8599-balances-card-layout @@ -0,0 +1,4 @@ +Significance: minor +Type: fix + +Improve the mobile rendering of the Balances box within Payment Overview diff --git a/client/components/account-balances/index.tsx b/client/components/account-balances/index.tsx index a72f884bed8..d2ddfb8b825 100644 --- a/client/components/account-balances/index.tsx +++ b/client/components/account-balances/index.tsx @@ -3,7 +3,7 @@ */ import React, { useState } from 'react'; import { useDispatch } from '@wordpress/data'; -import { Flex } from '@wordpress/components'; +import { Card, CardBody, CardHeader, Flex } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import interpolateComponents from '@automattic/interpolate-components'; import { Link } from '@woocommerce/components'; @@ -73,22 +73,25 @@ const AccountBalances: React.FC = () => { }; return ( - - - - + + Balance + + + + + ); } @@ -115,26 +118,31 @@ const AccountBalances: React.FC = () => { return ( <> - - } - /> - - } - /> - + + Balance + + + } + /> + + } + /> + + { selectedOverview.instantBalance && selectedOverview.instantBalance.amount > 0 && ( * + * { - border-left: 1px solid $gray-200; -} - .wcpay-account-balances__balances__item { flex-direction: column; align-items: flex-start; - padding: 24px; flex: 1; + padding-left: 16px; &__title { font-size: 12px; @@ -23,6 +19,13 @@ margin: 0; color: $gray-900; } + + @include breakpoint( '<660px' ) { + padding-left: 0; + &:not( :first-child ) { + padding-top: 16px; + } + } } .wcpay-account-balances__instant-deposit-notice .components-notice__content { @@ -35,6 +38,13 @@ } .wcpay-account-balances__balances { + display: flex; + margin-bottom: 0; + + & > * + * { + border-left: 1px solid $gray-200; + } + .wcpay-account-balances__balances__item__tooltip { line-height: 20px; } @@ -58,4 +68,18 @@ margin-right: 0; } } + + @include breakpoint( '<660px' ) { + flex-direction: column; + gap: 16px; + & > * + * { + border-left: none; + border-top: 1px solid $gray-200; + } + } +} + +.components-card.wcpay-account-balances { + margin-bottom: 0; + box-shadow: none; } diff --git a/client/components/account-balances/test/__snapshots__/index.test.tsx.snap b/client/components/account-balances/test/__snapshots__/index.test.tsx.snap index 49b207843f8..ecd04354d6c 100644 --- a/client/components/account-balances/test/__snapshots__/index.test.tsx.snap +++ b/client/components/account-balances/test/__snapshots__/index.test.tsx.snap @@ -3,102 +3,131 @@ exports[`AccountBalances renders the correct tooltip text for the total balance 1`] = `
- -

- -
- + + +

+ + + + +

+ + + + `; From 85865e803ca2c2ba908bfcf7cf3364f81bcbdd3a Mon Sep 17 00:00:00 2001 From: Shendy <73803630+shendy-a8c@users.noreply.github.com> Date: Wed, 1 Jan 2025 22:00:09 +0700 Subject: [PATCH 10/33] Remove payouts rename notice overlay. (#10039) Co-authored-by: Nagesh Pai --- .../update-9704-remove-payouts-rename-overlay | 4 + client/deposits/details/index.tsx | 2 - client/deposits/index.tsx | 2 - .../deposits/rename-notice/header-image.svg | 36 -------- client/deposits/rename-notice/index.tsx | 88 ------------------- client/deposits/rename-notice/style.scss | 77 ---------------- .../test/__snapshots__/index.tsx.snap | 9 -- client/deposits/rename-notice/test/index.tsx | 49 ----------- client/globals.d.ts | 1 - client/overview/index.js | 2 - client/overview/test/index.js | 20 ----- includes/admin/class-wc-payments-admin.php | 1 - includes/class-wc-payments-features.php | 9 -- includes/class-wc-payments.php | 1 - 14 files changed, 4 insertions(+), 297 deletions(-) create mode 100644 changelog/update-9704-remove-payouts-rename-overlay delete mode 100644 client/deposits/rename-notice/header-image.svg delete mode 100644 client/deposits/rename-notice/index.tsx delete mode 100644 client/deposits/rename-notice/style.scss delete mode 100644 client/deposits/rename-notice/test/__snapshots__/index.tsx.snap delete mode 100644 client/deposits/rename-notice/test/index.tsx diff --git a/changelog/update-9704-remove-payouts-rename-overlay b/changelog/update-9704-remove-payouts-rename-overlay new file mode 100644 index 00000000000..d6eacc2ada1 --- /dev/null +++ b/changelog/update-9704-remove-payouts-rename-overlay @@ -0,0 +1,4 @@ +Significance: minor +Type: update + +Remove the overlay that announces the rename from deposits to payouts. diff --git a/client/deposits/details/index.tsx b/client/deposits/details/index.tsx index 4e15a8653a8..795135f16cc 100644 --- a/client/deposits/details/index.tsx +++ b/client/deposits/details/index.tsx @@ -38,7 +38,6 @@ import { } from 'multi-currency/interface/functions'; import { depositStatusLabels } from '../strings'; import './style.scss'; -import { PayoutsRenameNotice } from '../rename-notice'; import { formatDateTimeFromString } from 'wcpay/utils/date-time'; import DateFormatNotice from 'wcpay/components/date-format-notice'; @@ -243,7 +242,6 @@ export const DepositDetails: React.FC< DepositDetailsProps > = ( { return ( - diff --git a/client/deposits/index.tsx b/client/deposits/index.tsx index 229acdbbb09..d500a05a6a5 100644 --- a/client/deposits/index.tsx +++ b/client/deposits/index.tsx @@ -17,7 +17,6 @@ import { __ } from '@wordpress/i18n'; import { TestModeNotice } from 'components/test-mode-notice'; import BannerNotice from 'components/banner-notice'; import DepositSchedule from 'components/deposits-overview/deposit-schedule'; -import { PayoutsRenameNotice } from './rename-notice'; import { useAllDepositsOverviews } from 'data'; import { useSettings } from 'wcpay/data'; import DepositsList from './list'; @@ -152,7 +151,6 @@ const DepositsPage: React.FC = () => { - diff --git a/client/deposits/rename-notice/header-image.svg b/client/deposits/rename-notice/header-image.svg deleted file mode 100644 index 8a96d1df244..00000000000 --- a/client/deposits/rename-notice/header-image.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/deposits/rename-notice/index.tsx b/client/deposits/rename-notice/index.tsx deleted file mode 100644 index 61ff61b142e..00000000000 --- a/client/deposits/rename-notice/index.tsx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * External dependencies - */ -import { __ } from '@wordpress/i18n'; -import React, { useState, useEffect } from 'react'; -import { TourKit } from '@woocommerce/components'; -import { useDispatch } from '@wordpress/data'; -import { createInterpolateElement } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import './style.scss'; - -export const PayoutsRenameNotice = () => { - const isPayoutsRenameNoticeDismissed = - wcpaySettings.isPayoutsRenameNoticeDismissed; - const { updateOptions } = useDispatch( 'wc/admin/options' ); - const [ showTour, setShowTour ] = useState( false ); - - const onClose = () => { - updateOptions( { - wcpay_payouts_rename_notice_dismissed: true, - } ); - setShowTour( false ); - wcpaySettings.isPayoutsRenameNoticeDismissed = true; - }; - - useEffect( () => { - if ( ! isPayoutsRenameNoticeDismissed ) { - setShowTour( true ); - } - }, [ isPayoutsRenameNoticeDismissed ] ); - - if ( ! showTour ) return null; - - return ( - Learn More.", - 'woocommerce-payments' - ), - { - link: ( - // eslint-disable-next-line jsx-a11y/anchor-has-content - - ), - } - ), - }, - }, - }, - ], - closeHandler: onClose, - } } - > - ); -}; diff --git a/client/deposits/rename-notice/style.scss b/client/deposits/rename-notice/style.scss deleted file mode 100644 index 3a2c51b7334..00000000000 --- a/client/deposits/rename-notice/style.scss +++ /dev/null @@ -1,77 +0,0 @@ -.wc-admin-payments-overview-payouts-rename-tour { - color: #1e1e1e; - - .woocommerce-tour-kit-step { - border-radius: 8px; - border: 1px solid #dcdcdc; - - /* Shadow / Popover */ - box-shadow: 0 2px 6px 0 rgba( 0, 0, 0, 0.05 ); - width: 257px; - padding-bottom: 0; - } - - .components-card__footer { - display: none; - } - - .tour-kit-frame__container { - box-shadow: none; - background: none; - } - - .components-elevation { - display: none; - } - - .woocommerce-tour-kit-step__body { - background-image: url( './header-image.svg' ); - background-repeat: no-repeat; - background-position-x: center; - background-position-y: 5px; - padding-bottom: 24px; - } - .woocommerce-tour-kit-step-navigation { - display: none; - } - h2 { - padding-top: 100px; - font-size: 14px; - line-height: 24px; - } - p.woocommerce-tour-kit-step__description { - font-size: 13px; - line-height: 18px; - margin-top: 8px; - } - .tour-kit-frame__arrow::before { - box-shadow: none !important; - } - - .tour-kit-frame__container[data-popper-placement^='bottom'] { - & > .tour-kit-frame__arrow { - background: #fff; - &::before { - border-top: 1px solid var( --gutenberg-gray-300, #ddd ); - border-left: 1px solid var( --gutenberg-gray-300, #ddd ); - } - } - } - - .tour-kit-frame__container[data-popper-placement^='right'] { - & > .tour-kit-frame__arrow { - background: #fff; - &::before { - border-bottom: 1px solid var( --gutenberg-gray-300, #ddd ); - border-left: 1px solid var( --gutenberg-gray-300, #ddd ); - } - } - } - - a { - display: block; - text-decoration: none; - margin-top: 12px; - padding-block: 11px; - } -} diff --git a/client/deposits/rename-notice/test/__snapshots__/index.tsx.snap b/client/deposits/rename-notice/test/__snapshots__/index.tsx.snap deleted file mode 100644 index 8d2131ec55c..00000000000 --- a/client/deposits/rename-notice/test/__snapshots__/index.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`PayoutsRenameNotice should render notice if isPayoutsRenameNoticeDismissed is false 1`] = ` -
-
- Tour Component -
-
-`; diff --git a/client/deposits/rename-notice/test/index.tsx b/client/deposits/rename-notice/test/index.tsx deleted file mode 100644 index 9f9f2d0c7a8..00000000000 --- a/client/deposits/rename-notice/test/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/** @format */ -/** - * External dependencies - */ -import React from 'react'; -import { render } from '@testing-library/react'; - -/** - * Internal dependencies - */ -import { PayoutsRenameNotice } from '..'; - -jest.mock( '@wordpress/api-fetch', () => jest.fn() ); - -jest.mock( '@wordpress/data', () => ( { - useDispatch: jest.fn().mockReturnValue( { updateOptions: jest.fn() } ), -} ) ); - -jest.mock( '@woocommerce/components', () => ( { - TourKit: () =>
Tour Component
, -} ) ); - -declare const global: { - wcpaySettings: { - isPayoutsRenameNoticeDismissed: boolean; - }; -}; - -describe( 'PayoutsRenameNotice', () => { - afterEach( () => { - jest.clearAllMocks(); - } ); - - test( 'should render null if isPayoutsRenameNoticeDismissed is true', () => { - global.wcpaySettings = { - isPayoutsRenameNoticeDismissed: true, - }; - const { container } = render( ); - expect( container.firstChild ).toBeNull(); - } ); - - test( 'should render notice if isPayoutsRenameNoticeDismissed is false', () => { - global.wcpaySettings = { - isPayoutsRenameNoticeDismissed: false, - }; - const { container } = render( ); - expect( container ).toMatchSnapshot(); - } ); -} ); diff --git a/client/globals.d.ts b/client/globals.d.ts index 8b91ee4b05f..482b6a436d7 100644 --- a/client/globals.d.ts +++ b/client/globals.d.ts @@ -89,7 +89,6 @@ declare global { fraudProtection: { isWelcomeTourDismissed?: boolean; }; - isPayoutsRenameNoticeDismissed: boolean; progressiveOnboarding?: { isEnabled: boolean; isComplete: boolean; diff --git a/client/overview/index.js b/client/overview/index.js index 5d6d06a52c2..4bce8041b07 100644 --- a/client/overview/index.js +++ b/client/overview/index.js @@ -32,7 +32,6 @@ import { useDisputes, useGetSettings, useSettings } from 'data'; import SandboxModeSwitchToLiveNotice from 'wcpay/components/sandbox-mode-switch-to-live-notice'; import './style.scss'; import BannerNotice from 'wcpay/components/banner-notice'; -import { PayoutsRenameNotice } from 'wcpay/deposits/rename-notice'; import DateFormatNotice from 'wcpay/components/date-format-notice'; const OverviewPageError = () => { @@ -197,7 +196,6 @@ const OverviewPage = () => { { showConnectionSuccess && } { ! accountRejected && ! accountUnderReview && ( - { showTaskList && ( diff --git a/client/overview/test/index.js b/client/overview/test/index.js index b0abd762054..f9fe1181b2f 100644 --- a/client/overview/test/index.js +++ b/client/overview/test/index.js @@ -352,24 +352,4 @@ describe( 'Overview page', () => { expect( query() ).not.toBeInTheDocument(); } ); - - it( 'shows payout rename notice if not yet dismissed', () => { - global.wcpaySettings.isPayoutsRenameNoticeDismissed = false; - - render( ); - - expect( - screen.queryByText( 'Deposits are now known as Payouts!' ) - ).toBeInTheDocument(); - } ); - - it( 'does not display payout rename notice if already dismissed', () => { - global.wcpaySettings.isPayoutsRenameNoticeDismissed = true; - - render( ); - - expect( - screen.queryByText( 'Deposits are now known as Payouts!' ) - ).not.toBeInTheDocument(); - } ); } ); diff --git a/includes/admin/class-wc-payments-admin.php b/includes/admin/class-wc-payments-admin.php index 392dec5c611..92010e4c302 100644 --- a/includes/admin/class-wc-payments-admin.php +++ b/includes/admin/class-wc-payments-admin.php @@ -959,7 +959,6 @@ private function get_js_settings(): array { 'fraudProtection' => [ 'isWelcomeTourDismissed' => WC_Payments_Features::is_fraud_protection_welcome_tour_dismissed(), ], - 'isPayoutsRenameNoticeDismissed' => WC_Payments_Features::is_payouts_rename_notice_dismissed(), 'enabledPaymentMethods' => $this->get_enabled_payment_method_ids(), 'progressiveOnboarding' => $this->account->get_progressive_onboarding_details(), 'accountDefaultCurrency' => $this->account->get_account_default_currency(), diff --git a/includes/class-wc-payments-features.php b/includes/class-wc-payments-features.php index fa1748f5311..6eefb80fb9b 100644 --- a/includes/class-wc-payments-features.php +++ b/includes/class-wc-payments-features.php @@ -298,15 +298,6 @@ public static function is_fraud_protection_welcome_tour_dismissed(): bool { return '1' === get_option( 'wcpay_fraud_protection_welcome_tour_dismissed', '0' ); } - /** - * Checks whether the Payouts Rename Spotlight notice was dismissed. - * - * @return bool - */ - public static function is_payouts_rename_notice_dismissed(): bool { - return '1' === get_option( 'wcpay_payouts_rename_notice_dismissed', '0' ); - } - /** * Checks whether the Stripe Billing feature is enabled. * diff --git a/includes/class-wc-payments.php b/includes/class-wc-payments.php index 7b4ae0750c2..a10e44d3fdf 100644 --- a/includes/class-wc-payments.php +++ b/includes/class-wc-payments.php @@ -1923,7 +1923,6 @@ public static function add_wcpay_options_to_woocommerce_permissions_list( $permi 'woocommerce_remind_me_later_todo_tasks', 'woocommerce_deleted_todo_tasks', 'wcpay_fraud_protection_welcome_tour_dismissed', - 'wcpay_payouts_rename_notice_dismissed', 'wcpay_capability_request_dismissed_notices', 'wcpay_onboarding_eligibility_modal_dismissed', 'wcpay_next_deposit_notice_dismissed', From 573a5b3f75e1ef0bb2b18fc125e23c647255c091 Mon Sep 17 00:00:00 2001 From: Alefe Souza Date: Wed, 1 Jan 2025 14:10:10 -0300 Subject: [PATCH 11/33] Fix incompatibility with other booking plugins (#10031) --- changelog/fix-bookings-incompatibily | 4 ++++ includes/class-wc-payments-woopay-button-handler.php | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 changelog/fix-bookings-incompatibily diff --git a/changelog/fix-bookings-incompatibily b/changelog/fix-bookings-incompatibily new file mode 100644 index 00000000000..9a57e9b0853 --- /dev/null +++ b/changelog/fix-bookings-incompatibily @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Fix incompatibility with some bookings plugins. diff --git a/includes/class-wc-payments-woopay-button-handler.php b/includes/class-wc-payments-woopay-button-handler.php index a42fe8046a4..6d731566ebf 100644 --- a/includes/class-wc-payments-woopay-button-handler.php +++ b/includes/class-wc-payments-woopay-button-handler.php @@ -367,12 +367,20 @@ private function is_product_supported() { } // Pre Orders products to be charged upon release are not supported. - if ( class_exists( 'WC_Pre_Orders_Product' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) { + if ( + class_exists( 'WC_Pre_Orders_Product' ) && + method_exists( 'WC_Pre_Orders_Product', 'product_is_charged_upon_release' ) && + WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) + ) { $is_supported = false; } // WC Bookings require confirmation products are not supported. - if ( is_a( $product, 'WC_Product_Booking' ) && $product->get_requires_confirmation() ) { + if ( + is_a( $product, 'WC_Product_Booking' ) && + method_exists( $product, 'get_requires_confirmation' ) && + $product->get_requires_confirmation() + ) { $is_supported = false; } From 8670a4e0d9a6b471cbc2571629b82aeb6ab9cf96 Mon Sep 17 00:00:00 2001 From: Jessy Pappachan <32092402+jessy-p@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:39:49 +0530 Subject: [PATCH 12/33] Changed the term "VAT" on Documents Listing Page to "Tax" to be applicable to all countries (#10055) Co-authored-by: Jessy --- changelog/fix-9923-replace-VAT-term | 4 ++++ .../filters/test/__snapshots__/index.tsx.snap | 2 +- client/documents/list/index.tsx | 4 ++-- .../list/test/__snapshots__/index.tsx.snap | 16 ++++++++-------- client/documents/strings.ts | 2 +- 5 files changed, 16 insertions(+), 12 deletions(-) create mode 100644 changelog/fix-9923-replace-VAT-term diff --git a/changelog/fix-9923-replace-VAT-term b/changelog/fix-9923-replace-VAT-term new file mode 100644 index 00000000000..9a0080c74f8 --- /dev/null +++ b/changelog/fix-9923-replace-VAT-term @@ -0,0 +1,4 @@ +Significance: patch +Type: update + +Replaced the term "VAT" with "Tax" in Documents Listing Page diff --git a/client/documents/filters/test/__snapshots__/index.tsx.snap b/client/documents/filters/test/__snapshots__/index.tsx.snap index b2f8a00d70f..f811c87401d 100644 --- a/client/documents/filters/test/__snapshots__/index.tsx.snap +++ b/client/documents/filters/test/__snapshots__/index.tsx.snap @@ -5,7 +5,7 @@ HTMLOptionsCollection [ , ] `; diff --git a/client/documents/list/index.tsx b/client/documents/list/index.tsx index 3223d45dcec..ff4a947f130 100644 --- a/client/documents/list/index.tsx +++ b/client/documents/list/index.tsx @@ -66,13 +66,13 @@ const getDocumentDescription = ( document: Document ) => { case 'vat_invoice': if ( document.period_from && document.period_to ) { return sprintf( - __( 'VAT invoice for %s to %s', 'woocommerce-payments' ), + __( 'Tax invoice for %s to %s', 'woocommerce-payments' ), formatDateTimeFromString( document.period_from ), formatDateTimeFromString( document.period_to ) ); } return __( - 'VAT invoice without proper period dates', + 'Tax invoice without proper period dates', 'woocommerce-payments' ); diff --git a/client/documents/list/test/__snapshots__/index.tsx.snap b/client/documents/list/test/__snapshots__/index.tsx.snap index 264f8523b33..7b894bd3285 100644 --- a/client/documents/list/test/__snapshots__/index.tsx.snap +++ b/client/documents/list/test/__snapshots__/index.tsx.snap @@ -222,12 +222,12 @@ exports[`Documents list renders correctly 1`] = ` - VAT Invoice + Tax Invoice - VAT invoice without proper period dates + Tax invoice without proper period dates - VAT Invoice + Tax Invoice - VAT invoice without proper period dates + Tax invoice without proper period dates - VAT Invoice + Tax Invoice - VAT invoice without proper period dates + Tax invoice without proper period dates - VAT Invoice + Tax Invoice - VAT invoice without proper period dates + Tax invoice without proper period dates Date: Fri, 3 Jan 2025 19:40:28 +0700 Subject: [PATCH 13/33] Add Payment Method to Transactions advanced filters (#10017) --- .../add-9490-filter-txns-by-payment-method | 4 ++ client/data/transactions/hooks.ts | 13 +++++ client/data/transactions/resolvers.js | 2 + client/transactions/declarations.d.ts | 2 + client/transactions/filters/config.ts | 48 ++++++++++++++++- client/transactions/filters/index.tsx | 14 ++++- .../filters/test/__snapshots__/index.tsx.snap | 20 +++++++ client/transactions/filters/test/index.tsx | 54 +++++++++++++++++++ client/transactions/list/index.tsx | 8 +++ ...-rest-payments-transactions-controller.php | 2 + .../request/class-list-transactions.php | 2 + 11 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 changelog/add-9490-filter-txns-by-payment-method diff --git a/changelog/add-9490-filter-txns-by-payment-method b/changelog/add-9490-filter-txns-by-payment-method new file mode 100644 index 00000000000..04e175479d1 --- /dev/null +++ b/changelog/add-9490-filter-txns-by-payment-method @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Allow transactions filtered by Payment Method diff --git a/client/data/transactions/hooks.ts b/client/data/transactions/hooks.ts index 0b860612dc9..3f1130ed08d 100644 --- a/client/data/transactions/hooks.ts +++ b/client/data/transactions/hooks.ts @@ -87,6 +87,7 @@ interface TransactionsSummary { currency?: string; store_currencies?: string[]; customer_currencies?: string[]; + sources?: Transaction[ 'source' ][]; }; isLoading: boolean; } @@ -158,6 +159,8 @@ export const useTransactions = ( store_currency_is: storeCurrencyIs, customer_currency_is: customerCurrencyIs, customer_currency_is_not: customerCurrencyIsNot, + source_is: sourceIs, + source_is_not: sourceIsNot, loan_id_is: loanIdIs, search, }: Query, @@ -196,6 +199,8 @@ export const useTransactions = ( storeCurrencyIs, customerCurrencyIs, customerCurrencyIsNot, + sourceIs, + sourceIsNot, channelIs, channelIsNot, customerCountryIs, @@ -230,6 +235,8 @@ export const useTransactions = ( storeCurrencyIs, customerCurrencyIs, customerCurrencyIsNot, + sourceIs, + sourceIsNot, channelIs, channelIsNot, customerCountryIs, @@ -256,6 +263,8 @@ export const useTransactionsSummary = ( store_currency_is: storeCurrencyIs, customer_currency_is: customerCurrencyIs, customer_currency_is_not: customerCurrencyIsNot, + source_is: sourceIs, + source_is_not: sourceIsNot, channel_is: channelIs, channel_is_not: channelIsNot, customer_country_is: customerCountryIs, @@ -286,6 +295,8 @@ export const useTransactionsSummary = ( storeCurrencyIs, customerCurrencyIs, customerCurrencyIsNot, + sourceIs, + sourceIsNot, channelIs, channelIsNot, customerCountryIs, @@ -315,6 +326,8 @@ export const useTransactionsSummary = ( storeCurrencyIs, customerCurrencyIs, customerCurrencyIsNot, + sourceIs, + sourceIsNot, channelIs, channelIsNot, customerCountryIs, diff --git a/client/data/transactions/resolvers.js b/client/data/transactions/resolvers.js index 77e517bdf6d..37b1c94fb0d 100644 --- a/client/data/transactions/resolvers.js +++ b/client/data/transactions/resolvers.js @@ -54,6 +54,8 @@ export const formatQueryFilters = ( query ) => ( { deposit_id: query.depositId, customer_currency_is: query.customerCurrencyIs, customer_currency_is_not: query.customerCurrencyIsNot, + source_is: query.sourceIs, + source_is_not: query.sourceIsNot, search: query.search, user_timezone: getUserTimeZone(), locale: query.locale, diff --git a/client/transactions/declarations.d.ts b/client/transactions/declarations.d.ts index 1ee8fe71627..15a6a4ccf27 100644 --- a/client/transactions/declarations.d.ts +++ b/client/transactions/declarations.d.ts @@ -139,6 +139,8 @@ declare module '@woocommerce/navigation' { risk_level_is_not?: string; customer_currency_is?: unknown; customer_currency_is_not?: unknown; + source_is?: string; + source_is_not?: string; store_currency_is?: string; loan_id_is?: string; search?: string[]; diff --git a/client/transactions/filters/config.ts b/client/transactions/filters/config.ts index b5552654494..61be5f4660d 100644 --- a/client/transactions/filters/config.ts +++ b/client/transactions/filters/config.ts @@ -154,7 +154,8 @@ export const getFilters = ( /*eslint-disable max-len*/ export const getAdvancedFilters = ( - customerCurrencyOptions?: TransactionsFilterEntryType[] + customerCurrencyOptions?: TransactionsFilterEntryType[], + transactionSourceOptions?: TransactionsFilterEntryType[] ): any => { // TODO: Remove this and all the checks once we drop support of WooCommerce 7.7 and below. const wooCommerceVersionString = getSetting( 'wcVersion' ); @@ -270,6 +271,51 @@ export const getAdvancedFilters = ( options: customerCurrencyOptions, }, }, + source: { + labels: { + add: __( 'Payment method', 'woocommerce-payments' ), + remove: __( + 'Remove payment method filter', + 'woocommerce-payments' + ), + rule: __( + 'Select a payment method filter match', + 'woocommerce-payments' + ), + title: __( + 'Payment method ', + 'woocommerce-payments' + ), + filter: __( + 'Select a payment method', + 'woocommerce-payments' + ), + }, + rules: [ + { + value: 'is', + /* translators: Sentence fragment, logical, "Is" refers to searching for transactions matching a chosen payment method. */ + label: _x( + 'Is', + 'payment method', + 'woocommerce-payments' + ), + }, + { + value: 'is_not', + /* translators: Sentence fragment, logical, "Is not" refers to searching for transactions that don\'t match a chosen payment method. */ + label: _x( + 'Is not', + 'payment method', + 'woocommerce-payments' + ), + }, + ], + input: { + component: 'SelectControl', + options: transactionSourceOptions, + }, + }, type: { labels: { add: __( 'Type', 'woocommerce-payments' ), diff --git a/client/transactions/filters/index.tsx b/client/transactions/filters/index.tsx index ef8c11d4f15..b468f0c5bed 100644 --- a/client/transactions/filters/index.tsx +++ b/client/transactions/filters/index.tsx @@ -11,15 +11,19 @@ import { getQuery } from '@woocommerce/navigation'; import { getFilters, getAdvancedFilters } from './config'; import { formatCurrencyName } from 'multi-currency/interface/functions'; import { recordEvent } from 'tracks'; +import { PAYMENT_METHOD_TITLES } from 'wcpay/constants/payment-method'; +import { Transaction } from 'wcpay/data'; interface TransactionsFiltersProps { storeCurrencies: string[]; customerCurrencies: string[]; + transactionSources: Transaction[ 'source' ][]; } export const TransactionsFilters = ( { storeCurrencies, customerCurrencies, + transactionSources, }: TransactionsFiltersProps ): JSX.Element => { const advancedFilters = useMemo( () => @@ -27,9 +31,15 @@ export const TransactionsFilters = ( { customerCurrencies.map( ( currencyCode: string ) => ( { label: formatCurrencyName( currencyCode ), value: currencyCode, - } ) ) + } ) ), + typeof transactionSources === 'undefined' + ? [] + : transactionSources.map( ( source ) => ( { + label: PAYMENT_METHOD_TITLES[ source ] || source, + value: source, + } ) ) ), - [ customerCurrencies ] + [ customerCurrencies, transactionSources ] ); const filters = useMemo( diff --git a/client/transactions/filters/test/__snapshots__/index.tsx.snap b/client/transactions/filters/test/__snapshots__/index.tsx.snap index b8aefe7a57b..a2a2a7bd3da 100644 --- a/client/transactions/filters/test/__snapshots__/index.tsx.snap +++ b/client/transactions/filters/test/__snapshots__/index.tsx.snap @@ -55,6 +55,26 @@ HTMLOptionsCollection [ ] `; +exports[`Transactions filters when filtering by payment method should render all types 1`] = ` +HTMLOptionsCollection [ + , + , + , +] +`; + exports[`Transactions filters when filtering by risk level should render all types 1`] = ` HTMLOptionsCollection [