Skip to content

Conversation

@mgascam
Copy link
Contributor

@mgascam mgascam commented Dec 4, 2025

Fixes WOOPMNT-5430

Changes proposed in this Pull Request

This PR introduces a matrix-based architecture for managing dispute evidence document recommendations based on dispute reason and product type combinations.

Why this change is needed:
The dispute challenge form needs to show different recommended evidence documents depending on the combination of dispute reason (fraudulent, duplicate, subscription_canceled, etc.) and product type (booking_reservation, physical_product, etc.). Previously, this logic was spread across multiple conditionals. This matrix approach provides:

  • Better scalability for adding new reason × product type combinations
  • Clearer organization of evidence suggestions
  • Easier maintenance as new product types or reasons are added

What this change does:

  1. Creates an evidence matrix (evidence-matrix.ts) that maps [reason][productType] to recommended document fields
  2. Extracts DOCUMENT_FIELD_KEYS to a separate file to avoid circular dependencies
  3. Adds feature-flag-gated logic in getRecommendedDocumentFields() to use the matrix when available
  4. Implements new evidence suggestions for fraudulent + booking_reservation (WOOPMNT-5430):
    • Prior undisputed transaction history
    • Receipt
    • Customer communication
    • Refund policy
  5. Migrates existing develop branch changes to the matrix:
    • subscription_canceled + multiple (no subscription logs)
    • subscription_canceled + other (simplified fields)
    • duplicate + booking_reservation entries for both is_duplicate and is_not_duplicate scenarios

Fallback behavior:

  • Feature flag OFF: Uses trunk (production) behavior for all combinations
  • Feature flag ON + matrix entry exists: Uses matrix entry
  • Feature flag ON + no matrix entry: Falls back to trunk behavior

This allows incremental implementation - each [reason][productType] combination can be added to the matrix task by task, while unimplemented combinations safely fall back to trunk behavior.

Trade-offs:

  • Composite keys (productType__status) are used for status-dependent lookups (duplicate disputes) rather than a nested structure, keeping the lookup simple while supporting the additional dimension

How can this code break?

  • If the feature flag is disabled, the code falls back to trunk behavior (backward compatible)
  • If a matrix entry doesn't exist for a combination, falls back to trunk behavior

What are we doing to make sure this code doesn't break?

  • 19 unit tests covering matrix combinations and fallback scenarios
  • All tests pass
  • Feature-flagged behind isDisputeAdditionalEvidenceTypesEnabled

Testing instructions

Prerequisites:
Enable the feature flag:

wp option update _wcpay_feature_dispute_additional_evidence_types 1

Test cases:

  1. Fraudulent + Booking/Reservation (new feature - WOOPMNT-5430):

    • Create a dispute with reason fraudulent for a booking/reservation product
    • Navigate to the dispute challenge form
    • Verify recommended documents show:
      • Prior undisputed transaction history
      • Receipt
      • Customer communication
      • Refund policy
  2. Subscription Canceled + Multiple:

    • Create a dispute with reason subscription_canceled for an order with multiple products
    • Verify recommended documents do NOT include "Subscription logs"
  3. Subscription Canceled + Other:

    • Create a dispute with reason subscription_canceled for an "other" product type
    • Verify simplified fields: Proof of Purchase, Order details
  4. Duplicate + Booking/Reservation + Is Duplicate:

    • Create a duplicate dispute for a booking/reservation product, select "It was a duplicate"
    • Verify fields: Order receipt, Refund receipt, Refund policy
  5. Duplicate + Booking/Reservation + Is Not Duplicate:

    • Create a duplicate dispute for a booking/reservation product, select "It was not a duplicate"
    • Verify fields: Order receipt, Any additional receipts, Customer communication, Refund policy, Other documents
  6. Feature flag OFF (backward compatibility):

    • Disable the feature flag: wp option delete _wcpay_feature_dispute_additional_evidence_types
    • Verify all dispute types show original recommended documents (trunk behavior)
  7. Unimplemented combinations fall back to trunk:

    • With feature flag ON, test subscription_canceled + physical_product
    • Verify it shows trunk behavior (with "Proof of active subscription" label)
    • With feature flag ON, test duplicate + physical_product
    • Verify it shows trunk behavior (not the booking_reservation-specific fields)

  • Run npm run changelog to add a changelog file, choose patch to leave it empty if the change is not significant.
  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Post merge

@github-actions
Copy link
Contributor

github-actions bot commented Dec 4, 2025

Test the build

Option 1. Jetpack Beta

  • Install and activate Jetpack Beta.
  • Use this build by searching for PR number 11181 or branch name woopmnt-5430-booking-reservation-fraudulent-purchase-info-page-update 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: 22090cf
  • Build time: 2025-12-05 19:04:34 UTC

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

@github-actions
Copy link
Contributor

github-actions bot commented Dec 4, 2025

Size Change: +50.6 kB (+6%) 🔍

Total Size: 927 kB

Filename Size Change
release/woocommerce-payments/dist/index-rtl.css 21.8 kB +572 B (+3%)
release/woocommerce-payments/dist/index.css 21.8 kB +569 B (+3%)
release/woocommerce-payments/dist/index.js 158 kB +2.95 kB (+2%)
release/woocommerce-payments/dist/multi-currency-switcher-block.js 18.9 kB +635 B (+3%)
release/woocommerce-payments/dist/multi-currency.js 25.3 kB +618 B (+3%)
release/woocommerce-payments/dist/order.js 22 kB +657 B (+3%)
release/woocommerce-payments/dist/settings-rtl.css 12.4 kB +556 B (+5%) 🔍
release/woocommerce-payments/dist/settings.css 12.2 kB +551 B (+5%) 🔍
release/woocommerce-payments/dist/settings.js 152 kB +11.4 kB (+8%) 🔍
release/woocommerce-payments/dist/subscription-edit-page.js 1.81 kB +1.11 kB (+158%) 🆘
release/woocommerce-payments/dist/wc-payments-settings-spotlight-rtl.css 1.59 kB +1.59 kB (new file) 🆕
release/woocommerce-payments/dist/wc-payments-settings-spotlight.css 1.59 kB +1.59 kB (new file) 🆕
release/woocommerce-payments/dist/wc-payments-settings-spotlight.js 27.8 kB +27.8 kB (new file) 🆕
ℹ️ 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/multi-currency-analytics.js 1.08 kB
release/woocommerce-payments/dist/multi-currency-rtl.css 3.82 kB
release/woocommerce-payments/dist/multi-currency.css 3.83 kB
release/woocommerce-payments/dist/order-rtl.css 740 B
release/woocommerce-payments/dist/order.css 740 B
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/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 December 4, 2025 21:17
Copilot finished reviewing on behalf of mgascam December 4, 2025 21:18
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 refactors the dispute evidence recommendation system by extracting constants and introducing a feature-flagged evidence matrix for more granular control over recommended document fields based on dispute reason and product type combinations.

  • Extracts DOCUMENT_FIELD_KEYS constants into a separate module for better code organization
  • Introduces an evidence matrix system that maps dispute reasons and product types to specific recommended document fields
  • Adds comprehensive test coverage for the new feature-flagged evidence matrix functionality

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
client/disputes/new-evidence/document-field-keys.ts New file extracting document field key constants previously defined inline
client/disputes/new-evidence/recommended-document-fields.ts Refactored to import constants from separate module and integrate feature-flagged evidence matrix lookup
client/disputes/new-evidence/evidence-matrix.ts New file implementing evidence matrix mapping dispute reasons and product types to recommended document fields
client/disputes/new-evidence/__tests__/recommended-document-fields.test.ts Added test setup for feature flag mocking and comprehensive test coverage for evidence matrix scenarios

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

'woocommerce-payments'
),
description: __(
'Proof of past undisputed transactions from the same customer, with matching billing and device details',
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

Missing period at the end of the description. For consistency with other descriptions in this file and throughout the codebase, this description should end with a period.

Suggested change
'Proof of past undisputed transactions from the same customer, with matching billing and device details',
'Proof of past undisputed transactions from the same customer, with matching billing and device details.',

Copilot uses AI. Check for mistakes.
@mgascam mgascam changed the title [WIP] Woopmnt 5430 booking reservation fraudulent purchase info page update feat: implement evidence matrix for dispute document recommendations Dec 5, 2025
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 4 out of 4 changed files in this pull request and generated 2 comments.


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

Comment on lines 151 to 187
? [
// For is_duplicate: Order receipt, Refund receipt, Refund policy
{
key: DOCUMENT_FIELD_KEYS.RECEIPT,
label: __(
'Order receipt',
'woocommerce-payments'
),
description: __(
"A copy of the customer's receipt, which can be found in the receipt history for this transaction.",
'woocommerce-payments'
),
order: 10,
},
{
key:
DOCUMENT_FIELD_KEYS.REFUND_RECEIPT_DOCUMENTATION,
key: DOCUMENT_FIELD_KEYS.ACCESS_ACTIVITY_LOG,
label: __(
'Refund receipt',
'Proof of active subscription',
'woocommerce-payments'
),
description: __(
'A confirmation that the refund was processed.',
'Any documents showing the billing history, subscription status, or cancellation logs, for example.',
'woocommerce-payments'
),
order: 15,
order: 30,
},
{
key: DOCUMENT_FIELD_KEYS.REFUND_POLICY,
label: __(
'Refund policy',
'Store refund policy',
'woocommerce-payments'
),
description: __(
"A screenshot of your store's refund policy.",
'woocommerce-payments'
),
order: 20,
order: 40,
},
]
: [
// For is_not_duplicate: Order receipt, Any additional receipts, Customer communication, Refund policy, Other documents
{
key:
DOCUMENT_FIELD_KEYS.DUPLICATE_CHARGE_DOCUMENTATION,
key: DOCUMENT_FIELD_KEYS.CANCELLATION_POLICY,
label: __(
'Any additional receipts',
'Terms of service',
'woocommerce-payments'
),
description: __(
'Receipt(s) for any other order(s) from this customer.',
"A screenshot of your store's terms of service.",
'woocommerce-payments'
),
order: 12,
order: 50,
},
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

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

The fallback logic for duplicate disputes with is_duplicate status appears incorrect. When the feature flag is OFF and duplicateStatus === 'is_duplicate', this returns fields for subscription-related disputes (ACCESS_ACTIVITY_LOG with "Proof of active subscription" label, cancellation_policy), which don't make sense for duplicate charge disputes.

According to the PR description and test cases, when the feature flag is enabled, the is_duplicate scenario should show: "Order receipt, Refund receipt, Refund policy". The fallback should mirror this behavior or provide appropriate duplicate-specific fields, not subscription-related fields.

Copilot uses AI. Check for mistakes.
'woocommerce-payments'
),
description: __(
'Proof of past undisputed transactions from the same customer, with matching billing and device details',
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

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

Missing period at the end of the sentence. The description should end with a period for consistency with other field descriptions.

Suggested change
'Proof of past undisputed transactions from the same customer, with matching billing and device details',
'Proof of past undisputed transactions from the same customer, with matching billing and device details.',

Copilot uses AI. Check for mistakes.
The duplicate dispute entries from develop (eb1b9ca, 95b3cc1) were
specifically for booking_reservation product type, not defaults for
all product types.

Changes:
- Rename default__is_duplicate to booking_reservation__is_duplicate
- Rename default__is_not_duplicate to booking_reservation__is_not_duplicate
- Remove fallback to default entries in getMatrixFields
- Update tests to pass booking_reservation as productType
- Fix physical_product test to expect trunk fallback behavior (6 fields)

This ensures unimplemented productTypes (like physical_product) fall
back to trunk behavior, maintaining consistency with the incremental
implementation approach.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
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 4 out of 4 changed files in this pull request and generated 1 comment.


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


if ( isFeatureFlagEnabled ) {
// For duplicate disputes, use duplicateStatus for composite key lookup
// and fall back to 'default' productType if not provided
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

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

The comment "fall back to 'default' productType if not provided" is misleading. The value 'default' doesn't actually exist in the evidence matrix - it's just used as a placeholder to trigger the matrix lookup, which will return undefined and cause the function to fall back to trunk behavior. Consider updating the comment to clarify this, e.g., "use 'default' as placeholder to attempt matrix lookup (will fall back if no entry exists)"

Suggested change
// and fall back to 'default' productType if not provided
// use 'default' as placeholder to attempt matrix lookup (will fall back if no entry exists)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants