Commit 191cd69dd11 for woocommerce

commit 191cd69dd111827b6ace08a08b9fb3fdcf0b175b
Author: Waqas Ahmed <wakqasahmed@gmail.com>
Date:   Wed Oct 14 09:02:48 2026 -0700

    Only tax pickup_location rates at a block pickup location (#69346)

    * Only use pickup location addresses for pickup_location tax lookups

    ShippingController::filter_taxable_address() treated the number after the
    colon of any local pickup rate id as an index into the block pickup
    locations. For the zone local_pickup method that number is a shipping zone
    instance id, so the cart could be taxed at an unrelated pickup location.
    Restrict the lookup to pickup_location rates and default missing
    state/postcode/city keys.

    Fixes #69267

    * Add changefile(s) from automation for the following project(s): woocommerce

    * delete extra changelog

    * Apply suggestion from @senadir

    * Apply suggestion from @senadir

    * Add changefile(s) from automation for the following project(s): woocommerce

    * Remove duplicate local pickup changelog entry

    ---------

    Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
    Co-authored-by: Seghir Nadir <nadir.seghir@gmail.com>

diff --git a/plugins/woocommerce/changelog/69346-fix-issue-69267-local-pickup-tax-address b/plugins/woocommerce/changelog/69346-fix-issue-69267-local-pickup-tax-address
new file mode 100644
index 00000000000..86850af637d
--- /dev/null
+++ b/plugins/woocommerce/changelog/69346-fix-issue-69267-local-pickup-tax-address
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Stop taxing a zone Local pickup order at the block pickup location whose list position matches the method's instance id.
diff --git a/plugins/woocommerce/src/Blocks/Shipping/ShippingController.php b/plugins/woocommerce/src/Blocks/Shipping/ShippingController.php
index 8a17a052e33..cf0edf5ca46 100644
--- a/plugins/woocommerce/src/Blocks/Shipping/ShippingController.php
+++ b/plugins/woocommerce/src/Blocks/Shipping/ShippingController.php
@@ -450,17 +450,18 @@ class ShippingController {
 		$chosen_method_id       = explode( ':', $chosen_method )[0];
 		$chosen_method_instance = explode( ':', $chosen_method )[1] ?? 0;

+		// Only pickup_location rates should get their address from the saved settings, local_pickup has another filter, and third party pickup locations should have their own filter and logic for the address as well.
 		// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment -- Documented in WC_Abstract_Order::get_tax_location().
-		if ( $chosen_method_id && true === apply_filters( 'woocommerce_apply_base_tax_for_local_pickup', true ) && in_array( $chosen_method_id, LocalPickupUtils::get_local_pickup_method_ids(), true ) ) {
+		if ( 'pickup_location' === $chosen_method_id && true === apply_filters( 'woocommerce_apply_base_tax_for_local_pickup', true ) ) {
 			$pickup_locations = get_option( 'pickup_location_pickup_locations', array() );
 			$pickup_location  = $pickup_locations[ $chosen_method_instance ] ?? array();

 			if ( isset( $pickup_location['address'], $pickup_location['address']['country'] ) && ! empty( $pickup_location['address']['country'] ) ) {
 				$address = array(
-					$pickup_locations[ $chosen_method_instance ]['address']['country'],
-					$pickup_locations[ $chosen_method_instance ]['address']['state'],
-					$pickup_locations[ $chosen_method_instance ]['address']['postcode'],
-					$pickup_locations[ $chosen_method_instance ]['address']['city'],
+					$pickup_location['address']['country'],
+					$pickup_location['address']['state'] ?? '',
+					$pickup_location['address']['postcode'] ?? '',
+					$pickup_location['address']['city'] ?? '',
 				);
 			}
 		}
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Shipping/ShippingControllerTest.php b/plugins/woocommerce/tests/php/src/Blocks/Shipping/ShippingControllerTest.php
index b89e67e7469..c93708745f4 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Shipping/ShippingControllerTest.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Shipping/ShippingControllerTest.php
@@ -93,6 +93,7 @@ class ShippingControllerTest extends \WC_Unit_Test_Case {

 		try {
 			$woocommerce = $this->backup_wc;
+			WC()->session->set( 'chosen_shipping_methods', null );
 			foreach ( $this->previous_shipping_address as $key => $value ) {
 				WC()->customer->{"set_shipping_{$key}"}( $value );
 			}
@@ -317,6 +318,91 @@ class ShippingControllerTest extends \WC_Unit_Test_Case {
 		$this->assertSame( $default_location, $location, 'Without a captured pickup address the location should be unchanged.' );
 	}

+	/**
+	 * @testdox filter_taxable_address does not tax a zone local_pickup rate at the pickup location sharing its instance id.
+	 */
+	public function test_filter_taxable_address_ignores_pickup_locations_for_zone_local_pickup(): void {
+		$this->save_pickup_locations();
+		WC()->session->set( 'chosen_shipping_methods', array( 'local_pickup:1' ) );
+
+		$address = array( 'US', 'CA', '90210', 'Beverly Hills' );
+
+		$this->assertSame( $address, $this->shipping_controller->filter_taxable_address( $address ), 'A zone local_pickup instance id is not a pickup location index.' );
+	}
+
+	/**
+	 * @testdox filter_taxable_address returns the chosen pickup location address for pickup_location rates.
+	 */
+	public function test_filter_taxable_address_returns_chosen_pickup_location_address(): void {
+		$this->save_pickup_locations();
+		WC()->session->set( 'chosen_shipping_methods', array( 'pickup_location:1' ) );
+
+		$this->assertSame(
+			array( 'US', 'NY', '10001', 'New York' ),
+			$this->shipping_controller->filter_taxable_address( array( 'US', 'CA', '90210', 'Beverly Hills' ) )
+		);
+	}
+
+	/**
+	 * @testdox filter_taxable_address tolerates a pickup location address without a state.
+	 */
+	public function test_filter_taxable_address_handles_pickup_location_without_state(): void {
+		update_option(
+			'pickup_location_pickup_locations',
+			array(
+				array(
+					'name'    => 'Paris',
+					'address' => array(
+						'country'  => 'FR',
+						'postcode' => '75001',
+						'city'     => 'Paris',
+					),
+					'details' => '',
+					'enabled' => true,
+				),
+			)
+		);
+		WC()->session->set( 'chosen_shipping_methods', array( 'pickup_location:0' ) );
+
+		$this->assertSame(
+			array( 'FR', '', '75001', 'Paris' ),
+			$this->shipping_controller->filter_taxable_address( array( 'US', 'CA', '90210', 'Beverly Hills' ) )
+		);
+	}
+
+	/**
+	 * Saves two pickup locations, Austin at index 0 and New York at index 1.
+	 */
+	private function save_pickup_locations(): void {
+		update_option(
+			'pickup_location_pickup_locations',
+			array(
+				array(
+					'name'    => 'Austin',
+					'address' => array(
+						'country'  => 'US',
+						'state'    => 'TX',
+						'postcode' => '73301',
+						'city'     => 'Austin',
+					),
+					'details' => '',
+					'enabled' => true,
+				),
+				array(
+					'name'    => 'New York',
+					'address' => array(
+						'country'  => 'US',
+						'state'    => 'NY',
+						'postcode' => '10001',
+						'city'     => 'New York',
+					),
+					'details' => '',
+					'enabled' => true,
+				),
+			)
+		);
+	}
+
 	/**
 	 * Overrides the WC logger.
 	 *