• Resuelto zelarra821

    (@zelarra)


    Buenas tardes. Tengo una tienda con un único producto variable, que puede venderse en físico o en digital. Necesito personalizar el correo que se manda al usuario en función de la variable que se escoge (o físico o papel). Estoy modificando la plantilla del correo electrónico, pero no lo consigo hacer funcionar. He visto que hay hooks que modifican el header, el footer…, pero no el texto que pone «Hola, tu pedido… está siendo procesando» (más o menos, no sé el texto estándar ahora mismo, es para que te sitúes).

    Esto es lo que he añadido en la plantilla.

    <p>
    <?php
    add_action( 'woocommerce_thankyou', 'bbloomer_check_order_product_id');
      
    function bbloomer_check_order_product_id( $order_id ){
    $order = new WC_Order( $order_id );
    $items = $order->get_items(); 
    foreach ( $items as $item ) {
       $product_id = $item['product_id'];
          if ( $product_id == 314 ) {
            echo 'Hola';
          }
    }
    }
    ?>
    </p>

    En vez del código predeterminado que es este:

    <?php /* translators: %s: Customer first name */ ?>
    <p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
    <?php /* translators: %s: Order number */ ?>
    <p><?php printf( esc_html__( 'Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>

    ¿Sabes en qué puedo estar fallando? ¡Muchas gracias!

Viendo 7 respuestas - de la 1 a la 7 (de un total de 7)
  • Moderador kallookoo

    (@kallookoo)

    Hola @zelarra

    Veamos ese action se usa para especificar el template primario del order.

    Lo que yo haria seria crear dos templates dentro de tu theme para modificar el contenido del mail.

    Copias estos dos archivos:
    woocommerce/templates/emails/customer-processing-order.php
    woocommerce/templates/emails/plain/customer-processing-order.php
    En:
    theme/woocommerce/emails/customer-processing-order.php
    theme/woocommerce/emails/plain/customer-processing-order.php

    Como veras se pasa una variable $order (WC_Order instance), con lo que podras comprobar los ids de los productos y modificar el output.

    Iniciador del debate zelarra821

    (@zelarra)

    Hola. Ya había copiado los archivos a la carpeta de mi theme.

    Lo que no doy con la tecla es con el código. Si sustituyo el action que he puesto por el código por defecto, no hace nada.

    No sé si me explico. Entiendo lo que hace el action, entiendo lo que hace la plantilla del email, pero no sé cómo sustituir el texto predeterminado, o combinar ese texto con la función.

    Mil gracias.

    Moderador kallookoo

    (@kallookoo)

    Hola,

    Si lo que quieres es modificar el contenido del mail ese action woocommerce_thankyou no sirve. Es para el checkout.

    Para el mail debes editar esos dos archivos, por ejemplo:

    
    do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
    
    <?php
    foreach ( $order->get_items() as $item ) {
    	if ( is_object( $item ) && method_exists( $item, 'get_product' ) ) {
    		$item_product    = $item->get_product();
    		$item_product_id = $item_product->get_id();
    	} elseif ( is_array( $item ) && array_key_exists( 'product_id', $item ) ) {
    		$item_product_id = $item['product_id'];
    	}
    	if ( isset( $item_product_id ) && 900 === absint( $item_product_id ) ) {
    		$exists = true;
    		break;
    	}
    }
    ?>
    
    <?php if ( isset( $exists ) ) : ?>
    	<?php /* translators: %s: Customer first name */ ?>
    	<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
    	<?php /* translators: %s: Order number */ ?>
    	<p><?php printf( esc_html__( 'Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>	
    <?php else : ?>
    	<?php /* translators: %s: Customer first name */ ?>
    	<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
    	<?php /* translators: %s: Order number */ ?>
    	<p><?php printf( esc_html__( 'Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>
    <?php endif; ?>
    

    Cambia el 900 por el id del unico producto que dices y modifica el contenido a gusto, en el ejemplo son exactamente igual.

    Edit:
    Es solo un ejemplo y no lo he probado.

    • Esta respuesta fue modificada hace 5 años por kallookoo.
    Iniciador del debate zelarra821

    (@zelarra)

    Hola, eso es.

    Ahora, el problema es que no tengo dos posibilidades, sino tres (un producto con tres variables). Había pensado en añadir una variable que te diera el número de producto, y luego hacer dos elseif, pero no. Y ya no se me ocurre ninguna opción más, ¿cómo podría hacerlo?

    ¡Gracias!

    Iniciador del debate zelarra821

    (@zelarra)

    Estoy probando esto y no me deja comprar, me da un error que no puedo decirte cuál es porque no me lo muestra.

    do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
    
    <?php
    foreach ( $order->get_items() as $item ) {
    	if ( is_object( $item ) && method_exists( $item, 'get_product' ) ) {
    		$item_product    = $item->get_product();
    		$item_product_id = $item_product->get_id();
    	} elseif ( is_array( $item ) && array_key_exists( 'product_id', $item ) ) {
    		$item_product_id = $item['product_id'];
    	}
    	if ( isset( $item_product_id ) && 314 === absint( $item_product_id ) ) {
    		$exists = true;
    		
            <?php if ( isset( $exists ) ) : ?>
            	<?php /* translators: %s: Customer first name */ ?>
            	<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
            	<?php /* translators: %s: Order number */ ?>
            	<p><?php printf( esc_html__( '314Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>	
            <?php else : ?>
            
            	<?php if ( isset( $item_product_id ) && 315 === absint( $item_product_id ) ) {
            		$exists = true;
            	}?>
            
                    <?php if ( isset( $exists ) ) : ?>
                    	<?php /* translators: %s: Customer first name */ ?>
                    	<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
                    	<?php /* translators: %s: Order number */ ?>
                    	<p><?php printf( esc_html__( '315Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>	
                    <?php else : ?>
                    	<?php /* translators: %s: Customer first name */ ?>
                    	<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
                    	<?php /* translators: %s: Order number */ ?>
                    	<p><?php printf( esc_html__( '316Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>
                    <?php endif; ?>
            <?php endif; ?>
    		
    	}
    }
    ?>
    Moderador kallookoo

    (@kallookoo)

    Hola

    Veamos el codigo que puse de ejemplo, veras que tiene is_object( $item ) ... y is_array( $item ) ... el motivo fue porque para versiones antiguas no se pasaba una instancia de la class WP_Product.. asi que primero debes saber si lo estas haciendo para todas las versiones del WooCommerce o solo para la 3.*+, que si pasa una instancia de la class.
    Para simplificar el codigo y determinar como capturar x valor.

    Te sugiero que revises el codigo del WooCommerce y https://docs.woocommerce.com/ ya que debes entender como funciona. Te lo comento porque diria que eres programador y es algo importante, no es necesario que te lo aprendas todo, obviamente pero si lo basico.

    Viendo el codigo que pones ahora no se si eres programador.
    Te comento:
    – Es recomendable habilitar el debug del WordPress para ver los errores.
    – Ese codigo esta mal
    Tienes etiquetas <?php que no deberian existir y faltan cerrarlas.
    Metes el mensaje dentro del bucle, no entiendo porque?

    Para simplificar un poco.
    Copia esta function en el functions.php del theme o en tu plugin de functions si es que lo usas como no se para que version del WooCommerce es sigo con las dos maneras para conseguir el ID del producto.

    
    function zelarra_detect_product_id_in_order( $product_id, $order ) {
    	$product_id = ( is_numeric( $product_id ) ? absint( $product_id ) : 0 );
    	if ( $product_id && is_object( $order ) && method_exists( $order, 'get_items' ) ) {
    		foreach ( $order->get_items() as $item ) {
    			if ( is_array( $item ) && array_key_exists( 'product_id', $item ) ) {
    				$item_product_id = $item['product_id'];
    			} elseif ( is_object( $item ) && method_exists( $item, 'get_product' ) ) {
    				$item_product    = $item->get_product();
    				$item_product_id = $item_product->get_id();
    			}
    
    			if ( isset( $item_product_id ) && $product_id === absint( $item_product_id ) ) {
    				return true;
    			}
    		}
    	}
    	return false;
    }
    

    Esa function te devolvera verdadero o falso si el product_id existe en el order.

    Copia esto en los templates de los emails.

    
    <?php if ( zelarra_detect_product_id_in_order( 314, $order ) ) : ?>
    	<?php /** Custom message for product id 314 */ ?>
    <?php elseif ( zelarra_detect_product_id_in_order( 315, $order ) ) : ?>
    	<?php /** Custom message for product id 315 */ ?>
    <?php elseif ( zelarra_detect_product_id_in_order( 316, $order ) ) : ?>
    	<?php /** Custom message for product id 316 */ ?>
    <?php else : ?>
    	<?php /** Default message */ ?>
    	<?php /* translators: %s: Customer first name */ ?>
    	<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
    	<?php /* translators: %s: Order number */ ?>
    	<p><?php printf( esc_html__( 'Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>
    <?php endif; ?>
    

    Sustituyendo esto:

    
    <?php /* translators: %s: Customer first name */ ?>
    <p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $order->get_billing_first_name() ) ); ?></p>
    <?php /* translators: %s: Order number */ ?>
    <p><?php printf( esc_html__( 'Just to let you know &mdash; we\'ve received your order #%s, and it is now being processed:', 'woocommerce' ), esc_html( $order->get_order_number() ) ); ?></p>
    

    Ojo con las tags de PHP.
    Es otro ejemplo de como podrias hacerlo, que tampoco lo he probado.
    Igualmente tambien podrias meter el codigo de los templates en una function o incluso crearte un filtro. Lo importante es que lo hagas la mejor manera posible para entenderlo si alguna vez necesitas modificarlo.

    Iniciador del debate zelarra821

    (@zelarra)

    Solucionado. Me funciona el código que me has pasado. El error que me estaba dando era porque Woocommerce tiene como obligatoria la segunda línea de dirección. La pasado a opcional con este código:

    add_filter( 'woocommerce_checkout_fields' , 'db_address_optional', 99 );
    function db_address_optional( $fields ) {
         $fields['billing']['billing_address_2']['required'] = false;
         return $fields;
    }

    Muchísimas gracias por la ayuda.

    Un saludo.

Viendo 7 respuestas - de la 1 a la 7 (de un total de 7)
  • El debate ‘Email personalizado para productos variables’ está cerrado a nuevas respuestas.