En WooCommerce, uso el complemento [complemento de pago de WooCommerce] [1] y he agregado a la página de pago un campo adicional hecho de botones de opción (opción múltiple). Me gustaría cambiar la tasa de impuestos cuando el cliente selecciona una opción específica en ese campo de botones de opción.
Basado en Cambiar la clase de impuestos de los artículos del carrito de Woocommerce según el código de respuesta del método de pago elegido que cambia la tasa de impuestos para el método de pago específico, he intentado personalizar el código:
// Change Tax add_action( 'woocommerce_before_calculate_totals', 'change_tax_class_based_on_radio_choice', 10, 1 ); function change_tax_class_based_on_radio_choice( $cart ) { $installation = WC()->session->get('wc_checkout_add_ons') ; // This code must be change $value = 'pas-dinstallation' ; // the value of the radio button "woocommerce checkout addon" $value2 = 'bacs' ; // value of payement methode $payement_methode = WC()->session->get('chosen_payment_method') ; //if ( $payement_methode !== $value2 ) //this one is ok for change tax if payement methode is bank transfert //return; if ( $installation !== $value ) // here i try to set the same condition with one of radio button "woocommerce checkout addon" return; if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; // Loop through cart items foreach( $cart->get_cart() as $cart_item ){ // We set "Zero rate" tax class $cart_item['data']->set_tax_class("Reduced rate"); } } add_action('wp_footer', 'option_trigger_update_checkout'); function option_trigger_update_checkout() { if( is_checkout() && ! is_wc_endpoint_url() ) : ?> <script type="text/javascript"> jQuery(function($){ $( 'form.checkout' ).on('change', 'input[type="radio"]', function() { $(document.body).trigger('update_checkout'); }); }); </script> <?php endif; }Pero todavía no sé cómo hacer que funcione para mi caso. Entiendo que:
$installation = WC()->session->get('wc_checkout_add_ons')no está bien implementado. ¿Qué me estoy perdiendo?
Como no necesito restricciones de métodos de pago, eliminé esta línea relacionada:
// Only for a specific defined payment method if ( ! in_array( WC()->session->get('chosen_payment_method'), $payment_ids ) ) return;Entonces el código funciona bien ahora como esperaba.
Sin embargo, con el complemento "Complemento de pago de WooCommerce", cuando se selecciona un botón de opción, puedo ver en administración en el resumen del pedido y en el correo electrónico recibido, qué elección se ha hecho.
con este codigo se cambia el impuesto, pero no tengo informacion de la eleccion de radio del cliente en admin ni por correo electronico.
¿Tienes solución?
Algo más:
Quiero mover los botones de radio antes del pago.
Pero cuando reemplazo esto:
// Display radio buttons field (optional) add_action( 'woocommerce_after_order_notes', 'installation_custom_radio_field' ); function installation_custom_radio_field( $checkout ) {por
// Display radio buttons field (optional) add_action( 'woocommerce_review_order_before_payment', 'installation_custom_radio_field' ); function installation_custom_radio_field( $checkout ) {ya no funciona ¿Puedes explicar porque? ¿Cómo hacer que funcione?
Actualización 2: Es mucho más complicado hacerlo funcionar ya que también requiere Ajax y mucho más código adicional...
Entonces, lo siguiente permitirá cambiar la clase de impuestos de los artículos del carrito en la página de pago, dependiendo de:
Como las personas no usan su complemento comercial de complementos de pago de WooCommerce , el siguiente código muestra algunos botones de opción en la página de pago.
Para hacer que el código sea más dinámico, comenzamos con una función personalizada que manejará todas las configuraciones requeridas:
// Custom function that handle your settings function change_tax_class_settings(){ return array( 'payment_ids' => array(), // (optional) Your targeted payment method Id(s) | Leave an empty array to disable. 'tax_class' => 'Reduced rate', // The desired tax rate 'field_id' => 'additonal_services', // the Field Id (from property name ="?????") 'field_value' => 'no-dinstallation', // The field targetted option key (value) // The below lines are optional (used for the radio buttons field display) 'field_type' => 'radio', // Field type 'field_title' => __('Additional services', 'woocommerce'), 'field_default' => 'basic-installation', // The field targetted option key (value) 'field_options' => array( 'basic-installation' => __('Basic Installation', 'woocommerce'), 'premium-installation' => __('Premium Installation', 'woocommerce'), 'no-dinstallation' => __('No Installation', 'woocommerce'), ), ); }Ahora podemos cargar esa configuración en cualquier función donde sea necesario.
Luego, los botones de radio que se muestran antes de la sección de pago de métodos de pago:
// Display radio buttons field (optional) add_action( 'woocommerce_review_order_before_payment', 'installation_custom_radio_field' ); function installation_custom_radio_field() { extract( change_tax_class_settings() ); // Load settings and convert them in variables echo "<style>.$field_id-wrapper{padding:1em 1.41575em;background-color:#f5f5f5;margin-bottom:24px;} .form-row.$field_id-$field_type span label{display:inline-block;margin:0 18px 0 6px;} .$field_id-wrapper h3{font-weight:bold;}</style>"; echo '<div class="'.$field_id.'-wrapper"> <h3>'.$field_title.'</h3>'; // Get WC Session variable value $value = WC()->session->get($field_id); woocommerce_form_field( $field_id, array( 'type' => $field_type, 'label' => '', 'class' => array('form-row-wide ' . $field_id . '-' . $field_type ), 'options' => $field_options, 'default' => $field_default, 'required' => true, ), empty($value) ? WC()->checkout->get_value('_'.$field_id) : $value ); echo '</div>'; }La parte Ajax (jQuery Ajax y PHP Admin Wordpress Ajax remitente y receptor + variable de sesión WC) :
// jQuery code (client side) - Ajax sender add_action('wp_footer', 'installation_checkout_js_script'); function installation_checkout_js_script() { if( is_checkout() && ! is_wc_endpoint_url() ) : // Load settings and convert them in variables extract( change_tax_class_settings() ); // jQuery Ajax code ?> <script type="text/javascript"> jQuery( function($){ if (typeof wc_checkout_params === 'undefined') return false; var field = '#<?php echo $field_id; ?>_field input', fchecked = field+':checked'; // Function that sen the Ajax request function sendAjaxRequest( value ) { $.ajax({ type: 'POST', url: wc_checkout_params.ajax_url, data: { 'action': '<?php echo $field_id; ?>', 'value': value }, success: function (result) { $(document.body).trigger('update_checkout'); // Refresh checkout } }); } // On ready (DOM loaded) sendAjaxRequest( $(fchecked).val() ); // On change event $(document.body).on( 'change', field, function(){ sendAjaxRequest( $(fchecked).val() ); }); // Refresh checkout on payment method change $( 'form.checkout' ).on('change', 'input[name="payment_method"]', function() { $(document.body).trigger('update_checkout'); // Refresh checkout }); }); </script> <?php endif; } // The Wordpress Ajax PHP receiver add_action( 'wp_ajax_additonal_services', 'get_additonal_services' ); add_action( 'wp_ajax_nopriv_additonal_services', 'get_additonal_services' ); function get_additonal_services() { if ( isset($_POST['value']) ){ // Load settings and convert them in variables extract( change_tax_class_settings() ); // Update session variable WC()->session->set($field_id, esc_attr($_POST['value'])); // Send back the data to javascript (json encoded) echo $_POST['value']; // optional die(); } }Luego, la función que cambia la clase de impuestos del artículo del carrito condicionalmente según las elecciones del cliente:
// Change the tax class conditionally add_action( 'woocommerce_before_calculate_totals', 'change_tax_class_conditionally', 1000 ); function change_tax_class_conditionally( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; extract( change_tax_class_settings() ); // Load settings and convert them in variables // Only for a specific defined payment methods (can be disabled in the settings, with an empty array) if ( ! empty($payment_ids) && ! in_array( WC()->session->get('chosen_payment_method'), $payment_ids ) ) return; $choice = WC()->session->get($field_id); // Loop through cart items foreach( $cart->get_cart() as $cart_item ){ if( $choice === $field_value ) { $cart_item['data']->set_tax_class($tax_class); } } }Adición: guardar la elección del cliente en el pedido y mostrarla en todas partes en los pedidos en el front-end, el administrador y en las notificaciones por correo electrónico:
// Save custom field as order meta data add_action( 'woocommerce_checkout_create_order', 'save_additonal_services_as_order_meta' ); function save_additonal_services_as_order_meta( $order ) { // Load settings and convert them in variables extract( change_tax_class_settings() ); $choice = WC()->session->get($field_id); if( ! empty( $choice ) ) { $order->update_meta_data( '_'.$field_id, $choice ); } } // Display additonal services choice before payment method everywhere (orders and emails) add_filter( 'woocommerce_get_order_item_totals', 'display_additonal_services_on_order_item_totals', 1000, 3 ); function display_additonal_services_on_order_item_totals( $total_rows, $order, $tax_display ){ // Load settings and convert them in variables extract( change_tax_class_settings() ); $choice = $order->get_meta( '_'.$field_id ); // Get additonal services choice if( ! empty($choice) ) { $new_total_rows = []; // Loop through order total rows foreach( $total_rows as $key => $values ) { // Inserting the pickp store under shipping method if( $key === 'payment_method' ) { $new_total_rows[$field_id] = array( 'label' => $field_title, 'value' => esc_html($field_options[$choice]), ); } $new_total_rows[$key] = $values; } return $new_total_rows; } return $total_rows; } // Display additonal services choice in Admin order pages add_action( 'woocommerce_admin_order_data_after_billing_address', 'admin_order_display_additonal_services', 1000 ); function admin_order_display_additonal_services( $order ) { // Load settings and convert them in variables extract( change_tax_class_settings() ); $choice = $order->get_meta( '_'.$field_id ); // Get additonal services choice if( ! empty($choice) ) { // Display echo '<p><strong>' . $field_title . '</strong>: ' . $field_options[$choice] . '</p>'; } }Todo el código va en el archivo functions.php de su tema secundario activo (o tema). Probado y funciona.
Opción mostrada en pedidos y notificaciones por correo electrónico (aquí en la página Pedido recibido)
En las páginas de pedidos individuales de administración: