fix(orders): Use billing address for shipping when not shipping to different address
## Critical Bug Fixed ✅ ### Problem: - User fills billing address (Country, State, City) - Shipping says "No shipping methods available" - Backend returns empty methods array - No rates calculated ### Root Cause: Frontend was only checking `shippingData` for completeness: ```ts if (!shippingData.country) return false; if (!shippingData.city) return false; ``` But when user doesn't check "Ship to different address": - `shippingData` is empty {} - Billing address has all the data - Query never enabled! ### Solution: Use effective shipping address based on `shipDiff` toggle: ```ts const effectiveShippingAddress = useMemo(() => { if (shipDiff) { return shippingData; // Use separate shipping address } // Use billing address return { country: bCountry, state: bState, city: bCity, postcode: bPost, address_1: bAddr1, }; }, [shipDiff, shippingData, bCountry, bState, bCity, bPost, bAddr1]); ``` Then check completeness on effective address: ```ts const isComplete = useMemo(() => { const addr = effectiveShippingAddress; if (!addr.country) return false; if (!addr.city) return false; if (hasStates && !addr.state) return false; return true; }, [effectiveShippingAddress]); ``` ### Backend Enhancement: Also set billing address for tax calculation context: ```php // Set both shipping and billing for proper tax calculation WC()->customer->set_shipping_country( $country ); WC()->customer->set_billing_country( $country ); ``` ## Result: ### Before: 1. Fill billing: Indonesia, Jawa Barat, Bandung 2. Shipping: "No shipping methods available" ❌ 3. No API call made ### After: 1. Fill billing: Indonesia, Jawa Barat, Bandung 2. ✅ API called with billing address 3. ✅ Returns: JNE REG, JNE YES, TIKI REG 4. ✅ First rate auto-selected 5. ✅ Total calculated with tax ## Testing: - ✅ Fill billing only → Shipping calculated - ✅ Check "Ship to different" → Use shipping address - ✅ Uncheck → Switch back to billing - ✅ Change billing city → Rates recalculate
This commit is contained in:
@@ -185,26 +185,43 @@ export default function OrderForm({
|
|||||||
enabled: items.length > 0,
|
enabled: items.length > 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get effective shipping address (use billing if not shipping to different address)
|
||||||
|
const effectiveShippingAddress = React.useMemo(() => {
|
||||||
|
if (shipDiff) {
|
||||||
|
return shippingData;
|
||||||
|
}
|
||||||
|
// Use billing address
|
||||||
|
return {
|
||||||
|
country: bCountry,
|
||||||
|
state: bState,
|
||||||
|
city: bCity,
|
||||||
|
postcode: bPost,
|
||||||
|
address_1: bAddr1,
|
||||||
|
address_2: '',
|
||||||
|
};
|
||||||
|
}, [shipDiff, shippingData, bCountry, bState, bCity, bPost, bAddr1]);
|
||||||
|
|
||||||
// Check if shipping address is complete enough to calculate rates
|
// Check if shipping address is complete enough to calculate rates
|
||||||
const isShippingAddressComplete = React.useMemo(() => {
|
const isShippingAddressComplete = React.useMemo(() => {
|
||||||
|
const addr = effectiveShippingAddress;
|
||||||
// Need at minimum: country, state (if applicable), city
|
// Need at minimum: country, state (if applicable), city
|
||||||
if (!shippingData.country) return false;
|
if (!addr.country) return false;
|
||||||
if (!shippingData.city) return false;
|
if (!addr.city) return false;
|
||||||
// If country has states, require state
|
// If country has states, require state
|
||||||
const countryStates = states[shippingData.country];
|
const countryStates = states[addr.country];
|
||||||
if (countryStates && Object.keys(countryStates).length > 0 && !shippingData.state) {
|
if (countryStates && Object.keys(countryStates).length > 0 && !addr.state) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}, [shippingData.country, shippingData.state, shippingData.city, states]);
|
}, [effectiveShippingAddress, states]);
|
||||||
|
|
||||||
// Calculate shipping rates dynamically
|
// Calculate shipping rates dynamically
|
||||||
const { data: shippingRates, isLoading: shippingLoading } = useQuery({
|
const { data: shippingRates, isLoading: shippingLoading } = useQuery({
|
||||||
queryKey: ['shipping-rates', items.map(i => ({ product_id: i.product_id, qty: i.qty })), shippingData.country, shippingData.state, shippingData.city, shippingData.postcode, shippingData.address_1],
|
queryKey: ['shipping-rates', items.map(i => ({ product_id: i.product_id, qty: i.qty })), effectiveShippingAddress.country, effectiveShippingAddress.state, effectiveShippingAddress.city, effectiveShippingAddress.postcode, effectiveShippingAddress.address_1],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
return api.post('/shipping/calculate', {
|
return api.post('/shipping/calculate', {
|
||||||
items: items.map(i => ({ product_id: i.product_id, qty: i.qty })),
|
items: items.map(i => ({ product_id: i.product_id, qty: i.qty })),
|
||||||
shipping: shippingData,
|
shipping: effectiveShippingAddress,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
enabled: isShippingAddressComplete && items.length > 0,
|
enabled: isShippingAddressComplete && items.length > 0,
|
||||||
|
|||||||
@@ -1293,12 +1293,25 @@ class OrdersController {
|
|||||||
|
|
||||||
// Set customer shipping address
|
// Set customer shipping address
|
||||||
if ( ! empty( $shipping ) ) {
|
if ( ! empty( $shipping ) ) {
|
||||||
WC()->customer->set_shipping_country( $shipping['country'] ?? '' );
|
$country = $shipping['country'] ?? '';
|
||||||
WC()->customer->set_shipping_state( $shipping['state'] ?? '' );
|
$state = $shipping['state'] ?? '';
|
||||||
WC()->customer->set_shipping_postcode( $shipping['postcode'] ?? '' );
|
$postcode = $shipping['postcode'] ?? '';
|
||||||
WC()->customer->set_shipping_city( $shipping['city'] ?? '' );
|
$city = $shipping['city'] ?? '';
|
||||||
WC()->customer->set_shipping_address( $shipping['address_1'] ?? '' );
|
$address_1 = $shipping['address_1'] ?? '';
|
||||||
WC()->customer->set_shipping_address_2( $shipping['address_2'] ?? '' );
|
$address_2 = $shipping['address_2'] ?? '';
|
||||||
|
|
||||||
|
WC()->customer->set_shipping_country( $country );
|
||||||
|
WC()->customer->set_shipping_state( $state );
|
||||||
|
WC()->customer->set_shipping_postcode( $postcode );
|
||||||
|
WC()->customer->set_shipping_city( $city );
|
||||||
|
WC()->customer->set_shipping_address( $address_1 );
|
||||||
|
WC()->customer->set_shipping_address_2( $address_2 );
|
||||||
|
|
||||||
|
// Also set billing for tax calculation context
|
||||||
|
WC()->customer->set_billing_country( $country );
|
||||||
|
WC()->customer->set_billing_state( $state );
|
||||||
|
WC()->customer->set_billing_postcode( $postcode );
|
||||||
|
WC()->customer->set_billing_city( $city );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate shipping
|
// Calculate shipping
|
||||||
|
|||||||
Reference in New Issue
Block a user