Skip to content

Conversation

@mgascam
Copy link
Contributor

@mgascam mgascam commented Nov 18, 2025

Summary

Fixes #WOOPMNT-5550

Adds a remediation tool to fix incorrect analytics data caused by a bug that existed between April 2023 and November 2025. When payment authorizations were canceled (not captured), the system incorrectly:

  1. Recorded transaction fees (_wcpay_transaction_fee and _wcpay_net metadata)
  2. Created WCPay refund objects for the full order amount
  3. Set order status to "refunded" instead of "cancelled"

This caused negative values in WooCommerce Analytics for affected stores using manual capture.

Changes

File Purpose
includes/migrations/class-wc-payments-remediate-canceled-auth-fees.php Core remediation logic with batch processing via Action Scheduler
includes/notes/class-wc-payments-notes-canceled-auth-remediation.php WC Admin Inbox Note to notify affected merchants
includes/class-wc-payments.php Registers remediation class and inbox note
includes/class-wc-payments-status.php Adds tool to WooCommerce > Status > Tools
tests/unit/migrations/test-class-wc-payments-remediate-canceled-auth-fees.php 48 unit tests
tests/unit/notes/test-class-wc-payments-notes-canceled-auth-remediation.php 2 unit tests

How It Works

  1. Detection: Finds orders with _intention_status = canceled created after April 2023 that have incorrect fee metadata, WCPay refunds, or "refunded" status
  2. Remediation: Removes fee metadata, deletes WCPay refunds (preserves manual refunds), changes status to "cancelled"
  3. Analytics Sync: Cleans up wp_wc_order_stats table and triggers WooCommerce Analytics sync
  4. Audit Trail: Adds detailed order note documenting all changes

Safety Measures

  • ✅ Only affects orders with _intention_status = canceled
  • ✅ Only deletes refunds with _wcpay_refund_id metadata (preserves manual refunds)
  • ✅ Supports both HPOS and legacy CPT storage
  • ✅ Processes in adaptive batches (10-100 orders) to avoid timeouts
  • ✅ Safe to run multiple times
  • ✅ Detailed logging via wc_get_logger()

Testing Instructions

Setup - Create test data

  1. Use the test data generator script
  2. Place it in your WordPress root and run: wp eval-file create-test-data-canceled-auth.php
  3. This creates 7 test orders covering all affected scenarios

Verify the problem exists

  1. Go to WooCommerce > Analytics > Revenue
  2. You should see negative "Returns" values from the fake refund objects

Run the remediation

  1. Go to WooCommerce > Status > Tools
  2. Find "Fix canceled authorization analytics" tool
  3. Click "Run" and confirm the prompt
  4. Refresh page to see progress (Running → Completed)

Verify the fix

  1. Tool shows "Completed" with processed/remediated counts
  2. Analytics > Revenue - Returns should now be correct
  3. Check affected orders:
    • Fee metadata removed
    • WCPay refunds deleted
    • Status changed from "refunded" to "cancelled"
    • Order note documents all changes

Test scenarios

Order Scenario Expected Result
1 Fee metadata only Metadata removed
2 WCPay refund only Refund deleted
3 Fee + WCPay refund Both removed
4 WCPay + manual refund WCPay deleted, manual preserved
5 "Refunded" status only Status → "cancelled"
6 Before bug date (Feb 2023) NOT remediated
7 Succeeded intent NOT remediated

Cleanup

wp option delete wcpay_test_data_created
wp option delete wcpay_fee_remediation_status
wp option delete wcpay_fee_remediation_stats

  • Run npm run changelog to add a changelog file
  • Covered with tests (50 unit tests)
  • Tested on mobile (N/A - admin tool only)

Post merge

  • QA Testing Not Applicable (analytics fix, no user-facing payment flow changes)

@mgascam mgascam force-pushed the cancel-auth-fee-remediation branch from baba383 to e41ef6a Compare November 18, 2025 13:13
@github-actions
Copy link
Contributor

github-actions bot commented Nov 18, 2025

Test the build

Option 1. Jetpack Beta

  • Install and activate Jetpack Beta.
  • Use this build by searching for PR number 11140 or branch name cancel-auth-fee-remediation in your-test.site/wp-admin/admin.php?page=jetpack-beta&plugin=woocommerce-payments

Option 2. Jurassic Ninja - available for logged-in A12s

🚀 Launch a JN site with this branch 🚀

ℹ️ Install this Tampermonkey script to get more options.


Build info:

  • Latest commit: fa03b13
  • Build time: 2025-12-04 13:19:22 UTC

Note: the build is updated when a new commit is pushed to this PR.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 18, 2025

Size Change: 0 B

Total Size: 877 kB

ℹ️ View Unchanged
Filename Size
release/woocommerce-payments/assets/css/admin.css 1.45 kB
release/woocommerce-payments/assets/css/admin.rtl.css 1.45 kB
release/woocommerce-payments/assets/css/success.css 1.06 kB
release/woocommerce-payments/assets/css/success.rtl.css 1.06 kB
release/woocommerce-payments/dist/blocks-checkout-rtl.css 3.05 kB
release/woocommerce-payments/dist/blocks-checkout.css 3.05 kB
release/woocommerce-payments/dist/blocks-checkout.js 54.6 kB
release/woocommerce-payments/dist/cart-block-rtl.css 113 B
release/woocommerce-payments/dist/cart-block.css 112 B
release/woocommerce-payments/dist/cart-block.js 16.7 kB
release/woocommerce-payments/dist/cart.js 5.27 kB
release/woocommerce-payments/dist/checkout-rtl.css 1.13 kB
release/woocommerce-payments/dist/checkout.css 1.13 kB
release/woocommerce-payments/dist/checkout.js 34.6 kB
release/woocommerce-payments/dist/express-checkout-rtl.css 367 B
release/woocommerce-payments/dist/express-checkout.css 367 B
release/woocommerce-payments/dist/express-checkout.js 16.8 kB
release/woocommerce-payments/dist/frontend-tracks.js 833 B
release/woocommerce-payments/dist/index-rtl.css 21.2 kB
release/woocommerce-payments/dist/index.css 21.3 kB
release/woocommerce-payments/dist/index.js 155 kB
release/woocommerce-payments/dist/multi-currency-analytics.js 1.08 kB
release/woocommerce-payments/dist/multi-currency-rtl.css 3.82 kB
release/woocommerce-payments/dist/multi-currency-switcher-block.js 18.2 kB
release/woocommerce-payments/dist/multi-currency.css 3.83 kB
release/woocommerce-payments/dist/multi-currency.js 24.7 kB
release/woocommerce-payments/dist/order-rtl.css 740 B
release/woocommerce-payments/dist/order.css 740 B
release/woocommerce-payments/dist/order.js 21.3 kB
release/woocommerce-payments/dist/plugins-page-rtl.css 484 B
release/woocommerce-payments/dist/plugins-page.css 484 B
release/woocommerce-payments/dist/plugins-page.js 2.64 kB
release/woocommerce-payments/dist/product-details-rtl.css 433 B
release/woocommerce-payments/dist/product-details.css 436 B
release/woocommerce-payments/dist/product-details.js 12.3 kB
release/woocommerce-payments/dist/settings-rtl.css 11.8 kB
release/woocommerce-payments/dist/settings.css 11.7 kB
release/woocommerce-payments/dist/settings.js 141 kB
release/woocommerce-payments/dist/subscription-edit-page.js 703 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal-rtl.css 527 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.css 527 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.js 1.98 kB
release/woocommerce-payments/dist/subscription-product-onboarding-toast.js 730 B
release/woocommerce-payments/dist/subscriptions-empty-state-rtl.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.js 1.9 kB
release/woocommerce-payments/dist/success.js 6.03 kB
release/woocommerce-payments/dist/tos-rtl.css 235 B
release/woocommerce-payments/dist/tos.css 235 B
release/woocommerce-payments/dist/tos.js 3 kB
release/woocommerce-payments/dist/woopay-direct-checkout.js 5.68 kB
release/woocommerce-payments/dist/woopay-express-button.js 22.8 kB
release/woocommerce-payments/dist/woopay-rtl.css 4.27 kB
release/woocommerce-payments/dist/woopay.css 4.25 kB
release/woocommerce-payments/dist/woopay.js 70.8 kB
release/woocommerce-payments/includes/subscriptions/assets/css/plugin-page.css 625 B
release/woocommerce-payments/includes/subscriptions/assets/js/plugin-page.js 814 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/i18n-loader.js 2.46 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/jetpack-script-data.js 957 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/i18n-loader.js 1.02 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/script-data.js 69 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/babel.config.js 163 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.css 2.47 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.js 14.3 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.rtl.css 2.47 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.css 10.1 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.js 29.7 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.rtl.css 10.1 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.js 280 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.rtl.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.css 625 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.js 333 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.rtl.css 626 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-users.js 417 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-users-connection.js 161 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-ajax.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-callables.js 585 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.css 215 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.css 721 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.js 412 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-users.js 625 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/about.css 1.04 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-empty-state.css 294 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-order-statuses.css 408 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin.css 3.59 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/checkout.css 301 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/modal.css 746 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/view-subscription.css 574 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/wcs-upgrade.css 414 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin-pointers.js 543 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin.js 9.4 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.js 6.78 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.min.js 3.84 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-coupon.js 545 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-subscription.js 2.52 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.js 22.2 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.min.js 11.7 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/payment-method-restrictions.js 1.29 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/wcs-meta-boxes-order.js 507 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/payment-methods.js 358 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/single-product.js 428 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/view-subscription.js 1.38 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/wcs-cart.js 782 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/modal.js 1.09 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/wcs-upgrade.js 1.26 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.css 391 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.js 3.04 kB

compressed-size-action

@mgascam mgascam requested a review from Copilot November 19, 2025 18:31
Copilot finished reviewing on behalf of mgascam November 19, 2025 18:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a data remediation migration to fix incorrect transaction fees and refund records that were created for canceled payment authorizations. The bug affected orders between April 2023 and November 2025 where canceled authorizations incorrectly had transaction fees and refund objects created despite no actual payment occurring.

Key Changes

  • New migration class that processes affected orders in adaptive batches using Action Scheduler
  • Integration with plugin upgrade hooks to automatically schedule remediation when updating from affected versions
  • Comprehensive test coverage for the remediation logic and batch processing

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
includes/migrations/class-wc-payments-remediate-canceled-auth-fees.php Core migration class implementing batch processing, order remediation, and adaptive batch sizing
includes/class-wc-payments.php Integration of remediation into plugin initialization and update hooks
tests/unit/migrations/test-class-wc-payments-remediate-canceled-auth-fees.php Comprehensive unit tests covering all migration functionality

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mgascam mgascam requested a review from Copilot November 26, 2025 11:09
Copilot finished reviewing on behalf of mgascam November 26, 2025 11:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mgascam mgascam requested a review from Copilot November 26, 2025 19:25
Copilot finished reviewing on behalf of mgascam November 26, 2025 19:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mgascam mgascam changed the title Add remediation for canceled authorization fees Add remediation tool to fix incorrect analytics data from canceled authorizations Nov 27, 2025
@mgascam mgascam requested a review from Copilot November 27, 2025 13:54
Copilot finished reviewing on behalf of mgascam November 27, 2025 13:56
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mgascam mgascam marked this pull request as ready for review November 27, 2025 18:28
@mgascam mgascam requested review from a team and Copilot November 27, 2025 18:28
@mgascam mgascam requested a review from elazzabi November 27, 2025 18:29
@mgascam
Copy link
Contributor Author

mgascam commented Nov 27, 2025

Hi @elazzabi I requested your review because you worked on the fix and have some context already.

Copilot finished reviewing on behalf of mgascam November 27, 2025 18:30
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@frosso frosso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work with the addition of the dry run option!

I ran all the steps for the "Fix canceled authorization analytics", and they worked flawlessly!

Image Image Image Image

I later reset the DB with your instructions, and launched the "Dry run" option (I know it's uncommon to first launch the full action and then the dry run).
I stumbled into a state where I couldn't run the full action, anymore. But the wcpay-fee-remediation log was created:

Image Image

Is this due to my testing approach? 👀

Comment on lines +86 to +89
/**
* Version where bug was introduced (5.8.0 = April 2023, commit 2d13751).
*/
const BUG_INTRODUCED_VERSION = '5.8.0';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed as part of a const? Or can it just be a comment on the class?

}

include_once WCPAY_ABSPATH . 'includes/migrations/class-wc-payments-remediate-canceled-auth-fees.php';
return as_has_scheduled_action( WC_Payments_Remediate_Canceled_Auth_Fees::ACTION_HOOK );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that here, we only checked if WC_Payments_Remediate_Canceled_Auth_Fees::ACTION_HOOK is scheduled. But on the schedule_canceled_auth_dry_run method, we check both WC_Payments_Remediate_Canceled_Auth_Fees::ACTION_HOOK and WC_Payments_Remediate_Canceled_Auth_Fees::DRY_RUN_ACTION_HOOK.

Could this lead to some inconsistent UI state? I'm unsure if we need to check for the "dry run" action here, as well 🤷

@mgascam mgascam self-assigned this Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants