fix(orders): Use WooCommerce cart for shipping calculation in order creation
## Issues Fixed: 1. ✅ Shipping cost was zero in created orders 2. ✅ Live rates (UPS, Rajaongkir) not calculated 3. ✅ Shipping title shows service level (e.g., "JNE - REG") ## Root Cause: Order creation was manually looking up static shipping cost: ```php $shipping_cost = $method->get_option( 'cost', 0 ); ``` This doesn't work for: - Live rate methods (UPS, FedEx, Rajaongkir) - Service-level rates (JNE REG vs YES vs OKE) - Dynamic pricing based on weight/destination ## Solution: Use WooCommerce cart to calculate actual shipping cost: ```php // Initialize cart WC()->cart->empty_cart(); WC()->cart->add_to_cart( $product_id, $qty ); // Set shipping address WC()->customer->set_shipping_address( $address ); // Set chosen method WC()->session->set( 'chosen_shipping_methods', [ $method_id ] ); // Calculate WC()->cart->calculate_shipping(); WC()->cart->calculate_totals(); // Get calculated rate $packages = WC()->shipping()->get_packages(); $rate = $packages[0]['rates'][ $method_id ]; $cost = $rate->get_cost(); $label = $rate->get_label(); // "JNE - REG (1-2 days)" $taxes = $rate->get_taxes(); ``` ## Benefits: - ✅ Live rates calculated correctly - ✅ Service-level labels preserved - ✅ Shipping taxes included - ✅ Works with all shipping plugins - ✅ Same logic as frontend preview ## Testing: 1. Create order with UPS → Shows "UPS Ground" + correct cost 2. Create order with Rajaongkir → Shows "JNE - REG" + correct cost 3. Order detail page → Shows full service name 4. Shipping cost → Matches preview calculation
This commit is contained in:
@@ -872,8 +872,65 @@ class OrdersController {
|
||||
], 'shipping' );
|
||||
}
|
||||
|
||||
// Shipping method line (parse id:instance if provided)
|
||||
// Shipping method - calculate using WooCommerce cart for accurate rates
|
||||
if ( $shipping_method ) {
|
||||
// Initialize cart if needed
|
||||
if ( ! WC()->cart ) {
|
||||
wc_load_cart();
|
||||
}
|
||||
if ( ! WC()->session ) {
|
||||
WC()->session = new \WC_Session_Handler();
|
||||
WC()->session->init();
|
||||
}
|
||||
|
||||
// Temporarily use cart to calculate shipping
|
||||
WC()->cart->empty_cart();
|
||||
|
||||
// Add items to cart
|
||||
foreach ( $items as $row ) {
|
||||
$pid = absint( $row['product_id'] ?? 0 );
|
||||
$qty = max( 1, absint( $row['qty'] ?? 1 ) );
|
||||
if ( $pid ) {
|
||||
WC()->cart->add_to_cart( $pid, $qty );
|
||||
}
|
||||
}
|
||||
|
||||
// Set shipping address for calculation
|
||||
if ( $ship_addr ) {
|
||||
WC()->customer->set_shipping_country( $ship_addr['country'] ?? '' );
|
||||
WC()->customer->set_shipping_state( $ship_addr['state'] ?? '' );
|
||||
WC()->customer->set_shipping_postcode( $ship_addr['postcode'] ?? '' );
|
||||
WC()->customer->set_shipping_city( $ship_addr['city'] ?? '' );
|
||||
WC()->customer->set_shipping_address( $ship_addr['address_1'] ?? '' );
|
||||
}
|
||||
|
||||
// Set chosen shipping method
|
||||
WC()->session->set( 'chosen_shipping_methods', [ $shipping_method ] );
|
||||
|
||||
// Calculate shipping
|
||||
WC()->cart->calculate_shipping();
|
||||
WC()->cart->calculate_totals();
|
||||
|
||||
// Get the calculated rate
|
||||
$packages = WC()->shipping()->get_packages();
|
||||
$shipping_cost = 0;
|
||||
$shipping_title = $shipping_method;
|
||||
$shipping_taxes = [];
|
||||
|
||||
foreach ( $packages as $package ) {
|
||||
if ( isset( $package['rates'][ $shipping_method ] ) ) {
|
||||
$rate = $package['rates'][ $shipping_method ];
|
||||
$shipping_cost = $rate->get_cost();
|
||||
$shipping_title = $rate->get_label();
|
||||
$shipping_taxes = $rate->get_taxes();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up cart
|
||||
WC()->cart->empty_cart();
|
||||
|
||||
// Parse method ID and instance ID
|
||||
$method_id = $shipping_method;
|
||||
$instance_id = null;
|
||||
if ( strpos( $shipping_method, ':' ) !== false ) {
|
||||
@@ -881,36 +938,7 @@ class OrdersController {
|
||||
$instance_id = absint( $instance_str );
|
||||
}
|
||||
|
||||
// Get shipping method cost
|
||||
$shipping_cost = 0;
|
||||
$shipping_title = $method_id;
|
||||
|
||||
if ( $instance_id ) {
|
||||
// Get shipping zone and method instance
|
||||
$zones = \WC_Shipping_Zones::get_zones();
|
||||
foreach ( $zones as $zone ) {
|
||||
foreach ( $zone['shipping_methods'] as $method ) {
|
||||
if ( $method->id === $method_id && $method->instance_id == $instance_id ) {
|
||||
$shipping_cost = $method->get_option( 'cost', 0 );
|
||||
$shipping_title = $method->get_title();
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check zone 0 (rest of the world)
|
||||
if ( $shipping_cost == 0 ) {
|
||||
$zone = new \WC_Shipping_Zone( 0 );
|
||||
foreach ( $zone->get_shipping_methods() as $method ) {
|
||||
if ( $method->id === $method_id && $method->instance_id == $instance_id ) {
|
||||
$shipping_cost = $method->get_option( 'cost', 0 );
|
||||
$shipping_title = $method->get_title();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add shipping line item
|
||||
$ship_item = new \WC_Order_Item_Shipping();
|
||||
$ship_item->set_method_id( $method_id );
|
||||
if ( null !== $instance_id && method_exists( $ship_item, 'set_instance_id' ) ) {
|
||||
@@ -918,6 +946,12 @@ class OrdersController {
|
||||
}
|
||||
$ship_item->set_method_title( $shipping_title );
|
||||
$ship_item->set_total( $shipping_cost );
|
||||
|
||||
// Set shipping taxes if available
|
||||
if ( ! empty( $shipping_taxes ) ) {
|
||||
$ship_item->set_taxes( [ 'total' => $shipping_taxes ] );
|
||||
}
|
||||
|
||||
$order->add_item( $ship_item );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user