首页 > 解决方案 > 在 WooCommerce 中选择租期时显示折扣和产品数量

问题描述

我目前正在研究租赁产品的范围日期。为此,我使用 Jquery UI Datepicker。

这使我可以选择两个日期并计算这些日期范围内的天数。

注册和脚本初始化:

// Register main Datepicker jQuery plugin script
add_action('wp_enqueue_scripts', 'enabling_date_picker');

function enabling_date_picker() {

    // Only on front-end and product page
    if (is_product() && !is_wc_endpoint_url()):

            // Load the Datepicker jQuery-ui plugin script
            wp_enqueue_style('jquery-ui', 'https://code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css');                
    wp_enqueue_script('jquery-ui-datepicker');

    endif;
}

// The jQuery script
//add_action( 'wp_footer', 'rental_date_jquery_script');
function rental_date_jquery_script() {
    // Only on front-end and product page
    global $product;
    if (is_product() && !is_wc_endpoint_url() && !$product - > is_type('woosb')):

            ?>
            <script>

            jQuery(function($) {
                    var from = new Date(),
                            to = new Date(),
                            dayDiff = 1;

                    var _onSelect = function(selectedDate) {
                            var option = this.id == "rental_period_from" ? "minDate" : "maxDate",
                                    instance = $(this).data("datepicker"),
                                    date = $.datepicker.parseDate(
                                            instance.settings.dateFormat || $.datepicker._defaults.dateFormat,
                                            selectedDate, instance.settings);
                            dates.not(this).datepicker("option", option, date);

                            if (this.id == "rental_period_from") {
                                    from = $(this).datepicker('getDate');
                                    if (to) {
                                            update_days();
                                    }
                            }
                            if (this.id == "rental_period_to") {
                                    to = $(this).datepicker('getDate');
                                    update_days();
                            }
                    };

                    var dates = $("#rental_period_from, #rental_period_to").datepicker({
                            defaultDate: "+1w",
                            changeMonth: true,
                            numberOfMonths: 1,
                            dateFormat: "dd.mm.yy",
                            minDate: 0,
                            //maxDate: 14,
                            onSelect: _onSelect
                    });

                    function update_days() {
                            dayDiff = Math.ceil((to - from) / (1000 * 60 * 60 * 24));
                            $("#days").empty();
                            $("#days").append(dayDiff);
                    }

                    //Auto-update on page load - before any user interactions.
                    (function($from, $to) {
                            _onSelect.call($from.get(0), $from.val());
                            _onSelect.call($to.get(0), $to.val());
                    })($('#rental_period_from'), $('#rental_period_to'));
            });       

    </script>

    <?php

    endif;
}

显示字段:

//Add a custom field before single add to cart
add_action( 'woocommerce_before_variations_form', 'display_rental_date_custom_fields', 5 );

function display_rental_date_custom_fields() {
    ?>
    <label>Rental Period:</label>
    <div>       
    <span>
        <input id="rental_period_from" type="date" name="rental_period_from" value="<?php echo esc_attr( filter_input( INPUT_POST, 'rental_period_from' ) ); ?>" placeholder="dd.mm.yy" />
    </span>
    <span>
        <input id="rental_period_to" type="date" name="rental_period_to" value="<?php echo esc_attr( filter_input( INPUT_POST, 'rental_period_to' ) ); ?>" placeholder="dd.mm.yy" />
    </span>
    </div>
    <div>
        <span>You have chosen: </span>
        <span id="days">0</span> days
    </div>
    <input type="hidden" name="is_rental" value="1">
<?php
}

处理提交的租期:

add_filter('woocommerce_add_cart_item_data', 'my_add_rental_period_data');

function my_add_rental_period_data($cart_item_data) {
    if (!empty($_POST['is_rental'])) {
            //Throwing an Exception will prevent the product from being added to the cart.

            //Validate POSTed values.
            if (empty($_POST['rental_period_from']) ||
                    empty($_POST['rental_period_to'])) {
                    throw new Exception('Rental start and end dates must both be specified.');
            }

            $now = date_create('now');
            $from = date_create($_POST['rental_period_from']);
            $to = date_create($_POST['rental_period_to']);
            // Validate rental dates.
            if (!$from || !$to || $to < $from) {
                    throw new Exception('Invalid rental dates.');
            }

            $format = 'd.m.Y'; //dd.mm.yyyy
            $rental_days = date_diff($from, $to)->days;
            $cart_item_data['rental_period'] = [
                    'from' => $from->format($format),
                    'to' => $to->format($format),
                    'days' => $rental_days,
            ];
    }
    return $cart_item_data;
}

将折扣应用于购物车中的租赁产品:

function my_set_rental_product_price(array $cart_item) {
    if (!empty($cart_item['rental_period'])) {
            $rental_days = $cart_item['rental_period']['days'];
            $regular_price = $cart_item['data']->get_regular_price();

            if ($rental_days > 1) {
                    $days = $rental_days - 1;
                    $price = $regular_price / 2 * $days + $regular_price;
                    $cart_item['data']->set_price($price);
            }
            //else, no discount.
    }
    return $cart_item['data'];
}

add_action('woocommerce_before_calculate_totals', 'my_apply_discount_to_rental_products');

function my_apply_discount_to_rental_products() {
    foreach(WC()->cart->get_cart() as $cart_item_key => $cart_item) {
            my_set_rental_product_price($cart_item);
    }
}

add_filter('woocommerce_cart_item_product', 'my_apply_discount_to_rental_product', 10, 2);

function my_apply_discount_to_rental_product($product, $cart_item) {
    return my_set_rental_product_price($cart_item);
}

在购物车页面的主表格中显示租赁期:

add_filter('woocommerce_get_item_data', 'my_add_rental_period_meta', 10, 2);

function my_add_rental_period_meta($item_data, $cart_item) {
    if (!empty($cart_item['rental_period'])) {
            $period =& $cart_item['rental_period'];

            $days = $period['days'].
            ' '._n('day', 'days', $period['days']);
            $range = ($period['from'] === $period['to']) ? $period['from'].
            ' (today)':
            $days.
            ' ('.$period['from'].
            ' - '.$period['to'].
            ')';

            $item_data[] = [
                    'key' => 'Rental Period',
                    'value' => $range,
            ];
    }
    return $item_data;
}

在订单中添加租赁期作为产品的元数据:

add_action('woocommerce_checkout_create_order_line_item', 'my_add_rental_period_meta2', 10, 3);

function my_add_rental_period_meta2($item, $cart_item_key, $cart_item) {
    if (!empty($cart_item['rental_period'])) {
            $item->add_meta_data('_rental_period', $cart_item['rental_period']);
    }
    return $item;
}

允许显示上面保存的元数据,例如,在“订单详细信息”表和“新订单”管理员电子邮件中:

add_filter('woocommerce_order_item_get_formatted_meta_data', 'my_add_rental_period_meta3', 10, 2);

function my_add_rental_period_meta3($formatted_meta, $item) {
    if ($period = $item->get_meta('_rental_period', true)) {
            $days = $period['days'].
            ' '._n('day', 'days', $period['days']);
            $range = ($period['from'] === $period['to']) ? $period['from'].
            ' (today)':
            $days.
            ' ('.$period['from'].
            ' - '.$period['to'].
            ')';

            $formatted_meta[] = (object)[
                    'key' => 'rental_period',
                    'value' => $period,
                    'display_key' => 'Rental Period',
                    'display_value' => $range,
            ];
    }
    return $formatted_meta;
}

更新:

如何根据客户选择的时间段显示折扣文本和折扣总额?

例如,如果客户选择超过一天的租期,则显示“您选择了 5 天。您的折扣是 50%。金额 - 200 美元。”</p>

如果客户选择了一日租赁,则不会显示折扣。例如,“您选择了 1 天。金额 - 400 美元。”

选择租期后,此文本应显示在单个产品页面上。


更新 2: 基于WooCommerce 中每天的折扣动态计算

标签: wordpresswoocommerce

解决方案


您只需使用 jQuery 中的 update_days() 函数稍微修改页脚中的 rent_date_jquery_script() 即可。这是代码:

add_action( 'wp_footer', 'rental_date_jquery_script');

function rental_date_jquery_script() {
    global $product;

    // Only on front-end and product page
    if (is_product() && !is_wc_endpoint_url() && !$product->is_type('woosb')) {

    // get regular_price for product
    $regular_price = '';

    if ($product->is_type('simple')) {
        $regular_price = $product->get_regular_price();
    } elseif ($product->is_type('variable')) {
        $regular_price = $product->get_variation_price( 'max' );
    }

    if ( ! $regular_price) {
        return;
    }

    ?>

    <script>
        jQuery(function($) {
                // pass regular_price to js var
                var regular_price = <?php echo intval($regular_price); ?>;

                var from = new Date(),
                        to = new Date(),
                        dayDiff = 1;

                var _onSelect = function(selectedDate) {
                        var option = this.id == "rental_period_from" ? "minDate" : "maxDate",
                                instance = $(this).data("datepicker"),
                                date = $.datepicker.parseDate(
                                        instance.settings.dateFormat || $.datepicker._defaults.dateFormat,
                                        selectedDate, instance.settings);
                        dates.not(this).datepicker("option", option, date);

                        if (this.id == "rental_period_from") {
                                from = $(this).datepicker('getDate');
                                if (to) {
                                        update_days();
                                }
                        }
                        if (this.id == "rental_period_to") {
                                to = $(this).datepicker('getDate');
                                update_days();
                        }
                };

                var dates = $("#rental_period_from, #rental_period_to").datepicker({
                        defaultDate: "+1w",
                        changeMonth: true,
                        numberOfMonths: 1,
                        dateFormat: "dd.mm.yy",
                        minDate: 0,
                        //maxDate: 14,
                        onSelect: _onSelect
                });

                function update_days() {
                        dayDiff = Math.ceil((to - from) / (1000 * 60 * 60 * 24));

                        var new_price = regular_price,
                            text = dayDiff > 1 ? 'You have chosen ' + dayDiff + ' days. ' : 'You choose 1 day. ';

                        if (dayDiff > 1) {
                            new_price = regular_price / 2 * (dayDiff - 1) + regular_price;
                            text += 'Your discount is 50%. Amount - $' + new_price;
                        } else {
                            text += 'Amount - $' + regular_price;
                        }

                        $("#days").html(text);
                }

                //Auto-update on page load - before any user interactions.
                (function($from, $to) {
                        _onSelect.call($from.get(0), $from.val());
                        _onSelect.call($to.get(0), $to.val());
                })($('#rental_period_from'), $('#rental_period_to'));
        });       

    </script>

    <?php

    } // endif
}

推荐阅读