Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Payment Method to Transactions advanced filters #10017

Merged
merged 10 commits into from
Jan 3, 2025
4 changes: 4 additions & 0 deletions changelog/add-9490-filter-txns-by-payment-method
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Allow transactions filtered by Payment Method
13 changes: 13 additions & 0 deletions client/data/transactions/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ interface TransactionsSummary {
currency?: string;
store_currencies?: string[];
customer_currencies?: string[];
sources?: Transaction[ 'source' ][];
};
isLoading: boolean;
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -196,6 +199,8 @@ export const useTransactions = (
storeCurrencyIs,
customerCurrencyIs,
customerCurrencyIsNot,
sourceIs,
sourceIsNot,
channelIs,
channelIsNot,
customerCountryIs,
Expand Down Expand Up @@ -230,6 +235,8 @@ export const useTransactions = (
storeCurrencyIs,
customerCurrencyIs,
customerCurrencyIsNot,
sourceIs,
sourceIsNot,
channelIs,
channelIsNot,
customerCountryIs,
Expand All @@ -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,
Expand Down Expand Up @@ -286,6 +295,8 @@ export const useTransactionsSummary = (
storeCurrencyIs,
customerCurrencyIs,
customerCurrencyIsNot,
sourceIs,
sourceIsNot,
channelIs,
channelIsNot,
customerCountryIs,
Expand Down Expand Up @@ -315,6 +326,8 @@ export const useTransactionsSummary = (
storeCurrencyIs,
customerCurrencyIs,
customerCurrencyIsNot,
sourceIs,
sourceIsNot,
channelIs,
channelIsNot,
customerCountryIs,
Expand Down
2 changes: 2 additions & 0 deletions client/data/transactions/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions client/transactions/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand Down
48 changes: 47 additions & 1 deletion client/transactions/filters/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
Expand Down Expand Up @@ -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: __(
'<title>Payment method</title> <rule /> <filter />',
'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' ),
Expand Down
14 changes: 12 additions & 2 deletions client/transactions/filters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,35 @@ 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(
() =>
getAdvancedFilters(
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(
Expand Down
20 changes: 20 additions & 0 deletions client/transactions/filters/test/__snapshots__/index.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@ HTMLOptionsCollection [
]
`;

exports[`Transactions filters when filtering by payment method should render all types 1`] = `
HTMLOptionsCollection [
<option
value="visa"
>
Visa
</option>,
<option
value="mastercard"
>
Mastercard
</option>,
<option
value="sofort"
>
SOFORT
</option>,
]
`;

exports[`Transactions filters when filtering by risk level should render all types 1`] = `
HTMLOptionsCollection [
<option
Expand Down
54 changes: 54 additions & 0 deletions client/transactions/filters/test/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getQuery, updateQueryString } from '@woocommerce/navigation';
* Internal dependencies
*/
import { TransactionsFilters } from '../';
import { Transaction } from 'wcpay/data';

// TODO: this is a bit of a hack as we're mocking an old version of WC, we should relook at this.
jest.mock( '@woocommerce/settings', () => ( {
Expand All @@ -33,6 +34,11 @@ function addAdvancedFilter( filter: string ) {

const storeCurrencies = [ 'eur', 'usd' ];
const customerCurrencies = [ 'eur', 'usd', 'gbp' ];
const transactionSources: Transaction[ 'source' ][] = [
'visa',
'mastercard',
'sofort',
];

declare const global: {
wcSettings: { countries: Record< string, string > };
Expand Down Expand Up @@ -71,6 +77,7 @@ describe( 'Transactions filters', () => {
<TransactionsFilters
storeCurrencies={ storeCurrencies }
customerCurrencies={ customerCurrencies }
transactionSources={ transactionSources }
/>
);

Expand All @@ -85,6 +92,7 @@ describe( 'Transactions filters', () => {
<TransactionsFilters
storeCurrencies={ storeCurrencies }
customerCurrencies={ customerCurrencies }
transactionSources={ transactionSources }
/>
);
} );
Expand Down Expand Up @@ -250,6 +258,52 @@ describe( 'Transactions filters', () => {
} );
} );

describe( 'when filtering by payment method', () => {
let ruleSelector: HTMLElement;

beforeEach( () => {
addAdvancedFilter( 'Payment method' );
ruleSelector = screen.getByRole( 'combobox', {
name: /payment method filter/i,
} );
} );

test( 'should render all types', () => {
const typeSelect = screen.getByRole( 'combobox', {
name: /payment method$/i,
} ) as HTMLSelectElement;
expect( typeSelect.options ).toMatchSnapshot();
} );

test( 'should filter by is', () => {
user.selectOptions( ruleSelector, 'is' );

user.selectOptions(
screen.getByRole( 'combobox', {
name: /Select a payment method$/i,
} ),
'visa'
);
user.click( screen.getByRole( 'link', { name: /Filter/ } ) );

expect( getQuery().source_is ).toEqual( 'visa' );
} );

test( 'should filter by is_not', () => {
user.selectOptions( ruleSelector, 'is_not' );

user.selectOptions(
screen.getByRole( 'combobox', {
name: /Select a payment method$/i,
} ),
'visa'
);
user.click( screen.getByRole( 'link', { name: /Filter/ } ) );

expect( getQuery().source_is_not ).toEqual( 'visa' );
} );
} );

describe( 'when filtering by source device', () => {
let ruleSelector: HTMLElement;

Expand Down
8 changes: 8 additions & 0 deletions client/transactions/list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -624,13 +624,17 @@ export const TransactionsList = (
risk_level_is_not: riskLevelIsNot,
customer_currency_is: customerCurrencyIs,
customer_currency_is_not: customerCurrencyIsNot,
source_is: sourceIs,
source_is_not: sourceIsNot,
} = params;
const depositId = props.depositId;

const isFiltered =
!! dateAfter ||
!! dateBefore ||
!! dateBetween ||
!! sourceIs ||
!! sourceIsNot ||
!! search ||
!! typeIs ||
!! typeIsNot ||
Expand Down Expand Up @@ -673,6 +677,8 @@ export const TransactionsList = (
sourceDeviceIsNot,
customerCurrencyIs,
customerCurrencyIsNot,
sourceIs,
sourceIsNot,
channelIs,
channelIsNot,
customerCountryIs,
Expand Down Expand Up @@ -825,13 +831,15 @@ export const TransactionsList = (
transactionsSummary.store_currencies ||
( isCurrencyFiltered ? [ getQuery().store_currency_is ?? '' ] : [] );
const customerCurrencies = transactionsSummary.customer_currencies || [];
const transactionSources = transactionsSummary.sources || [];

return (
<Page>
{ showFilters && (
<TransactionsFilters
storeCurrencies={ storeCurrencies }
customerCurrencies={ customerCurrencies }
transactionSources={ transactionSources }
/>
) }
<TableCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ function ( $transaction_date ) use ( $user_timezone ) {
'store_currency_is' => $request->get_param( 'store_currency_is' ),
'customer_currency_is' => $request->get_param( 'customer_currency_is' ),
'customer_currency_is_not' => $request->get_param( 'customer_currency_is_not' ),
'source_is' => $request->get_param( 'source_is' ),
'source_is_not' => $request->get_param( 'source_is_not' ),
'loan_id_is' => $request->get_param( 'loan_id_is' ),
'search' => $request->get_param( 'search' ),
],
Expand Down
2 changes: 2 additions & 0 deletions includes/core/server/request/class-list-transactions.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ function ( $transaction_date ) use ( $user_timezone ) {
'store_currency_is' => $request->get_param( 'store_currency_is' ),
'customer_currency_is' => $request->get_param( 'customer_currency_is' ),
'customer_currency_is_not' => $request->get_param( 'customer_currency_is_not' ),
'source_is' => $request->get_param( 'source_is' ),
'source_is_not' => $request->get_param( 'source_is_not' ),
'loan_id_is' => $request->get_param( 'loan_id_is' ),
'search' => (array) $request->get_param( 'search' ),
'deposit_id' => $request->get_param( 'deposit_id' ),
Expand Down
Loading