diff --git a/changelog/fix-server-5934-payment-widget-data-mismatch b/changelog/fix-server-5934-payment-widget-data-mismatch new file mode 100644 index 00000000000..71e70f6c681 --- /dev/null +++ b/changelog/fix-server-5934-payment-widget-data-mismatch @@ -0,0 +1,5 @@ +Significance: patch +Type: fix +Comment: Make the numbers on the payment activity widget match the totals on the clicked detailed reports screen. + + diff --git a/client/components/payment-activity/payment-activity-data.tsx b/client/components/payment-activity/payment-activity-data.tsx index 09fea5b38f2..255770e587f 100644 --- a/client/components/payment-activity/payment-activity-data.tsx +++ b/client/components/payment-activity/payment-activity-data.tsx @@ -68,6 +68,8 @@ const PaymentActivityDataComponent: React.FC< Props > = ( { const disputes = paymentActivityData?.disputes ?? 0; const refunds = paymentActivityData?.refunds ?? 0; const currency = paymentActivityData?.currency; + const siteTimeZone = wcSettings.admin.timeZone; + // We need to add a time offset to the date range to ensure the correct dates are passed on to the transactions report via the view report link. return (
@@ -114,12 +116,12 @@ const PaymentActivityDataComponent: React.FC< Props > = ( { path: '/payments/transactions', filter: 'advanced', store_currency_is: currency, - 'date_between[0]': moment( - paymentActivityData?.date_start - ).format( 'YYYY-MM-DD' ), - 'date_between[1]': moment( - paymentActivityData?.date_end - ).format( 'YYYY-MM-DD' ), + 'date_between[0]': moment( paymentActivityData?.date_start ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), + 'date_between[1]': moment( paymentActivityData?.date_end ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), ...getSearchParams( searchTermsForViewReportLink.totalPaymentVolume ), @@ -159,10 +161,14 @@ const PaymentActivityDataComponent: React.FC< Props > = ( { store_currency_is: currency, 'date_between[0]': moment( paymentActivityData?.date_start - ).format( 'YYYY-MM-DD' ), + ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), 'date_between[1]': moment( paymentActivityData?.date_end - ).format( 'YYYY-MM-DD' ), + ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), ...getSearchParams( searchTermsForViewReportLink.charge ), @@ -182,10 +188,14 @@ const PaymentActivityDataComponent: React.FC< Props > = ( { store_currency_is: currency, 'date_between[0]': moment( paymentActivityData?.date_start - ).format( 'YYYY-MM-DD' ), + ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), 'date_between[1]': moment( paymentActivityData?.date_end - ).format( 'YYYY-MM-DD' ), + ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), ...getSearchParams( searchTermsForViewReportLink.refunds ), @@ -232,10 +242,14 @@ const PaymentActivityDataComponent: React.FC< Props > = ( { store_currency_is: currency, 'date_between[0]': moment( paymentActivityData?.date_start - ).format( 'YYYY-MM-DD' ), + ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), 'date_between[1]': moment( paymentActivityData?.date_end - ).format( 'YYYY-MM-DD' ), + ) + .add( siteTimeZone ) + .format( 'YYYY-MM-DD' ), ...getSearchParams( searchTermsForViewReportLink.dispute ), diff --git a/client/components/payment-activity/test/index.test.tsx b/client/components/payment-activity/test/index.test.tsx index fe3d29376de..fdba8a5a8ed 100644 --- a/client/components/payment-activity/test/index.test.tsx +++ b/client/components/payment-activity/test/index.test.tsx @@ -74,6 +74,11 @@ declare const global: { country: string; }; }; + wcSettings: { + admin: { + timeZone: string; + }; + }; }; describe( 'PaymentActivity component', () => { @@ -118,6 +123,11 @@ describe( 'PaymentActivity component', () => { Date.now = jest.fn( () => new Date( '2024-04-08T12:33:37.000Z' ).getTime() ); + global.wcSettings = { + admin: { + timeZone: 'UTC', + }, + }; } ); afterEach( () => { diff --git a/client/globals.d.ts b/client/globals.d.ts index 972f0731403..ec99d1150b7 100644 --- a/client/globals.d.ts +++ b/client/globals.d.ts @@ -176,6 +176,7 @@ declare global { woocommerce_coming_soon: string; woocommerce_private_link: string; }; + timeZone: string; }; adminUrl: string; countries: Record< string, string >; diff --git a/includes/admin/class-wc-rest-payments-reporting-controller.php b/includes/admin/class-wc-rest-payments-reporting-controller.php index 56fce001f5e..dccc7b1a87d 100644 --- a/includes/admin/class-wc-rest-payments-reporting-controller.php +++ b/includes/admin/class-wc-rest-payments-reporting-controller.php @@ -6,6 +6,7 @@ */ use WCPay\Core\Server\Request\Get_Reporting_Payment_Activity; +use WCPay\Core\Server\Request\Request_Utils; defined( 'ABSPATH' ) || exit; @@ -44,11 +45,27 @@ public function register_routes() { * @param WP_REST_Request $request The request. */ public function get_payment_activity( $request ) { - $wcpay_request = Get_Reporting_Payment_Activity::create(); - $wcpay_request->set_date_start( $request->get_param( 'date_start' ) ); - $wcpay_request->set_date_end( $request->get_param( 'date_end' ) ); + $wcpay_request = Get_Reporting_Payment_Activity::create(); + $date_start_in_store_timezone = $this->format_date_to_wp_timezone( $request->get_param( 'date_start' ) ); + $date_end_in_store_timezone = $this->format_date_to_wp_timezone( $request->get_param( 'date_end' ) ); + $wcpay_request->set_date_start( $date_start_in_store_timezone ); + $wcpay_request->set_date_end( $date_end_in_store_timezone ); $wcpay_request->set_timezone( $request->get_param( 'timezone' ) ); $wcpay_request->set_currency( $request->get_param( 'currency' ) ); return $wcpay_request->handle_rest_request(); } + + + + /** + * Formats a date string to the WordPress timezone. + * + * @param string $date_string The date string to be formatted. + * @return string The formatted date string in the 'Y-m-d\TH:i:s' format. + */ + private function format_date_to_wp_timezone( $date_string ) { + $date = Request_Utils::format_transaction_date_by_timezone( $date_string, '+00:00' ); + $date = new DateTime( $date ); + return $date->format( 'Y-m-d\\TH:i:s' ); + } }