2012-11-21 11 views
11

Muszę dodać do koszyka niektóre elementy zamówienia z niestandardową kwotą. Produkt komercyjny jest zapisywany z ceną = 0, a mój moduł oblicza cenę i dodaje element zamówienia do koszyka/zamówienia, ale nie rozumiem, jak ustawić programowo cenę.Elementy Drupal Commerce Line: zmienić cenę?

Przeczytałem o używaniu reguł, ale potrzebuję mojego modułu, aby móc ustawić/zmienić cenę, bez wywoływania reguł.

Próbowałem z opakowaniem jednostkowym, próbowałem zmienić element zamówienia utworzony za pomocą funkcji commerce_product_line_item_new(), ale nic, gdy element zamówienia trafia do koszyka, zawsze ma oryginalną cenę produktu (w moim przypadku 0) .

Jak programowo zmienić cenę elementu zamówienia?

Mój kod wygląda tak daleko:

// 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'; 
} 

Najdziwniejsze jest to, że ja tryed dostosować kod commerce_line_item_unit_price_amount() znalezione w handlu/modules/LINE_ITEM/commerce_line_item.rules.inc, ale ten 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); 
?> 

nadal nie powiodło się, linia line_item dostaje się do koszyka, ale z pierwotną ceną produktu referencyjnego.

Każdy pomysł?

+0

Nie jesteś zapisywania obwolut ... że może być problem (czyli '$ line_item_wrapper-> Zapisz(); ') – Clive

+0

@ Clive Myślę, że też to wypróbowałem, ale pozwól mi spróbować jeszcze raz na wszelki wypadek. – Strae

+0

Och, musisz też zapisać' $ order_wrapper' (ten dostał mnie, gdy robiłem coś podobnie kilka miesięcy wstecz) – Clive

Odpowiedz

18

Dla osób, które nie chcą stosować zasad i mają nadzieję na bezpośrednią zmianę ceny. Oto moje rozwiązanie:

// 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

Cześć Tim, Powyższy 'hak' nie uruchamiał się z mojego modułu. Próbowano Strona pojedynczego produktu 'hak'. Używam DC Kickstart. – james

+0

Czy masz jakieś inne miejsce na ustalenie ceny? możesz spróbować kpr ($ line_item) w haku, aby zobaczyć, jak to jest. –

4

Przez cały dzień zmagałem się z tym problemem i ostatecznie ustaliłem prawidłową ścieżkę do zmiany cen elementów. Problem polega na tym, że nawet jeśli z powodzeniem zmienisz cenę elementu zamówienia na wartość niestandardową, po odświeżeniu strony koszyk zresetuje elementy zamówienia, by dopasować je do pierwotnej ceny produktu. Zapoznaj się z funkcją commerce_cart_order_refresh(), aby uzyskać szczegółowe informacje. Ta funkcja jest wykonywana za każdym razem, gdy zamówienie/wózek jest załadowany na stronę i nie ma możliwości obejścia go.

Okazuje się, że właściwym sposobem zmiany ceny elementu zamówienia jest użycie reguł lub wdrożenie funkcji hook_commerce_cart_line_item_refresh(). Tak czy inaczej, Drupal Commerce musi mieć możliwość stosowania logiki zmian za każdym razem, gdy załadowany jest wózek/zlecenie.

Skończyło się na utworzeniu niestandardowego pola w elemencie zamówienia, w którym zapisałem niestandardową wartość ceny, którą chciałem. Następnie użyłem reguły cenowej, aby skopiować wartość ceny niestandardowej do wartości ceny produktu za każdym razem, gdy koszyk jest odświeżany.

Następujący post na blogu był bardzo pomocny w ustaleniu tego. Pokazuje, jak dodać niestandardowe pole do typu elementu zamówienia i jak skonfigurować regułę cenową, by skopiować niestandardową kwotę do ceny jednostkowej.

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

+1

Dzięki za udostępnienie! Drupal Commerce jest potężny i elastyczny, ale wciąż nie rozumiem, dlaczego zmiany cen są ograniczone do reguł w tak surowy sposób. – Strae

+0

Czy umieścisz ostatni kod? – MSD

+0

@MichaelStevens Wysłałem przykład, który implementuje tę funkcję. – mpoplin

1

Ostatnio miałem wdrożyć formę darowizny w Handlu, ale moduł Commerce Express Checkout nie obsługuje elementów niestandardowych linii. Ponieważ to była darowizna i wszyscy (kto próbuje spieprzyć dom?), Uznałem za stosowne przekazać kwotę darowizny jako trzeci parametr w adresie URL, który zapewnia moduł ekspresowej realizacji transakcji. Oto jak poszedłem o hacking moduł:

I dodał nowy wpis do routera:

$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, 
); 

I duplikowane i manipulowane domyślny zwrotnego i dołączona „_extra” do niego.Zauważ, że właściwość "data" wydaje się być magazynem zmiennych statycznych w takich sytuacjach jak ta i utrzymuje trwałość elementu zamówienia.

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 ""; 
} 

Tutaj jest elementem, który zakończył się najbardziej kłopotliwe po prostu ze względu na krzywej uczenia się i nie wiedząc, co funkcja cholery używać:

/**                    
* 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 
    ); 
    } 
} 

każdym razem wózek jest modyfikowany, odświeża i próbuje ustawić produkty w koszyku na ich prototypowy kod. Wydaje mi się to również mało skuteczne, ale mógłbym czegoś nie zauważyć.

6

Jeśli szukasz ignorować cokolwiek poprzednie wartości zostały zapisane do pozycji i ponownie całości z nowej kwoty funkcję, której szukasz jest commerce_line_item_rebase_unit_price.

ustawić nową wartość kwoty, a następnie uruchomić swój przedmiot linii przez nie, zapisz element zamówienia i porządek:

$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

Moim zdaniem jest to najlepsza odpowiedź. Jestem pewien, że są sytuacje, w których skomplikowany system ustalania cen Drupal Commerce jest bardzo pomocny, ale w przypadkach użycia, na które natknąłem, po prostu chcę ** ustawić cenę dang ** i nie chcę mieć zaimplementuj kolejny hak (co sprawia, że ​​mój kod jest jeszcze trudniejszy do zrozumienia). – jaskho

0

Ten post wskazał mi w dobrym kierunku dla programowo zmieniając pozycję Drupal linii commerce przez przy użyciu hook_commerce_cart_line_item_refersh(). Jednak niektóre z odpowiedzi są albo całkowicie błędne, albo bardzo nieskuteczne i niechlujne.

To byłoby poprawne roztwór roboczy o zmianę typu elementu zamówienia w Drupal Commerce:

/* 
* 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(); 
    } 
} 
Powiązane problemy