2012-11-21 5 views
11

Devo aggiungere al mio carrello alcuni elementi pubblicitari con un importo personalizzato. Il prodotto commerciale viene salvato con il prezzo = 0 e il mio modulo calcola il prezzo e aggiunge l'elemento pubblicitario al carrello/ordine, ma non capisco come impostare a livello di programmazione il prezzo.Elementi pubblicitari di Drupal Commerce: modifica il prezzo?

Ho letto sull'utilizzo di Regole, ma ho bisogno del mio modulo per poter impostare/modificare il prezzo, senza richiamare le regole.

Ho provato con un wrapper di entità, ho provato a modificare l'elemento pubblicitario creato con commerce_product_line_item_new(), ma nulla, quando l'elemento pubblicitario entra nel carrello ha sempre il prezzo del prodotto originale (nel mio caso, 0) .

Come modificare un prezzo di elemento pubblicitario a livello di programmazione?

Il mio codice sembra così lontano come:

// For debugging, this function is called by hook_menu() 
function mymodule_test($product_id) 
{ 
    global $user; 
    $user = user_load($user->uid); 

    $order = commerce_cart_order_load($user->uid); 
    $order_wrapper = entity_metadata_wrapper('commerce_order', $order); 

    $product = commerce_product_load($product_id); 

    $line_item = commerce_product_line_item_new(
      $product, 
      1, 
      0, 
      array(
      ), 
      'cover' 
    ); 

    $line_item_wrapper = entity_metadata_wrapper("commerce_line_item", $line_item); 

    $line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
      $line_item_wrapper->commerce_unit_price->value(), 
      'base_price', 
      array(
          'amount' => 1234, 
          'currency_code' => 'EUR', 
          'data' => array(), 
      ), 
      TRUE 
    ); 

    $insert_line_item = commerce_cart_product_add($user->uid, $line_item_wrapper->value(), FALSE); 

    return 'done'; 
} 

La cosa strana, è che ho provato ad adattare il codice di commerce_line_item_unit_price_amount() in commercio/modules/Line_Item/commerce_line_item.rules.inc, ma questo Test:

<?php 
    global $user; 
    $product = commerce_product_load(4); // my commerce product for test 

    $line_item = commerce_product_line_item_new(
     $product, 
     1, 
     0, 
     array(
     ), 
     'cover' // I do have this line_items type 
    ); 

    // manually set amount and component name 
    $amount = 1234; 
    $component_name = 'base_price'; // tryed with discount, nothing change 

    $wrapper = entity_metadata_wrapper('commerce_line_item', $line_item); 
    $unit_price = commerce_price_wrapper_value($wrapper, 'commerce_unit_price', TRUE); 

    // Calculate the updated amount and create a price array representing the 
    // difference between it and the current amount. 
    $current_amount = $unit_price['amount']; 
    $updated_amount = commerce_round(COMMERCE_ROUND_HALF_UP, $amount); 

    $difference = array(
     'amount' => $updated_amount - $current_amount, 
     'currency_code' => $unit_price['currency_code'], 
     'data' => array(), 
    ); 

    // Set the amount of the unit price and add the difference as a component. 
    $wrapper->commerce_unit_price->amount = $updated_amount; 

    $wrapper->commerce_unit_price->data = commerce_price_component_add(
     $wrapper->commerce_unit_price->value(), 
     $component_name, 
     $difference, 
     TRUE 
    ); 

    $insert_line_item = commerce_cart_product_add($user->uid, $line_item, FALSE); 
?> 

ancora non riescono, il Line_Item entrare nel carrello, ma con il prezzo originale del prodotto di riferimento.

Qualche idea?

+0

Non stai salvando i vostri wrapper ... che potrebbe essere il problema (cioè '$ line_item_wrapper-> salvare(); ') – Clive

+0

@Clive penso di averlo provato anche io, ma lasciatemi fare un altro tentativo nel caso – Strae

+0

Oh, dovrai anche salvare' $ order_wrapper' (che mi ha beccato mentre stavo facendo qualcosa simile a qualche mese fa) – Clive

risposta

18

Per coloro che non vogliono utilizzare le regole e sperano di modificare direttamente il prezzo. Qui è la mia soluzione:

// Alter the price in list and single product page. 
function my_module_commerce_product_calculate_sell_price_line_item_alter($line_item){ 

    $price = 100; //1 dollar 
    $line_item->commerce_unit_price[LANGUAGE_NONE]['0']['amount'] = $price; 

} 

// Alter the price in cart & order. 
function my_module_commerce_cart_line_item_refresh($line_item, $order_wrapper){ 

    $price = 100; //1 dollar 
    $line_item->commerce_unit_price[LANGUAGE_NONE]['0']['amount'] = $price; 
    // Alter the base_price component. 
    $line_item->commerce_unit_price[LANGUAGE_NONE]['0']['data']['components']['0']['price']['amount'] = $price; 

} 
+0

Ciao Tim, il precedente 'gancio' non si stava attivando dal mio modulo. Ho provato la pagina del singolo prodotto "gancio". Sto usando DC Kickstart. – james

+0

Hai qualche altro posto dove impostare il prezzo? puoi provare a kpr ($ line_item) nel gancio per vedere come è. –

4

Ho affrontato questo problema tutto il giorno oggi e la finale ha individuato il percorso corretto per modificare i prezzi degli elementi pubblicitari. Il problema è che, anche se modifichi con successo il prezzo dell'elemento pubblicitario su un valore personalizzato, nella pagina successiva aggiorni il carrello reimposterà gli elementi pubblicitari in modo che corrispondano al prezzo originale del prodotto. Dai un'occhiata alla funzione commerce_cart_order_refresh() per i dettagli. Questa funzione viene eseguita ogni volta che un ordine/carrello viene caricato sulla pagina e non c'è modo di aggirarlo.

Si scopre che il modo corretto di modificare il prezzo di un elemento pubblicitario consiste nell'utilizzare le regole o implementare la funzione hook_commerce_cart_line_item_refresh(). In ogni caso, Drupal Commerce deve essere in grado di applicare la logica di alterazione ogni volta che viene caricato il carrello/ordine.

Ho finito per creare un campo personalizzato nell'elemento pubblicitario in cui ho archiviato il valore di prezzo personalizzato che volevo. Ho quindi utilizzato una regola dei prezzi per copiare il valore del prezzo personalizzato sul valore del prezzo del prodotto ogni volta che il carrello viene aggiornato.

Il seguente post del blog è stato molto utile per capire questo. Ti mostra come aggiungere un campo personalizzato a un tipo di elemento pubblicitario e come impostare una regola di determinazione del prezzo per copiare l'importo personalizzato sul prezzo unitario.

http://commerceguys.com/blog/using-custom-line-items-provide-donation-feature-drupal-commerce

+1

Grazie per aver condiviso! Drupal Commerce è potente e flessibile, ma non riesco ancora a capire perché l'alterazione dei prezzi sia limitata alle regole in modo così rigoroso. – Strae

+0

Puoi pubblicare il codice finale? – MSD

+0

@MichaelStevens Ho pubblicato un esempio che implementa questa funzione. – mpoplin

1

Recentemente ho dovuto implementare un modulo di donazione in materia di commercio, ma il modulo Commerce Express Checkout non gestisce gli elementi di linea personalizzati. Dato che si trattava di una donazione e tutti (chi sta cercando di fregare la casa?), Ho ritenuto opportuno trasferire l'importo della donazione come terzo parametro nell'URL fornito dal modulo Express Checkout. Ecco come sono andato di hacking del modulo:

ho aggiunto una nuova voce al router:

$items['commerce-express-checkout/%/%/%'] = array(
     'title' => 'Express Checkout w/ extra argument', 
     // 'page callback' => 'commerce_express_checkout_create_order', 
     'page callback' => 'commerce_express_checkout_create_order_extra', 
     'page arguments' => array(1, 2, 3), 
     'access arguments' => array('access checkout'), 
     'type' => MENU_CALLBACK, 
); 

ho duplicato e ottimizzato il callback di default e appiccicato '_extra' ad esso.Si noti che la proprietà "data" sembra essere un archivio variabile statico per le occasioni proprio come questa e persiste la vita dell'elemento pubblicitario.

function commerce_express_checkout_create_order_extra($product_id, $token, $amount) { 

    if (drupal_hmac_base64($product_id, drupal_get_private_key().drupal_get_hash_salt()) == $token && is_numeric($amount)) { 
    global $user; 

    $product = commerce_product_load($product_id); 

    $product->commerce_price['und'][0]['amount'] = (int)$amount; 

    $order = ($user->uid) ? commerce_order_new($user->uid, 'checkout_checkout') : commerce_cart_order_new(); 

    commerce_order_save($order); 

    $price = array('amount' => commerce_round(COMMERCE_ROUND_HALF_UP, $amount), 'currency_code' => commerce_default_currency()); 

    $line_item = commerce_product_line_item_new($product, 1, $order->order_id); 
    $line_item->data = array('und' => array('0' => $price)); 
    commerce_line_item_save($line_item); 

    $order_wrapper = entity_metadata_wrapper('commerce_order', $order); 

    $order_wrapper->commerce_line_items[] = $line_item; 

    $order->data['type'] = 'commerce_express_checkout_order'; 

    commerce_order_save($order); 

    drupal_goto('checkout/' . $order->order_id); 

    return ""; 
    } 

    return ""; 
} 

Qui è la parte che ha finito per essere più difficile semplicemente a causa della curva di apprendimento e non sapendo quale sia la funzione diamine da utilizzare:

/**                    
* Implements hook_commerce_cart_line_item_refresh().       
*/                    
function commerce_express_checkout_commerce_cart_line_item_refresh($line_item, $order_wrapper) { 
    if ($line_item->commerce_product['und'][0]['line_item_label'] == 'DONATE' || $line_item->commerce_product['und'][0]['product_id'] == '11') { 
    $price = array('amount' => commerce_round(COMMERCE_ROUND_HALF_UP, $line_item->data['und'][0]['amount']), 'currency_code' => commerce_default_currency()); 
    $line_item->commerce_unit_price = array('und' => array('0' => $price)); 
    $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item); 
    $line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
     $line_item_wrapper->commerce_unit_price->value(), 'base_price', $price, TRUE 
    ); 
    } 
} 

Ogni singola volta che il carro viene modificata, rinfresca e tenta di impostare i prodotti nel carrello per il loro prototipo in-code. Mi sembra abbastanza inefficiente, ma potrei mancare qualcosa.

6

Se stai cercando di ignorare ciò che i valori precedenti sono stati salvati a un elemento pubblicitario e ricalcolare il totale dal nuovo importo la funzione che stai cercando è commerce_line_item_rebase_unit_price.

Impostare il nuovo valore quantità e quindi eseguire l'elemento pubblicitario attraverso là, salvare la voce e l'ordine:

$line_item_wrapper->commerce_unit_price->amount = 13; 

commerce_line_item_rebase_unit_price($line_item_wrapper->value()); 

commerce_line_item_save($line_item_wrapper->value()); 
+2

A mio parere questa è la migliore risposta. Sono sicuro che ci sono situazioni in cui il complesso sistema di determinazione dei prezzi di Drupal Commerce è molto utile, ma nei casi d'uso che ho incontrato voglio solo ** impostare il prezzo dang **, e non voglio dover implementare un altro hook (rendendo quindi il mio codice ancora più difficile da capire). – jaskho

0

Questo post mi ha segnalato nella giusta direzione per programmazione alterare un elemento Drupal linea di commercio per utilizzando hook_commerce_cart_line_item_refersh(). Tuttavia, alcune delle risposte qui sono completamente sbagliate, o molto inefficienti e sciatte.

Questa sarebbe una soluzione di lavoro corretta per modificare il tipo di elemento linea in Drupal Commercio:

/* 
* implements hook_commerce_cart_line_item_refresh() 
* 
*/ 

function MYMODULE_commerce_cart_line_item_refresh($line_item, $order_wrapper){ 

    $line_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item); 

    $new_price = 100; //I use a function to calculate the value of $new_price 

    if(!empty($new_price)){ 
     $line_wrapper->commerce_unit_price->amount->set($new_price); 
     $line_wrapper->save(); 
    } 
} 
Problemi correlati