WooCommerce: Impedire acquisti ripetuti

Tempo di lettura: 5 minuti

A seconda del tipo di prodotti che vendi, potresti voler impedire ai clienti di acquistare un prodotto WooCommerce più di una volta dal tuo negozio, quindi non renderlo ripetibile.

Possiamo affrontare questa situazione in due modi: in primo luogo, disabilitare gli acquisti ripetuti per un particolare prodotto o disabilitare completamente eventuali acquisti ripetuti (che si applicherebbe a tutti i prodotti nel negozio).

Disabilitare acquisti ripetuti per un prodotto semplice specifico

Questo codice funziona SOLO per i prodotti semplici. Per farlo funzionare prima di tutto dobbiamo andare a recuperare l’id del nostro prodotto.

Poi inseriamo questo codice all’interno del file functions.php:

function evita_acquisto_ripetuto_prodotto_semplice() {
    //inseriamo l'id del nostro prodotto
    $no_repeats_id = 24;
    $no_repeats_product = wc_get_product( $no_repeats_id );
    
    global $product;
    
    if ( $no_repeats_product->is_type( 'variation' ) ) {
    
        if ( ! $no_repeats_product->get_parent_id() === $product->get_parent_id() ) {
            return;
        }
        
    } elseif ( $no_repeats_id === $product->get_id() ) {
        if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $no_repeats_id ) ) {
            //inseriamo il messaggio di errore
            echo '<div class="woocommerce"><div class="woocommerce-info wc-nonpurchasable-message">Hai già acquistato questo prodotto, purtroppo non è più possibile acquistarne un altro!</div></div>';
        }
    }
}
add_action( 'woocommerce_single_product_summary', 'evita_acquisto_ripetuto_prodotto_semplice', 31 );

Alla riga 3 inseriamo l’id del nostro prodotto.

Alla riga 17 possiamo modificare il messaggio di avviso con uno preferito.

Questo sarà il risultato:

prodotto semplice

Questa soluzione ha un piccolo problema di usabilità. Va bene se abbiamo un solo specifico prodotto da “bloccare”, ma se avessimo più prodotti, dobbiamo adottare una soluzione più pratica.

Utilizzando un plugin specifico possiamo scegliere noi quale prodotto bloccare, ma soprattutto possiamo controllarlo direttamente dalle impostazioni.

Scarichiamo il plugin da qui

download github

Una volta attivato all’interno del nostro prodotto potremmo vedere questa opzione: Prevent customers from purchasing this product more than once

opzione backend

Mettendo il flag, renderemo il prodotto acquistabile una volta sola e apparirà il messaggio di avviso per quel prodotto specifico. Possiamo fare la stessa cosa per tutti i prodotti che vogliamo bloccare.

Il messaggio sarà in inglese, ma possiamo tradurlo utilizzando questo plugin specifico, ovvero Loco Translate.

Disabilitare acquisti ripetuti per i prodotti variabili

I prodotti variabili hanno la caratteristica di permettere all’utente di scegliere la combinazione migliore. Utilizzeremo un codice che permette di far apparire il messaggio SOLO per la scelta specifica (se è già stata acquistata) per evitare di annoiarlo con un messaggio persistente.

Esempio specifico:

l’utente vuole acquistare una maglia che presenta la taglia S,M,L. Sceglie ed acquista la taglia L, se prova a ricomprare la taglia L, vedrà il messaggio di errore, altrimenti no.

Inseriamo questo codice all’interno del file functions.php:

function evita_acquisto_ripetuto_prodotto_variabile($purchasable, $product) {

    if ($product -> is_type('variable')) {
        return $purchasable;
    }

    $product_id = $product -> is_type('variation') ? $product -> variation_id : $product -> id;

    global $sitepress;
    $translated_ids = Array();
    if (!isset($sitepress)) return;
    $post_id = $product -> id;
    $trid = $sitepress -> get_element_trid($post_id, 'post_product');
    $translations = $sitepress -> get_element_translations($trid, 'product');
    foreach($translations as $lang => $translation) {
    $translated_ids[] = $translation -> element_id;
    }

    foreach($translated_ids as $item):
        if (wc_customer_bought_product(wp_get_current_user() -> user_email, get_current_user_id(), $item)) {
            $purchasable = false;
            break;
        }
    endforeach;

    if ($purchasable && $product -> is_type('variation')) {
        $purchasable = $product -> parent -> is_purchasable();
    }

    return $purchasable;

}
add_filter('woocommerce_is_purchasable', 'evita_acquisto_ripetuto_prodotto_variabile', 10, 2);

Poi inseriamo questo codice al di sotto che serve per mostrare l’avviso e alla riga 29 possiamo modificare il messaggio di avviso con uno preferito.

function messaggio_evita_acquisto_ripetuto_prodotto_variabile() {

    global $product;

    if ($product -> is_type('variable')) {

        foreach($product -> get_children() as $variation_id) {
            
            if (wc_customer_bought_product(wp_get_current_user() -> user_email, get_current_user_id(), $variation_id)) {
                sv_render_variation_non_purchasable_message($product, $variation_id);
            }
        }

    } else {
       
         global $sitepress;
         $translated_ids = Array();
         if (!isset($sitepress)) return;
         $post_id = $product -> id; 
         $trid = $sitepress -> get_element_trid($post_id, 'post_product');
         $translations = $sitepress -> get_element_translations($trid, 'product');
         foreach($translations as $lang => $translation) {
         $translated_ids[] = $translation -> element_id;
        }

        foreach($translated_ids as $item):
            if (wc_customer_bought_product(wp_get_current_user() -> user_email, get_current_user_id(), $item)) {
				//inseriamo il messaggio di errore
                echo '<div class="woocommerce"><div class="woocommerce-info wc-nonpurchasable-message">Hai già acquistato questo prodotto, purtroppo non è più possibile acquistarne un altro!</div></div>';
                break;
            }
        endforeach;
    }

}
add_action('woocommerce_single_product_summary', 'messaggio_evita_acquisto_ripetuto_prodotto_variabile', 31);

Inseriamo ancora questo codice aggiuntivo per effettuare il controllo sulle varianti presenti nei prodotti variabili, cosi da far apparire la scelta SOLO nella variante (scelta) già acquistata.

function sv_render_variation_non_purchasable_message($product, $no_repeats_id) {

        if ($product -> is_type('variable') && $product -> has_child()) {

            $variation_purchasable = true;

            foreach($product -> get_available_variations() as $variation) {

                if ($no_repeats_id === $variation['variation_id']) {
                    $variation_purchasable = false;
	            //inseriamo il messaggio di errore
                    echo '<div class="woocommerce"><div class="woocommerce-info wc-nonpurchasable-message js-variation-'.sanitize_html_class($variation['variation_id']).
                    '">Hai già acquistato questo prodotto, purtroppo non è più possibile acquistarne un altro!</div></div>';
                }
            }
        }

        if (!$variation_purchasable) {
            wc_enqueue_js("
                jQuery('.variations_form')
                .on('woocommerce_variation_select_change', function(event) {
                    jQuery('.wc-nonpurchasable-message').hide();
                })
                .on('found_variation', function(event, variation) {
                    jQuery('.wc-nonpurchasable-message').hide();
                    if (!variation.is_purchasable) {
                        jQuery('.wc-nonpurchasable-message.js-variation-' + variation.variation_id).show();
                    }
                })
                .find('.variations select').change();
                ");
            }

        }

Questo sarà il risultato:

risultato scelte variabili

Disabilitare acquisti ripetuti per tutti i prodotti in generale

Inseriamo la funzione che permette di controllare se è già presente un acquisto in tutti i nostri prodotti e alla riga 12 possiamo modificare il messaggio di avviso con uno preferito.

function evitiamo_acquisto_ripetuto_tutti_prodotti( $purchasable, $product ) {

    if ( $product->is_type( 'variable' ) ) {
        return $purchasable;
    }
    
    $product_id = $product->get_id(); 
   
    if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product_id ) ) {
        $purchasable = false;
    }
    
    if ( $purchasable && $product->is_type( 'variation' ) ) {
        $parent = wc_get_product( $product->get_parent_id() );
        $purchasable = $parent->is_purchasable();
    }
    
    return $purchasable;
}
add_filter( 'woocommerce_is_purchasable', 'evitiamo_acquisto_ripetuto_tutti_prodotti', 10, 2 );

Mostriamo l’avviso se l’ordine è già stato effettuato e alla riga 16 possiamo modificare il messaggio di avviso con uno preferito.

function messaggio_evitiamo_acquisto_ripetuto_tutti_prodotti() {
    
    global $product;
    
    if ( $product->is_type( 'variable' ) ) {
        
        foreach ( $product->get_children() as $variation_id ) {

            if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $variation_id ) ) {
                sv_render_variation_non_purchasable_message( $product, $variation_id );
            }
        }
        
    } else {
        if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product->get_id() ) ) {
            echo '<div class="woocommerce"><div class="woocommerce-info wc-nonpurchasable-message">Hai già acquistato questo prodotto, purtroppo non è più possibile acquistarne un altro!</div></div>';
        }
    }
}
add_action( 'woocommerce_single_product_summary', 'messaggio_evitiamo_acquisto_ripetuto_tutti_prodotti', 31 );

Mostriamo sempre l’avviso per i prodotti variabili in modo condizionale per la singola scelta se è già stata acquistata.

function sv_render_variation_non_purchasable_message($product, $no_repeats_id) {

        if ($product -> is_type('variable') && $product -> has_child()) {

            $variation_purchasable = true;

            foreach($product -> get_available_variations() as $variation) {

                if ($no_repeats_id === $variation['variation_id']) {
                    $variation_purchasable = false;
					//inseriamo il messaggio di errore
                    echo '<div class="woocommerce"><div class="woocommerce-info wc-nonpurchasable-message js-variation-'.sanitize_html_class($variation['variation_id']).
                    '">Hai già acquistato questo prodotto, purtroppo non è più possibile acquistarne un altro!</div></div>';
                }
            }
        }

        if (!$variation_purchasable) {
            wc_enqueue_js("
                jQuery('.variations_form')
                .on('woocommerce_variation_select_change', function(event) {
                    jQuery('.wc-nonpurchasable-message').hide();
                })
                .on('found_variation', function(event, variation) {
                    jQuery('.wc-nonpurchasable-message').hide();
                    if (!variation.is_purchasable) {
                        jQuery('.wc-nonpurchasable-message.js-variation-' + variation.variation_id).show();
                    }
                })
                .find('.variations select').change();
                ");
            }

        }

Avete soluzioni differenti? Commentate e discutiamone insieme!

2 commenti su “WooCommerce: Impedire acquisti ripetuti”

  1. Salve! è possibile bloccare l’acquisto di un prodotto specifico attraverso il controllo di un campo del checkout. anche per gli utenti non registrati? Per esempio fare un controllo sullo storico ordini e bloccare se la p.iva inserita al checkout esista già nell’archivio..

  2. CIao Emiliano, ho letto con interessde il tuo post e vorrei chiederti una cosa: io ho la necessità di vincolare l’acquisto di un prodotto virtuale in base ai suoi attributi. Il prodotto è un software con licenza annuale, software che può essere acquistato in più licenze da allocare in una o più sedi. In questo caso gli attributi sono quindi SEDE (da 1a n) e POSTAZIONE (da 01 a 10). L’acquisto è vincolato a questi due attributi quindi il clientre può acquistare più licenze contemporaneamente ma le licenze non possono ripetersi e devono essere sequenziali (es: SEDE1 – POSTAZIONE 01, SEDE 1 POSTAZIONE 02 è giusto, SEDE 1 POSTAZIONE 01; SEDE 2 POSTAZIONE 01 è giusto ma SEDE 1 POSTAZIONE 01 e poi nuovamente, magari dopo dieci giorni dal primo acquisto (ma anche nell’immediato del primo!) nuovamente SEDE 1 POSTAZIONE 01 deve dare errore.
    Come posso fare in modo che woocommerce mi metta nelle condizioni di gestire una simile transazione?

Lascia un commento