2012-11-21 7 views
11

カスタム金額の広告申込情報をカートに追加する必要があります。 コマース商品はprice = 0で保存され、モジュールは価格を計算してカート/オーダーに追加しますが、プログラムで価格を設定する方法はわかりません。Drupal Commerceラインアイテム:価格を変更しますか?

ルールの使用については読んだことがありますが、ルールを使用せずに価格を設定/変更できるようにするには、が必要です。

私はエンティティラッパーを試しましたが、commerce_product_line_item_new()で作成された広告申込情報を変更しようとしましたが、広告申込情報がカートに入るときは常にオリジナルの商品価格(私の場合は0) 。

プログラムで広告申込情報の価格を変更するにはどうすればよいですか?

私のコードは、これまでのようになります。

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

奇妙なことに、私は商業/モジュールは/ LINE_ITEM/commerce_line_item.rules.incで見つけcommerce_line_item_unit_price_amount()のコードを適応させるためにしようと試みたが、これをということです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); 
?> 

まだ失敗すると、line_itemはカートに入るが、参照された製品の元の価格となる。

+0

あなたのラッパーを保存していない...それは(すなわち、 '$ line_item_wrapper->保存の問題かもしれません(); ') – Clive

+0

@Clive私はそれもしようと試みたのだと思いますが、私は別の私が何かをやっていたとき、念のために – Strae

+0

ああ、あなたはまた、' $のorder_wrapper'を保存する必要があります(1つは私を得てみてください与えてみましょう同様の数ヶ月前) – Clive

答えて

18

ルールを使用したくない人には、価格を直接変更することを願っています。 commerce_line_item_rebase_unit_priceが

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

こんにちはTim、上記の「フック」が私のモジュールから起動していませんでした。単一の製品ページ「フック」を試しました。私はDCキックスタートを使用しています。 – james

+0

他に価格を設定する場所がありますか? あなたは、それが何であるかを見るためにフックでkpr($ line_item)を試すことができます。 –

4

今日はこの問題を苦労し、最終的に広告申込情報の価格を変更する正しい道を見つけました。問題は、広告申込情報の価格をカスタム値に変更しても、次のページの更新時にカートが広告申込情報を元の商品価格に合わせてリセットすることです。詳細については、commerce_cart_order_refresh()関数を見てください。この機能は、注文/カートがページにロードされ、その周りに道がないたびに実行されます。

広告申込情報の価格を変更する適切な方法は、ルールを使用するか、hook_commerce_cart_line_item_refresh()機能を実装することです。どちらの方法でも、Drupal Commerceはカート/注文がロードされるたびに変更ロジックを適用できる必要があります。

私は、私が欲しかったカスタム価格値を保存したラインアイテムにカスタムフィールドを作成しました。その後、価格設定ルールを使用して、カートを更新するたびにカスタム価格値を製品価格値にコピーしました。

以下のブログ記事は、これを理解するのに非常に役立ちました。ラインアイテムタイプにカスタムフィールドを追加する方法と、カスタム金額を単価にコピーする価格設定ルールを設定する方法を示します。

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

+1

共有ありがとう! Drupal Commerceは強力で柔軟性がありますが、なぜ価格改定が厳格な方法でルールに縛られているのかはまだ分かりません。 – Strae

+0

最終的なコードを投稿できますか? – MSD

+0

@MichaelStevens私はこの機能を実装した例を掲載しました。 – mpoplin

1

最近、私は、Commerceに寄付フォームを実装する必要がありましたが、Commerce Express Checkoutモジュールは、カスタム線の項目を処理しません。それは寄付であり、誰(誰かがスクリューをしようとしていますか?)なので、Express Checkoutモジュールが提供するURLの3番目のパラメータとして寄付額を渡すことが適切であると感じました。ここで私は、モジュールをハッキングについていった方法である:

私は、ルータに新しいエントリを追加しました:

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

私が複製され、微調整デフォルトのコールバックをしてそれに「_extra」をタック。「データ」プロパティは、このような機会のための静的な変数ストアであると思われ、広告申込情報の存続期間を維持します。ここで

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

は、単にによる学習曲線に最もトリッキーなものと一体の機能を使用するかを知らないことになった部分です:

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

カートが変更されたひとつひとつの時間、それが更新されますカート内の製品をコード内のプロトタイプに設定しようとします。私にとっても非常に非効率的だと思われますが、私は何かを見逃す可能性があります。

6

ラインアイテムに保存されている以前のものは何でも値無視して、あなたの新しい金額から、あなたが探している機能を、合計を再計算するために探している場合である。ここに私のソリューションです。

が新たな量の値を設定し、広告申込情報が通過し、行項目と順序を保存:

$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

これは私の考えでは最高の答えです。私は、Drupal Commerceの複雑な価格設定システムが非常に役立つ状況があると確信していますが、ユースケースでは、私はちょうど** dang price **を設定したいと思っています。 (したがって、私のコードを理解するのがさらに難しくなります)。 – jaskho

0

この投稿は、プログラムによってDrupalの商取引の行項目を変更するための正しい方向に私を指摘しましたhook_commerce_cart_line_item_refersh()を使用してください。しかし、ここでの答えのいくつかは、間違っているか、非常に非効率的で賢明ではありません。

これは、Drupalのコマースにライン・アイテム・タイプを変更するための正しい作業溶液のようになります。

/* 
* 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(); 
    } 
} 
関連する問題