Skip to content

Conversation

@bartech
Copy link
Collaborator

@bartech bartech commented Dec 18, 2025

Description

Revamped the Tax Rate Table population logic, improving handling of automated taxes, backend order calculations, and tax location normalization.

Changes:

  • Automated Taxes: Simplified insertion of automated tax settings and disabled conflicting core tax options.
  • Tax Calculation Logic: Refactored cart and backend tax calculation routines for WooCommerce 3.0+ to reduce redundant checks and improve reliability.
  • Normalized Addresses: Introduced normalization of shipping and billing addresses using wp_unslash and consistent uppercasing.
  • Jurisdiction Handling: Added logic to fetch and apply jurisdictions from TaxJar responses, simplifying tax labels and improving city/county assignment.
  • Removed Legacy Code: Dropped support for pre-WooCommerce 3.0 coupon and order item handling where unnecessary, including tooltip hacks and deprecated tax rate matching by street.
  • Schema Validation: Tightened validation for address fields, enforcing type, length, and pattern checks more consistently.
  • Code Cleanups: Replaced generic json_encode with wp_json_encode, unified style and comment formatting, and removed obsolete conditionals.

Related issue(s)

Closes https://linear.app/a8c/issue/WOOSHIP-1819/improve-woo-tax-tax-rate-table-population-logic

Steps to reproduce & screenshots/GIFs

Test tax calculation for multiple scenarios:

  • Add products to the cart for US, Canada (CA), and EU addresses.
  • Verify automated taxes are applied correctly at checkout.
  • Create backend orders and confirm taxes are calculated correctly.
  • Confirm city/county information is properly assigned in tax labels.
  • Ensure that zero-rate and non-taxable products are correctly excluded from tax calculations.

Checklist

  • unit tests
  • changelog.txt entry added
  • readme.txt entry added

Remove dead code (allow_street_address_for_matched_rates).
Remove WC 2.6 support.
Apply WPCS fixes.
@bartech bartech self-assigned this Dec 18, 2025
Copy link
Collaborator

@iyut iyut left a comment

Choose a reason for hiding this comment

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

The changes does a good job on better code organization and adding more strict type comparison. But I've left some comments that could improve this PR.

== Changelog ==

= 3.4.0 - 2025-xx-xx =
* Revamp - Tax Rate Table population logic.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are we allowed to use Revamp? I'm still not sure about this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

IDK but this is what actually fit the changes done here. * Tweak would mean small change. * Change would also fit.

@bartech bartech requested a review from iyut December 19, 2025 13:55
Copy link
Collaborator

@iyut iyut left a comment

Choose a reason for hiding this comment

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

I see the code changes that it's intended to not save the zip code. What do you think if we put on the description of this PR and also put that on the changelog at least. I think the user should know about this. And potentially, we should ask this to A8C team too.

@bartech
Copy link
Collaborator Author

bartech commented Jan 12, 2026

I see the code changes that it's intended to not save the zip code. What do you think if we put on the description of this PR and also put that on the changelog at least. I think the user should know about this. And potentially, we should ask this to A8C team too.

Yes, I'll reach out to change Woo Tax documentation and explain there that ZIP is not used in Tax Jurisdictions. Before that I want to have our internal validation that this change is good.

@bartech bartech requested a review from iyut January 15, 2026 09:27
$json = wp_json_encode( $request_body );
$cache_key = 'tj_tax_' . hash( 'md5', $json );
$location = $this->get_normalized_location( $request_body );
$location_catch_key = 'tj_jurisdictions_' . hash( 'md5', $location['to_country'] . $location['to_state'] . $location['to_zip'] . $location['to_city'] . $location['to_street'] );
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems the jurisdiction cache key generation differs between where it's set and where it's retrieved :

The GET (get_jurisdictions line 722):

$key = 'tj_jurisdictions_' . md5( strtoupper( implode( '', $location ) . $customer->get_shipping_address() ) );

This line uses hash('md5', ...) while GET uses md5(), these produce the same result, but the inputs are completely different

I think using

$location['to_country'] . $location['to_state'] . $location['to_zip'] . $location['to_city'] . $location['to_street'] )

Is safer that $customer->get_shipping_address() since this can be filtered

if ( 400 == $response_code
$jurisdictions = isset( $response_body_decoded->tax->jurisdictions ) ? $response_body_decoded->tax->jurisdictions : null;
if ( ! empty( $jurisdictions ) ) {
set_transient( $location_catch_key, $jurisdictions, $this->cache_time );
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
set_transient( $location_catch_key, $jurisdictions, $this->cache_time );
set_transient( $location_cache_key, $jurisdictions, $this->cache_time );

Comment on lines 1817 to 1819
} else {
$this->_error( 'Error retrieving the tax rates. Received (' . $response['response']['code'] . '): ' . $response['body'] );
$this->_error( 'Error retrieving the tax rates. Received (' . $response_code . '): ' . $response['body'] );
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing return statement

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.

4 participants