Virtuemat, raccolte punti fedeltà, coupon e buoni sconto a valore variabile

coupon a valore variabileUn argomento spesso dibattuto è come usare Virtuemart 2 per gestire raccolte punti fedeltà e, soprattutto come usare questi punti per ottenere un buono sconto sull'acquisto. In questo articolo ci concentreremo sulla seconda parte della questione, i coupon a valore variabile che è quella tecnicamente più complessa.

Virtuemart 2 ha mantenuto la capacità del suo predecessore di gestire i buoni sconto, coupon nella denominazione inerna, e nelle ultime versioni implementa la possibilità di un utilizzo parziale dei buoni, in modo che l'utente possa usare un medesimo buono più volte sino al concorrere del suo valore. Ciò che però resta una costante è che il valore del buono è prefissato e non può essere scelto dal cliente.

 

Buoni sconto dinamici

La situazione che tratteremo in questo articolo, affrontata di recente nella realizzazione di un sistema e-commerce, è quella in cui l'utente ha a disposizione un proprio credito, ottenuto tramite una raccolta punti fedeltà, e possa decidere liberamente quanta parte di tale credito usare come 'buono sconto' per un determinato acquisto.

Come molti sanno i buoni acquisto virtuali consistono di un codice alfanumerico da inserire nel negozio al momento del pagamento, in modo da ottenere uno sconto pari al valore del coupon. Tale valore può essere in termini assoluti o in percentuale, ma è comunque fisso e deve essere preimpostato dal venditore.

Quello che invece ci è stato richiesto di realizzare è un sistema in cui il cliente potesse scegliere, al momento del pagamento, il valore del buono che  avrebbe desiderato usare e in cui potesse ottenere il rilascio di detto buono immediatamente. Il coupon cioè doveva essere creato contestualmente alla richiesta del cliente e per il valore voluto da quest'ultimo, fatta salva la verifica della disponibilità del credito.

Nello specifico il sistema prevedeva una raccolta punti fedeltà per il cliente, che poteva acquisire punti bonus tramite acquisti nel negozio e/o di determinate azioni, quali possono essere l'iscriversi a mailing list ed il rispondere a sondaggi. I punti accumulati sono poi convertibili in uno sconto per l'acquisto di prodotti associati a determinate promozioni. La richiesta, come detto, era che il cliente indicasse, all'atto del pagamento, quanti punti usare della propria raccolta e che il sistema li trasformasse immediatamente in un buono sconto da usare per concludere l'acquisto.

Implementazioni non standard per VirtueMart o per altri e-commerce?

Volete aggiungere delle nuove caratteristiche al vostro e-commerce VirtueMart, come la gestione dei punti fedeltà o il rilascio di buoni acquisto alla registrazione di un utente e avete bisogno di assistenza? Contattateci, provvederemo noi alle implementazioni richieste. È uno dei nostri servizi.

 

Importo del buono sconto scelto dal cliente

Il sistema di funzionamento standard dei coupons in VirtueMart 2, prevede che il sistema abbia a disposizione, registrati in una apposita tabella, una serie di codici per buoni sconto, tra i quali scegliere quello da applicare all'ordine corrente, pertanto tutte le procedure prevedono il passaggio della sola informazione del codice del buono, almeno per quanto riguarda il coupon in sé. Sulla base di quanto detto il cliente dovrebbe avere una lista di codici tra i quali scegliere quello che più si avvicina a quanto desiderato, se non ha la fortuna di avere il buono esatto: ciò non è quanto vogliamo.   

Per ottenere invece quanto richiesto, dobbiamo fare riferimento al sistema di gestione buoni ed alla possibilità di estenderlo attraverso la creazione di plugins specifici. Purtroppo la documentazione di questo aspetto del funzionamento della nostra piattaforma e-commerce è parecchio carente, o meglio inesistente, e per capirne il funzionamento bisogna fare riferimento al codice dell' helper coupon.php presente nella relativa cartella del componente (lato fron end).

 

Flusso operativo dei buoni sconto

coupon a valore variabileI coupons fanno la loro apparizione al momento del pagamento dell'ordine, con una text box che ci invita ad inserire il codice del nostro buono virtuale. Tale valore, che ricordiamo può essere solo il codice del buono, viene inviato al sistema di validazione, che controlla se il codice esiste nella relativa tabella e se è usabile per l'acquisto, ovvero se il buono è attivo, se l'importo è coerente con l'acquisto e così via.

Superata la fase di validazione, VirtueMart applica lo sconto previsto dal buono e indica al cliente il nuovo importo da pagare.

All'atto del pagamento, quando lo stesso è eseguito, viene chiamato nuovamente il sistema di gestione dei coupons che deve provvedere alle opportune operazioni sul buono in questione, ad esempio  ad annullarlo se di tipo 'gift' cioè non ripetibile.

Virtuemart registra poi il numero del buono ed il suo valore all'interno della scheda dell'ordine, in modo che l'uso del buono risulti nell'ordine stesso.

Il processo è in realtà più complesso, ma noi abbiamo preferito limitare l'analisi agli aspetti funzionali a questo articolo.

 

Uso di un plugin per gestire i coupon

Ai due momenti evidenziati sopra, ovvero la verifica della validità del buono sconto e le operazioni complementari al suo utilizzo  sono associati due event handler, richiamati all'interno della gestione dei plugins di tipo vmcoupon, essi sono:

  • plgVmValidateCouponCode
  • plgVmCouponInUse

Le specifiche del nostro progetto prevedono che:

  1. Il cliente inserisca il numero di punti che intende usare nel sistema e-commerce (per semplicità assumeremo che il cliente indichi direttamente l'importo dello sconto, tralasciando la conversione da punti ad importo);
  2. il plugin verifichi che il cliente disponga di sufficienti punti, ed abbia comprato prodotti cui sia applicabile lo sconto;
  3. il plugin crei il buono sconto e ne registri il codice nella relativa tabella;
  4. il cliente effettui il pagamento dell'ordine utilizzando lo sconto garantito dal buono appena generato tramite il sistema e-commerce;
  5. il plugin decurti l' importo usato dal credito del cliente (tralasciamo anche qui la conversione in punti; del resto che la dote del cliente sia in punti convertibili in moneta o direttamente in moneta non cambia il senso della spiegazione qui fornita.

Nella descrizione del flusso desiderato, abbiamo evidenziato i termini plugin e  sistema e-commerce: il primo indica ciò che dovremo sviluppare il secondo la piattaforma Virtuemart esistente.

In questo articolo, che è già di suo abbastanza tecnico, abbiamo preferito concentrarci sulle parti di codice veramente necessarie alla realizzazione del sistema, pertanto sono state omesse le parti di codice non necessarie alla spiegazione, quali il file xml del plugin ed il codice base del plugin stesso; è lasciato al programmatore inserire le parti necessarie all' implementazione completa.

 

Codice coupon generato dinamicamente

Il primo problema che dobbiamo risolvere è che Virtuemart si aspetta un codice per il buono sconto e non accetta niente altro. Inoltre il valore inserito nella casella riservata l buono sconto non è modificabile in alcun modo (è accessibile solo per valore e non per puntatore) e verrà usato da qui in poi come codice del buono in ogni operazione di VirtueMart, ivi compresa la ricerca dello stesso nella tabella dei buoni sconto.

Dobbiamo pertanto fare sì che il cliente indichi sempre un codice valido all'atto della richiesta dello sconto, ed otterremo questo risultato creando una funzione che generi un codice da inserire all'atto della richiesta dell' importo dello sconto. Effettuiamo quindi un override del template degli sconti (default_discount.php nella directory 'cart') e riscriviamolo nel seguente modo:

<form method="post" name="enterCouponCode" action="<?php echo JRoute::_('index.php'); ?>">
  <label for="coupon_amount"><?php echo $this->coupon_text; ?></label>
  <input type="text" name="coupon_amount" id="coupon_amount" />
  <input class="details-button" type="submit" value="<?php echo JText::_('COM_VIRTUEMART_SAVE'); ?>"/>
  <input type="hidden" name="coupon_code" value="<?php echo getCouponCode(); ?>" />
  <input type="hidden" name="option" value="com_virtuemart" />
  <input type="hidden" name="view" value="cart" />
  <input type="hidden" name="task" value="setcoupon" />
  <input type="hidden" name="controller" value="cart" />
</form>

La funzione getCouponCode() è una funzione fittizia che ciascuno di voi dovrà scrivere. Il suo scopo sarà quello di generare dinamicamente un codice seriale per il coupon. Il formato del codice è libero, ma a parte gli ovvi consigli (alfanumerico senza apazi e caratteri speciali e senza collisioni, quindi evitate gli algoritmi random), vi suggerirei di usare uno schema tale da poter essere facilmente analizzato con una regular expression, al fine di capire velocemente se si tratta di un buono del sistema a punti o meno. Per semplicità qui assumeremo che il sistema non utilizzi altri tipi di buoni.

Il codice coupon, con il nome del campo che Virtuemart si aspetta di trovare (coupon_code), è inserito come campo hidden, mentre resta visibile l'importo dello sconto che il cliente intende chiedere nella text box.

 

Validazione del buono sconto

Come avete visto, nel precedente capoverso, abbiamo preservato il funzionamento di VirtueMart inviando allo stesso il codice sconto che si aspetta, però, al momento attuale, il buono non esiste, dato che non è stato ancora creato; dobbiamo pertanto implementare il codice che si occuperà della valutazione di congruità della richiesta del cliente e della creazione del buono sconto.

Quando viene premuto il pulsante di submit per inviare il codice del coupon, viene eseguito il task setcoupon del controller cart; all'interno del codice eseguito viene controllata l'esistenza di plugins di tipo vmcoupon, e se trovati viene eseguito l'evento plgVmValidateCouponCode(), pertanto scriviamo il codice che dovrà validare il buono:

public function plgVmValidateCouponCode($couponCode, $billTotal) {
  // recupera l'importo richiesto dal cliente
  $amount = JFactory::getApplication()->input->getFloat('coupon_amount', 0);
 
  if (!$amount) return FALSE;  // importo non valido
  if ($amount > $billTotal)  return FALSE; // non può generare un credito
  if ($amount > getUserBalance())  return FALSE; // non ci sono sufficienti punti promozione!
 
  // carica la classe di gestione del carrello di vm
  if(!class_exists('VirtueMartCart')) require(JPATH_VM_SITE.'/helpers/cart.php');       
  $vmcart = VirtueMartCart::getCart(false);
 
  $maxBonus=0;
  foreach ($vmcart->products as $pkey => $prow) {
    // calcola i prodotti che contribuisco  a $maxBonus
    if(isBonusProduct($prow->virtuemart_product_id)){
      $maxBonus+=(float)((float)$prow->product_override_price?$prow->product_override_price:$prow->product_price)*(int)$prow->quantity;
    }
  }
  if ($amount>$maxBonus) return FALSE; // Non sono presenti sufficienti prodotti in offerta!
 
  // tutto ok? allora crea il coupon per lo sconto richiesto
  $db = JFactory::getDBO();  
  $q = 
    'INSERT INTO `#__virtuemart_coupons`(' .
    'coupon_code, percent_or_total, coupon_type, coupon_value, coupon_used, published ' .
    ') VALUES ( ' .
    $db->quote($couponCode) .  ', ' . //
    $db->quote('total') .  ', ' .   //percent_or_total - IN enum('percent','total')
    $db->quote('gift') .  ', ' .    //coupon_type - IN enum('gift','permanent')
    $db->quote($amount) .  ', ' .    //coupon_value - IN decimal(15,5)
    $db->quote('0') .  ', ' .    //coupon_used
    $db->quote('1') .      //published - IN tinyint(1)
    ') ';
 
  $db->setQuery($q);
  $db->query($q);
 
  return '';
}
 
 

Come vedete il metodo riceve come parametri il codice del coupon ed il valore totale dell'ordine.

Il codice recupera l'importo del buono sconto richiesto dal cliente (coupon_amount) inserito nella form e provvede a due prime verifiche di massima: che l'importo non sia zero e che non sia superiore al valore dell'ordine; getUserBalance() è un'altra funzione fittizia, da scriversi a carico del lettore, che verifica che vi siano punti fedeltà sufficienti a coprire l'importo dello sconto che il cliente ha testé richiesto. Se una delle condizioni non è rispettata l'event handler restituisce il controllo al programma passando FALSE come valore di ritorno, comunicando così che la verifica non è andata a buon fine. Lasciamo al lettore anche l'implementazione degli opportuni messaggi di errore.

Il plugin ora richiama la classe che gestisce il carrello di VirtueMart  ed itera i prodotti contenuti nel carrello della spesa per vedere se corrispondono a quelli selezionati per la promozione; isBonusProduct($idProdotto) è un'altra funzione fittizia che verifica, dato l'id del prodotto, che il prodotto stesso faccia parte della promozione. Tale funzione varia enormemente in base al progetto del sistema, e quindi, in questa sede, non si può darne una definizione. Se i prodotti in esame concorrono alla promozione il loro importo viene considerato al fine dello sconto massimo ottenibile. L'ultima verifica è, appunto, che si siano acquistati prodotti in offerta per un importo almeno pari a quello del bonus richiesto.

Se tutti i controlli hanno esito positivo allora il plugin provvede ad inserire il codice del buono sconto, generato dalla funzione getCouponCode() vista prima, nella tabella dei buoni sconto di VirtueMart.Per le nostre esigenze il buono deve essere usabile una sola volta (gift) e l'importo deve essere in valore assoluto (total). A questo punto viene restituito il controllo a Virtuemart che procede con la sua normale esecuzione.

Come ultima cosa notate che la funzione deve ritornare il valore stringa vuota, e non TRUE come ci si aspetterebbe.

 

Registrazione dei punti fedeltà usati

Come ultimo passaggio dobbiamo decurtare il numero dei punti fedeltà a disposizione del cliente del numero di punti usati nell'acquisto corrente. All'atto del completamento dell'ordine, VirtueMart verifica nuovamente i plugins di tipo vmcoupon, e, se trovati, richiama il medoto plgVmCouponInUse() perché il plugin compia le necessarie operazioni conseguenti all'uso del plugin. 

public function plgVmCouponInUse($couponCode){
  $db = JFactory::getDBO();  
  $q = 'SELECT COALESCE(`coupon_value`, 0) AS `coupon_value` FROM `#__virtuemart_coupons` WHERE `coupon_code` = ' . $db->quote($couponCode) ;
  $db->setQuery($q);
  $amount=(float)$db->loadResult();
  if(!$amount) return FALSE;
 
  updateUserBalance($amount);
 
  return NULL;
}
 

All'event handler è passato il codice del plugin, e noi useremo tale informazione per ottenere l'importo usato del nostro buono sconto dalla tabella degli ordini. Ottenuto il valore dello sconto usufruito dal cliente, tramite la funzione updateUserBalance($importoSconto) provvederemo ad aggiornare la disponibilità dei punti fedeltà di conseguenza, ovviamente anche questa è una funzione fittizia che sta al lettore scrivere sulla base delle proprie esigenze. Se il cliente non conclude l'ordine allora i punti non saranno decurtati.

Versioni di VirtueMart precedenti alla 2.6.0 necessitano di un aggiornamento del codice dell'helper di gestione dei coupons per poter funzionare nel modo qui descritto; si faccia riferimento al seguente topic http://forum.virtuemart.net/index.php?topic=120972

Siamo giunti alla fine di questo articolo, tecnico sì, ma speriamo interessante. Sicuramente ora saprete che è possibile gestire le raccolte punti con VirtueMart e che tali punti possono essere usati per ottenere sconti. Se però non siete in grado di implementare il sistema da soli, ricordatevi che noi siamo a vostra disposizione.

Buon lavoro a tutti,

marco maria leoni

 

Commenti   

0 #2 Gabriel 2019-06-28 09:38
Buongiorno, volevo sapere se questa guida funzionasse per per Virtuemart 3.X???
Citazione
0 #1 Francesco 2015-09-25 13:04
Salve, non so se mi potete aiutare, ho bisogno di generare dei codici sconto da offrire ai clienti di un franchising, questi ultimi si recheranno presso un qualsiasi negozio del franchising a dopo un'acquisto presenteranno il codice sconto che il negoziante non conosce e ne deve verificare la reali emissione, collegandosi al sito dove inserendo quel codice deve generare una risposta positiva o negativa.
Grazie
Citazione

Aggiungi commento

Please note: URL in text are not linked and user's site address is only for internal use and is not published.

Comments are human checked. All spam will be removed, so don't waste your time and, especially, mine!

Codice di sicurezza
Aggiorna