Skip to content

Analytics report exports: add export column/item filters and forward currency from URL query#63618

Merged
louwie17 merged 8 commits intotrunkfrom
fix/wooplug-6385-analytics-export-currency
Mar 11, 2026
Merged

Analytics report exports: add export column/item filters and forward currency from URL query#63618
louwie17 merged 8 commits intotrunkfrom
fix/wooplug-6385-analytics-export-currency

Conversation

@louwie17
Copy link
Copy Markdown
Contributor

Submission Review Guidelines:

Changes proposed in this Pull Request:

Closes #63563.

This PR addresses two related gaps in the Analytics report CSV export pipeline, surfaced by multicurrency plugins (e.g. WooCommerce Multicurrency, YayCurrency):

1. Missing export column/item filters on Revenue Stats, Taxes, and Variations controllers

Seven of the ten exportable report controllers already expose woocommerce_report_{type}_export_columns and woocommerce_report_{type}_prepare_export_item filters, allowing plugins to extend the CSV schema. The remaining three — Revenue Stats, Taxes, and Variations — had no such hooks. This PR adds them, bringing all controllers in line.

2. Selected currency not forwarded into the export job payload

When the Download button triggers an email export, it calls startExport(endpoint, reportQuery). The reportQuery object (built by getReportTableQuery) only forwards a fixed set of fields — orderby, order, after, before, page, per_page, and active filter values. Params added by plugins via applyFilters on the report's filters config (such as currency) are omitted because live API requests rely on $_GET server-side. Exports run as Action Scheduler background jobs with no HTTP context, so $_GET is always empty and those params were silently dropped.

The fix introduces a getExportQuery utility that dynamically builds the export query by forwarding any URL params declared in the report's filters or advancedFilters config that are not already covered by reportQuery. This means any plugin adding a filter param via applyFilters will have it automatically included in the export job payload with no further changes needed.

Screenshots or screen recordings:

N/A

How to test the changes in this Pull Request:

Setup

  1. Install a multicurrency plugin (e.g. WooCommerce Multicurrency or YayCurrency) and configure a second currency (e.g. CAD).
  2. Place a few test orders in each currency.
  3. Install the Code Snippets plugin to apply the test snippet below.

Test 1 — Verify currency is forwarded to the export job

  1. Go to Analytics → Revenue.
  2. Use the currency selector to switch to the non-default currency (e.g. CAD).
  3. Confirm the on-screen data updates to show CAD figures.
  4. Click Download (the email export path — this triggers when the data set is larger than one page, or you can temporarily lower per_page via URL to force it).
  5. Open the exported CSV and confirm the amounts match the CAD figures shown on screen, not the default currency.

Test 2 — Verify the new export column/item filters work

  1. Add the following snippet via Code Snippets (PHP, run everywhere):
// Add a Currency column to the Revenue Stats CSV export.
add_filter( 'woocommerce_report_revenue_stats_export_columns', function( $columns ) {
    $columns['currency'] = 'Currency';
    return $columns;
} );

add_filter( 'woocommerce_report_revenue_stats_prepare_export_item', function( $export_item, $item ) {
    // The currency is available on the item when a multicurrency plugin
    // adds it via woocommerce_analytics_clauses_select.
    $export_item['currency'] = $item['currency'] ?? get_woocommerce_currency();
    return $export_item;
}, 10, 2 );
  1. Repeat the export from step 7.
  2. Open the CSV and confirm a Currency column is now present and populated.
  3. Repeat steps 9–11 substituting revenue_stats for taxes and variations to verify those controllers also respect their new filters (woocommerce_report_taxes_export_columns, woocommerce_report_taxes_prepare_export_item, woocommerce_report_variations_export_columns, woocommerce_report_variations_prepare_export_item).

Test 3 — Verify default behaviour is unchanged

  1. Remove the Code Snippets snippet.
  2. Export the Revenue, Taxes, and Variations reports without any currency plugin active.
  3. Confirm the CSV output is identical to before — no extra columns, correct default-currency values.

Testing that has already taken place:

  • Manually tested the Download flow on a local store with WooCommerce Multicurrency and YayCurrency installed, confirming the selected currency is now forwarded into the export job.
  • PHP unit tests added for all three new controller filter pairs (Revenue Stats, Taxes, Variations): default column sets, adding/removing columns via filter, extra column values via item filter, and correct second argument passed to filter. All 16 tests pass.
  • JS unit tests added for getExportQuery: filter param forwarding, multi-param support, blocking of undeclared URL params, no-override of reportQuery fields, nested sub-param support, advancedFilters params, empty string exclusion, and immutability. All 9 tests pass.
  • PHP linting clean on all changed files.
  • JS linting clean on all changed files.

Milestone

Changelog entry

  • This Pull Request does not require a changelog entry. (Comment required below)
Changelog Entry Comment

Comment

A changelog entry was created manually in the branch at plugins/woocommerce/changelog/wooplug-6385-analytics-export-currency-filters and is already committed.

@github-actions github-actions Bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Mar 10, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 10, 2026

Size Change: +224 B (0%)

Total Size: 5.98 MB

Filename Size Change
./plugins/woocommerce/client/admin/build/app/index.js 86.6 kB +224 B (+0.26%)

compressed-size-action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 10, 2026

Test using WordPress Playground

The changes in this pull request can be previewed and tested using a WordPress Playground instance.
WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Test this pull request with WordPress Playground.

Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds export extensibility and URL-filter forwarding for WooCommerce analytics: client-side getExportQuery merges selected URL filter params (including currency) into export payloads; Revenue Stats, Taxes, and Variations controllers expose filters around export columns and export rows; tests added for both JS and PHP.

Changes

Cohort / File(s) Summary
Changelog
plugins/woocommerce/changelog/wooplug-6385-analytics-export-currency-filters
Changelog entry documenting analytics export enhancements and currency/filter forwarding.
JS Report-Table (component + utils)
plugins/woocommerce/client/admin/client/analytics/components/report-table/index.js, plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js
Added getExportQuery(reportQuery, urlQuery, filters, advancedFilters) to collect declared filter param keys (including nested/advanced) and merge eligible URL params into the export query; updated report-table export trigger to use this merged query.
JS Report-Table Tests
plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
Jest tests for getExportQuery: preserves reportQuery, forwards declared URL params (including nested and advanced filters), omits empty strings, avoids overriding existing reportQuery keys, and ensures non-mutation.
PHP Revenue Stats Export Filters
plugins/woocommerce/src/Admin/API/Reports/Revenue/Stats/Controller.php
Wrapped export columns and prepared export row values with woocommerce_report_revenue_stats_export_columns and woocommerce_report_revenue_stats_prepare_export_item filters to allow external modification.
PHP Revenue Stats Tests
plugins/woocommerce/tests/php/src/Admin/API/Reports/Revenue/Stats/ControllerTest.php
New PHPUnit tests for default export columns/items, adding/removing columns via filter, item augmentation via filter, and that the original item is passed to the prepare-item filter.
PHP Taxes Export Filters
plugins/woocommerce/src/Admin/API/Reports/Taxes/Controller.php
Added woocommerce_report_taxes_export_columns and woocommerce_report_taxes_prepare_export_item filters (with docblocks) to enable modification of tax report export columns and rows.
PHP Taxes Tests
plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php
New PHPUnit tests covering default tax export columns, filter-driven column add/remove, item preparation extension via filter, and original-item propagation to the filter callback.
PHP Variations Export Filters
plugins/woocommerce/src/Admin/API/Reports/Variations/Controller.php
Added woocommerce_report_variations_export_columns and woocommerce_report_variations_prepare_export_item filters to allow customization of variation report export columns and items.
PHP Variations Tests
plugins/woocommerce/tests/php/src/Admin/API/Reports/Variations/ControllerTest.php
New PHPUnit tests for default variation export columns, filter-based column modifications, item augmentation via filter, and original-item argument propagation.

Sequence Diagram(s)

sequenceDiagram
    participant AdminUI as Admin UI (Client)
    participant ExportAPI as Reports API (Server)
    participant ExportJob as Export Job Processor

    AdminUI->>AdminUI: User clicks "Export" with URL query
    AdminUI->>AdminUI: getExportQuery(reportQuery, urlQuery, filters, advancedFilters)
    AdminUI->>ExportAPI: POST /export with merged query payload
    ExportAPI->>ExportJob: Enqueue export job with payload
    ExportJob->>ExportJob: Controller.prepare_item_for_export called (filters applied)
    ExportJob->>AdminUI: Deliver/export result (email or download)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the primary changes: adding export column/item filters to analytics report controllers and forwarding currency from URL parameters to export jobs.
Description check ✅ Passed The description comprehensively explains the changes, links to the issue being closed (#63563), provides context about the problem, and includes detailed testing steps and a code example.
Linked Issues check ✅ Passed All requirements from issue #63563 are met: export filters added to Revenue Stats/Taxes/Variations controllers [#63563], and getExportQuery utility forwards plugin-added filter params (like currency) to export jobs [#63563].
Out of Scope Changes check ✅ Passed All changes directly support the linked issue objectives: PHP controller filters, JavaScript export query utility, comprehensive test coverage for both, and changelog entry are all within scope.
Docstring Coverage ✅ Passed Docstring coverage is 96.88% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/wooplug-6385-analytics-export-currency

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php (1)

86-117: Consider adding a test for default export item structure.

The Revenue Stats ControllerTest includes a test_prepare_item_for_export_returns_defaults test that validates the default export row structure. This Taxes test suite is missing that equivalent test, which would verify that prepare_item_for_export returns the expected default fields (tax_code, rate, total_tax, etc.) before any filters are applied.

Adding this test would ensure consistent coverage across all report controller test suites.

💡 Suggested test to add
/**
 * `@testdox` prepare_item_for_export returns the default export row.
 */
public function test_prepare_item_for_export_returns_defaults(): void {
    $item = array(
        'tax_rate_id'  => 1,
        'country'      => 'US',
        'state'        => 'CA',
        'name'         => 'State Tax',
        'priority'     => 1,
        'tax_rate'     => '8.25',
        'total_tax'    => 82.50,
        'order_tax'    => 75.00,
        'shipping_tax' => 7.50,
        'orders_count' => 10,
    );

    $export_item = $this->sut->prepare_item_for_export( $item );

    $this->assertArrayHasKey( 'tax_code', $export_item );
    $this->assertArrayHasKey( 'rate', $export_item );
    $this->assertArrayHasKey( 'total_tax', $export_item );
    $this->assertArrayHasKey( 'order_tax', $export_item );
    $this->assertArrayHasKey( 'shipping_tax', $export_item );
    $this->assertArrayHasKey( 'orders_count', $export_item );
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php`
around lines 86 - 117, Add a new unit test in ControllerTest that verifies
prepare_item_for_export returns the expected default export fields before
filters run: create a test method (e.g.,
test_prepare_item_for_export_returns_defaults) that builds a representative
$item array (matching the one used in
test_prepare_item_for_export_filter_can_add_column), calls
$this->sut->prepare_item_for_export($item), and asserts the presence of keys
like 'tax_code', 'rate', 'total_tax', 'order_tax', 'shipping_tax', and
'orders_count' in the returned $export_item; place the test alongside the
existing tests so it runs with the same setup/teardown and does not rely on
add_filter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js`:
- Around line 13-25: The export query builders assume extension-supplied inputs
can be objects/arrays but may be null/undefined; update getExportQuery (and its
use of getFilterParamKeys) to defensively handle malformed inputs by treating
filters and advancedFilters as empty arrays if falsy, and urlQuery/reportQuery
as empty objects if falsy before accessing properties; ensure loops use (filters
|| []) and (advancedFilters || []) and property accesses use optional chaining
or default values (e.g., (urlQuery || {}).foo) so missing entries don’t throw,
and add one regression test that calls getExportQuery with null/undefined for
filters, advancedFilters, urlQuery, and reportQuery to verify it falls back to
the base report query without throwing.

---

Nitpick comments:
In
`@plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php`:
- Around line 86-117: Add a new unit test in ControllerTest that verifies
prepare_item_for_export returns the expected default export fields before
filters run: create a test method (e.g.,
test_prepare_item_for_export_returns_defaults) that builds a representative
$item array (matching the one used in
test_prepare_item_for_export_filter_can_add_column), calls
$this->sut->prepare_item_for_export($item), and asserts the presence of keys
like 'tax_code', 'rate', 'total_tax', 'order_tax', 'shipping_tax', and
'orders_count' in the returned $export_item; place the test alongside the
existing tests so it runs with the same setup/teardown and does not rely on
add_filter.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 7eaa47e4-33b1-4b69-b238-16a0044576b2

📥 Commits

Reviewing files that changed from the base of the PR and between 58ee5bb and e917c7f.

📒 Files selected for processing (10)
  • plugins/woocommerce/changelog/wooplug-6385-analytics-export-currency-filters
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/index.js
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js
  • plugins/woocommerce/src/Admin/API/Reports/Revenue/Stats/Controller.php
  • plugins/woocommerce/src/Admin/API/Reports/Taxes/Controller.php
  • plugins/woocommerce/src/Admin/API/Reports/Variations/Controller.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Revenue/Stats/ControllerTest.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Variations/ControllerTest.php

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js (1)

67-97: Add one malformed-extension config case.

These cases only exercise well-formed filters / advancedFilters, but this helper now consumes extension-provided report config. Please add a defensive test for missing settings, non-array filters, or non-object advancedFilters.filters so a bad plugin config can't break exports.

🧪 Suggested test
+	it( 'ignores malformed extension filter config', () => {
+		const reportQuery = { orderby: 'date' };
+		const urlQuery = { currency: 'EUR', status: 'completed' };
+		const filters = [
+			{ param: 'currency' },
+			{
+				param: 'filter',
+				filters: [ {}, { value: 'single', settings: null } ],
+			},
+		];
+		const advancedFilters = { filters: null };
+
+		expect( () =>
+			getExportQuery( reportQuery, urlQuery, filters, advancedFilters )
+		).not.toThrow();
+		expect(
+			getExportQuery( reportQuery, urlQuery, filters, advancedFilters )
+		).toMatchObject( {
+			orderby: 'date',
+			currency: 'EUR',
+		} );
+	} );

As per coding guidelines, "Don't trust that extension developers will follow the best practices, make sure the code: Guards against unexpected inputs."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js`
around lines 67 - 97, Add a defensive unit test in
plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
that calls getExportQuery with malformed extension config (e.g., a filter object
missing settings, a filters value that is not an array, and advancedFilters with
filters not being an object) and asserts the call does not throw and that no
unexpected params are added (e.g., result does not contain keys from the
malformed entries); reference getExportQuery and reuse the existing test pattern
(create reportQuery and urlQuery, pass malformed filters/advancedFilters, call
getExportQuery, expect no exception and expect result to only include valid
params).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js`:
- Around line 67-97: Add a defensive unit test in
plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
that calls getExportQuery with malformed extension config (e.g., a filter object
missing settings, a filters value that is not an array, and advancedFilters with
filters not being an object) and asserts the call does not throw and that no
unexpected params are added (e.g., result does not contain keys from the
malformed entries); reference getExportQuery and reuse the existing test pattern
(create reportQuery and urlQuery, pass malformed filters/advancedFilters, call
getExportQuery, expect no exception and expect result to only include valid
params).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: cd05606a-0142-4670-a8ae-97be842fb617

📥 Commits

Reviewing files that changed from the base of the PR and between e917c7f and 8156673.

📒 Files selected for processing (4)
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Revenue/Stats/ControllerTest.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Variations/ControllerTest.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js (1)

74-79: Consider whether null values should also be excluded.

The filter excludes undefined and empty strings, but null would pass through. URL params are typically strings, so this is unlikely to matter in practice, but for completeness:

 ( [ key, value ] ) =>
     filterParamKeys.has( key ) &&
     ! ( key in safeReportQuery ) &&
     value !== undefined &&
+    value !== null &&
     value !== ''
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js`
around lines 74 - 79, The current predicate used to filter params (the arrow
callback checking filterParamKeys.has(key), !(key in safeReportQuery), value !==
undefined, and value !== '') will allow null values; update this predicate to
also exclude null (add value !== null) so that null params are not included in
URL/query generation — locate the filter using filterParamKeys, safeReportQuery
and the arrow function shown and add the null check to the combined conditions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js`:
- Around line 74-79: The current predicate used to filter params (the arrow
callback checking filterParamKeys.has(key), !(key in safeReportQuery), value !==
undefined, and value !== '') will allow null values; update this predicate to
also exclude null (add value !== null) so that null params are not included in
URL/query generation — locate the filter using filterParamKeys, safeReportQuery
and the arrow function shown and add the null check to the combined conditions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 8a979833-b643-47cf-b9ff-cdc9e2be0111

📥 Commits

Reviewing files that changed from the base of the PR and between 8156673 and ec87815.

📒 Files selected for processing (2)
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js

@louwie17 louwie17 requested a review from a team March 10, 2026 16:03
@github-actions
Copy link
Copy Markdown
Contributor

Testing Guidelines

Hi @woocommerce/ventures,

Apart from reviewing the code changes, please make sure to review the testing instructions (Guide) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed.

Reminder: PR reviewers are required to document testing performed. This includes:

  • 🖼️ Screenshots or screen recordings.
  • 📝 List of functionality tested / steps followed.
  • 🌐 Site details (environment attributes such as hosting type, plugins, theme, store size, store age, and relevant settings).
  • 🔍 Any analysis performed, such as assessing potential impacts on environment attributes and other plugins, conducting performance profiling, or using LLM/AI-based analysis.

⚠️ Within the testing details you provide, please ensure that no sensitive information (such as API keys, passwords, user data, etc.) is included in this public issue.

Copy link
Copy Markdown
Member

@chihsuan chihsuan left a comment

Choose a reason for hiding this comment

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

Nice work. The allowlist approach for forwarding filter params is well-designed.

I tested on a JN site with WooCommerce Multicurrency and confirmed that it works as expected. Only left a minor comment on the code.

I just found this is related to a stale PR #59580, so we can close that one when this one is merged. 🙂

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js`:
- Around line 22-27: The code that builds filterParamKeys only reads
config.filters[].settings.param and misses nested filters; update the collection
logic used by getExportQuery (and the variable/collection filterParamKeys) to
also iterate over filter.subFilters (if present and Array.isArray) and add each
subFilter.settings.param to the keys set (guarding for null/undefined
settings.param), ensuring both top-level filters and nested subFilters are
included; then add a unit test that constructs a config with a filters entry
containing subFilters with settings.param and asserts those params appear in the
export query payload so this case cannot regress.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: c3a9b723-efed-44c9-a8ec-0815d78e8bb5

📥 Commits

Reviewing files that changed from the base of the PR and between ec87815 and 0b37ce7.

📒 Files selected for processing (2)
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js

louwie17 and others added 8 commits March 11, 2026 09:48
…tions report controllers

Adds `woocommerce_report_{type}_export_columns` and `woocommerce_report_{type}_prepare_export_item`
filters to the three report controllers that were missing them, bringing them in line with the
other seven controllers (Products, Orders, Categories, Coupons, Customers, Stock, Downloads).
This allows multicurrency plugins to extend the CSV schema with a currency column.

Fixes: https://linear.app/a8c/issue/WOOPLUG-6385

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts a `getExportQuery` utility that builds the export request query by
taking `reportQuery` as the base and merging in any URL params declared in the
report's filters or advancedFilters config that are not already covered by the
processed query. This makes the forwarding dynamic: plugins adding a filter
param (e.g. `currency`) via `applyFilters` on the report filters config will
have that param automatically included in the export job payload without any
further changes needed here.

The `reportQuery` (built by `getReportTableQuery`) only forwards a fixed set of
fields. Params added by plugins are omitted because live API requests rely on
`$_GET` server-side. Exports run as Action Scheduler background jobs with no
HTTP context, so those params must be carried explicitly in the job payload.

Fixes: https://linear.app/a8c/issue/WOOPLUG-6385

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uery

PHP: adds ControllerTest for Revenue Stats, Taxes, and Variations, covering
default column sets, filter extensibility (add/remove columns), extra column
values, and filter argument passing.

JS: adds unit tests for `getExportQuery`, covering filter param forwarding,
multi-param support, blocking of undeclared URL params, no-override of
reportQuery fields, nested sub-param support, advancedFilters params, empty
string exclusion, and immutability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Guard getFilterParamKeys and getExportQuery against null/undefined
extension-supplied inputs (filters, advancedFilters, urlQuery,
reportQuery) so a bad plugin config falls back gracefully instead
of throwing and breaking the export button.

Adds a regression test covering the null/undefined case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Refactor getFilterParamKeys into a recursive collectFilterParamKeys helper
that traverses both filters and subFilters, so params like `products` and
`variations` (defined via subFilters in the products report config) are
correctly forwarded to the export job payload.

Also add tests for subFilters param forwarding and null urlQuery value exclusion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@louwie17 louwie17 force-pushed the fix/wooplug-6385-analytics-export-currency branch from 03fe559 to 05a86ae Compare March 11, 2026 08:48
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php (1)

89-116: Add a baseline prepare_item_for_export() test.

Right now this only verifies that the hook can extend the row. It would be good to also assert the unfiltered default export item so a regression in the existing tax columns or formatting is caught directly.

As per coding guidelines, "Add unit or E2E tests where applicable".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php`
around lines 89 - 116, Add a baseline assertion for prepare_item_for_export to
verify the unfiltered default export row before/without filter modifications:
call $this->sut->prepare_item_for_export($item) in a new test or at the start of
test_prepare_item_for_export_filter_can_add_column and assert the expected
default keys and values (e.g. presence of tax_rate_id, country, state, name,
priority, tax_rate, total_tax, order_tax, shipping_tax, orders_count) and that
numeric/formatted fields match the expected unfiltered output; use the
prepare_item_for_export method and add a separate test name like
test_prepare_item_for_export_defaults or add assertions prior to adding the
filter so regressions in default columns/formatting are caught.
plugins/woocommerce/tests/php/src/Admin/API/Reports/Variations/ControllerTest.php (1)

88-116: Add a baseline prepare_item_for_export() test.

These assertions only prove the hook can append a field. A regression in the default row mapping or number formatting would still pass here, so it would be worth adding one unfiltered baseline test like the revenue suite has.

As per coding guidelines, "Add unit or E2E tests where applicable".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/woocommerce/tests/php/src/Admin/API/Reports/Variations/ControllerTest.php`
around lines 88 - 116, Add a baseline unfiltered unit test for
prepare_item_for_export that verifies the default row mapping and number
formatting (not just hook behavior): create a new test method (e.g.,
test_prepare_item_for_export_defaults) that calls
$this->sut->prepare_item_for_export with a representative $item (same shape used
in test_prepare_item_for_export_filter_can_add_column) without adding any
add_filter, then assert the expected default keys exist (e.g., 'items_sold',
'net_revenue', 'orders_count', and values from 'extended_info' like 'name' and
'sku') and assert net_revenue is formatted/returned as the expected
numeric/string representation used elsewhere in the suite; place this alongside
the existing test so regressions in the default mapping/formatting are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php`:
- Around line 89-116: Add a baseline assertion for prepare_item_for_export to
verify the unfiltered default export row before/without filter modifications:
call $this->sut->prepare_item_for_export($item) in a new test or at the start of
test_prepare_item_for_export_filter_can_add_column and assert the expected
default keys and values (e.g. presence of tax_rate_id, country, state, name,
priority, tax_rate, total_tax, order_tax, shipping_tax, orders_count) and that
numeric/formatted fields match the expected unfiltered output; use the
prepare_item_for_export method and add a separate test name like
test_prepare_item_for_export_defaults or add assertions prior to adding the
filter so regressions in default columns/formatting are caught.

In
`@plugins/woocommerce/tests/php/src/Admin/API/Reports/Variations/ControllerTest.php`:
- Around line 88-116: Add a baseline unfiltered unit test for
prepare_item_for_export that verifies the default row mapping and number
formatting (not just hook behavior): create a new test method (e.g.,
test_prepare_item_for_export_defaults) that calls
$this->sut->prepare_item_for_export with a representative $item (same shape used
in test_prepare_item_for_export_filter_can_add_column) without adding any
add_filter, then assert the expected default keys exist (e.g., 'items_sold',
'net_revenue', 'orders_count', and values from 'extended_info' like 'name' and
'sku') and assert net_revenue is formatted/returned as the expected
numeric/string representation used elsewhere in the suite; place this alongside
the existing test so regressions in the default mapping/formatting are caught.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 02269403-38d9-4937-94e8-642de8e9c62a

📥 Commits

Reviewing files that changed from the base of the PR and between 0b37ce7 and 05a86ae.

📒 Files selected for processing (10)
  • plugins/woocommerce/changelog/wooplug-6385-analytics-export-currency-filters
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/index.js
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js
  • plugins/woocommerce/src/Admin/API/Reports/Revenue/Stats/Controller.php
  • plugins/woocommerce/src/Admin/API/Reports/Taxes/Controller.php
  • plugins/woocommerce/src/Admin/API/Reports/Variations/Controller.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Revenue/Stats/ControllerTest.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Taxes/ControllerTest.php
  • plugins/woocommerce/tests/php/src/Admin/API/Reports/Variations/ControllerTest.php
🚧 Files skipped from review as they are similar to previous changes (4)
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/test/utils.js
  • plugins/woocommerce/src/Admin/API/Reports/Taxes/Controller.php
  • plugins/woocommerce/changelog/wooplug-6385-analytics-export-currency-filters
  • plugins/woocommerce/client/admin/client/analytics/components/report-table/utils.js

@louwie17 louwie17 merged commit 4c6cad2 into trunk Mar 11, 2026
72 of 74 checks passed
@louwie17 louwie17 deleted the fix/wooplug-6385-analytics-export-currency branch March 11, 2026 10:53
@github-actions github-actions Bot added this to the 10.7.0 milestone Mar 11, 2026
@github-actions github-actions Bot added the needs: documentation The issue/PR requires documentation to be added. label Mar 11, 2026
samnajian pushed a commit that referenced this pull request Mar 11, 2026
…currency from URL query (#63618)

* Add export column and item filters to Revenue Stats, Taxes, and Variations report controllers

Adds `woocommerce_report_{type}_export_columns` and `woocommerce_report_{type}_prepare_export_item`
filters to the three report controllers that were missing them, bringing them in line with the
other seven controllers (Products, Orders, Categories, Coupons, Customers, Stock, Downloads).
This allows multicurrency plugins to extend the CSV schema with a currency column.

Fixes: https://linear.app/a8c/issue/WOOPLUG-6385

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Forward selected currency into the analytics report export job payload

Extracts a `getExportQuery` utility that builds the export request query by
taking `reportQuery` as the base and merging in any URL params declared in the
report's filters or advancedFilters config that are not already covered by the
processed query. This makes the forwarding dynamic: plugins adding a filter
param (e.g. `currency`) via `applyFilters` on the report filters config will
have that param automatically included in the export job payload without any
further changes needed here.

The `reportQuery` (built by `getReportTableQuery`) only forwards a fixed set of
fields. Params added by plugins are omitted because live API requests rely on
`$_GET` server-side. Exports run as Action Scheduler background jobs with no
HTTP context, so those params must be carried explicitly in the job payload.

Fixes: https://linear.app/a8c/issue/WOOPLUG-6385

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add tests for report export column/item filters and currency export query

PHP: adds ControllerTest for Revenue Stats, Taxes, and Variations, covering
default column sets, filter extensibility (add/remove columns), extra column
values, and filter argument passing.

JS: adds unit tests for `getExportQuery`, covering filter param forwarding,
multi-param support, blocking of undeclared URL params, no-override of
reportQuery fields, nested sub-param support, advancedFilters params, empty
string exclusion, and immutability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix lint errors

* Harden getExportQuery against malformed extension config

Guard getFilterParamKeys and getExportQuery against null/undefined
extension-supplied inputs (filters, advancedFilters, urlQuery,
reportQuery) so a bad plugin config falls back gracefully instead
of throwing and breaking the export button.

Adds a regression test covering the null/undefined case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add one additional test

* fix: exclude null values from export query extra params

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: traverse subFilters when collecting export query filter params

Refactor getFilterParamKeys into a recursive collectFilterParamKeys helper
that traverses both filters and subFilters, so params like `products` and
`variations` (defined via subFilters in the products report config) are
correctly forwarded to the export job payload.

Also add tests for subFilters param forwarding and null urlQuery value exclusion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
jamesckemp pushed a commit that referenced this pull request Mar 11, 2026
…currency from URL query (#63618)

* Add export column and item filters to Revenue Stats, Taxes, and Variations report controllers

Adds `woocommerce_report_{type}_export_columns` and `woocommerce_report_{type}_prepare_export_item`
filters to the three report controllers that were missing them, bringing them in line with the
other seven controllers (Products, Orders, Categories, Coupons, Customers, Stock, Downloads).
This allows multicurrency plugins to extend the CSV schema with a currency column.

Fixes: https://linear.app/a8c/issue/WOOPLUG-6385

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Forward selected currency into the analytics report export job payload

Extracts a `getExportQuery` utility that builds the export request query by
taking `reportQuery` as the base and merging in any URL params declared in the
report's filters or advancedFilters config that are not already covered by the
processed query. This makes the forwarding dynamic: plugins adding a filter
param (e.g. `currency`) via `applyFilters` on the report filters config will
have that param automatically included in the export job payload without any
further changes needed here.

The `reportQuery` (built by `getReportTableQuery`) only forwards a fixed set of
fields. Params added by plugins are omitted because live API requests rely on
`$_GET` server-side. Exports run as Action Scheduler background jobs with no
HTTP context, so those params must be carried explicitly in the job payload.

Fixes: https://linear.app/a8c/issue/WOOPLUG-6385

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add tests for report export column/item filters and currency export query

PHP: adds ControllerTest for Revenue Stats, Taxes, and Variations, covering
default column sets, filter extensibility (add/remove columns), extra column
values, and filter argument passing.

JS: adds unit tests for `getExportQuery`, covering filter param forwarding,
multi-param support, blocking of undeclared URL params, no-override of
reportQuery fields, nested sub-param support, advancedFilters params, empty
string exclusion, and immutability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix lint errors

* Harden getExportQuery against malformed extension config

Guard getFilterParamKeys and getExportQuery against null/undefined
extension-supplied inputs (filters, advancedFilters, urlQuery,
reportQuery) so a bad plugin config falls back gracefully instead
of throwing and breaking the export button.

Adds a regression test covering the null/undefined case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add one additional test

* fix: exclude null values from export query extra params

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: traverse subFilters when collecting export query filter params

Refactor getFilterParamKeys into a recursive collectFilterParamKeys helper
that traverses both filters and subFilters, so params like `products` and
`variations` (defined via subFilters in the products report config) are
correctly forwarded to the export job payload.

Also add tests for subFilters param forwarding and null urlQuery value exclusion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs: documentation The issue/PR requires documentation to be added. plugin: woocommerce Issues related to the WooCommerce Core plugin.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Analytics revenue export ignores selected currency and omits currency column

2 participants