WooCommerce:部分退款后运输方式未更新?

问题描述 投票:0回答:2

我在一家 WooCommerce 商店工作,我们为超过 100 欧元的订单提供免费送货服务。但是,当对包含多个产品的订单进行部分退款时,例如退回 1 个产品,并且订单总价值低于 100 欧元,则不会重新计算送货方式。 “免费送货”选项仍然存在,但对于 100 欧元以下的订单,它应恢复为 9 欧元的统一费率。

示例:

产品 1 售价 33 欧元

产品 2 售价 44 欧元

产品 3 售价 55 欧元

订单总价:132€ = 免运费

客户请求退回产品 2,因此订单总价值低于 100 欧元。

订单总价:88 欧元 + 9 欧元标准运费。

但是现在当我退回 1 个产品时,它一直说免费送货,这是不正确的。

add_action('woocommerce_order_refunded', 'adjust_shipping_after_refund', 10, 2);

function adjust_shipping_after_refund($order_id, $refund_id) {
    $order = wc_get_order($order_id);
    $total_sale_price = 0;

    // Calculate new total after refund
    foreach ($order->get_items() as $item_id => $item) {
        $product = $item->get_product();
        $quantity = $item->get_quantity();
        $sale_price = $product->get_sale_price();

        if ($sale_price) {
            $total_sale_price += $sale_price * $quantity;
        } else {
            $total_sale_price += $product->get_regular_price() * $quantity;
        }
    }

    // If the total is under €100, apply flat rate shipping
    if ($total_sale_price < 100) {
        foreach ($order->get_shipping_methods() as $shipping_item_id => $shipping_item) {
            if ($shipping_item->get_method_id() === 'free_shipping') {
                $order->remove_item($shipping_item_id); // Remove free shipping
            }
        }

        // Add flat rate shipping of €9
        if (empty($order->get_shipping_methods())) {
            $rate = new WC_Shipping_Rate('flat_rate', 'Verzendkosten', 9, array(), 'flat_rate');
            $shipping_item = new WC_Order_Item_Shipping();
            $shipping_item->set_props(array(
                'method_title' => $rate->get_label(),
                'method_id' => $rate->get_method_id(),
                'total' => wc_format_decimal($rate->get_cost())
            ));
            $order->add_item($shipping_item);
        }

        // Recalculate totals
        $order->calculate_totals();
        $order->save();
    }
}

这是我迄今为止尝试过的:

  1. 参与了 woocommerce_order_refunded 操作以重新计算运费。
  2. 删除了总额低于 100 欧元时免运费的方式。
  3. 添加了新的运输方式,统一费率为 9 欧元。

我错过了什么或做错了什么?如何强制 WooCommerce 在退款后动态正确更新送货方式?

php wordpress woocommerce shipping-method
2个回答
0
投票

问题在于,WooCommerce 在部分退款后不会自动重新计算运费,导致当总额低于 100 欧元时,

Free Shipping
被错误应用。解决方案包括在退款后动态调整总额和运输方式。

这是更新后的代码:

add_action('woocommerce_order_refunded', 'adjust_shipping_after_refund', 10, 2);

function adjust_shipping_after_refund($order_id, $refund_id) {
    $order = wc_get_order($order_id);
    
    // Use WooCommerce's built-in method to get the total after refunds
    $total_sale_price = $order->get_total(); // This includes refunds automatically

    // If the total is under €100, switch to flat rate shipping
    if ($total_sale_price < 100) {
        // Remove free shipping if it's applied
        foreach ($order->get_shipping_methods() as $shipping_item_id => $shipping_item) {
            if ($shipping_item->get_method_id() === 'free_shipping') {
                $order->remove_item($shipping_item_id);
            }
        }

        // Add flat rate shipping of €9
        if (empty($order->get_shipping_methods())) {
            $rate = new WC_Shipping_Rate('flat_rate', 'Flat Rate Shipping', 9, array(), 'flat_rate');
            $shipping_item = new WC_Order_Item_Shipping();
            $shipping_item->set_props(array(
                'method_title' => $rate->get_label(),
                'method_id' => $rate->get_method_id(),
                'total' => wc_format_decimal($rate->get_cost())
            ));
            $order->add_item($shipping_item);
        }

        // Recalculate the totals after adding the new shipping cost
        $order->calculate_totals();
        $order->save();
    }
}

-1
投票

我找到了问题的答案:

<?php   
// Zorg ervoor dat de verzendkosten worden aangepast na een terugbetaling
add_action('woocommerce_order_refunded', 'adjust_shipping_after_refund', 10, 2);

function adjust_shipping_after_refund($order_id, $refund_id) {
    $order = wc_get_order($order_id);
    $refund = wc_get_order($refund_id);
    if (!$order || !$refund) {
        return;
    }

    $total_sale_price = 0;
    $total_refunded_sale_price = 0;
    $free_shipping_removed = false;

    // Pad naar je eigen logbestand in de wp-content map
    $log_file = WP_CONTENT_DIR . '/verzendkost_update.log';

    // Log de initiële status van de bestelling en het totaal
    error_log("Start processing refund for Order ID: {$order_id}. Refund ID: {$refund_id}" . PHP_EOL, 3, $log_file);

    // Bereken het totaalbedrag van de bestelling op basis van line items
    foreach ($order->get_items('line_item') as $item_id => $item) {
        $product = $item->get_product();
        if (!$product) {
            error_log("Product niet gevonden voor item ID $item_id in order ID $order_id." . PHP_EOL, 3, $log_file);
            continue;
        }
        $quantity = $item->get_quantity();
        $line_total = $item->get_total(); // Haal het lijntotaal op

        $total_sale_price += $line_total;

        // Log details van elk product en de prijs
        error_log("Product: {$product->get_name()}, Line Total: {$line_total}, Quantity: {$quantity}, Subtotal: {$line_total}" . PHP_EOL, 3, $log_file);
    }

    // Controleer welke itemtypes aanwezig zijn in de refund
    foreach ($refund->get_items() as $item_id => $item) {
        $item_type = $item->get_type();
        error_log("Refund Item Type: {$item_type}" . PHP_EOL, 3, $log_file);
    }

    // Bereken het totaalbedrag van de terugbetalingen op basis van line items in de refund
    foreach ($refund->get_items('line_item') as $refund_item_id => $refund_item) {
        $refund_product = $refund_item->get_product();
        if (!$refund_product) {
            error_log("Product niet gevonden voor refund item ID $refund_item_id in order ID $order_id." . PHP_EOL, 3, $log_file);
            continue;
        }
        $refunded_quantity = abs($refund_item->get_quantity());
        $refund_total = $refund_item->get_total(); // Dit is een negatieve waarde
        $refund_subtotal = abs($refund_total); // Absolute waarde voor berekening

        $total_refunded_sale_price += $refund_subtotal;

        // Log details van elk refund item en de prijs
        error_log("Refund Product: {$refund_product->get_name()}, Refund Total: {$refund_total}, Refunded Quantity: {$refunded_quantity}, Refund Subtotal: {$refund_subtotal}" . PHP_EOL, 3, $log_file);
    }

    // Bereken het netto totaalbedrag na terugbetalingen
    $net_sale_price = $total_sale_price - $total_refunded_sale_price;

    // Log het netto totale bedrag
    error_log("Net sale price after refund: {$net_sale_price}" . PHP_EOL, 3, $log_file);

    // Controleer of gratis verzending moet worden verwijderd en de verzendkosten van €9 moeten worden toegevoegd
    if ($net_sale_price < 100) {
        error_log("Net sale price is below 100 EUR. Checking for free shipping..." . PHP_EOL, 3, $log_file);

        // Log alle huidige verzendmethoden
        foreach ($order->get_shipping_methods() as $shipping_item) {
            $method_id = $shipping_item->get_method_id();
            $instance_id = $shipping_item->get_instance_id();
            $method_title = $shipping_item->get_method_title();
            error_log("Shipping Method Found - ID: {$method_id}, Instance ID: {$instance_id}, Title: {$method_title}" . PHP_EOL, 3, $log_file);
        }

        // Verwijder gratis verzending door te controleren op method_title
        foreach ($order->get_shipping_methods() as $item_id => $item) {
            if ($item->get_method_title() === 'Gratis verzending') {
                $order->remove_item($item_id); // Verwijder gratis verzending
                $free_shipping_removed = true; // Zet de vlag voor het verwijderen
                error_log("Free shipping removed." . PHP_EOL, 3, $log_file);
            }
        }

        if ($free_shipping_removed) {
            // Controleer of er al een flat rate shipping method bestaat
            $flat_rate_exists = false;
            foreach ($order->get_shipping_methods() as $item) {
                if ($item->get_method_id() === 'flat_rate') {
                    $item->set_total(9);
                    $item->save();
                    $flat_rate_exists = true;
                    error_log("Existing flat rate shipping updated to €9." . PHP_EOL, 3, $log_file);
                }
            }

            if (!$flat_rate_exists) {
                // Voeg een nieuwe flat rate shipping method toe
                $shipping_item = new WC_Order_Item_Shipping(); 
                $shipping_item->set_method_title("Verzendkosten");
                $shipping_item->set_method_id("flat_rate");
                $shipping_item->set_total(9);
                $order->add_item($shipping_item);
                $order->save();
                error_log("Flat rate shipping of €9 added." . PHP_EOL, 3, $log_file);
            }

            // Herbereken de bestelling en sla deze op
            $order->calculate_totals();
            $order->save();

            // Log de nieuwe bestellingstotalen
            error_log("New order totals after adding shipping: " . print_r($order->get_order_item_totals(), true) . PHP_EOL, 3, $log_file);
        } else {
            error_log("Free shipping was not removed." . PHP_EOL, 3, $log_file);
        }
    } else {
        error_log("Net sale price is above 100 EUR. No shipping changes required." . PHP_EOL, 3, $log_file);
    }
}
?>

我使用 _sale_price (我之前没有提到为什么使用它)。我使用这个是因为 _regular_price 不是我们的商店价格。

但更进一步,所有内容都与我的代码相同。如果您使用此功能,只需将其更改为 _regulare_price 即可。

上面的代码工作正确。

© www.soinside.com 2019 - 2024. All rights reserved.