英文:
How to change the subtotal and total based on the calculation of pickup and delivery date on checkout?
问题
我需要帮助使用wp日期选择器。我想要的是 - 结账页面上的客户可以选择提取和交付日期。选择日期后,购物车摘要显示计算 - 例如,如果我选择从24.07 - 26.07,那么计算显示为2天,并将产品价格乘以2。我会添加一个我需要的截图。
我现在有这个(functions.php) -
// 添加自定义结账日期选择器字段
add_action('woocommerce_before_order_notes', 'datepicker_custom_fields');
function datepicker_custom_fields($checkout) {
$pickup_datepicker_slug = 'pickup_datepicker';
$delivery_datepicker_slug = 'delivery_datepicker';
echo '<div id="datepicker-wrapper">';
woocommerce_form_field($pickup_datepicker_slug, array(
'type' => 'text',
'class'=> array('form-row-first my-datepicker'),
'label' => __('Pickup date'),
'required' => true,
), '');
woocommerce_form_field($delivery_datepicker_slug, array(
'type' => 'text',
'class'=> array('form-row-first my-datepicker'),
'label' => __('Delivery date'),
'required' => true,
), '');
echo '<br clear="all"></div>';
// Jquery: 启用日期选择器
?>
<script language="javascript">
jQuery( function($){
var pickup = '#<?php echo $pickup_datepicker_slug ?>';
var delivery = '#<?php echo $delivery_datepicker_slug ?>';
$(pickup).datepicker({
dateFormat: 'dd.mm.yy', // ISO格式化日期
});
$(delivery).datepicker({
dateFormat: 'dd.mm.yy', // ISO格式化日期
});
});
</script>
<?php
}
// 在结账后订单总额后显示额外信息
add_action('woocommerce_review_order_after_order_total', 'display_additional_info_after_total');
function display_additional_info_after_total() {
// 从POST请求(结账页面)获取提取和交付日期
$pickup_date = isset( $_POST['pickup_datepicker'] ) ? sanitize_text_field( $_POST['pickup_datepicker'] ) : '';
$delivery_date = isset( $_POST['delivery_datepicker'] ) ? sanitize_text_field( $_POST['delivery_datepicker'] ) : '';
// 计算提取日期和交付日期之间的天数差异
$pickup_timestamp = strtotime( $pickup_date );
$delivery_timestamp = strtotime( $delivery_date );
$days_difference = ceil( ( $delivery_timestamp - $pickup_timestamp ) / ( 60 * 60 * 24 ) );
// 基于购物车小计和天数差异计算费用
$cart = WC()->cart;
$fee = $cart->subtotal * $days_difference; // 根据需要修改此公式
// 显示额外信息
if ( $days_difference > 0 ) {
echo '<p>Total ' . wc_price( $cart->subtotal + $fee ) . ' ( ' . wc_price( $fee ) . ' x ' . $days_difference . ' dienas )</p>';
}
}
英文:
I need help with a wp date picker. The thing that I want is - customers on the checkout page can choose the pickup and delivery date. After choosing the date, the in-cart summary shows the calculation - For example, if I choose from 24.07 - 26.07, then the calculation shows 2 days and multiply the price of the product x2. I'll add a screenshot of what I need.
Right now I have this (functions.php) -
// Add custom checkout date picker fields
add_action( 'woocommerce_before_order_notes', 'datepicker_custom_fields' );
function datepicker_custom_fields( $checkout ) {
$pickup_datepicker_slug = 'pickup_datepicker';
$delivery_datepicker_slug = 'delivery_datepicker';
echo '<div id="datepicker-wrapper">';
woocommerce_form_field( $pickup_datepicker_slug, array(
'type' => 'text',
'class'=> array( 'form-row-first my-datepicker'),
'label' => __('Pickup date'),
'required' => true,
), '' );
woocommerce_form_field( $delivery_datepicker_slug, array(
'type' => 'text',
'class'=> array( 'form-row-first my-datepicker'),
'label' => __('Delivery date'),
'required' => true,
), '' );
echo '<br clear="all"></div>';
// Jquery: Enable the Datepicker
?>
<script language="javascript">
jQuery( function($){
var pickup = '#<?php echo $pickup_datepicker_slug ?>';
var delivery = '#<?php echo $delivery_datepicker_slug ?>';
$(pickup).datepicker({
dateFormat: 'dd.mm.yy', // ISO formatting date
});
$(delivery).datepicker({
dateFormat: 'dd.mm.yy', // ISO formatting date
});
});
</script>
<?php
}
// Display additional information after order total in checkout
add_action( 'woocommerce_review_order_after_order_total', 'display_additional_info_after_total' );
function display_additional_info_after_total() {
// Get the pickup and delivery dates from the POST request (checkout page)
$pickup_date = isset( $_POST['pickup_datepicker'] ) ? sanitize_text_field( $_POST['pickup_datepicker'] ) : '';
$delivery_date = isset( $_POST['delivery_datepicker'] ) ? sanitize_text_field( $_POST['delivery_datepicker'] ) : '';
// Calculate the difference in days between pickup and delivery dates
$pickup_timestamp = strtotime( $pickup_date );
$delivery_timestamp = strtotime( $delivery_date );
$days_difference = ceil( ( $delivery_timestamp - $pickup_timestamp ) / ( 60 * 60 * 24 ) );
// Calculate the fee based on the cart subtotal and days difference
$cart = WC()->cart;
$fee = $cart->subtotal * $days_difference; // Modify this formula if needed
// Display the additional information
if ( $days_difference > 0 ) {
echo '<p>Total ' . wc_price( $cart->subtotal + $fee ) . ' ( ' . wc_price( $fee ) . ' x ' . $days_difference . ' dienas )</p>';
}
}
答案1
得分: 0
以下是翻译好的部分:
我不确定您正在使用的主题,但您可以像这样做。
在日期选择器的`onSelect`事件中,您可以通过这个WooCommerce调用的`woocommerce_before_calculate_totals`来触发`update_checkout`
// 添加自定义结帐日期选择器字段
function datepicker_custom_fields( $checkout ) {
$pickup_datepicker_slug = 'pickup_datepicker';
$delivery_datepicker_slug = 'delivery_datepicker';
echo '<div id="datepicker-wrapper">';
woocommerce_form_field( $pickup_datepicker_slug, array(
'type' => 'text',
'class'=> array( 'form-row-first my-datepicker'),
'label' => __('Pickup date'),
'required' => true,
), WC()->session->get( 'pickup_datepicker' ) );
woocommerce_form_field( $delivery_datepicker_slug, array(
'type' => 'text',
'class'=> array( 'form-row-first my-datepicker'),
'label' => __('Delivery date'),
'required' => true,
), WC()->session->get( 'delivery_datepicker' ) );
echo '<br clear="all"></div>';
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
var pickup = '#pickup_datepicker';
var delivery = '#delivery_datepicker';
$(pickup).datepicker({
dateFormat: 'dd.mm.yy', // ISO formatting date
onSelect: function(selected) {
var selectedDate = selected.split('.').reverse().join('-'); // Convert to 'yy-mm-dd' format
var minDate = new Date(selectedDate);
minDate.setDate(minDate.getDate() + 1);
$(delivery).datepicker("option", "minDate", minDate);
calculateDays();
}
});
$(delivery).datepicker({
dateFormat: 'dd.mm.yy', // ISO formatting date
onSelect: function(selected) {
calculateDays();
}
});
// Function to calculate the days between two dates
function calculateDays() {
$( document.body ).trigger( 'update_checkout' );
}
});
</script>
<?php
}
add_action( 'woocommerce_before_order_notes', 'datepicker_custom_fields' );
在这个过滤器中,您可以捕获您的`pickup_datepicker`和`delivery_datepicker`的值,并使用`DateTime`类和`diff`函数来计算天数,并使用`set_price`函数来设置购物车项目价格。
function override_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
return;
}
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ){
return;
}
parse_str($_POST['post_data'], $post_data);
if (isset($post_data['pickup_datepicker']) && $post_data['pickup_datepicker'] != '' && isset($post_data['delivery_datepicker']) && $post_data['delivery_datepicker'] != '') {
WC()->session->set('pickup_datepicker', sanitize_text_field($post_data['pickup_datepicker']));
WC()->session->set('delivery_datepicker', sanitize_text_field($post_data['delivery_datepicker']));
$pickup_datepicker = sanitize_text_field($post_data['pickup_datepicker']);
$delivery_datepicker = sanitize_text_field($post_data['delivery_datepicker']);
$pickup_date_obj = new DateTime($pickup_datepicker);
$delivery_date_obj = new DateTime($delivery_datepicker);
$interval = $pickup_date_obj->diff($delivery_date_obj);
$days = $interval->days;
$days = ( $days > 1 ) ? $days : 1 ;
WC()->session->set('delivery_days', $days );
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Calculate the new subtotal and total based on the number of days
$new_price = $cart_item['data']->get_price() * $days;
$cart_item['data']->set_price( $new_price );
$cart_item['days'] = $days;
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'override_cart_item_price', 99, 1 );
通过使用这个过滤器,您可以在价格旁边显示天数。
function add_days_woocommerce_cart_item_subtotal( $total, $cart_item, $cart_item_key ){
$delivery_days = WC()->session->get( 'delivery_days' );
if( $delivery_days ){
$day_label = 'day';
$product = wc_get_product( $cart_item['product_id'] );
if( $delivery_days > 1 ){
$day_label = 'days';
}
$total = wc_price( $product->get_price() ) . ' x '. $delivery_days. '('.$day_label.')' . ' = '. $total;
}
return $total;
}
add_filter( 'woocommerce_cart_item_subtotal', 'add_days_woocommerce_cart_item_subtotal', 10, 3 );
英文:
I am not sure about which theme you are using but you can do something like this.
On date picker onSelect
event you can trigger update_checkout
by this woocommerce called woocommerce_before_calculate_totals
// Add custom checkout datepicker fields
function datepicker_custom_fields( $checkout ) {
$pickup_datepicker_slug = 'pickup_datepicker';
$delivery_datepicker_slug = 'delivery_datepicker';
echo '<div id="datepicker-wrapper">';
woocommerce_form_field( $pickup_datepicker_slug, array(
'type' => 'text',
'class'=> array( 'form-row-first my-datepicker'),
'label' => __('Pickup date'),
'required' => true,
), WC()->session->get( 'pickup_datepicker' ) );
woocommerce_form_field( $delivery_datepicker_slug, array(
'type' => 'text',
'class'=> array( 'form-row-first my-datepicker'),
'label' => __('Delivery date'),
'required' => true,
), WC()->session->get( 'delivery_datepicker' ) );
echo '<br clear="all"></div>';
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
var pickup = '#pickup_datepicker';
var delivery = '#delivery_datepicker';
$(pickup).datepicker({
dateFormat: 'dd.mm.yy', // ISO formatting date
onSelect: function(selected) {
var selectedDate = selected.split('.').reverse().join('-'); // Convert to 'yy-mm-dd' format
var minDate = new Date(selectedDate);
minDate.setDate(minDate.getDate() + 1);
$(delivery).datepicker("option", "minDate", minDate);
calculateDays();
}
});
$(delivery).datepicker({
dateFormat: 'dd.mm.yy', // ISO formatting date
onSelect: function(selected) {
calculateDays();
}
});
// Function to calculate the days between two dates
function calculateDays() {
$( document.body ).trigger( 'update_checkout' );
}
});
</script>
<?php
}
add_action( 'woocommerce_before_order_notes', 'datepicker_custom_fields' );
In this filter, you can catch your pickup_datepicker
and delivery_datepicker
value and calculate days using the DateTime
class and diff
function. and set the cart item price using the set_price
function.
function override_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
return;
}
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ){
return;
}
parse_str($_POST['post_data'], $post_data);
if (isset($post_data['pickup_datepicker']) && $post_data['pickup_datepicker'] != '' && isset($post_data['delivery_datepicker']) && $post_data['delivery_datepicker'] != '') {
WC()->session->set('pickup_datepicker', sanitize_text_field($post_data['pickup_datepicker']));
WC()->session->set('delivery_datepicker', sanitize_text_field($post_data['delivery_datepicker']));
$pickup_datepicker = sanitize_text_field($post_data['pickup_datepicker']);
$delivery_datepicker = sanitize_text_field($post_data['delivery_datepicker']);
$pickup_date_obj = new DateTime($pickup_datepicker);
$delivery_date_obj = new DateTime($delivery_datepicker);
$interval = $pickup_date_obj->diff($delivery_date_obj);
$days = $interval->days;
$days = ( $days > 1 ) ? $days : 1 ;
WC()->session->set('delivery_days', $days );
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Calculate the new subtotal and total based on the number of days
$new_price = $cart_item['data']->get_price() * $days;
$cart_item['data']->set_price( $new_price );
$cart_item['days'] = $days;
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'override_cart_item_price', 99, 1 );
By using this filter you can show a number of days beside the price.
function add_days_woocommerce_cart_item_subtotal( $total, $cart_item, $cart_item_key ){
$delivery_days = WC()->session->get( 'delivery_days' );
if( $delivery_days ){
$day_label = 'day';
$product = wc_get_product( $cart_item['product_id'] );
if( $delivery_days > 1 ){
$day_label = 'days';
}
$total = wc_price( $product->get_price() ) . ' x '. $delivery_days. '('.$day_label.')' . ' = '. $total;
}
return $total;
}
add_filter( 'woocommerce_cart_item_subtotal', 'add_days_woocommerce_cart_item_subtotal', 10, 3 );
References:
- Delivery Date Option on Checkout Page -
WordPress.org - Woocommerce checkout update totals with datepicker - WordPress Stack
Exchange - Custom WooCommerce datepicker checkout field saved and displayed on
orders and emails - Stack
Overflow
Tested and working.
UPDATE as per OP's comment.
You can override plugins/woocommerce/templates/checkout/review-order.php
to your theme yourthemename/woocommerce/checkout/review-order.php
Reference
You will find this below code. and change according to your requirement.
<tr class="order-total">
<th><?php esc_html_e( 'Total', 'woocommerce' ); ?></th>
<td><?php wc_cart_totals_order_total_html(); ?></td>
</tr>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论