Динамические комиссии, рассчитываемые на основе пользовательских полей оформления заказа в WooCommerce.Jquery

Программирование на jquery
Ответить
Anonymous
 Динамические комиссии, рассчитываемые на основе пользовательских полей оформления заказа в WooCommerce.

Сообщение Anonymous »

У меня есть магазин WooCommerce, специализирующийся на аренде пляжного инвентаря. Я добавил раскрывающееся меню на страницу оформления заказа, где покупатель может выбрать доставку заказа или возможность забрать его самостоятельно. Если они выберут вариант доставки, к общей сумме корзины будет добавлена ​​плата в размере 10 долларов США, указанная как «Сбор за доставку». Если они выберут самовывоз, появится второй раскрывающийся список, в котором они смогут выбрать место получения. Я хочу добавить для клиентов возможность покупать холодные напитки на странице оформления заказа, если они выбирают определенное место выдачи (Kamini's Kitchen), список которых должен появиться, когда они выберут это место выдачи. Я написал так, чтобы для каждого напитка появлялись галочки и количество, которое можно выбрать. Когда напиток добавляется, его следует добавить в корзину под своим собственным названием, а указанную цену следует добавить к общей сумме (умноженной на множитель). Наконец, выбранные варианты напитков должны появиться в электронных письмах с заказами и в административной панели.
Вот моя попытка кода, основанная на этой ветке ответов:

Код: Выделить всё

// Utility function: Get Delivery or Pickup options
function get_delivery_or_pickup_options() {
return array(
''          => esc_html__( 'Select an option', 'woocommerce' ),
'delivery'  => esc_html__( 'Delivery Service', 'woocommerce' ),
'pickup'    => esc_html__( 'Pickup', 'woocommerce' )
);
}

// Utility function: Get pickup location options
function get_pickup_location_options() {
return array(
''                  => esc_html__( 'Select an option', 'woocommerce' ),
'main_office'       => esc_html__( 'Pavia 20F - Main Office', 'woocommerce' ),
'kaminis_kitchen'   => esc_html__( "Kamini's Kitchen (Baby Beach)", 'woocommerce' )
);
}

add_action( 'woocommerce_before_order_notes', 'add_delivery_or_pickup_fields', 10 );
function add_delivery_or_pickup_fields( $checkout ) {
// Existing dropdowns...
woocommerce_form_field( 'delivery_or_pickup', array(
'type'      => 'select',
'class'     => array('form-row-wide'),
'label'     => esc_html__( 'Delivery or Pickup?', 'woocommerce' ),
'required'  => true,
'options'   => get_delivery_or_pickup_options(),
), $checkout->get_value('delivery_or_pickup') );

woocommerce_form_field('pickup_location', array(
'type' => 'select',
'class' => array('form-row-wide'),
'label' => esc_html__( 'Select pickup location:', 'woocommerce' ),
'required' => true,
'options' => get_pickup_location_options(),
), $checkout->get_value('pickup_location'));

// Drinks Section - Hidden by default, displayed by JS if pickup_location == kaminis_kitchen
echo '';
echo '' . esc_html__('If you’re renting a beach cooler, you have the option to pre-purchase drinks here and have the cooler loaded up with ice and drinks when picking it up', 'woocommerce') .  '';

$drink_items = array(
'bag_of_ice'       => array('Bag of Ice', 4.00),
'chill'            => array('Chill', 5.00),
'balashi'          => array('Balashi', 5.00),
'magic_mango'      => array('Magic Mango', 5.00),
'amstel_bright'    => array('Amstel Bright', 6.00),
'budweiser'        => array('Budweiser', 5.00),
'bud_light'        => array('Bud Light', 5.00),
'corona'           => array('Corona', 6.00),
'heineken'         => array('Heineken', 5.00),
'presidente'       => array('Presidente', 5.00),
'modelo'           => array('Modelo', 5.00),
'polar'            => array('Polar', 4.00),
'guinness'         => array('Guinness', 7.00),
'coke'             => array('Coke', 3.00),
'coke_zero'        => array('Coke Zero', 3.00),
'sprite'           => array('Sprite', 3.00),
'sprite_zero'      => array('Sprite Zero', 3.00),
'gingerale'        => array('Gingerale', 3.00),
'fuze_tea'         => array('Fuze Tea', 3.00),
'club_soda'        => array('Club Soda', 3.00),
'tonic_water'      => array('Tonic Water', 3.00),
'fanta_cherry'     => array('Fanta Cherry', 3.00),
'fanta_grape'      => array('Fanta Grape', 3.00),
'fanta_orange'     => array('Fanta Orange', 3.00),
'bottled_water'    => array('Bottled Water', 2.57),
);

foreach ( $drink_items as $key => $item ) {
echo '
 ' . esc_html($item[0]) . ' ($' . number_format($item[1], 2) . ') ';
echo '
';
}

echo '';
}

// JavaScript to toggle visibility of the pickup location dropdown and update delivery fee
add_action( 'woocommerce_checkout_init', 'add_delivery_or_pickup_js_script' );
function add_delivery_or_pickup_js_script() {
wc_enqueue_js("

const pickupField = $('#pickup_location_field');
const drinkOptions = $('#drink_options_section');

function toggleDrinkOptions() {
if ($('#pickup_location').val() === 'kaminis_kitchen') {
drinkOptions.show();
} else {
drinkOptions.hide();
}
}

if ($('#delivery_or_pickup').val() !== 'pickup') {
pickupField.hide();
drinkOptions.hide();
}

$(document.body).on('change', '#delivery_or_pickup', function() {
const val = $(this).val();
val === 'pickup' ? pickupField.show() : pickupField.hide();
$.post(wc_checkout_params.ajax_url, {
action: 'save_delivery_or_pickup_to_session',
delivery_or_pickup: val
}, function() {
$(document.body).trigger('update_checkout');
});
});

$(document.body).on('change', '#pickup_location', function() {
toggleDrinkOptions();
$(document.body).trigger('update_checkout');
});

// Send drink selections via AJAX
function updateDrinkSessionData() {
const selectedDrinks = {};
$('#drink_options_section input[type=checkbox]:checked').each(function() {
const key = $(this).attr('name').replace('drinks[', '').replace(']', '');
const qty = $('#drink_qty_' + key).val() || 1;
selectedDrinks[key] = qty;
});

$.post(wc_checkout_params.ajax_url, {
action: 'save_drink_options_to_session',
drinks: selectedDrinks
}, function() {
$(document.body).trigger('update_checkout');
});
}

$(document.body).on('change', '#drink_options_section input', updateDrinkSessionData);

toggleDrinkOptions();
");
}

// Ajax request: Save selection to WooCommerce session
add_action('wp_ajax_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session');
add_action('wp_ajax_nopriv_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session');
function save_delivery_or_pickup_to_session() {
if ( isset($_POST['delivery_or_pickup']) ) {
WC()->session->set('delivery_or_pickup', sanitize_text_field($_POST['delivery_or_pickup']));
}
wp_die();
}

// Add delivery fee if "Delivery Service" is selected
add_action( 'woocommerce_cart_calculate_fees', 'add_delivery_option_fee_based_on_session' );
function add_delivery_option_fee_based_on_session( $cart ) {
if (is_admin() && !defined('DOING_AJAX')) return;

if ( is_checkout() && WC()->session->get('delivery_or_pickup') === 'delivery' ) {
$delivery_fee = 10;
$cart->add_fee( esc_html__( 'Delivery Fee', 'woocommerce' ), $delivery_fee );
}
}

// Save drink selection to WooCommerce session
add_filter('woocommerce_checkout_posted_data', 'capture_drink_data_during_ajax');
function capture_drink_data_during_ajax( $data ) {
if ( isset($_POST['drinks']) && isset($_POST['drink_qty']) ) {
$data['drinks'] = $_POST['drinks'];
$data['drink_qty'] = $_POST['drink_qty'];
}
return $data;
}

add_action('wp_ajax_save_drink_options_to_session', 'save_drink_options_to_session');
add_action('wp_ajax_nopriv_save_drink_options_to_session', 'save_drink_options_to_session');
function save_drink_options_to_session() {
$drinks = isset($_POST['drinks']) ? $_POST['drinks'] : array();
$sanitized = array();

foreach ($drinks as $drink => $qty) {
$drink = sanitize_key($drink);
$qty = max(1, intval($qty));
$sanitized[$drink] = $qty;
}

WC()->session->set('drink_data', $sanitized);
wp_die();
}

add_action('woocommerce_cart_calculate_fees', 'add_drink_fee_via_ajax', 20, 1);
function add_drink_fee_via_ajax($cart) {
if (is_admin() &&  !defined('DOING_AJAX')) return;

$pickup_location = isset($_POST['pickup_location']) ? sanitize_text_field($_POST['pickup_location']) : WC()->session->get('pickup_location');
if ($pickup_location !== 'kaminis_kitchen') return;

$drink_data = WC()->session->get('drink_data', []);
if (empty($drink_data)) return;

$prices = array(
'bag_of_ice' => 4.00, 'chill' => 5.00, 'balashi' => 5.00, 'magic_mango' => 5.00,
'amstel_bright' => 6.00, 'budweiser' => 5.00, 'bud_light' => 5.00, 'corona' => 6.00,
'heineken' => 5.00, 'presidente' => 5.00, 'modelo' => 5.00, 'polar' => 4.00, 'guinness' => 7.00,
'coke' => 3.00, 'coke_zero' => 3.00, 'sprite' => 3.00, 'sprite_zero' => 3.00,
'gingerale' => 3.00, 'fuze_tea' => 3.00, 'club_soda' => 3.00, 'tonic_water' => 3.00,
'fanta_cherry' => 3.00, 'fanta_grape' => 3.00, 'fanta_orange' => 3.00, 'bottled_water' => 2.57,
);

$total = 0;
foreach ($drink_data as $drink => $qty) {
if (isset($prices[$drink])) {
$total += $prices[$drink] * $qty;
}
}

if ($total > 0) {
$cart->add_fee(__('Drink Options', 'woocommerce'), $total);
}
}

add_action('woocommerce_checkout_order_processed', function () {
WC()->session->__unset('drink_data');
}, 10, 1);

// Validate custom shipping options
add_action( 'woocommerce_after_checkout_validation', 'delivery_or_pickup_validation', 20, 2 );
function delivery_or_pickup_validation( $data, $errors ) {
// Delivery or Pickup validation
if ( isset($_POST['delivery_or_pickup']) && empty($_POST['delivery_or_pickup']) ) {
$errors->add( 'delivery_or_pickup', esc_html__( 'You must choose between "Delivery" or "Pickup" option.', 'woocommerce' ), 'error' );
}
// Pickup location validation
elseif ( isset($_POST['delivery_or_pickup']) && $_POST['delivery_or_pickup'] === 'pickup'
&& isset($_POST['pickup_location']) && empty($_POST['pickup_location']) ) {
$errors->add( 'pickup_location', esc_html__( 'You must choose a pickup location.', 'woocommerce' ), 'error' );
}
}

// Save custom chosen shipping option details as order metadata
add_action( 'woocommerce_checkout_create_order', 'save_delivery_or_pickup_as_order_metadata', 10 );
function save_delivery_or_pickup_as_order_metadata( $order ) {
if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) {
$order->add_meta_data('_delivery_or_pickup', esc_attr($_POST['delivery_or_pickup']), true );
}
if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) {
$order->add_meta_data('_pickup_location', esc_attr($_POST['pickup_location']), true);
}
// Remove the WC Session Variable
if (  WC()->session->__isset('delivery_or_pickup') ) {
WC()->session->__unset('delivery_or_pickup');
}
}

add_action( 'woocommerce_checkout_create_order', 'save_drinks_to_order_meta', 20, 1 );
function save_drinks_to_order_meta( $order ) {
if ( isset($_POST['drinks']) ) {
$items = array(
'bag_of_ice' => 'Bag of Ice', 'chill' => 'Chill', 'balashi' => 'Balashi', 'magic_mango' => 'Magic Mango',
'amstel_bright' => 'Amstel Bright', 'budweiser' => 'Budweiser', 'bud_light' => 'Bud Light',
'corona' => 'Corona', 'heineken' => 'Heineken', 'presidente' => 'Presidente',
'modelo' => 'Modelo', 'polar' => 'Polar', 'guinness' => 'Guinness', 'coke' => 'Coke',
'coke_zero' => 'Coke Zero', 'sprite' => 'Sprite', 'sprite_zero' => 'Sprite Zero',
'gingerale' => 'Gingerale', 'fuze_tea' => 'Fuze Tea', 'club_soda' => 'Club Soda',
'tonic_water' => 'Tonic Water', 'fanta_cherry' => 'Fanta Cherry', 'fanta_grape' => 'Fanta Grape',
'fanta_orange' => 'Fanta Orange', 'bottled_water' => 'Bottled Water'
);

$drinks_ordered = array();
foreach ($_POST['drinks'] as $key => $val) {
$qty = intval($_POST['drink_qty'][$key] ?? 1);
if ($qty > 0 && isset($items[$key])) {
$drinks_ordered[] = $items[$key] . ' x' .  $qty;
}
}

if ( !empty($drinks_ordered) ) {
$order->add_meta_data('_drink_options', implode(', ', $drinks_ordered));
}
}
}

// Update custom chosen shipping option details as USER metadata (useful for next checkout)
add_action( 'woocommerce_checkout_update_customer', 'save_delivery_or_pickup_as_user_metadata', 10 );
function save_delivery_or_pickup_as_user_metadata( $customer ) {
if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) {
$customer->update_meta_data('delivery_or_pickup', esc_attr($_POST['delivery_or_pickup']));
}
if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) {
$customer->update_meta_data('pickup_location', esc_attr($_POST['pickup_location']));
}
}

// Display chosen custom shipping option details in the admin panel under shipping address
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_delivery_or_pickup_meta_in_admin_order', 10 );
function display_delivery_or_pickup_meta_in_admin_order( $order ) {
// Delivery or Pickup
if ( $value = $order->get_meta('_delivery_or_pickup') ) {
$options = get_delivery_or_pickup_options();
printf( '
[b]%s:[/b] %s', esc_html__('Shipping', 'woocommerce' ), $options[$value] );

// Pickup location
if ( $value = $order->get_meta('_pickup_location') ) {
$options = get_pickup_location_options();
printf( '
[b]%s:[/b] %s', esc_html__('Location', 'woocommerce' ), $options[$value] );
}
echo '
';
}
}

// Display chosen custom shipping option details in order total lines (customer orders and email notifications)
add_filter( 'woocommerce_get_order_item_totals', 'insert_custom_line_order_item_totals', 10, 3 );
function insert_custom_line_order_item_totals( $total_rows, $order, $tax_display ){
$shipping = $order->get_meta('_delivery_or_pickup');
$options1  = get_delivery_or_pickup_options();
$location = $order->get_meta('_pickup_location');
$options2  = get_pickup_location_options();
$key_target = array_key_exists('discount', $total_rows) ? 'discount' : 'cart_subtotal';
$new_total_rows = array();

// Loop through total rows
foreach( $total_rows as $key => $value ){
$new_total_rows[$key] = $total_rows[$key];

if( 'cart_subtotal' === $key ) {
$new_total_rows['shipping2'] = array(
'label' => esc_html__('Shipping option:'),
'value' => $options1[$shipping],
);

if ( $location ) {
$new_total_rows['location'] = array(
'label' => esc_html__('Pickup location:'),
'value' => $options2[$location],
);
$new_total_rows['drink_options'] = array(
'label' => esc_html__('Drink Options:'),
'value' => esc_html($order->get_meta('_drink_options')),
);
}

}
}
return $new_total_rows;
}
Но когда клиент выбирает дополнительный напиток из списка, дополнительная соответствующая комиссия не добавляется: касса обновляется, но ничего не добавляется. Здесь часть «напитки» работает не так, как задумано. В моем коде я определил массив всех напитков с названием метки и стоимостью для каждого варианта, и этот список вариантов напитков отображается условно в зависимости от выбранного места получения с помощью JavaScript. Здесь я застрял на той части, где выбранные параметры должны динамически добавляться в корзину через AJAX.

Подробнее здесь: https://stackoverflow.com/questions/796 ... oocommerce
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Jquery»